事起
我发现ros在进行算法测试时经常会用到时间戳进行同步等操作,那么就需要数据的时间戳和我要使用的时间戳应该是在同一个尺度下的(比如都使用录制bag包当时的数据),ros中正好有这样的管理过程,之前没有注意里面具体的机制,这里详细的说明一下情况是怎么样的.
ROS1 时间系统详解
1. ROS时间系统概述
ROS (Robot Operating System) 提供了一套完整的时间管理系统,用于处理机器人系统中的时间同步问题。ROS时间系统的核心特点包括:
- 统一时间基准:所有节点共享同一个时间基准
- 仿真时间支持:支持仿真环境下的时间控制
- 时间同步机制:通过clock话题实现时间同步
- 灵活的时间模式:支持真实时间和仿真时间切换
1.1 时间类型
ROS中主要有两种时间类型:
- Wall Time(墙钟时间):系统真实时间,不受ROS参数影响(主要通过import time然后通过time.time()获取墙钟时间即可)
- ROS Time:ROS管理的时间,可以是真实时间或仿真时间
2. rospy.time 工作原理
2.1 基本概念
rospy.Time 是ROS Python API中的时间类,提供了时间相关的所有功能:
import rospy
from rospy import Time, Duration
import time
rospy.init_node('time_comparison_node')
# 获取当前ROS时间
current_time = rospy.Time.now()
# wall time
time_wall = time.time()
# 创建特定时间戳
specific_time = rospy.Time(secs=1234567890, nsecs=123456789)
# 时间运算
time_diff = current_time - specific_time
future_time = current_time + rospy.Duration(10) # 10秒后
print(f"当前ROS时间: {current_time.to_sec():.3f}")
print(f"当前墙钟时间: {time_wall:.3f}")
print(f"特定时间戳: {specific_time.to_sec():.3f}")
print(f"时间差: {time_diff.to_sec():.3f}")
print(f"10秒后的时间: {future_time.to_sec():.3f}")

正常运行过程时,ros都是以标准时间戳输出的信息.(注意,想要获得ros的时间戳,必须要初始化节点,也就是rospy.init_node(“time_node”))
2.2 时间获取机制
rospy.Time.now() 的行为取决于 use_sim_time 参数:
- use_sim_time=false:返回系统真实时间
- use_sim_time=true:返回从
/clock话题接收到的仿真时间
3. 仿真时间与真实时间的区别
3.1 真实时间模式(Wall Time Mode)
# 设置为真实时间模式
rosparam set use_sim_time false
特点:
- 时间与系统时钟同步
- 时间流逝速度固定(1:1)
- 适用于真实机器人系统
3.2 仿真时间模式(Simulation Time Mode)
# 设置为仿真时间模式
rosparam set use_sim_time true
特点:
- 时间由仿真器或外部源控制
- 可以暂停、加速或减速
- 适用于仿真环境和数据回放
注意,设置这个参数并不能实时修改我的ros时间,意思就是,如果之前已经通过py来获取了真实的ros时间,此时动态设置use_sim_time并不会直接起作用,重启节点之后可以起作用.
然后设置了这个参数之后我们可以再次打印一下这个时间戳的信息:
import rospy
from rospy import Time, Duration
import time
rospy.init_node('time_comparison_node')
while not rospy.is_shutdown():
# 获取当前ROS时间
current_time = rospy.Time.now()
# wall time
time_wall = time.time()
# 创建特定时间戳
specific_time = rospy.Time(secs=1234567890, nsecs=123456789)
# 时间运算
time_diff = current_time - specific_time
future_time = current_time + rospy.Duration(10) # 10秒后
print(f"当前ROS时间: {current_time.to_sec():.3f}")
print(f"当前墙钟时间: {time_wall:.3f}")
print(f"特定时间戳: {specific_time.to_sec():.3f}")
print(f"时间差: {time_diff.to_sec():.3f}")
print(f"10秒后的时间: {future_time.to_sec():.3f}")
time.sleep(1)
可以发现此时的时间表现为:
当前ROS时间: 0.000
当前墙钟时间: 1758607078.709
特定时间戳: 1234567890.123
时间差: -1234567890.123
也就是一直都是0!!
因为对于此时来说,ros的时间戳就是由话题来进行管理的了.接下来我们来发布这个话题.
4. Clock话题管理机制
4.1 Clock话题结构
/clock 话题使用 rosgraph_msgs/Clock 消息类型:
# rosgraph_msgs/Clock
time clock
4.2 时间发布者
仿真器(如Gazebo)或rosbag会发布clock消息:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
from rosgraph_msgs.msg import Clock
def clock_publisher():
"""时间发布节点示例"""
rospy.init_node('clock_publisher', anonymous=True)
# 创建clock发布者
clock_pub = rospy.Publisher('/clock', Clock, queue_size=10)
rate = rospy.Rate(100) # 100Hz
start_time = rospy.Time.now()
while not rospy.is_shutdown():
# 创建clock消息
clock_msg = Clock()
# 仿真时间(可以是任意时间流速)
elapsed = rospy.Time.now() - start_time
clock_msg.clock = start_time + rospy.Duration(elapsed.to_sec() * 2.0) # 2倍速
clock_pub.publish(clock_msg)
# rate.sleep()
if __name__ == '__main__':
try:
clock_publisher()
except rospy.ROSInterruptException:
pass

可以看到,第一次没有clock的时候还是打印了ros的0的时间戳,后来发布了clock之后就可以获得我们发布的clock中的时间戳了。
5. use_sim_time 参数作用机
制
5.1 参数设置方法
# 方法1:命令行设置
rosparam set use_sim_time true
# 方法2:launch文件设置
<param name="use_sim_time" value="true" />
# 方法3:代码中设置
rospy.set_param('use_sim_time', True)
5.2 参数影响范围
- 所有ROS节点:影响整个ROS系统的时间行为
- 消息时间戳:影响消息头中的时间戳
- TF变换:影响坐标变换的时间戳
- 定时器:影响rospy.Timer的行为
5.3 切换注意事项
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
def time_mode_switcher():
"""时间模式切换示例"""
rospy.init_node('time_switcher')
# 检查当前时间模式
use_sim_time = rospy.get_param('use_sim_time', False)
rospy.loginfo(f"当前时间模式: {'仿真时间' if use_sim_time else '真实时间'}")
# 等待时间同步(仿真时间模式下)
if use_sim_time:
rospy.loginfo("等待时间同步...")
rospy.wait_for_message('/clock', rospy.AnyMsg)
rospy.loginfo("时间同步完成")
# 显示当前时间
current_time = rospy.Time.now()
rospy.loginfo(f"当前ROS时间: {current_time.to_sec()}")
if __name__ == '__main__':
time_mode_switcher()
6. Rosbag与时间控制
6.1 Rosbag时间发布机制
Rosbag在回放时会自动发布clock消息:
# 正常回放(发布clock)
rosbag play data.bag --clock
# 指定回放速度
rosbag play data.bag --clock --rate=2.0 # 2倍速回放
# 暂停回放
rosbag play data.bag --clock --pause
6.2 时间控制选项
# 从指定时间开始回放
rosbag play data.bag --clock --start=10.0
# 回放指定时长
rosbag play data.bag --clock --duration=30.0
# 循环回放
rosbag play data.bag --clock --loop
# 立即开始(不等待订阅者)
rosbag play data.bag --clock --immediate
到这里我们就能理解所有的时间的关系了,以及为什么可以通过clock话题来实现过去时间戳的统一化。
1021

被折叠的 条评论
为什么被折叠?



