☰
Livox+海康相机实时彩色点云建图全流程实战解析
2026/10/7 3:38:39 网站建设 项目流程

做实时彩色点云建图这个项目之前,我天真地以为“跑通两个驱动,再拼一下就能出图”,实际折腾下来,踩的坑比想象中多得多。Livox雷达的点云特性、海康相机的曝光策略、时间戳同步、外参标定,每一步都有细节,少留意一个就可能导致颜色错位、点云飘移甚至整个系统崩溃。这篇文章把我从零搞定的完整流程整理出来,包括ROS环境配置、驱动编译、标定、同步、建图串联,还有我在实操中遇到的问题和排查方法,希望对正在做传感器融合或者准备上车这套设备的朋友有实际帮助。

先说下我的硬件选型:激光雷达用的是Livox Mid-360,相机是海康的MV-CA050-10GC(500万像素GigE工业相机),工控机是一台普通i7笔记本外加一个千兆交换机。整个项目的目标很简单:把海康相机拍摄的RGB信息映射到Livox产生的三维点云上,并用FAST-LIO这类建图算法实时输出带有真实颜色纹理的地图。这样生成的地图不仅好看,在后续做语义分割、目标识别、视觉定位时也非常有用。

1. 项目整体设计与硬件架构

1.1 为什么是“Livox + 海康”这套组合

激光雷达选型这件事,很多新手上来就纠结“多少线”“多少米”。说实话,对于中近距离的建图、导航、感知融合需求,Livox Mid-360这类非重复扫描固态雷达是性价比很高的选择。它的视场角是360度水平、-7度到+52度垂直,比传统多线机械雷达更适合安装在机器人顶部,而且点云密度在短时间积分后相当可观。更重要的是,Livox官方提供了一套完整的ROS驱动,配合FAST-LIO、Point-LIO等开源SLAM方案都有现成的接口,省去大量底层适配工作。

相机选择海康的原因也很实际:海康工业相机在国产设备里SDK成熟度很高,MVS的Linux版本做得完整,支持GigE Vision协议,可以方便地在ROS里通过驱动节点取流。和Livox雷达一样,海康相机也支持PTP(IEEE 1588)时间同步,这对后面做激光和图像的精确时间对齐非常关键。很多人在做雷达相机融合时会选择“雷达+普通USB摄像头”,虽然便宜,但USB摄像头的曝光时间和时间戳控制都比较弱,最后出现的拖影和颜色错位问题够折腾几个星期的。

成本上,一套Livox Mid-360加海康500万工业相机加镜头,大概在1.5万到2万之间。如果预算有限,雷达可以选Livox Avia或Horizon,相机可以降级到200万像素,但流程基本不变。核心是理解整套链路:传感器原始数据 → 时间同步 → 内外参标定 → 投影取色 → 累积成彩色地图。

1.2 硬件连接与网络规划

第一步先别急着写代码,把物理连接和网络规划做好。Livox Mid-360默认使用UDP协议传输点云数据,雷达的默认IP通常是192.168.1.50(不同批次可能不同,以雷达标签为准,也可以在Livox Viewer里修改)。海康工业相机的默认IP一般是192.168.1.100这类地址。我的做法是准备一台千兆交换机,把雷达、相机、工控机三台设备都接在同一个局域网里,然后给工控机的网卡设置一个静态IP,比如192.168.1.10,子网掩码255.255.255.0。

这一步很多人会踩坑:如果工控机有多个网卡,或者系统自带的网络管理工具(如Netplan)没配置好,可能会出现“雷达能收到数据但相机连不上”之类的奇怪问题。建议先把Livox Viewer和MVS客户端各自测试一遍,确保两个传感器能单独出数据再往下走。

注意:Livox雷达默认发送目标端口是2351,如果防火墙开着,记得放行UDP端口。海康相机在MVS里也需要调整“采流设置”里的包大小,一般建议设置成8192或1440,否则容易出现图像丢包导致的画面撕裂。

1.3 系统架构:从传感器到彩色点云

