点云格式转换:将 ros PointCloud2格式数据转为livox CustomMsg格式

2023-12-16 08:28

本文主要是介绍点云格式转换:将 ros PointCloud2格式数据转为livox CustomMsg格式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

将 ros PointCloud2格式数据转为livox CustomMsg格式

  • 前言
  • 点云格式
    • PointCloud2 点云格式
    • livox CustomMsg 点云格式
  • 将 ros PointCloud2格式数据转为livox CustomMsg格式
  • 测试

前言

览沃科技有限公司(Livox)成立于2016年。为了革新激光雷达行业,Livox致力于提供高性能、低成本的激光雷达传感器。通过降低使用门槛和生产成本,Livox将激光雷达技术集成到更多产品和应用之中,从而为自动驾驶、智慧城市、测绘、移动机器人等行业带来创新性改变。Livox产品已销往包括美国、加拿大、中国、日本和欧盟在内的 26 个国家和地区。

面向智能移动机器人市场,Livox 推出最新一代 3D 激光雷达 Mid-360,开启混合固态激光雷达 360° 立体感知新篇章。凭借小巧体积,Mid-360 的安装布置更加灵活。同时,Mid-360 充分考虑了移动机器人对导航、避障等升维感知的需求,兼容室内外场景,赋能移动机器人进入空间智能感知新时代。 但是这款产品官网一直购买不到, 本篇博客 在 gazebo 中 可实现对该激光雷达的仿真 。

传统激光雷达普遍采用机械扫描方式,扫描路径随时间重复。而Livox 激光雷达采用了独特的扫描⽅式,扫描路径不会重复。在非重复扫描方式中,视场中被激光照射到的区域面积会随时间增大,这意味着视场覆盖率随时间推移而显著提高,可减小视场内物体被漏检的概率,有助于探测视场中的更多细节。
在这里插入图片描述
下图中给出了一个直观的例子。(a)图由于采用了非重复扫描方式,随着时间的积累,视场覆盖率逐渐升高。而(b)图,由于扫描每次都是重复的,视场覆盖率几乎没有提升。

gazebo中自带的laser插件是上图中b的方式,并不能代表livox的这种雷达。

livox 的仿真功能包(livox_laser_simulation)中 提供了 多种半固体的雷达仿真模型,可以在gazebo中进行该雷达的仿真与其扫描方式(非重复式扫描)点云发布。

但是经过测试发现 livox_laser_simulation 雷达仿真功能包发布的是 ros PointCloud2 点云格式数据。

而现在针对livox雷达的激光slam算法用的是 livox CustomMsg 点云格式数据,例如 Fast-Lio2 、Faster-Lio 、Lio-livox等。所以想在gazebo中仿真这些算法,需要将 ros PointCloud2格式数据转为livox CustomMsg格式 。

点云格式

PointCloud2 点云格式

PointCloud2 是ros的一种点云格式

具体官方数据 http://docs.ros.org/en/jade/api/sensor_msgs/html/msg/PointCloud2.html

std_msgs/Header headeruint32 seqtime stampstring frame_id
uint32 height
uint32 width
sensor_msgs/PointField[] fieldsuint8 INT8=1uint8 UINT8=2uint8 INT16=3uint8 UINT16=4uint8 INT32=5uint8 UINT32=6uint8 FLOAT32=7uint8 FLOAT64=8string nameuint32 offsetuint8 datatypeuint32 count
bool is_bigendian
uint32 point_step
uint32 row_step
uint8[] data
bool is_dense

一个仿真的点云消息长这样

