资讯动态

Ubuntu 18.04下ROS Melodic数据采集:压缩图像与点云后录制bag实战

发布时间:2026/10/20 23:24:33 来源:尧图企业网站定制
做机器人、自动驾驶相关数据集采集的朋友应该对Ubuntu 18.04 ROS Melodic这套环境很熟。跑车的时候最头疼的不是传感器标定而是bag文件动不动几十GB。尤其是激光雷达点云和摄像头图像topic并存时稍有几分钟就会把磁盘塞满。我一开始也硬着头皮直接录原始topic直到某次连续采集光一个bag就冲出几十GB拷贝备份花了整整一晚上。后来改成“先压缩topic再录bag”的组合方案才把单次采集数据量压到一个合理范围。这篇内容主要解决一个具体任务在Ubuntu 18.04下把激光雷达点云topic和图像topic压缩后再录制ROS bag数据包。核心思路并不复杂图像走image_transport的compressed通道点云用pcl_ros的VoxelGrid降采样录制时再叠加rosbag record --lz4的bag级别压缩。写下来主要给做数据采集、传感器调试、SLAM算法验证的朋友一个可以直接抄的作业。1. 为什么非要在录制前压缩先把账算清楚1.1 激光雷达点云到底有多占空间很多人第一次录64线激光雷达数据时都会被吓到。以一帧常见的PointCloud2消息为例一个点通常包含x、y、z三个float32坐标12字节和intensity强度4字节有时候还带时间和ring信息单点轻松到16字节以上。64线雷达一帧大约有13万个点算下来一帧就是2MB左右。如果雷达10Hz工作每秒产生20MB以上的数据。半小时就是37GB这还只是点云。要是用16线雷达点数会少很多一帧约3万个点每秒约5MB。但16线雷达扫描范围广长时间采集下来一样撑不住。更麻烦的是点云topic不像图像那样有现成的标准化压缩消息直接录原始数据基本等于把磁盘当流水。1.2 图像的体积同样恐怖一台1080p摄像头原始图像按RGB888计算一帧是1920 * 1080 * 3字节约6.2MB。30帧每秒就是186MB/s。这个速率已经接近普通SATA固态盘的写盘上限了还不用说连续写入后缓存耗尽丢帧几乎是必然的。但图像有一个天然优势相邻像素信息冗余极大JPEG压缩后一帧通常只有100KB到300KB。即使30帧每秒也只需要每秒几MB的带宽。所以图像topic一定要在topic层做压缩千万别把原始图像直接灌进bag。1.3 两层压缩各有分工topic压缩和bag压缩不是一回事实际录制时存在两个层次的压缩topic压缩在消息尚未写入bag前就把它变成更小的消息。例如CompressedImage替代Image点云降采样替代原始密集点云。bag文件压缩rosbag record在写盘前对序列化后的bag数据流再做压缩常见格式是lz4和bz2。这两个层次可以叠加。图像topic压缩成JPEG后如果再叠加lz4虽然lz4对JPEG数据压缩率不高但也不会太亏。点云降采样后再叠加lz4节省效果的收益非常明显。我的经验是不要指望bag压缩能解决一切先把消息本身变小再用lz4收尾最后文件体积和CPU占用都比较理想。2. 图像topic压缩直接用republish2.1 最简单的一行命令raw转compressedUbuntu 18.04 ROS Melodic里先用命令行确认相关包已经装好。如果没装执行sudo apt install ros-melodic-image-transport ros-melodic-compressed-image-transport然后最常用的操作是启动一个image_transport republish节点把原始图像topic转换成压缩图像topicrosrun image_transport republish raw in:/camera/image_raw compressed out:/camera/image注意这里有个容易踩的坑out:/camera/image是基topic实际压缩后的topic会带/compressed后缀也就是/camera/image/compressed。有些教程会让人把out写成image_compressed结果查topic时发现多了一个/compressed后缀半天找不到消息。启动后用rostopic info检查rostopic info /camera/image/compressed正常会输出Type: sensor_msgs/CompressedImage Publishers: * /image_compressor ...这里的消息类型是sensor_msgs/CompressedImage不是原来的sensor_msgs/Image。录制bag时只要记录这个topic体积立刻就下来了。2.2 JPEG质量和参数怎么调compressed_image_transport默认使用JPEG编码默认质量在75左右。对比较关注细节的视觉SLAM任务我一般会把质量提到80到90因为压缩噪声太强会直接影响特征点提取。可以在启动republish时直接给私有参数rosrun image_transport republish raw in:/camera/image_raw compressed out:/camera/image _jpeg_quality:85如果想把图像压缩成无损PNG需要换一种传输插件这里不多展开。实际采集场景里JPEG基本够用。不过要注意JPEG是有损压缩如果数据要用于离线标定、目标检测精度评估不要上来就把质量压得太低。先录一小段测试bag回放看看图片清晰度再决定最终质量。2.3 怎么确认压缩topic真的变小知道topic存在还不够最好用rostopic bw看实际带宽。先把原始图像节点和republish节点都开着在两个终端分别运行rostopic bw /camera/image_raw rostopic bw /camera/image/compressed我实测过一组1080p、25帧的相机数据原始图像topic带宽稳定在150MB/s左右压缩后只有4MB/s到8MB/s。这个差距直接决定了bag能不能长期录制。3. 点云topic压缩体素降采样最实用3.1 用pcl_ros的VoxelGrid节点点云没有官方“压缩消息”但我们可以做空间降采样。最常用的工具是pcl_ros里的VoxelGrid思路很简单把三维空间划分成一个个小立方体每个立方体内部只保留一个代表点。这个代表点通常是体素内所有点的重心所以噪声也能被去掉一部分。如果pcl_ros还没装先装sudo apt install ros-melodic-pcl-ros ros-melodic-nodelet推荐用launch文件的方式启动点云降采样节点因为参数和topic映射都清清楚楚。例如把/velodyne_points降采样到/velodyne_points_downsampledlaunch node pkgnodelet typenodelet namepointcloud_voxel argsstandalone pcl/VoxelGrid outputscreen remap from~input to/velodyne_points/ remap from~output to/velodyne_points_downsampled/ param nameleaf_size value0.1/ /node /launch这里的核心参数是leaf_size单位是米。我通常默认用0.1m因为多数室外场景里10cm的体素对后续定位和避障算法足够。如果点云仍然太大可以改成0.2m。注意这个值越大信息丢失越严重要根据雷达线束和场景仔细权衡。3.2 更狠的方案3D点云转2D激光如果下游算法只需要2D范围内的环境信息比如2D激光SLAM、局部代价地图可以考虑把3D点云转成sensor_msgs/LaserScan。这个方案会丢掉高度信息但消息体量可以降到每帧几百KB甚至更小。实现上我会先用VoxelGrid降采样再接pointcloud_to_laserscan包里的节点做转换。对单一场景使用没关系但如果需要保存三维语义信息不建议长期采用这个方案因为一转换就是不可逆的损失。3.3 降采样后的数据完整性问题点云降采样一定会有信息损失这个必须提前想清楚。如果你录制的目的是长期训练点云分割模型那建议关键路段还是单独录一份原始点云或者把原始点云按“触发条件”小尺寸切片保存。降采样后的topic更适合做后端SLAM、实时建图、目标检测这类对数密度不敏感的任务。不要觉得一套压缩流程能通吃所有数据用途。4. 录制bag压缩topic 合理压缩参数的组合4.1 录制前先检查topic列表录制前不要偷懒先开几个终端确认所有压缩topic都在发布rostopic list | grep -E camera/image/compressed|velodyne_points_downsampled rostopic hz /camera/image/compressed rostopic hz /velodyne_points_downsampled同时确认TF相关topic也在rostopic list | grep -E ^/tf点云回放时一定要有tf和tf_static否则RViz里点云会显示在错误位置或者干脆不显示。4.2 最小录制命令模板我常用的录制命令是rosbag record -O sensor_data.bag --lz4 \ /camera/image/compressed \ /velodyne_points_downsampled \ /tf \ /tf_static-O后面跟输出bag文件名--lz4表示使用lz4压缩。注意这里别再去录/camera/image_raw和原始/velodyne_points不然压缩等于白做。新手最容易犯的错就是在命令里顺手加了原始topic录制完一看bag体积还是巨大。4.3 lz4和bz2到底怎么选rosbag record支持不同的压缩格式主要是lz4和bz2。我实际使用感受如下压缩方式速度压缩率适用场景none不压缩速度快无磁盘很大、CPU很弱的场景一般不推荐lz4很快CPU占用低中等实时采集首选写盘压力小丢帧概率低bz2较慢CPU占用高高离线对bag做后处理压缩率最好如果你在车机上采集CPU本身还要跑感知算法别用bz2。lz4虽然压缩率不如bz2但是快丢帧风险小。如果磁盘空间实在紧建议先用rosbag record --lz4录制事后离线再用rosbag compress --bz2压一层。这样可以避免录制过程中CPU过载。4.4 自动分割bag文件长时间录制时单个bag文件超过文件系统限制会很麻烦。我习惯用--split按大小分割rosbag record -O sensor_data.bag --lz4 --split --size2048 \ /camera/image/compressed \ /velodyne_points_downsampled \ /tf \ /tf_static--size2048表示每个bag达到2048MB就切换新文件。分割出来的文件会变成sensor_data_0.bag、sensor_data_1.bag这样。按大小分割比按时间分割更有利于后续拷贝和上传因为每个文件都在可控大小内。5. 回放与数据验证别让压缩成了坑5.1 验证图像topic是否正常解码录制完成后先跑rosbag info看一眼基本信息rosbag info sensor_data.bag输出里会列出topic名称、消息类型、消息数量、bag时长和压缩方式。重点确认/camera/image/compressed的消息类型是sensor_msgs/CompressedImage/velodyne_points_downsampled的消息类型是sensor_msgs/PointCloud2。然后播放bag并打开图像显示工具rosbag play sensor_data.bag rqt_image_view /camera/image/compressed如果rqt_image_view显示黑屏或提示找不到插件通常是compressed_image_transport包没装好。这个工具本身能自动解析CompressedImage但前提是插件已加载。5.2 验证点云topic是否在正确坐标系下用rosbag play播发bag然后在RViz里添加PointCloud2显示Fixed Frame选择点云消息里的frame_id比如velodyne或base_link。点云显示不出来很多时候不是点云消息坏了而是TF缺失。所以录制时一定要带上/tf和/tf_static。如果你在采集时使用了静态外参但没有发布tf_static回放时点云就会悬空或者报“No transform from ... to ...”。5.3 时间戳一致性问题如果数据来源是传感器直接采集通常时间戳来自各硬件驱动录制时消息会按ROS时间戳写入bag。如果是在仿真环境里采集且use_sim_time为true录制bag时最好也把/clock录进去回放时用rosbag play --clock sensor_data.bag否则仿真时间无法正确驱动算法。压缩不会直接影响时间戳但如果录制时CPU过载导致丢帧topic之间的时间对齐会变差。这也是我一直推荐lz4的原因。6. 常见问题与排查技巧实录6.1 压缩节点起不来如果image_transport republish启动时报错No transport found基本是两个原因compressed_image_transport没安装或者没有source对应的setup文件。检查方式rospack find compressed_image_transport如果包找得到再看是否在编译环境里多了一份其他ROSO版本。Ubuntu 18.04上用Melodic最容易遇到的是混装了Noetic相关的包。如果pcl/VoxelGrid节点启动时报类找不到一般是pcl_ros没装或者ROS环境变量没source。执行source /opt/ros/melodic/setup.bash然后再试。6.2 点云降采样后信息还是太多很多人把leaf_size设成0.01m结果发现点云数量基本没变。原因是体素太小时每个体素里可能就一个点根本起不到降采样效果。室外场景雷达建议从0.1m开始尝试不行再逐步加大。不要一上来就0.5m否则墙都变成麻子脸。如果只降采样还不够就加一个Passthrough滤波器把距离过远、z轴过高或过低的点直接滤掉。点云数据里100米外的点往往非常稀疏对大多数算法价值不大滤掉这部分再做体素降采样效果会更好。6.3 bag文件还是很大这种情况大概率是录制命令里包含了原始topic。用rosbag info看每个topic的消息类型和消息数如果发现/camera/image_raw或velodyne_points原样出现在列表里那就是录错topic了。也可能是TF频率太高。有些驱动会以100Hz甚至更高频率发/tf虽然单条消息很小但长时间累积也会占空间。如果外参是静态的尽量把外参放到/tf_static不要重复广播动态/tf。6.4 录制过程中丢帧丢帧主要是写盘速度和CPU占用导致的。我遇到过一个比较隐蔽的问题图像压缩节点和点云降采样节点都开了但bag写盘时还加了bz2压缩CPU被打满rostopic hz看到消息频率大幅度抖动。换成lz4之后丢帧立刻消失了。如果依旧丢帧检查是不是把bag写到了机械硬盘。采集数据最好写到独立固态盘或者确保磁盘剩余空间充足。我试过在剩余空间不到5%的盘上录制写盘速度会断崖式下降。6.5 回放时compressed图像topic显示异常如果rqt_image_view能显示但画面有绿边或花屏通常是JPEG质量参数调得过低或者图像分辨率过大压爆了压缩缓冲。可以先试试默认质量75如果正常再调整到目标质量。如果回放时图像有延迟可能是解码CPU瓶颈不是bag的问题。可以降低回放速率rosbag play --rate 0.5 sensor_data.bag确认是压缩画质问题还是解码性能问题再决定要不要提高图像压缩质量或降低图像分辨率。我自己在这套流程上踩过最大的坑是刚开始以为rosbag的lz4能替代topic层面压缩结果点云和图像全录原始topic再压lz4CPU直接被打满丢帧丢到没法看。后来把图像走JPEG、点云走体素降采样、bag再上lz4整体才稳定下来。如果你也在做长时间户外采集建议把bag写到独立SSD先录5分钟测试数据验证topic频率和文件大小再正式开录。压缩不是为了省那几十GB的磁盘而是为了让采集过程更可靠后续处理更顺手。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