ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

STM32硬件同步速腾雷达与海康相机,实现GAC-Mapping点云图像时间戳对齐

STM32硬件同步速腾雷达与海康相机,实现GAC-Mapping点云图像时间戳对齐 “速腾雷达与海康相机硬件同步实战基于STM32的GAC-Mapping时间戳对齐方案”做多传感器融合建图的朋友应该都遇到过这种场景激光雷达和相机各跑各的点云投影到图像上总是错开一截建出来的图拐角处发虚走一圈回来轨迹还飘了。问题八成出在时间同步上而且不是软件里加个队列等一等就能解决的那种。这篇博文就是拿我自己调通的一套方案来聊用一块STM32做硬件同步源同时给速腾雷达和海康相机喂同步信号让GAC-Mapping里点云和图像的时间戳真正做到硬对齐。整个过程从原理、接线、代码到踩过的坑都会提到适合正在搭雷达相机融合平台、或者被时间戳问题折腾得焦头烂额的开发者参考。1. 为什么GAC-Mapping必须要硬件同步1.1 时间戳误差带来的崩坏现场先说个我自己踩过的真实场景。最初我把速腾雷达和海康相机都接到一台工控机上各跑各的驱动想着采集完再离线对齐时间戳。雷达点云50Hz输出相机图像30Hz输出ROS里直接用TimeSynchronizer做近似时间同步消息时间戳差了10ms以内就当成同一帧。看着没问题可实际用GAC-Mapping跑回环的时候地图边缘一直有重影。后来把点云投影到图像上检查发现物体的轮廓在图上明显错开了半个车身宽度。问题的根源就在于两路传感器的时间基准不一样。雷达和相机都有自己的时钟晶振就算软件里做了时间戳同步也只是在消息到达主机那一刻打的系统时间戳。传感器本身从曝光到数据完整输出给主机之间有一段不确定的延迟而且延迟会随着网口负载、CPU占用波动。10ms的误差在旋转雷达上意味着什么10Hz的雷达转一圈100ms10ms就是36度的角度误差。点云上的每个点都带着这么大的角度偏差地图不糊才怪。GAC-Mapping这类基于图优化的建图算法对输入数据的质量非常敏感。它对时间戳的要求精确到单个点或者至少单帧扫描级别。如果帧与帧之间的时间关系是乱的前端里程计的解算就会引入系统性的漂移后端就算有回环检测一路拉也架不住每一帧的误差都往同一个方向偏。所以解决思路必须从源头改让雷达和相机从硬件层面共用同一个时钟源和触发信号。1.2 三种同步方案对比多传感器时间同步分几个层级软件同步、网络同步、硬件同步。软件同步最简单就是上述说的在主机侧给消息打时间戳然后用队列去匹配。问题在于传感器端到端的延迟完全是个黑盒精度能做到20ms以内就烧高香了。网络同步用PTPIEEE 1588协议理论上能达到微秒级但前提是网卡和交换机得支持硬件时间戳而且传感器端还得有对应的PTP实现。很多工业相机和激光雷达是支持PTP的但配置繁琐对网络环境要求也高。硬件同步是精度最可靠、也最难绕开的一条路。核心思路是建立一个统一的外部时钟源给每个传感器发送物理电平信号。雷达收到脉冲信号就知道这是某一帧开始的基准时刻相机收到触发信号立刻开始曝光。这样一来雷达和相机从物理上保证在同一时刻采集数据时间戳误差直接压在微秒甚至亚微秒级别。硬件同步方案里STM32作为同步信号发生器是性价比最高、灵活度也最好的选择。我做硬件同步的时候最初也考虑过直接用雷达输出的PPS信号去触发相机。速腾雷达本身支持接收GPS的PPS和GPRMC也可以用外部信号做外触发同步。但我实际测下来PPS只有每秒一个脉冲和相机需要的每帧触发10Hz或更高对不上。那就在中间加一块STM32由它来产生多路同步信号分别接雷达和相机。这样雷达和相机虽然在各自工作触发的源头却是同一个。1.3 同步方案选型为什么是STM32在选型同步主控时我对比过几种方案。用FPGA做精度确实高时序绝对可控但开发周期长不是所有人都能玩得转。用单片机里最常用的STM32自带定时器、PWM输出、输入捕获、串口功能刚好全覆盖而且有大量现成的库和参考代码。价格还便宜一块F407的开发板一百出头就能搞定。对做机器人、无人车的团队来说非常合适。STM32在同步方案里的职责有三个一是接收外部GPS模块的PPS信号和串口GPRMC数据作为绝对时间基准二是产生与PPS对齐的多路触发信号一路给雷达做帧同步一路给相机做外部触发三是通过串口或者USB把时间戳信息发送给主机方便后续驱动级的时间戳对齐。换句话说STM32既当“授时中心”又当“触发控制器”一举两得。2. 核心原理详解从PPS到帧对齐2.1 速腾雷达的同步机制速腾RoboSense的雷达不管是RS-LiDAR-16还是RS-Helios系列都支持两种同步模式一种是内部自由运行模式雷达按自己的时钟输出扫描帧另一种是外部同步模式雷达接收外部输入的PPS脉冲和GPRMC时间报文用这些信息校准自身的时间戳并进行帧同步。雷达在外部同步模式下其实有两层对齐逻辑。第一层是频率校准PPS每秒一个脉冲雷达收到后能校准自己的秒级时间。第二层是帧对齐雷达通常还会接收一个帧同步脉冲频率匹配雷达的扫描频率比如10Hz雷达只有在收到这个脉冲后才开始下一帧的扫描。这样一来只要上游的同步源准确雷达输出的每一帧点云就有一个可预期的起始时刻。在同步信号的电气连接上速腾雷达一般提供一个航空插头里面有PPS、GPRMC和同步输入引脚。不同型号的接口定义有差异接线前一定要查对应的硬件手册。我用的RS-LiDAR-16是12Pin航空插头里面包含了电源、网口、PPS输入、GPRMC输入、同步输入等引脚。如果你的雷达型号不一样接口引脚分布可能不同务必以官方手册为准。2.2 海康相机的硬件触发与Strobe信号海康机器人HIKROBOT的工业相机大部分型号都支持硬件外部触发。通过相机的GPIO接口接入外部信号可以控制相机开始曝光。和雷达相似相机有两种触发模式内触发Free Run和外触发External Trigger。在外触发模式下相机的每一帧曝光都由外部脉冲信号启动脉冲的上升沿或者下降沿可以配置触发一次曝光。海康相机在硬件触发的基础上还能输出一个Strobe信号。所谓Strobe就是相机在曝光开始或结束时通过GPIO输出一个电平信号通知其他设备“我正在曝光”。这个信号可以用示波器测量用来验证相机的实际曝光时刻。在实际同步系统中Strobe信号是重要的反馈信息可以接到STM32的输入捕获引脚上用来计算相机曝光与雷达扫描之间的真实延迟。这里要特别强调一点相机在硬件触发模式下曝光时间和触发周期必须匹配。触发频率不能太高否则相机来不及完成一帧的曝光和读出会丢帧。触发信号的电平也需要和相机GPIO的要求匹配海康相机一般为3.3V或5V输入STM32的GPIO输出电平可以通过配置和外围电路调整。2.3 时间戳对齐的数学定义与误差预算谈硬件同步绕不开一个核心指标时间戳对齐误差到底是多少这个误差指的是雷达某一帧扫描起始时刻和相机曝光起始时刻之间的时间差。在理想情况下这个时间差应该为0即两者同时开始采集。实际工程中完全为0是不可能的但做到1ms以内是被业界广泛认可的“合格线”。来算一笔账。假设雷达扫描频率为10Hz雷达的角分辨率为0.2度那么雷达转完一整圈需要100ms扫描一个点的间隔大概是0.16ms。如果雷达和相机的同步误差是1ms那么在雷达扫描的点云中就会有一个点的角度偏移约0.6度。当投影到图像上时假设图像分辨率为1920x1080水平视场角约70度那么1ms的同步误差会导致图像上约16个像素的偏移。这对于建图来说已经是肉眼可见的误差了。所以我把同步误差预算分成两部分一是触发信号的物理传播延迟通常小于100ns可以忽略二是传感器自身的曝光和读出延迟这个才是误差的大头。比如海康相机在外部触发模式下从触发信号到曝光中点的延迟约为曝光时间的一半曝光时间越长延迟越大。雷达在收到同步脉冲后有固件处理时间大概几百微秒。因此在设计同步方案时还需要用软件或硬件补偿这部分固定的延迟。在STM32方案里可以通过调整触发信号的相位来补偿让相机在雷达帧扫描的零度位置附近开始曝光。3. 基于STM32的硬件同步搭建实操3.1 系统接线与信号流向整套系统的接线并不复杂核心信号流是这样的GPS模块的PPS和GPRMC接入STM32STM32解析出绝对时间再产生两路同步脉冲信号分别给速腾雷达和海康相机。雷达和相机各自把数据通过网线传给主机主机再根据同步时间戳进行融合。具体到引脚接线以STM32F407VET6为例GPS模块如u-blox NEO-M8N的PPS引脚接到STM32的PA0TIM2_CH1输入捕获GPRMC数据通过串口USART2的PA2/PA3接入。STM32的PA8TIM1_CH1PWM输出接到速腾雷达的同步输入引脚输出10Hz的帧同步脉冲。STM32的PB6TIM4_CH1PWM输出接到海康相机的Line0触发输入输出10Hz的触发脉冲占空比设为20%左右。海康相机的Line3Strobe输出接回STM32的PB0TIM3_CH3输入捕获用来验证曝光时刻。共地非常重要STM32、GPS模块、雷达、相机必须共地否则信号参考电位不一致容易出现误触发和丢帧。主机端雷达和相机分别连接网口。雷达利用官方驱动解析PPS同步脉冲校准后的时间戳相机则通过海康SDK获取触发时间戳。两边的时间戳都基于GPS时间这样在算法层面就实现了对齐。3.2 STM32CubeMX配置详拆开发环境用STM32CubeMX生成初始化代码配合HAL库。工程创建时选择STM32F407VET6作为MCU。RCC配置里选择外部高速时钟HSE时钟树设置系统主频为168MHz。定时器时钟源来自APB1和APB2我分别将APB1设为42MHzAPB2设为84MHz这样后续设置定时器频率时方便计算。时钟配置这块要注意TIM1挂在APB2上84MHzTIM2和TIM4挂在APB1上42MHz。定时器的实际计数频率还需要再乘以定时器自身的分频系数。接下来配置定时器TIM2PPS输入捕获设置为Input Capture模式通道1映射到PA0。预分频器设为84-1计数频率为1MHz即分辨率1us。上升沿捕获。打开捕获中断。TIM1雷达帧同步输出设置为PWM Generation模式通道1映射到PA8。预分频器设为84-1计数频率为1MHz。自动重载值ARR设为100000-1即周期100ms输出频率10Hz。占空比设为1%CCR1000即输出100us的高电平脉冲。TIM4相机触发输出同样设置为PWM模式通道1映射到PB6。参数和TIM1一致也是10Hz占空比可以适当调宽设成5%CCR5000输出500us的高电平。TIM3Strobe输入捕获设置为Input Capture模式通道3映射到PB0。预分频器84-1计数频率1MHz上升沿捕获。USART2波特率115200接收GPS的GPRMC报文。启用串口接收中断。GPIOPA8、PB6配置为复用推挽输出PA0、PB0配置为复用输入。为了在中断服务函数中获取时间戳还需要在main.c里定义全局变量记录捕获时刻的计数器和PWM更新时间戳。3.3 同步触发与时间戳生成的代码实现下面这段代码是我基于STM32CubeMX生成后在stm32f4xx_it.c中断处理文件里写的核心逻辑。代码逻辑不难但有一些容易出错的细节。首先是PPS捕获中断处理uint32_t pps_capture_cnt 0; uint32_t pps_timestamp_us 0; void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM2) { pps_capture_cnt __HAL_TIM_GET_COUNTER(htim2); pps_timestamp_us pps_capture_cnt; // 记录PPS触发时刻之后可以和PWM更新中断对比 } else if (htim-Instance TIM3) { // 相机Spike信号捕获处理 } }然后是TIM1更新中断用于记录帧同步脉冲的发射时刻uint32_t frame_sync_timestamp_us 0; void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM1) { frame_sync_timestamp_us __HAL_TIM_GET_COUNTER(htim2); } }在串口GPRMC数据解析方面核心是从NMEA协议中解析出UTC时间、日期、经纬度信息。因为雷达和相机的时间戳以GPS时间为基准所以GPRMC的UTC时间必须解析正确。解析逻辑是用字符串匹配$GPRMC开头的行找到时间字段和日期字段。两个缓冲区的数据都用环形队列来处理避免在中断里做复杂的字符串解析。解析完成之后在main循环里更新全局的绝对时间变量。当PPS中断触发时GPS的秒计数已经由串口解析维护当前完整时间戳就等于秒计数加上PPS中断时刻的微秒偏移。关键点是PPS中断和GPRMC更新之间可能有几毫秒的错位需要通过锁定机制来确保时间对齐逻辑。最后STM32把当前误差修正后得到的时间戳通过USART1发送给主机。主机端驱动读取到该时间戳后直接覆盖雷达和相机驱动生成的时间戳即可。3.4 主机端ROS驱动与时间戳对齐验证雷达和相机接入主机后ROS驱动本身也会产生时间戳。我们要做的是利用STM32发出的同步时间戳替换或者校准驱动默认的时间戳。对速腾雷达官方驱动rslidar_sdk可以直接读取雷达内部的PPSGPRMC同步信息通过配置config.yaml里的use_gps选项为true雷达就会自动把时间戳同步到GPS时间。对海康相机我使用的是ROS工业相机驱动hikrobot_camera需要在相机配置里设置触发模式为External Trigger然后驱动会把相机时间戳作为消息的时间戳。这里有一个坑相机默认时间戳是相机内部时钟和GPS时间不在同一个基准上必须手动把相机的内部时钟和GPS时间对齐或者利用海康SDK的GigE时间戳模式将相机时钟同步到主机PTP时间。在GAC-Mapping里时间戳对齐的验证分两步。第一步用rostopic echo分别查看雷达和相机消息的header.stamp时间戳对比两者是否同步。第二步在GAC-Mapping的建图界面里把点云投影到图像上观察轮廓是否对齐。如果同步做得好点云的边缘和图像的边缘应该是严丝合缝的。我自己在验证时发现即便时间戳对上了偶尔还会出现点云投影错乱的现象。后来排查发现是相机和雷达的坐标外参标定不准确导致的。时间同步管的是“什么时候拍的”外参标定管的是“在哪拍的”两者缺一不可。大家如果遇到投影对不齐的问题除了检查时间戳也要复查外参。4. 常见问题与排查技巧实录4.1 排查问题速查表现象可能原因排查方法相机不触发/不曝光触发线接错或电平不匹配用示波器查看触发引脚脉冲检查相机GPIO配置雷达点云时间戳乱跳PPS信号未接入或干扰示波器确认PPS波形是否干净检查GPRMC是否解析成功相机偶发丢帧触发频率过高或曝光时间过长降低触发频率或缩短曝光时间点云与图像轮廓错位时间戳同步误差过大或外参标定不准先用单点同步验证时间再重新标定外参STM32死机或卡死中断优先级配置不当或串口解析阻塞用调试器检查卡死位置合理分配中断优先级时间戳漂移明显GPS失锁或天线遮挡查看GPS模块的定位状态增加GPS信号稳定时间4.2 实操心得与避坑技巧整个同步系统从画板到跑通有几个比较容易踩的坑我单独拿出来说一下。第一个坑是共地问题。最初我调试时STM32、GPS、雷达都各自用独立的电源适配器供电没有把电源的负极连在一起。结果就是STM32输出的触发脉冲雷达和相机经常识别不到。用万用表一量STM32输出的3.3V对雷达的地参考电位漂了0.7V导致电平判断出错。把所有的地线全部短接之后问题立刻消失。第二个坑是STM32定时器的PWM初始化顺序。HAL库中必须先启动PWM输出再启动定时器更新中断。如果顺序反了会导致在初始化完成前就触发中断程序直接跑飞。第三个坑是PPS信号的边沿抖动。GPS模块的PPS通常有几十纳秒到几百纳秒的抖动对STM32的输入捕获来说完全能接受但对雷达来说部分型号对PPS的上升沿斜率有要求。我用的GPS模块默认是CMOS电平输出接到雷达的差分输入上无法识别换了个带差分输出的模块或者加一个电平转换板才解决。第四个坑是相机Strobe信号对触发的“回环”验证。刚开始我完全没有用Strobe只记录STM32发出的触发时间认为那就是相机的曝光时间。后来发现相机的曝光中点和触发信号之间有一个固定的延迟加上曝光时间后实际曝光中点比触发信号滞后了好几毫秒。接上Strobe信号通过STM32的输入捕获获得真实曝光中点补偿这个误差整个系统的精度才算真正达标。5. 方案扩展与后续改进方向硬件同步方案打通之后如果想进一步提升系统的精度和稳定性还有几个可以扩展的方向。第一个方向是增加相机曝光时间补偿。现在只是用固定延迟补偿曝光中点但曝光时间在自动曝光模式下会动态变化。优化方案是在STM32中读取相机的Strobe信号用硬件方式实时测量触发信号和Strobe上升沿的时间差反馈到同步时间戳里在原时间戳基础上加上这个动态延迟让时间戳的精度不受自动曝光的影响。第二个方向是引入IEEE 1588 PTP。STM32F407系列自带以太网MAC但想要支持硬件时间戳还需要外接PHY芯片。目前我们用的是外部GPS PPS作为时间基准PTP可以作为无GPS环境下的替代方案让主机作为Grandmaster时钟STM32作为边界时钟或者从时钟精度也能做到亚微秒级。第三个方向是在GAC-Mapping中增加基于点云畸变的时间戳补偿。雷达扫描一圈需要时间所以即便是硬件同步点云中的每个点仍然对应不同的时刻。如果相机图像是在帧同步脉冲后立刻曝光图像对应的是零度方向附近的时刻。在GAC-Mapping的预处理阶段可以把点云按时间戳拆分成子帧用IMU做畸变补偿这样建图的精度还能再上一个台阶。我在实际使用中发现把这三个方向逐步补齐整个系统的鲁棒性会明显提升。尤其是动态曝光补偿在室外光照变化大的场景里效果立竿见影。建图的重影问题完全消失回环检测的准确率也高了不少。最后再分享一个小技巧在调试整个同步系统的时候建议先用示波器同时接雷达的同步输入和相机的触发输入观察两路信号的相位关系。软件层面的时间戳验证能力有限示波器看到的两路信号才是硬件同步最直接的证据。这个习惯帮我节省了不少排查时间强烈推荐给每一位在做传感器同步的朋友。
返回列表