关于在ROS中会出现的两种ROS Time
作者:互联网
做实验的过程中发现,ROS里面其实会计算两个ROS Time
- 一个是仿真的时间:sim time,这个时间应该是从启动程序时才开始计算的
- 一个是系统的时间:system time,这个应该跟系统的时间是match的
这两个时间,很多人可能没有怎么了解,应该确实很多地方也需要考虑到它,系统内部会帮忙我们处理好它们的关系。
同时,读取它们的函数都是同一个,ros::Time::now()
如果有留意的话,会发现,有些节点的更新频率是一串很长的时间数字,有些节点的更新频率却是很多的一个时间,这就说明一个节点读取的是系统时间,另一个读取的是SIM time,所以这两个节点的时间其实可以说是不一样的。
在一般应用过程中,只是通过topic发布信息,和接收信息,不考虑ros time的情况下,可以忽略上面的问题,但是有些节点要做规划的时候,需要根据ros time对应的数据来做计算,这时这个ros time如果一个是系统时间另一个是sim time就会出问题,因为系统时间是很大的一组数,它会认为sim time是属于它很久远的一个数值,然后就会报错,如1631889779.809762075是系统时间,42.56851是sim time,这种情况下,即使我们知道它们两个时间在含义上是对等的,但在数值上,这两个数就相差很远很远了。
要处理这个问题,可以看看自己是否启动了gazebo的simi time,如下:
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="world_name" value="worlds/empty.world"/>
<arg name="debug" value="$(arg debug)" />
<arg name="gui" value="$(arg gui)" />
<arg name="paused" value="false"/>
<arg name="use_sim_time" value="true"/>
<arg name="headless" value="$(arg headless)"/>
</include>
里面有一个参数名叫use_sim_time
,如果选true,它就会发布sim time,不使用系统时间,选false就会变为系统时间。
知道这个选项后就可以解决部分问题。
但是如果有人使用的是ROS自带的关节控制器,如下所示。
<node name="controller_spawner" pkg="controller_manager" type="spawner" respawn="false"
output="screen" ns="/mobile_manipulator" args="joint_state_controller
first_joint_position_controller second_joint_position_controller third_joint_position_controller"/>
这时会发现,不管是关闭或选择开启gazebo的sim time,对它都是没有影响的,它一直使用SIM time,这就很恶心了,如果gazebo中选了系统时间,而这个关节控制器使用的是sim time,就会导致机器人状态发布器robot_state_publisher
发布的TF关系也是sim time,这就导致TF报错,无法连接上,TF就会出错,导致机器人无法正常显示,如下图所示
从图中可以看出,最顶端用的是系统时间,一串很长的数,但是下方的关节处,first link 和 second link以及arm link那里更新的时间是sim time,很小的值,这两个时间完全match不上,就会导致机器人没办法正常在rivz中显示。
所以要解决的方案是,不使用ROS自带的这个关节控制器,而是自己写一个关节状态发布器,来维护关节的状态信息。当然这个关节状态发布器也要考虑到,不能只是收到指令才发布状态,在没有收到指令时也要一直发布关节信息。
以下是一个简易版的关节状态发布器,下周再更新完整版的:
#include <string>
#include <ros/ros.h>
#include <sensor_msgs/JointState.h>
#include <tf/transform_broadcaster.h>
int main(int argc, char** argv) {
ros::init(argc, argv, "state_publisher");
ros::NodeHandle n;
ros::Publisher joint_pub = n.advertise<sensor_msgs::JointState>("/mobile_manipulator/joint_states", 1);
tf::TransformBroadcaster broadcaster;
ros::Rate loop_rate(100);
// message declarations
sensor_msgs::JointState joint_state;
/**/
double num = 1;
while (ros::ok()) {
//update joint_state
num++;
joint_state.header.stamp = ros::Time::now();
joint_state.name.resize(3);
joint_state.position.resize(3);
joint_state.name[0] ="first_joint";
joint_state.position[0] = num*0.01;
joint_state.name[1] ="second_joint";
joint_state.position[1] = num*0.01;
joint_state.name[2] ="third_joint";
joint_state.position[2] = num*0.01;
joint_pub.publish(joint_state);
// This will adjust as needed per iteration
loop_rate.sleep();
}
// joint_state.header.stamp = ros::Time::now();
// joint_state.name.resize(3);
// joint_state.position.resize(3);
// joint_state.name[0] ="first_joint";
// joint_state.position[0] = 0;
// joint_state.name[1] ="second_joint";
// joint_state.position[1] = 0;
// joint_state.name[2] ="third_joint";
// joint_state.position[2] = 0;
// joint_pub.publish(joint_state);
// ros::spin();
return 0;
}
以上都是个人的理解,如果有大神有更准确的信息,请评论留言指正。
Reference
- ROS学习笔记(十六):Using urdf with robot_state_publisher:
https://blog.csdn.net/qq_42910179/article/details/107038351
标签:ros,name,Time,joint,state,time,ROS,sim,中会 来源: https://blog.csdn.net/Will_Ye/article/details/120366625