header:  // 点云的头信息seq: 963 //stamp:  // 时间戳secs: 1541143772nsecs: 912011000frame_id: "/camera_init"
height: 1   // If the cloud is unordered, height is 1  如果cloud 是无序的 height 是 1
width: 852578  //点云的长度
fields:  //  sensor_msgs/PointField[] fields - name: "x"offset: 0datatype: 7 	// 	uint8 INT8    = 1//	uint8 UINT8   = 2//	uint8 INT16   = 3//	uint8 UINT16  = 4//	uint8 INT32   = 5//	uint8 UINT32  = 6//	uint8 FLOAT32 = 7//	uint8 FLOAT64 = 8count: 1- name: "y"offset: 4datatype: 7count: 1- name: "z"offset: 8datatype: 7count: 1- name: "intensity"offset: 16datatype: 7count: 1
is_bigendian: False
point_step: 32 // Length of a point in bytes 一个点占的比特数 
row_step: 27282496 // Length of a row in bytes 一行的长度占用的比特数
data: [ .......................................................... ] //  Actual point data, size is (row_step*height)
is_dense: True // 没有非法数据点

livox CustomMsg 点云格式

CustomMsg 是 livox雷达的 专有的点云格式,其格式如下:

Header header             # ROS standard message header
uint64 timebase          # The time of first point
uint32 point_num      # Total number of pointclouds
uint8 lidar_id               # Lidar device id number
uint8[3] rsvd                 # Reserved use
CustomPoint[] points    # Pointcloud data

上述自定义数据包中的自定义点云(CustomPoint)格式 :

uint32 offset_time      # offset time relative to the base time
float32 x               # X axis, unit:m
float32 y               # Y axis, unit:m
float32 z               # Z axis, unit:m
uint8 reflectivity      # reflectivity, 0~255
uint8 tag               # livox tag
uint8 line              # laser number in lidar
  • line
    最后一行line是激光雷达扫描的线数(livox avia为6线),从原始扫描点云可以看出,后期可以按线来对原始点处理、筛选
  • tag
    tag: 主要指示多回波信息及噪点信息。是一个二进制表达,标记信息的格式如下:bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0

bit7 bit6 保留位

bit5 bit4 回波序号 : 00: 第 0 个回波 01: 第 1 个回波 10: 第 2 个回波 11: 第 3 个回波 由于Livox Avia 采用同轴光路,即使外部无被测物体,其内部的光学系统也会产生一个回波,该回波记为第 0个回波。随后,若激光出射方向存在可被探测的物体,则最先返回系统的激光回波记为第 1 个回波,随后为第 2个回波,以此类推。如果被探测物体距离过近(例如 1.5 m),第 1 个回波将会融合到第 0 个回波里,该回波记为第 0 个回波。

bit3 bit2 基于强度的点属性: 00:正常点 01:回波能量噪点置信度高 10:回波能量噪点置信度中 11:保留位
基于回波能量强度判断采样点是否为噪点。通常情况下,激光光束受到类似灰尘、雨雾、雪等干扰产生的噪点的回波能量很小。目前按照回波能量强度大小将噪点置信度分为二档:01表示回波能量很弱,这类采样点有较高概率为噪点,例如灰尘点;10表示回波能量中等,该类采样点有中等概率为噪点,例如雨雾噪点。噪点置信度越低,说明该点是噪点的可能性越低。

bit1 bit0 基于空间位置的点属性 : 00:正常点 01:空间噪点置信度高 10:空间噪点置信度中 11:空间噪点置信度低
基于采样点的空间位置判断是否为噪点。例如,激光探测测距仪在测量前后两个距离十分相近的物体时,两个物体之间可能会产生拉丝状的噪点。目前按照不同的噪点置信度分为三档,噪点置信度越低,说明该点是噪点的可能性越低。

  • offset_time
    时间戳
    点云数据及 IMU 数据中都包含时间戳信息。

  • reflectivity
    目标反射率
    目标反射率:以 0 至 255 表示。其中 0 至 150 对应反射率介于 0 至 100% 的漫散射物体;而 151 至255 对应全反射物体。

  • x y z
    坐标信息:Livox Avia 的坐标信息可表示为直角坐标(x, y, z)或球坐标(r, θ, φ)。如果前方无被探测物体或者被探测物体超出量程范围(例如 600 m),在直角坐标系下,点云输出为(0,0,0);在球坐标系下,点云输出为(0,θ, φ)。

