ROS2开发BUG记录:在将 use_sim_timer 置为 true 时,节点的 Timer_Callback 行为“异常”

问题:

在将 use_sim_timer 置为 true 时,节点 Timer_Callback 行为 "异常" 。在回调函数中,使用 self.get_logger().info("xxxx") 输出信息,希望通过查看 Info 中的时间戳(如下),测试 Timer_Callback 回调频率是否正常。发现该时间戳与预期回调频率不符。

basic 复制代码
[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

解决:

  1. debug的方式有错。即使将 use_sim_timer 置为 true , Info 中的时间戳依旧与现实时间同步。这意味着如果要通过 Info 时间戳估计回调函数的调用频率,需要根据仿真时间因子进行换算。

  2. 换算方式。查看运行中的Gazebo的参数 real_time_factor ,确定仿真时间与现实时间的比率。举一个简单的例子:当回调函数的频率设置为 5Hz 时,Gazebo参数 real_time_factor 为 0.8,则Info时间戳下的频率应该为 5 * 0.8 = 4 Hz 。所以当受限于电脑性能,Gazebo参数 real_time_factor 不稳定时,Info时间戳也将会变得不稳定。

  3. 当然,如果早知道 Info 时间戳不会随之改变,我们也可以直接读取时钟,将其放入Info中检查回调频率,这种方式免去了换算的必要 : ) 例如:

    python 复制代码
    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 的发布频率的方法: