ROS中激光雷达数据类型传递转换及自定义点云数据类型介绍

2023-05-16

目录

一、ROS中激光雷达数据类型传递转换;

二、点云数据解析;

三、自定义点云数据类型;


一、ROS中激光雷达数据类型传递转换;

     ROS中涉及激光雷达传递的消息类型有两种,一种是针对2D雷达:sensor_msgs::LaserScan;一种是针对3D雷达的即点云数据的:sensor_msgs::PointCloud2.

(1) 2D激光雷达LaserScan;

ROS中LaserScan.msg定义类型如下:

File: sensor_msgs/LaserScan.msg
Raw Message Definition
# Single scan from a planar laser range-finder
#
# If you have another ranging device with different behavior (e.g. a sonar
# array), please find or create a different message, since applications
# will make fairly laser-specific assumptions about this data

Header header            # timestamp in the header is the acquisition time of 
                         # the first ray in the scan.
                         #
                         # in frame frame_id, angles are measured around 
                         # the positive Z axis (counterclockwise, if Z is up)
                         # with zero angle being forward along the x axis
                         
float32 angle_min        # start angle of the scan [rad]
float32 angle_max        # end angle of the scan [rad]
float32 angle_increment  # angular distance between measurements [rad]

float32 time_increment   # time between measurements [seconds] - if your scanner
                         # is moving, this will be used in interpolating position
                         # of 3d points
float32 scan_time        # time between scans [seconds]

float32 range_min        # minimum range value [m]
float32 range_max        # maximum range value [m]

float32[] ranges         # range data [m] (Note: values < range_min or > range_max should be discarded)
float32[] intensities    # intensity data [device-specific units].  If your
                         # device does not provide intensities, please leave
                         # the array empty.

发布: 

#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>

int main(int argc, char** argv){

  ros::init(argc, argv, "laser_scan_publisher");
  ros::NodeHandle n;

  ros::Publisher scan_pub = n.advertise<sensor_msgs::LaserScan>("scan", 50);

  unsigned int num_readings = 1000;
  double laser_frequency = 50;
  double ranges[num_readings];
  double intensities[num_readings];
  int count = 0;
  ros::Rate r(10.0);

  while(n.ok()){
    //generate some fake data for our laser scan
    for(unsigned int i = 0; i < num_readings; ++i){
      ranges[i] = count;
      intensities[i] = 100 + count;
    }

    ros::Time scan_time = ros::Time::now();

    //populate the LaserScan message
    sensor_msgs::LaserScan scan;
    scan.header.stamp = scan_time;
    scan.header.frame_id = "laser_frame";
    scan.angle_min = -1.57;           //雷达扫描起始角度;
    scan.angle_max = 1.57;            //雷达扫描结束角度;
    scan.angle_increment = 3.14 / num_readings;     //水平角度分辨率;
    scan.time_increment = (1 / laser_frequency) / (num_readings);   //相邻点时间间隔
    scan.range_min = 0.0;            //雷达有效测量最小值;
    scan.range_max = 100.0;          //雷达有效测量最大值;
    scan.ranges.resize(num_readings);   // num_readings = 扫描角 / 角度分辨率;根据雷达参数计算;
    scan.intensities.resize(num_readings);
    //实际中,距离值根据激光雷达传感器测得;
    for(unsigned int i = 0; i < num_readings; ++i){
      scan.ranges[i] = ranges[i];
      scan.intensities[i] = intensities[i];
    }
    scan_pub.publish(scan);

    r.sleep();
  }

}

接收:

#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>

#define PI 3.1415926

void laserCallback(const sensor_msgs::LaserScan::ConstPtr& msg)
{
   std::vector<float> ranges = msg->ranges;
   
   //转换到二维XY平面坐标系下;
   for(int i=0; i< ranges.size(); i++)
   {
     double angle = msg.angle_min + i * msg.angle_increment;
     double X = ranges[i] * cos(angle);
     double Y = ranges[i] * sin(angle);
     float intensity = msg.intensities[i];
     std::cout << ranges[i] << " , " << std::endl;
   }
}

int main(int argc, char **argv)
{
   ros::init(argc, argv, "laser_listener");
   ros::NodeHandle nh;

   ros::Subscriber sub = nh.subscribe("/scan", 10, laserCallback);

   ros::spin();

   return 0;
}

 

(2) 3D点云数据PointCloud2;

     接收:

#include <stdio.h>
#include <ros/ros.h>
#include <pcl_ros/point_cloud.h>
#include <pcl/point_types_conversion.h>
#include <sensor_msgs/PointCloud2.h>

//点云数据接收回调函数;
void PointCloud_callback(const sensor_msgs::PointCloud2ConstPtr& points_msg)
{
  const auto& stamp = points_msg->header.stamp;
  pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_in(new pcl::PointCloud<pcl::PointXYZI>());             //

  pcl::fromROSMsg(*points_msg, *cloud_in);

}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "point_cloud_subscriber");
  ros::NodeHandle node;

  ros::Subscriber points_sub = node.subscribe("/points_cloud", 5, PointCloud_callback);
  
  ros::spin();

  return 0;
}

     发布:

#include <stdio.h>
#include <ros/ros.h>
#include <pcl_ros/point_cloud.h>
#include <pcl/point_types_conversion.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl/filters/voxel_grid.h>
 
ros::Subscriber points_sub;   //订阅者;
ros::Publisher Map_pub;       //发布者;

//降采样函数;
void DownSample_Filter(pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_in,
                       pcl::PointCloud<pcl::PointXYZI>::Ptr &cloud_downsize,
                       double downsize){
   pcl::VoxelGrid<pcl::PointXYZI> downsample_filter;
   downsample_filter.setLeafSize(downsize, downsize, downsize);
   downsample_filter.setDownsampleAllData(true);    //对全字段进行下采样;
   downsample_filter.setInputCloud(cloud_in);
   downsample_filter.filter(*cloud_downsize);
}

//点云数据发布;
void publish_result(pcl::PointCloud<pcl::PointXYZI>::Ptr fliter_map){
if(Map_pub.getNumSubscribers() != 0){
   sensor_msgs::PointCloud2 cloud_out;
   pcl::toROSMsg(*fliter_map, cloud_out);
   cloud_out.header.frame_id = "map";
   cloud_out.header.stamp = stamp_now;
   Map_pub.publish(cloud_out);
   std::cout << " map size: " << fliter_map->points.size() << std::endl;
  }
}

//点云数据接收回调函数;
void PointCloud_callback(const sensor_msgs::PointCloud2ConstPtr& points_msg)
{
  const auto& stamp = points_msg->header.stamp;
  pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_in(new pcl::PointCloud<pcl::PointXYZI>());             //

  pcl::fromROSMsg(*points_msg, *cloud_in);

  pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_filter(new pcl::PointCloud<pcl::PointXYZI>());

  DownSample_Filter(cloud_in, cloud_filter, 0.15);

  publish_result(cloud_filter);

}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "point_cloud_subscriber");
  ros::NodeHandle node;

  points_sub = node.subscribe("/points_cloud", 5, PointCloud_callback);
  
  Map_pub= node.advertise<sensor_msgs::PointCloud2>("/filtered_map", 5, true);

  ros::spin();

  return 0;
}

(3)pointcloud  to laserscan 转换;

    pointcloud类型可以转化为 laserScan,github有专门的代码包:

    https://github.com/ros-perception/pointcloud_to_laserscan

二、点云数据解析;

       在进行ROS消息类型和PCL库点云类型之间转换时,除了可以利用PCL自带的转换函数,也可以自己解析。参考代码如下:

  void velodyPointCloundCallback(const sensor_msgs::PointCloud2ConstPtr &point_clound)
  {
     std::string frame_id = point_clound->header.frame_id;
     ros::Time received_time = point_clound->header.stamp;

      std::vector<pcl::PointXYZI> *gridpoints;
      gridpoints = new std::vector<pcl::PointXYZI>[laser_rings];
      pcl::PointXYZI point;

      //通过迭代器获取参数;
     for (sensor_msgs::PointCloud2ConstIterator<float> its(*point_clound, "x"); its != its.end(); ++its)
      {
        const uint16_t r = *((const uint16_t*)(&its[5])); // ring
        float x_p = its[0]; // x
        float y_p = its[1]; // y
        float z_p = its[2]; // z
        float in_p = its[4]; // intensity

        point.x = x_p;
        point.y = y_p;
        point.z = z_p;
        point.intensity = in_p;

        gridpoints[r].push_back(point);
    }
 }

 

三、自定义点云数据类型;

     在PCL点云库中,提供了自定义模板扩展,用户可以自己定义点云的数据类型。PCL提供了常见的点云类型,包括:pcl::PointXYZ, pcl::PointXYZI,pcl::PointXYZL等。pcl提供的点云数据类型

    如果需要自己重新添加自定义的点云类型,可参考如下:

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>

struct PointXYZIRPYT
{
    PCL_ADD_POINT4D
    PCL_ADD_INTENSITY;
    float roll;
    float pitch;
    float yaw;
    double time;
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
} EIGEN_ALIGN16;

POINT_CLOUD_REGISTER_POINT_STRUCT (PointXYZIRPYT,
                                   (float, x, x) (float, y, y)
                                   (float, z, z) (float, intensity, intensity)
                                   (float, roll, roll) (float, pitch, pitch)
                                   (float, yaw, yaw)
                                   (double, time, time)
)

typedef PointXYZIRPYT PointTypePose;
#include <stdint.h>

#define PCL_NO_PRECOMPILE
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/impl/instantiate.hpp>

struct _Kitti_PointExtended {
  inline _Kitti_PointExtended(const _Kitti_PointExtended &p)
    : data { p.x, p.y, p.z, 1.0f }, i(p.i){
  }

  inline _Kitti_PointExtended()
    : data { 0.0f, 0.0f, 0.0f, 1.0f }, i(0.0f) {
  }

  friend std::ostream& operator << (std::ostream& os, const _Kitti_PointExtended& p) {
    return os << "x: "<< p.x << ", y: " << p.y << ", z: " << p.z
        << ", intensity : " << p.i;
  }
  PCL_ADD_POINT4D;
  union {
    struct {
      float i;
    };
    float data_c[4];
  };
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
}EIGEN_ALIGN16;       // 强制SSE对齐

// Register the point type.
POINT_CLOUD_REGISTER_POINT_STRUCT (_Kitti_PointExtended,
                                   (float, x, x)
                                   (float, y, y)
                                   (float, z, z)
                                   (float, i, i)
)

typedef _Kitti_PointExtended PointKittiExtended;

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ROS中激光雷达数据类型传递转换及自定义点云数据类型介绍 的相关文章

  • ROS与navigation教程——ACML参数配置

  • 无人飞行器智能感知竞赛--模拟器安装

    开发环境 win11 wsl2 注意事项 请配合视频使用 如果不看视频会对下面的配置过程迷惑 因为一开始我是想安装在ubuntu18 04的 中途发现ubuntu18 04没有ros noetic 所以转入ubuntu20 04配置 视频链
  • ROS诸多调试工具总结1

    ROS有许多调试工具来为ROS调试你的工具 1 rosnode 参数 用法 作用 list rosnode list 查看当前运行了哪些节点 info rosnode info node name 查看该节点发布 接受哪些话题以及服务 ki
  • V-REP安装

    小知识 是当前目录 是父级目录 是根目录 1 下载V REP 官网地址 http www v rep eu downloads html 我用ubuntu16 04下载V REP PRO EDU V3 5 0 Linux tar 2 解压安
  • 关于相机与激光雷达数据采集与标定

    最近在做一个关于车路协同的项目 需要做一个路侧系统 传感器有摄像头和激光雷达 相机和激光雷达联合标定费了老半天劲 在此记录一下 雷达时间戳不对 导致摄像头和雷达的数据无法对齐 解决办法 修改雷达驱动发布点云消息时的时间戳 相机内参标定可以使
  • 激光雷达LMS111在ROS上的使用

    LMS111 10100 在ROS上的测试与使用 准备工作 设备 硬件 LMS111 101000激光雷达 软件 ubuntu16 04 ROS 开始 设备连接 将激光雷达与处理器 电脑 工控机等 通过以太网连接好 激光雷达默认的IP地址为
  • ROS 第四天 ROS中的关键组件

    1 Launch文件 通过XML文件实现多节点的配置和启动 可自动启动ROS Master
  • 局域网下ROS多机通信的网络连接配置

    1 在路由器设置中固定各机器IP地址 在浏览器中输入路由器的IP地址 例如TP LINK路由器的IP为 192 168 1 1 进入登录页面后 输入用户名和密码登录 用户名一般为admin 密码为自定义 在 基本设置 gt LAN设置 gt
  • 【ROS】usb_cam相机标定

    1 唠叨两句 当我们要用相机做测量用途时 就需要做相机标定了 不然得到的计算结果会有很大误差 标定的内容包括三部分 内参 外参还有畸变参数 所以标定的过程就是要求得上面这些参数 以前弄这个事估计挺麻烦 需要做实验和计算才能得到 现在通过ro
  • roslaunch error: ERROR: cannot launch node of type

    今天在因为github上有个之前的包更新了 重新git clone后出现了一个问题 ERROR cannot launch node of type crazyflie demo controller py can t locate nod
  • 如何将视频或图像序列转换为包文件?

    我是 ROS 新手 我需要转换预先存在的视频文件 或者large可以连接到视频流中的图像数量 bagROS 中的文件 我在网上找到了这段代码 http answers ros org question 11537 creating a ba
  • 什么是 void `std::allocator`?即:`std::allocator`

    自动生成ROS 机器人操作系统 message C 头文件包含如下类型定义 typedef std msgs Header
  • 将 CUDA 添加到 ROS 包

    我想在 ros 包中使用 cuda 有人给我一个简单的例子吗 我尝试使用 cuda 函数构建一个静态库并将该库添加到我的包中 但总是出现链接错误 未定义的引用 cuda 我已经构建了一个可执行文件而不是库并且它可以工作 请帮忙 我自己找到了
  • Caught exception in launch(see debug for traceback)

    Caught exception in launch see debug for traceback Caught exception when trying to load file of format xml Caught except
  • 在 Ubuntu 18.10 上安装 ROS Melodic

    I can t是唯一对 Cosmic 与 Wayland 和 Melodic 的组合感兴趣的人 我会坦白说 我似乎已经在 XPS 13 9370 上成功管理了此操作 或者至少安装脚本 最终 成功完成 然而 有一个非常棘手的解决方法 无论结果
  • catkin_make 编译报错 Unable to find either executable ‘empy‘ or Python module ‘em‘...

    文章目录 写在前面 一 问题描述 二 解决方法 参考链接 写在前面 自己的测试环境 Ubuntu20 04 一 问题描述 自己安装完 anaconda 后 再次执行 catkin make 遇到如下问题 CMake Error at opt
  • 可以在catkin工作区之外创建ROS节点吗?

    我想在catkin工作区之外创建一个ROS发布者节点 可以创建吗 当然可以 像对待任何其他 cpp 库或 python 包一样对待 ROS 在Python中你必须保留PYTHONPATH环境变量指向ros包 opt ros kinetic
  • 如何使用 PyQT5 连接和分离外部应用程序或对接外部应用程序?

    我正在使用 ROS 为多机器人系统开发 GUI 但我对界面中最不想做的事情感到困惑 在我的应用程序中嵌入 RVIZ GMAPPING 或其他屏幕 我已经在界面中放置了一个终端 但我无法解决如何向我的应用程序添加外部应用程序窗口的问题 我知道
  • 使用 CMake 链接 .s 文件

    我有一个我想使用的 c 函数 但它是用Intel编译器而不是gnu C编译器 我在用着cmake构建程序 我实际上正在使用ROS因此rosmake但基础是cmake所以我认为这更多是一个 cmake 问题而不是ROS问题 假设使用构建的文件
  • ROS中spin和rate.sleep的区别

    我是 ROS 新手 正在尝试了解这个强大的工具 我很困惑spin and rate sleep功能 谁能帮助我了解这两个功能之间的区别以及何时使用每个功能 ros spin and ros spinOnce 负责处理通信事件 例如到达的消息

随机推荐

  • 51单片机定时器初值计算详解

    前言 xff1a 本文详细介绍了51单片机学习过程中定时器的初值计算问题以及相关概念 xff0c 力求把每一个学习过程中的可能会遇到的难点说清楚 xff0c 并举相关的例子加以说明 学习完毕 xff0c 又顺手利用刚学到定时器的相关知识写了
  • STM32平台下官方DMP库6.12超详细移植教程

    前记 Motion Driver官方库 xff1a Motion Driver 6 12 STM32工程源码 xff1a STM32F103C8 软件MPU6050 xff08 DMP xff09 MPU6050软件I2C驱动 xff0c
  • STM32F103C8-平衡小车笔记

    STM32F103C8 平衡小车笔记 1 PID的作用 xff08 1 xff09 比例项 xff1a 提高响应速度 xff0c 减小静差 xff08 2 xff09 积分项 xff1a 消除稳态误差 xff08 3 xff09 微分项 x
  • 嵌入式Linux系统开发笔记(十四)

    U Boot环境变量 uboot 中有两个非常重要的环境变量 bootcmd 和 bootargs xff0c bootcmd 和 bootagrs 是采用类似 shell 脚本语言编写的 xff0c 里面有很多的变量引用 xff0c 这些
  • 嵌入式Linux系统开发笔记(十五)

    Linux内核启动验证 5 1 编译内核 span class token comment 清除工程 span span class token comment make distclean span span class token co
  • 基于ROS搭建机器人仿真环境

    别人的发复现及经验 https blog csdn net qq 38620941 article details 125321347 gazebo默认仿真环境 1 gazebo models 是系统下gazebo放置模型库的默认位置 2
  • 嵌入式Linux系统开发笔记(十六)

    根文件系统rootfs启动验证测试 接下来我们使用测试一下前面创建好的根文件系统 rootfs xff0c 测试方法使用 NFS 挂载 6 1 检查是否在Ubuntu主机中安装和开启了NFS服务 xff08 特别注意 xff1a nfs 配
  • 安卓5.0以上7.0以下使用Termux

    参考 xff1a https zhuanlan zhihu com p 400507701 说明 xff1a Termux支持5 0以上的安卓系统 Termux7 3版本之后 xff0c 仅支持7 0以上的安卓系统 1 安装Termux 设
  • 关于DSP的CCS6.0平台下的工程搭建(完全可移植)

    本工程以CCS6 0下新建TMS320F28335工程为例 xff0c 其他系列处理器工程搭建类似 xff0c 参考本例即可 工程搭建用到的F2833x TI官方库文件 下载链接 也可直接参考笔者搭建好CCS6 0的工程 下载链接 所建工程
  • STM32Fxx JTAG/SWD复用功能重映射

    问题描述 xff1a 在实验室调车过程中 xff0c 遇到的一个问题 xff1a 为了每次下载程序方便 xff0c 队员们往往会把 Jlink 插在板子上 xff0c 可是在调车过程中发现 xff0c 有时程序会莫名死掉 xff0c 而同样
  • VS2012编译RTKLIB——GNSS定位开源库

    RTKLIB 开源库 有着强大的 GPS 数据实时和后处理功能 xff0c 由于 笔者的毕业设计中需要对GPS 载波相位观测量进行 RTK 解算 xff0c 故而 xff0c 对 RTKLIB 开源库进行了学习与研究 RTKLIB 提供了很
  • 51单片机串行口波特率计算

    1 工作方式介绍 xff1a 方式 0 xff1a 这种工作方式比较特殊 xff0c 与常见的微型计算机的串行口不同 xff0c 它又叫 同步移位寄存器输出方式 在这种方式下 xff0c 数据从 RXD 端串行输出或输入 xff0c 同步信
  • 数码管显示问题总结

    1 数码管显示原理 我们最常用的是七段式和八段式 LED 数码管 xff0c 八段比七段多了一个小数点 xff0c 其他的基本相同 所谓的八段就是指数码管里有八个小 LED 发光二极管 xff0c 通过控制不同的 LED 的亮灭来显示出不同
  • 单片机与嵌入式linux 比较

    MCU门槛低 xff0c 入门容易 xff0c 但是灵活 xff0c 其实对工程师的软硬件功底要求更高 xff0c 随着半导体的飞速发展 xff0c MCU能实现很多匪夷所思匪夷所思的功能 xff0c 比如 xff0c 使用GPIO模拟1个
  • rtk 精确定位 简介

    RTK又称载波相位差分 xff1a 基准站通过数据链及时将其载波观测量及站坐标信息一同传送给用户站 用户站接收GPS卫星的载波相位与来自基准站的载波相位 xff0c 并组成相位差分观测值进行及时处理 xff0c 能及时给出厘米级的定位结果
  • STM32开发利器:STM32CubeMX

    这篇博客篇幅不长 xff0c 主要是为大家介绍ST公司推出的STM32CubeMX开发工具 xff0c 当成下周更新STM32 10个项目工程的预备篇 xff0c 同时FPGA FPGA 20个例程篇 xff1a 8 SD卡任意地址的读写
  • ROS命名空间

    ROS命令空间是一个很重要的内容 xff0c 官方文档 xff1a http wiki ros org Names 分为三类 xff1a relative xff0c global xff0c private 下边是一个官网给的示例 Nod
  • STM32CubeMX关于添加DSP库的使用

    前言 人生如逆旅 xff0c 我亦是行人 一 介绍 STM32 系列基于专为要求高性能 低成本 低功耗的嵌入式应用专门设计的 ARM Cortex M3 内核 而 DSP 应该是 TMS320 系列 xff0c TMS320 系列 DSP
  • STM32H750VBT6的DSP使用的学习——基于CubeMX

    前言 人生如逆旅 xff0c 我亦是行人 1 STM32H7的DSP功能介绍 xff08 STMicroelectronics xff0c 简称ST xff09 推出新的运算性能创记录的H7系列微控制器 新系列内置STM32平台中存储容量最
  • ROS中激光雷达数据类型传递转换及自定义点云数据类型介绍

    目录 一 ROS中激光雷达数据类型传递转换 xff1b 二 点云数据解析 三 自定义点云数据类型 一 ROS中激光雷达数据类型传递转换 xff1b ROS中涉及激光雷达传递的消息类型有两种 xff0c 一种是针对2D雷达 sensor ms