RK3588 与 PX4 高精度时间同步
做无人机多传感器融合,时间同步精度直接影响定位结果。PX4 飞控跑在 STM32 上,机载计算机跑在 RK3588 上,两边各有各的时钟,需要把它们对齐。
问题
PX4 发出的 IMU 数据带的是飞控 boot 时间,RK3588 上的 ROS 用的是系统 CLOCK_MONOTONIC。同一个物理事件,两边的时钟差了几百万微秒。不解决这个问题,VIO、SLAM 全白搭。
设计思路
核心就一句话:RK3588时间 = PX4时间 + offset,关键是 offset 怎么算。
PX4 每秒输出一个 PPS 脉冲(1Hz),同时通过串口发 TIMESYNC 消息,里面带着 PPS 发生时刻的时间戳 tc1。RK3588 用 GPIO 捕获 PPS 上升沿,拿到本地时间戳。两边一减就是 offset。
PX4 RK3588
│ │
├── PPS 上升沿 │
│ tc1 = 1000000 us │ GPIO 捕获
│ │ = 1234567890 ns
│ │
│ offset = 1234567890 - 1000000000 = 234567890 ns有了 offset,后续收到 IMU 数据直接加 offset 就行了。
为什么串口延迟不影响
TIMESYNC 消息里的 tc1 是 PX4 发出 PPS 的时刻,不是发出消息的时刻。即使串口有 1ms 延迟,tc1 记录的还是 PPS 那一瞬间的时间,offset 计算基于的是同一个硬件事件。
offset 平滑
原始 offset 每次算出来都会抖动(GPIO 中断延迟、晶振偏差等),用 EMA 滤波:
cpp
if (pps_count < 10) {
offset = (raw_offset + offset) / 2; // 快速收敛
} else {
offset = (raw_offset + 9*offset) / 10; // 稳定跟踪
}前 10 个 PPS 脉冲用大权重快速拉上去,之后切换到小权重平滑跟踪。
硬件连接
| 信号 | PX4 | RK3588 | 说明 |
|---|---|---|---|
| PPS | GPIO 输出 | GPIO3_C6 | 1Hz 脉冲 |
| UART TX | UART TX | UART RX | MAVLink |
| UART RX | UART RX | UART TX | MAVLink |
| GND | GND | GND | 共地 |
整体架构
PX4 (STM32H7) ──┬── PPS (1Hz) ──▶ RK3588 GPIO3_C6
│
└── UART ────────▶ /dev/ttyS9
│
▼
timesync_node
├── PpsCapture (GPIO 中断捕获)
├── MavlinkReceiver (串口解析)
├── TimeSynchronizer (offset 计算 + 滤波)
└── ROS Topics (发布时间戳对齐的 IMU 数据)实现
完整代码在 GitHub 上,基于 ROS Noetic,主要模块:
- PpsCapture — 用 libgpiod 捕获 GPIO 上升沿,纳秒精度
- MavlinkReceiver — 串口解析 TIMESYNC 和 RAW_IMU 消息
- TimeSynchronizer — offset 计算和 EMA 滤波
- TimeSyncNode — ROS 主节点,串起来发布数据
编译运行:
bash
cd ~/ros_ws
catkin build timesync
roslaunch timesync timesync.launch