Skip to content

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 脉冲用大权重快速拉上去,之后切换到小权重平滑跟踪。

硬件连接

信号PX4RK3588说明
PPSGPIO 输出GPIO3_C61Hz 脉冲
UART TXUART TXUART RXMAVLink
UART RXUART RXUART TXMAVLink
GNDGNDGND共地

整体架构

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