2. 时间戳基础:系统时间、UTC时间、GPS时间、传感器时间戳的获取方式

做多传感器融合,第一道坎就是时间。我见过太多项目,算法写得再漂亮,时间没对齐,结果全是废的。说白了,时间戳就是传感器的“身份证”,你得知道每个数据是什么时候出生的。

这一节,我们聊聊四种最常见的时间体系。嗯,别觉得基础,这里面的坑,我踩过不少。

2.1 系统时间:你最熟悉的“墙钟时间”

系统时间,就是你的电脑或嵌入式板卡上显示的时间。比如你在Linux里敲date命令看到的那个。

它的获取方式很简单:

// C++ 获取系统时间戳(毫秒级)
#include <chrono>
auto now = std::chrono::system_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();

但我要提醒你:系统时间不可靠。为什么?

  • 用户可能手动改时间
  • NTP同步时会有跳变
  • 休眠唤醒后可能不准
⚠️ 我曾经在自动驾驶项目里,就因为系统时间被运维人员手动调整了1秒,导致整个传感器融合模块的位姿估计全乱了。排查了整整两天。

所以,我个人习惯:系统时间只用来做“人可读”的日志记录,绝不用于传感器融合的时间基准。

2.2 UTC时间:全球统一的标准

UTC,协调世界时。你可以理解为“全球统一的时间标准”。它基于原子钟,非常稳定。

获取UTC时间的方式:

// 从系统时间转UTC
time_t rawtime;
struct tm * ptm;
time(&rawtime);
ptm = gmtime(&rawtime);  // gmtime返回的就是UTC
printf("UTC: %s", asctime(ptm));

UTC和系统时间的关系?系统时间通常就是UTC加上时区偏移。比如北京时间是UTC+8。

这里有个关键点:传感器数据的时间戳,最好统一用UTC。这样不管你在北京、纽约还是伦敦,数据拿到手里,时间基准是一样的。

💡 我建议:所有传感器的时间戳,在存储时都转成UTC。别偷懒用本地时间。否则数据融合时,时区转换能让你疯掉。

2.3 GPS时间:卫星给你的“绝对时间”

GPS时间,是GPS卫星系统内部使用的时间体系。它从1980年1月6日0点开始计时,单位是周+秒。

获取方式:

// 从GPS接收机获取时间(伪代码)
uint32_t gps_week;      // GPS周
double   gps_seconds;   // 周内秒(精度可达纳秒级)

// 读取接收机数据
read_gps_time(&gps_week, &gps_seconds);

GPS时间和UTC有个差异:闰秒。因为地球自转在变慢,UTC会不定期加1秒(闰秒),但GPS时间不加。所以目前GPS时间比UTC快了18秒(2024年数据)。

时间体系 起点 精度 是否跳变
系统时间 1970-01-01 毫秒级 可能跳变
UTC 1972-01-01 纳秒级 闰秒调整
GPS时间 1980-01-06 纳秒级 无跳变
🔑 核心要点:GPS时间没有闰秒,是连续的时间轴。做传感器融合时,GPS时间比UTC更“干净”。

2.4 传感器时间戳:硬件给你的“原始时间”

每个传感器都有自己的时钟。比如激光雷达、IMU、相机。它们的时间戳怎么来的?

  • 相机:通常由硬件触发信号产生,精度在微秒级
  • IMU:内部晶振计时,精度较高,但会漂移
  • 激光雷达:每个点云帧都有时间戳,但不同厂商实现方式不同

获取方式示例(以ROS为例):

// 从ROS消息中获取传感器时间戳
sensor_msgs::Imu imu_msg;
ros::Time stamp = imu_msg.header.stamp;
double secs = stamp.toSec();  // 秒为单位

这里有个大坑:传感器时间戳和系统时间戳可能不同步。比如相机的时间戳是硬件给的,但你的电脑系统时间可能已经漂移了。

⚠️ 我曾经遇到过:某款激光雷达的时间戳用的是内部晶振,但晶振温漂严重。开机前10分钟,时间戳误差能到100毫秒。如果不做补偿,融合结果直接炸裂。

我的建议:

  1. 每个传感器的时间戳,尽量用硬件触发,别用软件打戳
  2. 定期用GPS时间校准传感器时钟
  3. 记录时间戳时,同时记录它的“来源”(系统时间?GPS?硬件?)

2.5 四种时间体系的关系图

下面这张图,是我自己总结的。四种时间体系的关系,一目了然:

四种时间体系关系图 系统时间 依赖NTP/手动设置 精度:毫秒级 UTC时间 原子钟基准 精度:纳秒级 GPS时间 1980年起算 无闰秒 传感器时间戳 硬件触发/晶振 精度:微秒级 时区转换 +闰秒 校准 PPS同步 核心:传感器时间戳需要向GPS/UTC对齐,系统时间仅作人机交互

2.6 实际项目中的选择

说了这么多,到底用哪个?

我个人经验:

  • 有GPS信号的环境(室外无人车、无人机):直接用GPS时间作为主时钟。所有传感器通过PPS信号同步。
  • 无GPS信号的环境(室内机器人、隧道):用UTC时间,但必须保证NTP稳定。或者用高精度晶振自己维护一个时间基准。
  • 传感器内部时间戳:永远保留原始值。别自作聪明去转换,万一转换公式错了,数据就废了。
💡 一个小技巧:在记录数据时,同时记录三种时间戳——传感器原始时间、接收时的系统时间、GPS时间(如果有)。这样即使一种时间出问题,还有备份可以校准。

嗯,时间戳基础就聊这么多。下一节我们聊聊更具体的——怎么把这些时间戳对齐到同一个时间轴上。到时候我会分享一个我实际用过的对齐算法。

可可精品资料库