整个系统分四层,分别是数据采集层、同步层、标定层和建图层:

  • 数据采集层:Livox雷达驱动发布/livox/lidar(PointCloud2消息),海康相机驱动发布/hik_camera/image_raw(Image消息)。
  • 同步层:通过PTP硬件同步或message_filters软同步,确保两路数据的时间戳对齐。
  • 标定层:先做相机内参标定(Kalibr或OpenCV),再做雷达相机外参标定(得到从激光雷达坐标系到相机坐标系的变换矩阵)。
  • 建图层:使用FAST-LIO(或自己写的彩色点云拼接节点),在SLAM位姿估计的基础上,把每一帧彩色点云变换到世界坐标系,累积成彩色地图。

这一架构的好处是松耦合:每一层都可以单独调试、替换。比如你不想用FAST-LIO,换成LIO-SAM或者Point-LIO,只需要改最后一个建图节点就行,前两层的代码都不用大变。这也是我推荐“把步骤拆开做”的原因,如果一上来就想把整个系统一次性跑通,排错会非常痛苦。

2. 软件环境准备与驱动部署

2.1 ROS环境:选择Noetic还是Humble

Livox雷达和海康相机的驱动在ROS1和ROS2下都有方案,但考虑到外参标定工具链(比如livox_camera_calib、Autoware的标定模块)很多还是ROS1实现,初学者建议先用ROS1。我使用的是Ubuntu 20.04 + ROS Noetic,这也是目前Livox生态兼容性最好的一套组合。如果你的系统已经装了Ubuntu 22.04 + ROS2 Humble,也可以跑,但很多标定工具需要自己折腾移植,不建议新手直接上。

安装ROS本身不是这篇文章的重点,“鱼香ROS一键安装”这个工具确实能省不少事,执行一条命令就可以把ROS装好:

wget http://fishros.com/install -O fishros && . fishros

选择“一键安装ROS Noetic”即可。装完之后记得验证一下:

source /opt/ros/noetic/setup.bash roscore

能正常启动roscore就说明ROS环境没问题。然后创建一个工作空间:

mkdir -p ~/color_mapping_ws/src cd ~/color_mapping_ws catkin_make source devel/setup.bash

2.2 Livox雷达驱动编译与配置

Livox官方的驱动分两个版本:旧版livox_ros_driver和新版livox_ros_driver2。对于Mid-360,建议直接用livox_ros_driver2,它对Mid-360支持更完整,而且代码结构更清晰。

cd ~/color_mapping_ws/src git clone https://github.com/Livox-SDK/livox_ros_driver2.git

编译之前,需要修改livox_ros_driver2/launch/msg_MID360.launch里的配置:

<param name="user_config_path" value="$(find livox_ros_driver2)/config/MID360_config.json" />

在对应的config/MID360_config.json文件中,修改主机IP,让驱动知道给工控机哪个地址发数据:

{ "lidar_config": [ { "ip": "192.168.1.50", "host_ip": "192.168.1.10", "cmd_port": 56000, "msg_port": 56100, "enable": true } ] }

然后编译:

cd ~/color_mapping_ws catkin_make source devel/setup.bash roslaunch livox_ros_driver2 msg_MID360.launch

启动后,另开一个终端,用rostopic hz /livox/lidar检查点云话题频率,正常情况下Mid-360是10Hz左右,点云数量根据场景不同会有起伏。

提示:如果雷达一直连不上,先在Livox Viewer里确认雷达IP和设备状态,然后测试工控机和雷达之间的连通性。Mid-360用的是网口直接通信,不经过路由器中转,所以交换机和网线质量也会影响连接稳定性。

2.3 海康相机驱动编译与ROS节点配置

海康相机的驱动分两层:底层是官方MVS SDK(负责相机发现、参数配置、图像采集),上层是ROS驱动节点(把图像数据转换成ROS的sensor_msgs/Image消息发布出去)。

先下载MVS SDK的Linux版本,解压后按照README安装。安装完成之后验证一下能否用mvs_sample自带的客户端看到图像。能出图,再编译ROS驱动。GitHub上有不少海康相机的ROS驱动包,比如hikrobot_camera(支持海康机器人所有GigE和USB相机),或者基于MvCameraControl写的自定义节点。我用的驱动包大概长这样:

cd ~/color_mapping_ws/src git clone https://github.com/luckylucky/hikrobot_camera.git cd ~/color_mapping_ws catkin_make

驱动节点启动后,一般会发布类似/hik_camera/image_raw的Image话题。为了让图像的频率和曝光稳定,建议在驱动配置里固定参数:分辨率设为1280x1024、帧率设为10fps(和雷达频率接近)、曝光模式设为手动曝光,曝光时间根据环境光调整,室内一般3到8毫秒,室外常见0.5到2毫秒。

rosrun hikrobot_camera hikrobot_camera_node rostopic hz /hik_camera/image_raw

能稳定输出图像之后,记得用rqt_image_view看一眼画面,确保没有过曝或过暗,这一步能避免后面彩色点云整体偏色。

3. 相机内参与激光雷达外参标定

3.1 相机内参标定:用Kalibr还是OpenCV

彩色点云的精准度,一半取决于外参,一半取决于内参。如果内参不准确,投影出的颜色会有明显的系统性偏移。相机内参标定有两种常见选择:OpenCV的calibrateCamera和Kalibr。Kalibr的优势在于标定板类型丰富,标定结果还会直接给出相机畸变模型参数文件,适合后面扩展双目或IMU融合的场景。

我用的是Kalibr,因为它对标定板角点检测的鲁棒性更好。Kalibr使用的棋盘格或Aprilgrid你需要事先准备好一张打印出来的标定板。我的经验是:标定板一定要贴平整,不能有褶皱;打印精度要高,最好是A3尺寸,格子边长不小于30mm。然后录制一段连续运动的图像,运动时要保证标定板在不同位置、不同角度都有出现,画面边缘也要覆盖到,因为畸变参数主要靠边缘信息约束。

rosbag record -O camera_calib.bag /hik_camera/image_raw

录制一分钟左右,转为Kalibr格式,然后运行:

kalibr_calibrate_cameras --target april_6x6_80x80cm.yaml \ --bag camera_calib.bag \ --topics /hik_camera/image_raw \ --models pinhole-equi --show-extraction

标定完成后会生成camchain.yaml,里面包含了相机内参矩阵、畸变系数和畸变模型。如果你手里的相机是针孔模型,畸变模型一般选择radtan,如果是鱼眼镜头就选equi,千万别选错,选错了后期标定外参会非常痛苦。

3.2 激光雷达与相机外参标定

外参标定是整个流程里最磨人、也是最核心的一步。外参变换矩阵的含义是“激光雷达坐标系下的三维点,经过坐标变换后落在相机坐标系下的位置”。标定方法有很多,我尝试过Autoware自带的calibration_camera_lidar,也试过港科大的livox_camera_calib,最终推荐后者,原因是它对Livox点云和棋盘格标定板做了专门优化,标定精度高,过程也相对自动化。

livox_camera_calib的原理大致是:在点云中拟合标定板的平面,提取出板面的四条边界线和角点,同时在图像中检测棋盘格角点,然后通过非线性优化求出旋转矩阵和平移向量。这个方案很适合Mid-360这种“点云分布不规则”的雷达,它不需要你人为在点云里切出完整的棋盘格形状,算法会自动处理。

使用时需要准备以下条件:

  • 一个硬质棋盘格标定板,我建议A1尺寸,如果找不到就用A2,但一定要贴在硬纸板或KT板上,不能弯曲。
  • 标定板距离雷达不要太远,我一般放在1到3米范围内,太远点云太疏,太近视场角内可能拍不全。
  • 整个标定过程需要保持雷达和相机静止,标定板通过旋转、平移变换不同的姿态,至少采集10组数据。
# 采集标定数据 rosbag record -O calib_data.bag /livox/lidar /hik_camera/image_raw # 启动标定程序 roslaunch livox_camera_calib calib.launch

标定完成后会得到外参矩阵,通常表现为一个4x4的齐次变换矩阵。保存好这个矩阵,下一节的投影取色全靠它。