将 ros PointCloud2格式数据转为livox CustomMsg格式

为了使 livox_laser_simulation 功能包可以输出 CustomMsg 格式数据用于 fast-lio仿真,需要对其代码进行修改。主要是livox_laser_simulation/src/livox_points_plugin.cpp 这个文件。

重新编写这个函数

void LivoxPointsPlugin::OnNewLaserScans()

前面的这些可以不变

    if (rayShape) {std::vector<std::pair<int, AviaRotateInfo>> points_pair;InitializeRays(points_pair, rayShape);rayShape->Update();msgs::Set(laserMsg.mutable_time(), world->SimTime());msgs::LaserScan *scan = laserMsg.mutable_scan();InitializeScan(scan);SendRosTf(parentEntity->WorldPose(), world->Name(), raySensor->ParentName());auto rayCount = RayCount();auto verticalRayCount = VerticalRayCount();auto angle_min = AngleMin().Radian();auto angle_incre = AngleResolution();auto verticle_min = VerticalAngleMin().Radian();auto verticle_incre = VerticalAngleResolution();

声明要发布的 custom格式的livox 点云

        livox_ros_driver::CustomMsg pp_livox;//声明要发布的 custom格式的livox 点云

赋值点云帧头

        // 赋值点云帧头pp_livox.header.stamp = ros::Time::now();//时间pp_livox.header.frame_id = "livox";//坐标系int count = 0;

用 high_resolution_clock 记录 起始时间

        boost::chrono::high_resolution_clock::time_point start_time = boost::chrono::high_resolution_clock::now();

遍历每个点

        for (auto &pair : points_pair){

获得点的距离

            auto range = rayShape->GetRange(pair.first);

获得点的强度

            auto intensity = rayShape->GetRetro(pair.first);

最大最小距离限制

            if (range >= RangeMax()) {range = 0;} else if (range <= RangeMin()) {range = 0;}

将极坐标转为x y z

            auto rotate_info = pair.second;// 将极坐标转为x y  z ignition::math::Quaterniond ray;ray.Euler(ignition::math::Vector3d(0.0, rotate_info.zenith, rotate_info.azimuth));auto axis = ray * ignition::math::Vector3d(1.0, 0.0, 0.0);auto point = range * axis;

声明一个 Custom 点

livox_ros_driver::CustomPoint p;//声明一个 Custom 点

赋值坐标

            p.x = point.X();p.y = point.Y();p.z = point.Z();

赋值强度

 p.reflectivity = intensity;

计算当前点时间到起始时间差

            boost::chrono::high_resolution_clock::time_point end_time = boost::chrono::high_resolution_clock::now();// 当前点时间boost::chrono::nanoseconds elapsed_time = boost::chrono::duration_cast<boost::chrono::nanoseconds>(end_time - start_time);

赋值偏移时间

p.offset_time = elapsed_time.count();

将当前点存入点云中

pp_livox.points.push_back(p);
// 计点个数的计数器加1
count ++;
}//结束遍历每个点

赋值点云中点的个数

        pp_livox.point_num = count;

发布点云

        livox_pub.publish(pp_livox);ros::spinOnce();}

测试

将功能包进行编译,需要引入 livox_ros_driver 功能包

find_package(catkin REQUIRED COMPONENTSroscpptflivox_ros_driver  # 新增
)

包含头文件

#include <livox_ros_driver/CustomMsg.h>

完成编译后启动仿真环境
在这里插入图片描述
产看当前话题名
可以看到这个 /livox/lidar 话题名

查看这个话题信息

rostopic info /livox/lidar

在这里插入图片描述

