提取 Livox Mid-360 的自定义点云(Custom Point Cloud) 和提取标准的sensor_msgs/msg/PointCloud2 格式点云有所不同,关键在于其消息类型。
Livox Mid-360 的 livox_ros_driver2 驱动通常会发布两种格式的点云:
标准格式: 话题名通常是 /livox/lidar,消息类型为 sensor_msgs/msg/PointCloud2。这种格式兼容性好,可以直接用 PCL (Point Cloud Library) 等工具处理。 自定义格式: 话题名通常是 /livox/lidar_custom,消息类型为 livox_ros_driver2/msg/CustomMsg。这种格式保留了 Livox 激光雷达更多的原始信息,如时间戳、线号、标签等,但需要专门的解析。
安装依赖: 确保 ROS 2 环境已经安装好。此外,我们需要一个库来处理和保存点云数据
pip install open3d numpy
ROS 2 工作空间需要能够识别 livox_ros_driver2/msg/CustomMsg 这个消息类型。执行以下命令检查系统是否能找到该消息类型:
ros2 interface show livox_ros_driver2/msg/CustomMsg
执行以下脚本后播放bag 包便可以提取bag包中的点云
pythonimport rclpy
from rclpy.node import Node
import numpy as np
import open3d as o3d
import os
# 导入Livox自定义消息类型
from livox_ros_driver2.msg import CustomMsg
class LivoxBagExtractor(Node):
"""
一个用于从ROS 2 Bag文件中提取Livox CustomMsg并保存为PCD文件的节点。
"""
def __init__(self):
super().__init__('livox_bag_extractor')
# --- 参数配置 ---
# 从bag文件中监听的Livox自定义点云话题
self.livox_topic = '/livox/lidar' # !! 重要:根据你的bag文件信息修改此话题名 !!
# 保存PCD文件的输出目录
self.output_dir = 'livox_pcd_output'
# ----------------
# 创建订阅者
self.subscription = self.create_subscription(
CustomMsg,
self.livox_topic,
self.custom_msg_callback,
10 # QoS profile depth
)
# 创建输出目录
if not os.path.exists(self.output_dir):
os.makedirs(self.output_dir)
self.frame_count = 0
self.get_logger().info(f"节点已启动,正在监听话题: '{self.livox_topic}'")
self.get_logger().info(f"PCD文件将保存在目录: '{self.output_dir}'")
def custom_msg_callback(self, msg: CustomMsg):
"""
回调函数,处理接收到的每一条CustomMsg消息。
"""
self.get_logger().info(f"接收到第 {self.frame_count + 1} 帧数据,包含 {len(msg.points)} 个点。")
# 准备一个列表来存储所有点的坐标
points_list = []
# 遍历消息中的每一个点
# CustomMsg中的 'points' 是一个 CustomPoint 类型的数组
for point in msg.points:
# 提取x, y, z坐标
x = point.x
y = point.y
z = point.z
points_list.append([x, y, z])
# 你也可以提取其他信息,例如:
# reflectivity = point.reflectivity
# tag = point.tag
# line = point.line
if not points_list:
self.get_logger().warn("接收到的帧不包含任何点,跳过保存。")
return
# 将点列表转换为NumPy数组
points_np = np.array(points_list, dtype=np.float64)
# 使用Open3D创建点云对象
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points_np)
# 构建文件名,使用帧计数器以保证唯一性
filename = os.path.join(self.output_dir, f"livox_frame_{self.frame_count:05d}.pcd")
# 保存为PCD文件
o3d.io.write_point_cloud(filename, pcd)
self.get_logger().info(f"成功保存文件: {filename}")
self.frame_count += 1
def main(args=None):
rclpy.init(args=args)
livox_extractor = LivoxBagExtractor()
try:
rclpy.spin(livox_extractor)
except KeyboardInterrupt:
pass
finally:
# 销毁节点并关闭rclpy
livox_extractor.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
有时候可能会遇到open3d与numpy的版本不兼容,执行以下命令升级相关库即可:
pip install --upgrade open3d scipy
为了确保提取的点云文件正常,用pcl_viewer进行可视化
首先安装相关工具
sudo apt install pcl_tools
然后执行可视化命令:
pcl_viewer xxx.pcd
本文作者:James
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!