注意:我在标定时发现一个很常见的坑——标定板在图像中反光严重,导致棋盘格角点检测失败。解决办法是使用哑光打印纸,或者把标定板稍微调整角度,避免镜面反射。另外,标定板不能悬空晃动,稍微抖一下点云拟合就会偏。

4. 时间同步:彩色点云不出错的关键

4.1 硬件同步方案:PTP

如果雷达和相机的时间不同步,哪怕只有几十毫秒的偏差,叠加在移动的机器人上,颜色就会错位得离谱。举例来说,雷达在t0时刻扫描的点云,和相机在t0+100ms时刻拍摄的图像,如果机器人以0.5m/s的速度前进,就已经有5厘米的位置偏移,反映在彩色点云上就是边缘颜色溢出。

最理想的方式是硬件同步,时间基准由PTP(IEEE 1588)提供。Livox Mid-360自带PTP从时钟功能,海康工业相机也支持IEEE 1588。配置方法是在工控机上安装PTP客户端(如linuxptp),运行ptp4l把工控机变成PTP主时钟,雷达和相机自动同步到主时钟上。这样两路信号的时间戳可以做到亚毫秒级对齐。

sudo apt install linuxptp sudo ptp4l -i eth0 -m -S

输出里的master offset值越小越好,一般维持在微秒量级就说明同步生效了。需要注意:PTP要求整个链路是千兆网线直连或通过千兆交换机,百兆老交换机对PTP支持不好,同步精度会明显下降。

4.2 软同步方案:message_filters

如果你的硬件不支持PTP,也可以退而求其次用软同步。ROS里最常用的工具是message_filters的ApproximateTimeSynchronizer,它会寻找时间戳最接近的图像和点云进行匹配。

typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::PointCloud2, sensor_msgs::Image> SyncPolicy; message_filters::Subscriber<sensor_msgs::PointCloud2> lidar_sub(nh, "/livox/lidar", 10); message_filters::Subscriber<sensor_msgs::Image> image_sub(nh, "/hik_camera/image_raw", 10); message_filters::Synchronizer<SyncPolicy> sync(SyncPolicy(10), lidar_sub, image_sub); sync.registerCallback(boost::bind(&callback, _1, _2));

采用软同步时,建议把雷达频率和相机帧率都设置成10Hz,这样匹配效果会好很多。但软同步的代价是偶尔会漏帧,而且如果传感器频率差异过大,回调可能长时间触发不了。因此,如果你做的是移动速度比较快的系统(比如无人车、无人机),尽量上PTP硬同步;如果是原地建图或者速度很慢的巡检机器人,软同步可以应付。

5. 实时彩色点云生成与融合

5.1 点云投影取色的数学原理

彩色点云的生成本质上是坐标系变换和相机投影。假设激光雷达坐标系下有一个三维点 (P_l = (x_l, y_l, z_l)),我们要把它变换到相机坐标系:

[ P_c = R_{lc} \cdot P_l + t_{lc} ]

其中 (R_{lc}) 和 (t_{lc}) 就是上一节标定得到的外参。然后将相机坐标系下的点投影到像素平面:

[ u = f_x \cdot \frac{x_c}{z_c} + c_x, \quad v = f_y \cdot \frac{y_c}{z_c} + c_y ]

其中 (f_x, f_y) 是相机内参中的焦距,(c_x, c_y) 是主点坐标。最后把像素坐标 ((u,v)) 处的RGB值赋给这个三维点,就完成了取色。

需要注意一个细节:每个三维点投影到图像后,像素坐标如果落在图像边界之外,或者该点的深度值 (z_c) 是负数(说明点在相机后面),都要直接丢弃,否则会出现明显的彩色飞点。在ROS的PointCloud2消息里,颜色的存储方式是把RGB三个通道打包成一个浮点数,赋值时用pcl::PointXYZRGB结构体会方便很多。

5.2 实时拼接彩色点云节点