jk-jone@JKKC:~$ rostopic info /livox/lidar
Type: livox_ros_driver/CustomMsg
Publishers:
/gazebo (http://JKKC:38793/)
Subscribers: None

消息类型改成了 livox_ros_driver/CustomMsg

这篇关于点云格式转换:将 ros PointCloud2格式数据转为livox CustomMsg格式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/499829

相关文章

使用Python实现网页表格转换为markdown

《使用Python实现网页表格转换为markdown》在日常工作中,我们经常需要从网页上复制表格数据,并将其转换成Markdown格式,本文将使用Python编写一个网页表格转Markdown工具,需... 在日常工作中,我们经常需要从网页上复制表格数据,并将其转换成Markdown格式,以便在文档、邮件或

使用Python获取JS加载的数据的多种实现方法

《使用Python获取JS加载的数据的多种实现方法》在当今的互联网时代,网页数据的动态加载已经成为一种常见的技术手段,许多现代网站通过JavaScript(JS)动态加载内容,这使得传统的静态网页爬取... 目录引言一、动态 网页与js加载数据的原理二、python爬取JS加载数据的方法(一)分析网络请求1

8种快速易用的Python Matplotlib数据可视化方法汇总(附源码)

《8种快速易用的PythonMatplotlib数据可视化方法汇总(附源码)》你是否曾经面对一堆复杂的数据,却不知道如何让它们变得直观易懂?别慌,Python的Matplotlib库是你数据可视化的... 目录引言1. 折线图(Line Plot)——趋势分析2. 柱状图(Bar Chart)——对比分析3

Spring Boot 整合 Redis 实现数据缓存案例详解

《SpringBoot整合Redis实现数据缓存案例详解》Springboot缓存,默认使用的是ConcurrentMap的方式来实现的,然而我们在项目中并不会这么使用,本文介绍SpringB... 目录1.添加 Maven 依赖2.配置Redis属性3.创建 redisCacheManager4.使用Sp

Python Pandas高效处理Excel数据完整指南

《PythonPandas高效处理Excel数据完整指南》在数据驱动的时代,Excel仍是大量企业存储核心数据的工具,Python的Pandas库凭借其向量化计算、内存优化和丰富的数据处理接口,成为... 目录一、环境搭建与数据读取1.1 基础环境配置1.2 数据高效载入技巧二、数据清洗核心战术2.1 缺失

Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题

《Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题》:本文主要介绍Ubuntu上手动安装Go环境并解决“可执行文件格式错误”问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未... 目录一、前言二、系统架构检测三、卸载旧版 Go四、下载并安装正确版本五、配置环境变量六、验证安装七、常见

Python将字符串转换为小写字母的几种常用方法

《Python将字符串转换为小写字母的几种常用方法》:本文主要介绍Python中将字符串大写字母转小写的四种方法:lower()方法简洁高效,手动ASCII转换灵活可控,str.translate... 目录一、使用内置方法 lower()(最简单)二、手动遍历 + ASCII 码转换三、使用 str.tr

Python处理超大规模数据的4大方法详解

《Python处理超大规模数据的4大方法详解》在数据的奇妙世界里,数据量就像滚雪球一样,越变越大,从最初的GB级别的小数据堆,逐渐演变成TB级别的数据大山,所以本文我们就来看看Python处理... 目录1. Mars:数据处理界的 “变形金刚”2. Dask:分布式计算的 “指挥家”3. CuPy:GPU

Java如何将文件内容转换为MD5哈希值

《Java如何将文件内容转换为MD5哈希值》:本文主要介绍Java如何将文件内容转换为MD5哈希值的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java文件内容转换为MD5哈希值一个完整的Java示例代码代码解释注意事项总结Java文件内容转换为MD5

使用Vue-ECharts实现数据可视化图表功能

《使用Vue-ECharts实现数据可视化图表功能》在前端开发中,经常会遇到需要展示数据可视化的需求,比如柱状图、折线图、饼图等,这类需求不仅要求我们准确地将数据呈现出来,还需要兼顾美观与交互体验,所... 目录前言为什么选择 vue-ECharts?1. 基于 ECharts,功能强大2. 更符合 Vue