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中激光雷达数据类型传递转换及自定义点云数据类型介绍 的相关文章

  • 分享一下工作以来我看过计算机书籍

    由于自工作依赖一直专注于linux 下的c c 43 43 编程工作 xff0c 所以 xff0c 我的书籍也大的都是这方 这边书尽管很经典 xff0c 但是我的能力实在有限 xff0c 只把数据结构的那点看了一下 xff0c 其他的 看的

随机推荐

  • 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