问题:
在将 use_sim_timer
置为 true
时,节点 Timer_Callback 行为 “异常” 。在回调函数中,使用 self.get_logger().info("xxxx")
输出信息,希望通过查看 Info 中的时间戳(如下),测试 Timer_Callback 回调频率是否正常。发现该时间戳与预期回调频率不符。
[target_server-7] [INFO] [1720427228.138427518] [target_server]: timer callback
[target_server-7] [INFO] [1720427228.278225224] [target_server]: timer callback
[target_server-7] [INFO] [1720427228.537763996] [target_server]: timer callback
[target_server-7] [INFO] [1720427228.661480401] [target_server]: timer callback
解决:
-
debug的方式有错。即使将
use_sim_timer
置为true
, Info 中的时间戳依旧与现实时间同步。这意味着如果要通过 Info 时间戳估计回调函数的调用频率,需要根据仿真时间因子进行换算。 -
换算方式。查看运行中的Gazebo的参数
real_time_factor
,确定仿真时间与现实时间的比率。举一个简单的例子:当回调函数的频率设置为 5Hz 时,Gazebo参数real_time_factor
为 0.8,则Info时间戳下的频率应该为 5 * 0.8 = 4 Hz 。所以当受限于电脑性能,Gazebo参数real_time_factor
不稳定时,Info时间戳也将会变得不稳定。 -
当然,如果早知道 Info 时间戳不会随之改变,我们也可以直接读取时钟,将其放入Info中检查回调频率,这种方式免去了换算的必要 : ) 例如:
self.get_logger().info("timer callback at " + str(self.get_clock().now().to_msg()))
一些在Debug中额外的发现:
当将 use_sim_timer
置为 true
后,ROS将通过话题 /clock
获取当前时间。我们可以通过修改仿真速率或是话题的发布频率来设置ROS收到的时间的分辨率,以此保证ROS的timer callback的行为符合预期。
举一个例子:如果在ROS中存在一个 20Hz 的 timer callback,则时间分辨率要至少为 0.05s。如果仿真时间分辨率小于 0.05s,则在仿真时间的 1s 内,该callback的回调次数将小于20次。
设置时间分辨率的方法:假设仿真速率,也就是 Gazebo参数 real_time_factor
为 0.1,话题 \clock
的发布频率为 0.1,则预期的时间分辨率为 0.01s。但是时间分辨率需要大于Gazebo的运算步长 max_step_size
,当时间分辨率小于该步长时,经测试话题 \clock
的发布频率将会自适应的减小,只有计算完一步后才会向 /clock
发布最新时间。
调整 Gazebo参数 real_time_factor
的方法:
-
在Gazebo的
world.model
的文件中,设置仿真运行速率-
real_time_update_rate:每秒期望迭代次数(实际受到计算资源的约束,可能达不到)
-
max_step_size:迭代时间步长
-
real_time_factor:与实际时间的比率 (为real_time_update_rate * max_step_size) ,大于1则比实际时间运行的快
-
调整话题 \clock
的发布频率的方法:
- 通过参数文件设置,设置gazebo节点的参数
publish_rate
。 - 参考链接:https://github.com/cpslabor-education/robotwiki/wiki/[Simulation][Gazebo]-Gazebo-simulation-in-ROS-2