看原理不难,写起来也不复杂。我自己写了一个color_fusion_node,订阅三路数据:雷达点云、相机图像、外参(或者从静态tf加载),然后对每一帧点云做投影取色,发布成/color_cloud。核心部分如下:

void cloudCallback(const sensor_msgs::PointCloud2::ConstPtr& cloud_msg, const sensor_msgs::Image::ConstPtr& image_msg) { cv::Mat image = cv_bridge::toCvCopy(image_msg, "bgr8")->image; pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>()); pcl::fromROSMsg(*cloud_msg, *cloud); pcl::PointCloud<pcl::PointXYZRGB>::Ptr color_cloud(new pcl::PointCloud<pcl::PointXYZRGB>()); for (auto& point : cloud->points) { Eigen::Vector3d p_lidar(point.x, point.y, point.z); Eigen::Vector3d p_cam = R_lc * p_lidar + t_lc; if (p_cam(2) <= 0) continue; double u = fx * p_cam(0) / p_cam(2) + cx; double v = fy * p_cam(1) / p_cam(2) + cy; if (u < 0 || u >= image.cols || v < 0 || v >= image.rows) continue; pcl::PointXYZRGB pt; pt.x = point.x; pt.y = point.y; pt.z = point.z; pt.b = image.at<cv::Vec3b>(v, u)[0]; pt.g = image.at<cv::Vec3b>(v, u)[1]; pt.r = image.at<cv::Vec3b>(v, u)[2]; color_cloud->points.push_back(pt); } // 发布 /color_cloud }

这个节点本身不涉及SLAM,只是实时输出“当前视觉范围内的彩色点云”。如果机器人静止,你可以在Rviz里直观地看到三维空间中物体的颜色;如果机器人动了,你会发现点云是重叠的,因为还没有累积到世界坐标系里。

单帧彩色点云看起来没问题之后,就可以进入建图阶段了。

6. 实时彩色点云建图实操流程

6.1 建图方案选型与FAST-LIO部署

提到Livox雷达的实时建图,大家首先想到的就是FAST-LIO和它的改进版FAST-LIO2,以及港科大的Point-LIO。这些算法都在Livox点云上做过很好的适配,Mid-360可以直接跑。FAST-LIO2的核心思想是“迭代误差状态卡尔曼滤波器”,它把IMU和激光雷达点云紧耦合在一起,即使在快速旋转或移动的场景下,也能保持较高的定位建图精度。

我的建图配置很简单:Mid-360本身不带IMU,但雷达内有一个IMU数据可以通过驱动发布(话题名通常是/livox/imu)。如果你外接另外的IMU,也可以配置到FAST-LIO里,但初次调试建议直接用雷达内置IMU,省事。

cd ~/color_mapping_ws/src git clone https://github.com/hku-mars/FAST_LIO.git cd FAST_LIO git submodule update --init cd ~/color_mapping_ws catkin_make

FAST-LIO的launch文件需要根据雷达型号修改配置,最常见的是改config/下的yaml文件,把点云话题名设为/livox/lidar,IMU话题设为/livox/imu,并且关掉外接IMU相关参数。

6.2 完整的启动流程与launch整合

我最推荐的方式是把整套流程做成一个launch文件依次启动:驱动 → 相机 → 彩色融合节点 → FAST-LIO → TF发布。

<launch> <!-- Livox雷达 --> <include file="$(find livox_ros_driver2)/launch/msg_MID360.launch" /> <!-- 海康相机 --> <node name="hik_camera_node" pkg="hikrobot_camera" type="hikrobot_camera_node" output="screen" /> <!-- 外参静态TF --> <node pkg="tf2_ros" type="static_transform_publisher" name="lidar_to_camera_broadcaster" args="0.123 -0.014 0.058 0.002 -0.015 0.009 base_link camera_link" /> <!-- 彩色点云融合 --> <node name="color_fusion_node" pkg="color_map" type="color_fusion_node" output="screen" /> <!-- FAST-LIO建图 --> <include file="$(find fast_lio)/launch/mapping_mid360.launch" /> </launch>

