ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Livox Mid-360 与 ROS2 联合标定实战:从驱动配置到外参求解

Livox Mid-360 与 ROS2 联合标定实战:从驱动配置到外参求解 1. 为什么选择 Livox Mid-360 搭配 ROS2 做联合标定如果你正在做机器人感知、SLAM 或者自动驾驶相关的小项目大概率绕不开两个核心传感器激光雷达和相机。激光雷达给你精确的三维空间信息相机给你丰富的纹理和语义信息两者融合才能让机器人真正“看懂”周围的世界。而 Livox Mid-360 这台固态激光雷达凭借其非重复扫描模式和 360 度水平视场角在近两年成了不少中小型机器人项目的首选。价格相对友好点云密度在近距离表现优秀体积也小装在移动底盘或者机械臂末端都不算累赘。但问题来了雷达和相机各自都有自己的坐标系你要把雷达点云投影到图像上或者把图像特征映射到三维空间就必须知道这两个传感器之间的相对位姿关系。这个位姿关系就是外参求解外参的过程就是联合标定。没有准确的联合标定后面的融合就是空中楼阁点云和图像对不上SLAM 建图会漂目标检测的三维定位会偏机械臂抓取会抓空。ROS2 这边从 Foxy 到 Humble 再到 Jazzy生态已经相当成熟了。Livox 官方也提供了 ROS2 版本的驱动包但实际部署过程中从 SDK 编译、驱动配置、网络参数设置到和相机的时间同步、联合标定每一步都有坑。网上能找到的教程要么是 ROS1 时代的要么只讲了驱动安装没讲标定要么标定部分一笔带过。我前后部署过三套 Mid-360 加相机的系统踩过的坑足够写一篇完整的实战记录。这篇文章面向的是有一定 Linux 基础、刚接触 ROS2 或者正在做多传感器融合项目的开发者。我会从零开始把 Livox Mid-360 在 ROS2 下的驱动配置、相机选型与配置、时间同步、联合标定的完整流程拆开来讲每个步骤都解释为什么这么做参数怎么算遇到问题怎么排查。你照着走一遍应该能少走不少弯路。2. 环境准备与依赖梳理2.1 系统版本与 ROS2 发行版选择Ubuntu 22.04 加 ROS2 Humble 是目前最稳妥的组合。Humble 是 LTS 版本维护到 2027 年社区支持最完善Livox 的 ROS2 驱动在 Humble 上测试也最充分。如果你用的是 Ubuntu 20.04对应的是 ROS2 Foxy也能跑但部分依赖包的版本会比较老编译 Livox SDK2 的时候可能会遇到 CMake 版本不够的问题。Ubuntu 24.04 加 ROS2 Jazzy 是最新的组合但 Livox 官方驱动对 Jazzy 的适配还在完善中新手不建议上来就挑战。ROS2 的安装方式我推荐用 apt 安装不要用源码编译。apt 安装的包管理干净依赖自动解决卸载也方便。安装步骤这里不展开网上教程很多核心就是设置软件源、安装 ros-humble-desktop、配置环境变量。装完之后验证一下source /opt/ros/humble/setup.bash ros2 topic list如果能看到/parameter_events和/rosout两个话题说明 ROS2 基础环境没问题。注意每次打开新终端都要 source 一次建议直接写进~/.bashrc省得每次都手动敲。2.2 Livox SDK2 编译与安装Livox Mid-360 用的是 SDK2不是老款的 SDK1。这一点很多人搞混下载错了 SDK 版本编译出来的驱动根本连不上雷达。SDK2 的 GitHub 仓库直接搜Livox-SDK2就能找到。编译之前先确认系统里有这几个依赖sudo apt install cmake build-essential libpcap-devlibpcap-dev是关键Livox 雷达通过网口通信底层抓包依赖这个库。没有它编译能过但运行的时候会报找不到网卡设备。编译流程很标准git clone https://github.com/Livox-SDK/Livox-SDK2.git cd Livox-SDK2 mkdir build cd build cmake .. make -j$(nproc) sudo make installmake -j$(nproc)是用满所有 CPU 核心并行编译能快不少。安装完成后库文件会放到/usr/local/lib头文件在/usr/local/include。你可以用ldconfig -p | grep livox确认一下库有没有被系统识别。实操心得如果你之前装过 SDK1先把 SDK1 的库卸干净两个版本的库文件名有重叠混在一起会导致链接错误。用sudo find / -name *livox*搜一遍把 SDK1 相关的.so和头文件都删掉。2.3 Livox ROS2 驱动包获取与编译驱动包在 GitHub 上搜livox_ros_driver2。注意分支选择Humble 对应的是ros2分支不是master。克隆下来之后放到你的 ROS2 工作空间的src目录下mkdir -p ~/livox_ws/src cd ~/livox_ws/src git clone -b ros2 https://github.com/Livox-SDK/livox_ros_driver2.git编译之前要改一个地方驱动包里的package.xml和CMakeLists.txt默认可能写的是ament_cmake的旧写法你需要确认package.xml里的 build_type 是ament_cmake然后CMakeLists.txt里找到find_package(rosidl_default_generators REQUIRED)这一行确保消息生成部分配置正确。编译命令cd ~/livox_ws colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPERelease--symlink-install的好处是你改 Python 脚本或者 launch 文件的时候不用重新编译直接生效。-DCMAKE_BUILD_TYPERelease是开优化点云数据量大Debug 模式跑起来会卡。编译完成后 source 一下source ~/livox_ws/install/setup.bash2.4 网络配置与雷达连接Mid-360 出厂默认 IP 是192.168.1.1XX具体最后两位看雷达标签。你的电脑网口要设成同一网段的静态 IP比如192.168.1.50子网掩码255.255.255.0。用nmcli或者图形界面设置都行命令行方式sudo nmcli con add type ethernet ifname eth0 con-name livox ip4 192.168.1.50/24 sudo nmcli con up livox设完之后ping 192.168.1.1XX确认能通。如果 ping 不通先检查网线是不是插在雷达的以太网口上Mid-360 有一个以太网口和一个电源口别插错然后检查防火墙sudo ufw disableUbuntu 默认的 ufw 防火墙会拦截雷达的 UDP 数据包直接关掉最省事。生产环境的话可以配规则放行但调试阶段关掉最方便。3. ROS2 驱动配置与点云数据验证3.1 配置文件参数详解Livox ROS2 驱动的配置文件在livox_ros_driver2/config/目录下有两个文件MID360_config.json和livox_ros_driver2_config.json。前者是雷达硬件相关的配置后者是 ROS2 话题和发布相关的配置。先看MID360_config.json{ lidar_configs: [ { ip: 192.168.1.1XX, pcl_data_type: 1, pattern_mode: 0, extrinsic_parameter: { roll: 0.0, pitch: 0.0, yaw: 0.0, x: 0, y: 0, z: 0 } } ], host_net_info: { cmd_data_ip: 192.168.1.50, cmd_data_port: 56101, push_msg_ip: 192.168.1.50, push_msg_port: 56201, point_data_ip: 192.168.1.50, point_data_port: 56301, imu_data_ip: 192.168.1.50, imu_data_port: 56401, log_data_ip: , log_data_port: 56501 } }几个关键参数ip雷达的 IP改成你雷达标签上的实际地址。pcl_data_type点云数据类型1 表示 XYZI含强度2 表示 XYZIT含时间戳。做标定和 SLAM 建议用 2时间戳对运动补偿很重要。pattern_mode扫描模式0 是非重复扫描1 是重复扫描。Mid-360 默认非重复建图效果更好。host_net_info里的 IP 全部改成你电脑网口的 IP端口保持默认即可除非有冲突。再看livox_ros_driver2_config.json{ publish_freq: 10.0, output_data_type: 0, frame_id: livox_frame, lvx_file_path: , xfer_format: 0 }publish_freq点云发布频率10Hz 是常用值。Mid-360 原始数据率很高设太高会吃满 CPU。output_data_type0 是点云1 是 IMU2 是两者都发。做联合标定建议设 2IMU 数据可以用来做运动补偿。frame_id点云的坐标系名称后面标定的时候要和相机坐标系做变换这个名字要记住。xfer_format0 是 PointCloud21 是自定义格式。用 PointCloud2 兼容性最好RViz2 直接能看。3.2 启动驱动与 RViz2 可视化启动命令ros2 launch livox_ros_driver2 rviz_MID360_launch.py这个 launch 文件会同时启动驱动和 RViz2并且自动加载好点云显示的配置。如果只想启动驱动不看 RViz2用ros2 launch livox_ros_driver2 msg_MID360_launch.py启动之后在 RViz2 里应该能看到点云。如果没有先检查话题ros2 topic list正常应该能看到/livox/lidar和/livox/imu两个话题。再看频率ros2 topic hz /livox/lidar应该稳定在 10Hz 左右。如果频率是 0 或者报错说明驱动没收到雷达数据回去检查网络配置和配置文件里的 IP。常见坑RViz2 里点云显示不出来但话题有数据。这种情况多半是 Fixed Frame 设错了。在 RViz2 左侧 Displays 面板里把 Global Options 的 Fixed Frame 改成livox_frame和配置文件里的frame_id保持一致。3.3 点云质量检查与常见异常处理点云能显示之后别急着往下走先花几分钟检查点云质量。好的点云应该是这样的近距离物体轮廓清晰地面平整远处有合理的噪声但不过分。如果出现以下几种情况需要针对性处理第一种点云全是噪点没有结构。这通常是雷达镜头脏了或者有遮挡。Mid-360 的视场角很大但镜头表面如果有灰尘或者指纹近距离会出现大量杂散点。用擦镜纸轻轻擦一下就好。第二种点云只有一半或者有扇形缺失。检查pattern_mode是不是设成了 1重复扫描重复扫描模式下视场角会变小。改回 0 重启驱动。第三种点云频率不稳定忽高忽低。大概率是网络带宽不够或者 CPU 占用太高。Mid-360 的点云数据率在非重复模式下大概 20MB/s 左右千兆网口完全够用但如果你同时跑着其他吃网络的任务可能会抢带宽。用iftop看一下网口流量确认没有其他大流量进程。第四种IMU 数据没有或者异常。ros2 topic echo /livox/imu看一下正常应该有角速度和加速度数据。如果没有检查output_data_type是不是设成了 0。4. 相机选型、配置与时间同步4.1 相机选型建议与 ROS2 驱动联合标定对相机的要求其实不高普通 USB 相机或者工业相机都行。但有几个点要注意第一相机要能输出稳定的帧率不能忽快忽慢第二曝光时间要可调标定的时候需要固定曝光避免自动曝光导致图像亮度变化影响角点检测第三分辨率不用太高1280x720 足够太高反而增加计算量。我用过 RealSense D435i 和普通 USB 相机做标定D435i 的好处是自带 IMU 和深度ROS2 驱动realsense-ros很成熟ros2 launch realsense2_camera rs_launch.py就能起来。普通 USB 相机用usb_cam或者v4l2_camera包配置稍微麻烦一点但成本低。以usb_cam为例安装sudo apt install ros-humble-usb-cam启动ros2 run usb_cam usb_cam_node_exe --ros-args -p video_device:/dev/video0 -p image_width:1280 -p image_height:720 -p framerate:30.0启动后在 RViz2 里添加 Image 显示话题选/image_raw应该能看到画面。4.2 硬件时间同步方案时间同步是联合标定里最容易被忽视但影响最大的环节。雷达和相机各自有自己的时钟如果两个时钟不同步标定的时候采集的数据在时间上对不齐算出来的外参会偏。最理想的方案是硬件同步用同一个触发信号同时触发雷达和相机曝光。Mid-360 支持 PPS 和 GPS 时间同步但需要额外的硬件模块。对于大多数中小项目硬件同步成本太高用软件同步也够用。软件同步的思路是在 ROS2 里用message_filters做时间戳近似对齐。具体做法是订阅雷达点云话题和相机图像话题用ApproximateTimeSynchronizer把时间戳接近的消息配对然后一起送入标定算法。时间容差设 0.05 秒左右具体看你的传感器频率。还有一个更简单的办法标定的时候让场景静止雷达和相机都对着标定板不动这样即使时间戳有偏差数据内容也是一致的。这个方法牺牲了动态场景的标定能力但对于求外参来说完全够用。实操心得如果你的相机支持硬件触发强烈建议用硬件同步。我试过用软件同步标定重投影误差在 2-3 像素左右换成硬件同步后降到 1 像素以内。对于高精度应用这个差距很关键。4.3 相机内参标定联合标定之前相机内参必须先标好。内参包括焦距、主点、畸变系数这些是相机自身的属性和雷达无关。内参不准外参再怎么标都是错的。标定工具用 ROS2 的camera_calibration包sudo apt install ros-humble-camera-calibration准备一块棋盘格标定板打印出来贴在平整的硬板上。棋盘格的大小和格子数要提前量好比如 8x6 的格子每个格子 25mm。标定的时候ros2 run camera_calibration cameracalibrator --size 8x6 --square 0.025 image:/image_raw camera:/camera然后在 GUI 里移动标定板覆盖画面的各个区域和角度。X 轴方向左右移动Y 轴上下移动Size 前后移动Skew 倾斜。每个维度都要有足够的数据进度条满了之后点 CALIBRATE等一会儿点 SAVE内参会保存到/tmp/calibrationdata.tar.gz。解压后找到ost.yaml里面的camera_matrix就是内参矩阵distortion_coefficients是畸变系数。这两个后面标定外参的时候要用。注意标定板一定要平整打印的纸如果翘边角点检测会不准。我一般把打印好的棋盘格用胶水贴在亚克力板上效果比直接贴纸好很多。5. 雷达相机联合标定实战5.1 标定方案选型与原理雷达相机联合标定的方法大致分两类基于特征的方法和基于运动的方法。基于特征的方法需要找到雷达和相机都能识别的对应点比如标定板上的圆孔或者棋盘格角点。基于运动的方法不需要标定板通过让传感器一起运动利用运动约束求解外参。对于 Mid-360 和普通相机的组合我推荐基于标定板的方法因为实现简单、精度可控。具体来说用一块带圆孔的标定板相机检测圆孔在图像中的位置雷达检测圆孔在点云中的位置然后通过 PnP 或者最小二乘求解外参。标定板的制作找一块不反光的板子比如哑光亚克力在上面打几个圆孔。圆孔的直径要足够大让雷达能扫到孔边缘的点云同时要足够小让相机能清晰成像。我用的方案是直径 60mm 的圆孔四个孔呈矩形排列孔间距 200mm。板子背面贴一层反光材料这样雷达扫到板子正面的时候孔的位置会因为穿透或者边缘效应产生特征点。为什么用圆孔而不是棋盘格棋盘格的角点在点云里很难精确定位因为雷达的分辨率有限角点附近的点云比较模糊。圆孔的边缘在点云里表现为一圈点拟合圆心比找角点更稳定。5.2 数据采集与预处理标定数据采集的流程第一步固定好雷达和相机的相对位置。两者之间的外参在标定过程中不能变所以要用支架把雷达和相机刚性连接。我用的是铝型材支架拧紧之后基本不会动。第二步把标定板放在雷达和相机都能看到的位置。距离大概 2-3 米太近雷达点云太密但视场覆盖不全太远点云太稀疏。标定板要正对传感器不要倾斜太厉害。第三步启动雷达驱动和相机驱动确认两个话题都有数据。第四步采集数据。让标定板在画面里移动几个不同的位置和角度每个位置停留几秒记录一段数据。我一般采集 10-15 组数据覆盖画面的中心、四角、远近不同距离。数据采集的时候用ros2 bag record把雷达点云和相机图像都录下来ros2 bag record /livox/lidar /image_raw -o calibration_bag录完之后回放用ros2 bag play calibration_bag然后逐帧检查数据质量。预处理包括点云去畸变如果雷达有运动畸变、图像去畸变用之前标定的内参、时间对齐。点云去畸变可以用雷达自带的 IMU 数据做运动补偿但标定的时候场景静止这一步可以跳过。图像去畸变用 OpenCV 的undistort函数把畸变系数传进去就行。5.3 外参求解与精度验证外参求解我用的是基于 OpenCV 和 PCL 的混合方案。核心思路是在图像中检测标定板的圆孔得到圆孔在图像坐标系下的二维坐标。在点云中分割出标定板平面然后检测圆孔在点云中的三维坐标。把二维坐标和三维坐标配对用solvePnP求解旋转和平移。图像圆孔检测用cv2.HoughCircles参数需要调dp1minDist50param150param230minRadius20maxRadius80。检测到的圆心坐标存下来。点云圆孔检测稍微麻烦一点。先用 RANSAC 拟合标定板平面把平面上的点提取出来。然后在平面内做圆拟合用最小二乘或者 Hough 变换找圆心。PCL 里有SampleConsensusModelCircle3D可以用但参数不好调。我一般自己写一个简单的圆拟合把平面点投影到二维用cv2.minEnclosingCircle或者cv2.fitEllipse找圆心再反投影回三维。配对的时候要注意顺序图像里检测到的四个圆孔和点云里检测到的四个圆孔要一一对应。我一般按顺时针或者逆时针排序确保配对正确。求解外参的代码框架import cv2 import numpy as np # 图像圆孔坐标 (N, 2) image_points np.array([...], dtypenp.float32) # 点云圆孔坐标 (N, 3) object_points np.array([...], dtypenp.float32) # 相机内参 camera_matrix np.array([[fx, 0, cx], [0, fy, cy], [0, 0, 1]]) dist_coeffs np.array([k1, k2, p1, p2, k3]) # 求解外参 ret, rvec, tvec cv2.solvePnP(object_points, image_points, camera_matrix, dist_coeffs) # 旋转向量转旋转矩阵 R, _ cv2.Rodrigues(rvec) print(Rotation:\n, R) print(Translation:\n, tvec)精度验证的方法把求解出的外参应用到点云上把点云投影到图像看投影点和图像里的标定板是否对齐。如果对齐得好说明外参准确。还可以计算重投影误差把三维点用外参投影到图像和实际检测到的二维点比较误差应该在几个像素以内。常见问题重投影误差很大点云投影和图像对不上。排查顺序先检查相机内参对不对再检查时间同步有没有问题最后检查圆孔配对顺序有没有搞错。我遇到过因为圆孔排序方向反了导致外参完全错误的情况调了一下午才发现。5.4 标定结果的应用与验证标定完成后你会得到从雷达到相机的旋转矩阵 R 和平移向量 t。在 ROS2 里这个变换通常用 TF2 来管理。你可以写一个静态 TF 发布器from tf2_ros import StaticTransformBroadcaster from geometry_msgs.msg import TransformStamped t TransformStamped() t.header.stamp node.get_clock().now().to_msg() t.header.frame_id livox_frame t.child_frame_id camera_link t.transform.translation.x tvec[0] t.transform.translation.y tvec[1] t.transform.translation.z tvec[2] # 旋转用四元数表示 from scipy.spatial.transform import Rotation as R_scipy quat R_scipy.from_matrix(R).as_quat() t.transform.rotation.x quat[0] t.transform.rotation.y quat[1] t.transform.rotation.z quat[2] t.transform.rotation.w quat[3]发布之后在 RViz2 里同时显示点云和图像把点云的颜色设成按距离或者按强度然后叠加到图像上看是否对齐。如果对齐说明标定成功。实际应用中这个外参可以用来做点云着色、三维目标检测、视觉 SLAM 的初始化等。我做过一个项目用 Mid-360 加相机做室内建图标定好外参之后把点云投影到图像上做语义分割然后把分割结果反投影回三维建出来的地图带语义标签效果比纯几何建图好很多。6. 常见问题排查与避坑指南6.1 驱动与网络类问题速查问题现象可能原因排查方法解决方案驱动启动后无点云雷达 IP 配置错误ping 雷达 IP修改配置文件中的 IP点云频率为 0防火墙拦截sudo ufw status关闭防火墙或放行端口点云有大量噪点镜头脏污目视检查镜头用擦镜纸清洁IMU 数据缺失output_data_type 设错检查配置文件改为 2编译报错找不到 pcap缺少 libpcap-devdpkg -lgrep pcapRViz2 不显示点云Fixed Frame 错误检查 RViz2 设置改为 livox_frame6.2 标定精度不达标时的排查思路标定精度不达标重投影误差大按以下顺序排查第一检查相机内参。内参标定的时候如果标定板移动不充分或者角点检测不准内参会偏。重新标定一次确保覆盖画面各个区域。第二检查时间同步。如果雷达和相机的数据时间戳差太多标定板在运动数据就对不上。标定的时候尽量让场景静止或者用硬件同步。第三检查圆孔检测精度。图像里圆孔检测受光照影响大光照不均匀会导致圆心偏移。标定的时候用均匀光源避免阴影。点云里圆孔检测受雷达分辨率影响距离太远点云稀疏圆心拟合不准。标定距离控制在 2-3 米。第四检查外参求解的数值稳定性。如果标定板只在一个位置采集数据求解方程可能病态。多采集几个位置和角度让约束更充分。避坑技巧标定的时候记录每组数据的重投影误差如果某一组误差特别大直接剔除。我一般采集 15 组剔除误差最大的 3 组用剩下的 12 组求解精度会明显提升。6.3 实操心得与经验总结第一个心得标定板的设计很关键。我试过用棋盘格、圆孔板、ArUco 码最后发现圆孔板最适合雷达相机联合标定。棋盘格的角点在点云里定位不准ArUco 码的码点在点云里根本看不清圆孔的边缘在点云里表现为一圈点拟合圆心最稳定。第二个心得标定的时候把雷达和相机的曝光都固定。相机自动曝光会导致图像亮度变化影响圆孔检测。雷达的强度信息虽然不受曝光影响但固定场景能让点云更干净。第三个心得外参求解完之后一定要做可视化验证。把点云投影到图像上看边缘是否对齐。我一般会选几个不同距离的物体比如近处的桌子边缘、远处的墙角看投影线是否和图像里的边缘重合。如果近处对齐远处不对齐说明旋转矩阵有偏差如果整体偏移说明平移向量有偏差。第四个心得标定不是一劳永逸的。雷达和相机的相对位置如果发生碰撞或者振动外参会变。我一般每隔几个月重新标定一次或者在重要任务前重新验证一下。验证方法很简单拿一个已知位置的物体看投影是否对齐。第五个心得ROS2 的 QoS 设置会影响数据订阅。雷达点云数据量大默认的 QoS 可能丢包。订阅点云的时候把 Reliability 设成 Best EffortDepth 设成 10 以上。相机图像用默认的 Reliable 就行。from rclpy.qos import QoSProfile, ReliabilityPolicy, HistoryPolicy qos QoSProfile( reliabilityReliabilityPolicy.BEST_EFFORT, historyHistoryPolicy.KEEP_LAST, depth10 )这个 QoS 配置我实测下来很稳点云基本不丢帧。如果你发现点云有跳变或者缺失先检查 QoS 设置。6.4 性能优化与扩展方向Mid-360 的点云数据率很高如果同时跑 SLAM 和标定CPU 占用会比较大。优化方向有几个一是降频。如果应用不需要 10Hz 的点云可以降到 5HzCPU 占用直接减半。在配置文件里改publish_freq就行。二是裁剪点云。如果只关心前方一定角度内的点云可以在驱动里配置或者写一个节点做裁剪把无关区域的点云滤掉减少后续处理的计算量。三是用零拷贝。ROS2 支持零拷贝传输点云数据不经过序列化和反序列化直接共享内存。需要配置 Fast DDS 的共享内存传输具体配置在FASTRTPS_DEFAULT_PROFILES_FILE环境变量指向的 XML 文件里。这个优化对大数据量传输效果很明显我实测 CPU 占用能降 20% 左右。扩展方向的话标定完之后可以做很多事情。比如用点云做深度补全把稀疏的点云和稠密的图像结合生成稠密的深度图。或者做三维目标检测用图像做二维检测把检测框投影到点云里做三维定位。再或者做语义 SLAM把图像的语义分割结果融合到点云地图里建出来的地图带语义标签对导航和交互很有用。我个人在实际操作中的体会是联合标定这件事理论不难难在细节。每一个参数、每一个步骤都有讲究差一点结果就差很多。但只要按照流程一步步来把每个环节都验证到位最终的结果是可靠的。Mid-360 加 ROS2 这套组合生态在不断完善社区资源也越来越多遇到问题多搜搜 GitHub issue 和 ROS 论坛大部分坑都有人踩过。
返回列表