运行后,在Rviz里添加两个显示:一个是FAST-LIO发布的全局地图(一般话题名是/Odometry或/cloud_registered),另一个是彩色融合节点发布的/color_cloud。

实际操作时,我建议先把机器人固定好,原地旋转一周,让FAST-LIO初始化成功;然后缓慢移动,观察/color_cloud是否随着运动逐渐累积成一幅清晰的彩色地图。如果颜色和位置都正确,说明驱动、同步、标定、建图全链路都通了。整个过程我一般会在室内灯光充足的走廊测试,光线均匀、墙面纹理清晰,非常适合验证彩色映射效果。

7. 常见问题与排查技巧

7.1 常见问题速查表

把我在项目里或朋友测试时遇到的问题整理成一张速查表,方便你对照排查:

现象可能原因解决办法
雷达收不到数据IP配置错误、网线松动、防火墙拦截用Livox Viewer检查雷达状态,确认工控机与雷达在同一网段,开放UDP端口
相机图像撕裂网络包被拆分不合理、交换机性能不足在MVS里调整“包大小”为8192,使用千兆交换机,避免Wi-Fi连接相机
图像正常但点云颜色错位外参不准确或时间不同步重新做外参标定,检查是否有PTP公告消息,确认两路数据的时间戳差值
点云颜色有大量黑点投影坐标超出图像边界,或者点被遮挡增加深度判断条件,排除z<0以及像素坐标越界的点
FAST-LIO建图飘IMU未正确初始化、点云畸变严重、雷达安装震动让雷达静止几秒后再移动,检查IMU数据频率是否稳定,加固雷达安装
彩色点云整体偏色相机曝光设置不当,白平衡未校正把海康相机白平衡设为自动或手动校准,室外交为标准D65色温

7.2 几个必须强调的细节

时间戳对齐是最容易出问题的地方。我见过很多人外参标定得很准,但最后出来的彩色点云还是错位,排查半天发现是相机驱动发布的话题时间戳用的是本地系统时间,而雷达用的是PTP时间,两者有几百毫秒偏差。遇到这种情况,可以直接用rostopic echo看两路消息头的时间戳,把偏差算出来,在相机驱动里加一个time_offset参数补偿。

另外,外参标定后一定不要动雷达和相机的物理位置,哪怕只是松了一颗螺丝,外参会全部失效。我在小车刚装好的头几天,因为线材拉扯导致雷达支架移位,重新标定了两次,后来干脆用了带定位销的安装板,才彻底避免这个问题。

彩色点云拼接节点在长时间运行时,内存增长也很值得关注。如果你用PCL累积全局地图,点云数量会不断膨胀。建议在插入全局地图时加上体素滤波(voxel grid),比如设置0.05m的体素,每隔一段时间做一次降采样,既能控制内存,又能让地图更干净。

注意:如果在移动过程中发现彩色点云的“颜色部分”延迟比几何部分大,多半是图像曝光时间过长或者相机处理管线的延时过高。把曝光时间调小,并且关闭相机自动曝光,改用固定曝光,延迟会低很多。

最后再分享两个小技巧

第一个是调参的顺序问题。很多新手喜欢一次性把所有参数调到完美,但彩色点云这个系统里,建议按“点云几何准确 → 颜色对齐 → 整体融合”的顺序来调。先把激光雷达的建图跑稳,确认几何不飘,再调整彩色融合,否则几何都飘着,你根本不知道颜色错位到底是外参的锅还是建图的锅。

第二个是数据记录的思路。每次试验前,我习惯先录一段原始rosbag,包括雷达点云、相机图像和FAST-LIO的位姿轨迹。这样如果事后发现彩色地图有问题,可以离线反复重放数据调参,不用一遍遍推着机器人在外面跑。这个习惯帮我省了大量现场调试时间。

这套Livox加海康的实时彩色点云建图流程,完整跑通之后你会发现,其实每个环节都不是特别难,难的是把细节串联起来。希望这篇文章能帮你少走一些弯路,后面做基于彩色点云的目标检测、语义地图、或者室内三维重建的时候,这套系统都可以作为很好的数据基础。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询