如何在ROS中使用PCL—数据格式(1)-程序员宅基地

技术标签: 数据结构与算法  c/c++  

在ROS中点云的数据类型

在ROS中表示点云的数据结构有: sensor_msgs::PointCloud      sensor_msgs::PointCloud2     pcl::PointCloud<T>

关于PCL在ros的数据的结构,具体的介绍可查 看            wiki.ros.org/pcl/Overview

关于sensor_msgs::PointCloud2   和  pcl::PointCloud<T>之间的转换使用pcl::fromROSMsgpcl::toROSMsg 

sensor_msgs::PointCloud   和   sensor_msgs::PointCloud2之间的转换

使用sensor_msgs::convertPointCloud2ToPointCloudsensor_msgs::convertPointCloudToPointCloud2.

那么如何在ROS中使用PCL呢?
(1)在建立的包下的CMakeLists.txt文件下添加依赖项

在package.xml文件里添加:

<build_depend>libpcl-all-dev</build_depend>
  <run_depend>libpcl-all</run_depend>

在src文件夹下新建.cpp文件


#include <ros/ros.h> // PCL specific includes #include <sensor_msgs/PointCloud2.h> #include <pcl_conversions/pcl_conversions.h> #include <pcl/point_cloud.h> #include <pcl/point_types.h> ros::Publisher pub; void cloud_cb (const sensor_msgs::PointCloud2ConstPtr& input) { // Create a container for the data. sensor_msgs::PointCloud2 output; // Do data processing here... output = *input; // Publish the data. pub.publish (output); } int main (int argc, char** argv) { // Initialize ROS ros::init (argc, argv, "my_pcl_tutorial"); ros::NodeHandle nh; ros::Subscriber sub = nh.subscribe ("input", 1, cloud_cb); pub = nh.advertise<sensor_msgs::PointCloud2> ("output", 1); // Spin ros::spin (); }

在 CMakeLists.txt 文件中添加:

add_executable(example src/example.cpp)
target_link_libraries(example ${catkin_LIBRARIES})

catkin_make之后生成可执行文件,运行以下命令

  roslaunch openni_launch openni.launch    这是打开kinect发布的命令
$ rosrun ros_slam example input:=/camera/depth/points      //运行我们生成的文件

运行RVIZ可视化以下,添加了程序发布的点云的话题既可以显示。同时也可以使用PCL自带的显示的函数可视化(这里不再一一赘述)

$ rosrun rviz rviz
在RVIZ中显示的点云的数据格式sensor_msgs::PointCloud2;

那么如果我们想实现对获取的点云的数据的滤波的处理,这里就是进行一个简单的体素网格采样的实验

同样在src文件夹下新建.cpp文件,然后我们的程序如下。也就是要在回调函数中实现对获取的点云的滤波的处理,但是我们要特别注意每个程序中的点云的数据格式以及我们是如何使用函数实现对ROS与PCL 的转化的。

程序如下

/***********************************************************
关于使用sensor_msgs/PointCloud2,
***********************************************************/

#include <ros/ros.h>
// PCL 的相关的头文件
#include <sensor_msgs/PointCloud2.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
//滤波的头文件
#include <pcl/filters/voxel_grid.h>
//申明发布器
ros::Publisher pub;
 //回调函数
void 
cloud_cb (const sensor_msgs::PointCloud2ConstPtr& input)  //特别注意的是这里面形参的数据格式
{
 // 声明存储原始数据与滤波后的数据的点云的 格式
  pcl::PCLPointCloud2* cloud = new pcl::PCLPointCloud2;    //原始的点云的数据格式
  pcl::PCLPointCloud2ConstPtr cloudPtr(cloud); 
  pcl::PCLPointCloud2 cloud_filtered;     //存储滤波后的数据格式

  // 转化为PCL中的点云的数据格式
  pcl_conversions::toPCL(*input, *cloud);

  // 进行一个滤波处理
  pcl::VoxelGrid<pcl::PCLPointCloud2> sor;   //实例化滤波
  sor.setInputCloud (cloudPtr);     //设置输入的滤波
  sor.setLeafSize (0.1, 0.1, 0.1);   //设置体素网格的大小
  sor.filter (cloud_filtered);      //存储滤波后的点云

  // 再将滤波后的点云的数据格式转换为ROS 下的数据格式发布出去
  sensor_msgs::PointCloud2 output;   //声明的输出的点云的格式
  pcl_conversions::fromPCL(cloud_filtered, output);    //第一个参数是输入,后面的是输出

  //发布命令
  pub.publish (output);
}

int
main (int argc, char** argv)
{
  // 初始化 ROS节点
  ros::init (argc, argv, "my_pcl_tutorial");
  ros::NodeHandle nh;   //声明节点的名称

  // 为接受点云数据创建一个订阅节点
  ros::Subscriber sub = nh.subscribe ("input", 1, cloud_cb);

  //创建ROS的发布节点
  pub = nh.advertise<sensor_msgs::PointCloud2> ("output", 1);

  // 回调
  ros::spin ();
}

看一下结果如图,这是在RVIZ中显示的结果,当然也可以使用PCL库实现可视化(注意我们在rviz中显示的点云的数据格式都是sensor_msgs::PointCloud2

要区别pcl::PCLPointCloud2  这是PCL点云库中定义的一种的数据格式,在RVIZ中不可显示,)

/**************************************************************************
关于使用pcl/PointCloud<T>的举例应用。这一类型的数据格式是PCL库中定义的一种数据格式
这里面使用了两次数据转换从

                      sensor_msgs/PointCloud2       到        pcl/PointCloud<T>
                     pcl::ModelCoefficients                到         pcl_msgs::ModelCoefficients.

代码

#include <ros/ros.h>
// PCL specific includes
#include <sensor_msgs/PointCloud2.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/ros/conversions.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
//关于平面分割的头文件
#include <pcl/sample_consensus/model_types.h>   //分割模型的头文件
#include <pcl/sample_consensus/method_types.h>   //采样一致性的方法
#include <pcl/segmentation/sac_segmentation.h>  //ransac分割法

ros::Publisher pub;

void 
cloud_cb (const sensor_msgs::PointCloud2ConstPtr& input)
{
  // 将点云格式为sensor_msgs/PointCloud2 格式转为 pcl/PointCloud
  pcl::PointCloud<pcl::PointXYZ> cloud;
  pcl::fromROSMsg (*input, cloud);   //关键的一句数据的转换

  pcl::ModelCoefficients coefficients;   //申明模型的参数
  pcl::PointIndices inliers;             //申明存储模型的内点的索引
  // 创建一个分割方法
  pcl::SACSegmentation<pcl::PointXYZ> seg;
  // 这一句可以选择最优化参数的因子
  seg.setOptimizeCoefficients (true);
  // 以下都是强制性的需要设置的
  seg.setModelType (pcl::SACMODEL_PLANE);   //平面模型
  seg.setMethodType (pcl::SAC_RANSAC);    //分割平面模型所使用的分割方法
  seg.setDistanceThreshold (0.01);        //设置最小的阀值距离

  seg.setInputCloud (cloud.makeShared ());   //设置输入的点云
  seg.segment (inliers, coefficients);       //cloud.makeShared() 创建一个 boost shared_ptr
  
  // 把提取出来的内点形成的平面模型的参数发布出去
  pcl_msgs::ModelCoefficients ros_coefficients;
  pcl_conversions::fromPCL(coefficients, ros_coefficients);
  pub.publish (ros_coefficients);
}

int
main (int argc, char** argv)
{
  // Initialize ROS
  ros::init (argc, argv, "my_pcl_tutorial");
  ros::NodeHandle nh;

  // Create a ROS subscriber for the input point cloud
  ros::Subscriber sub = nh.subscribe ("input", 1, cloud_cb);

  // Create a ROS publisher for the output model coefficients
  pub = nh.advertise<pcl_msgs::ModelCoefficients> ("output", 1);

  // Spin
  ros::spin ();
}

提取点云中平面的参数并且发布出去

 PCL对ROS的接口的总结

比如: pcl::toROSMsg(*cloud,output);

实现的功能是将pcl里面的pcl::PointCloud<pcl::PointXYZ>   cloud   转换成ros里面的sensor_msgs::PointCloud2   output 这个类型。

PCL对ROS的接口提供PCL数据结构的转换,通过通过ROS提供的以消息为基础的转换系统系统。这有一系列的转换函数提供用来转换原始的PCL数据类型成消息型。一些最有用常用的的message类型列举在下面。

std_msgs:Header:这不是真的消息类型,但是用在Ros消息里面的每一个部分。它包含了消息被发送的时间和序列号和框名。PCL等于pcl::Header类型

sensor_msgs::PointCloud2:这是最重要的类型。这个消息通常是用来转换pcl::PointCloud类型的,pcl::PCLPointCloud2这个类型也很重要,因为前面版本的可能被废除。

pcl_msgs::PointIndices:这个类型存储属于点云里面的点的下标,在pcl里面等于pcl::PointIndices

pcl_msgs::PolygonMesh这个类型包括消息需要描述多边形网眼,就是顶点和边,在pcl里面等于pcl::PolygonMesh

pcl_msgs::Vertices:这个类型包含了一系列的顶点作为一个数组的下标,来描述一个多边形。在pcl里面等于pcl::Vertices

pcl_msgs::ModelCoefficients:这存储了一个模型的不同的系数,比如描述一个平面需要4个系数。在PCL里面等于pcl::ModelCoefficients

上面的数据可以从PCL转成ROS里面的PCL。所有的函数有一个类似的特征,意味着一旦我们知道这样去转换一个类型,我们就能学会转换其他的类型。下面的函数是在pcl_conversions命名空间里面提供的函数

下面的函数是在pcl_conversions命名空间里面提供的函数

void  copyImageMetaData (const sensor_msgs::Image &image, pcl::PCLImage &pcl_image)
void  copyPCLImageMetaData (const pcl::PCLImage &pcl_image, sensor_msgs::Image &image)
void  copyPCLPointCloud2MetaData (const pcl::PCLPointCloud2 &pcl_pc2, sensor_msgs::PointCloud2 &pc2)
void
copyPointCloud2MetaData (const sensor_msgs::PointCloud2 &pc2, pcl::PCLPointCloud2 &pcl_pc2)
void  fromPCL (const pcl::PCLImage &pcl_image, sensor_msgs::Image &image)
void  fromPCL (const std::vector< pcl::PCLPointField > &pcl_pfs, std::vector< sensor_msgs::PointField > &pfs)
void  fromPCL (const pcl::PCLPointCloud2 &pcl_pc2, sensor_msgs::PointCloud2 &pc2)
void  moveFromPCL (pcl::PCLImage &pcl_image, sensor_msgs::Image &image)
void  moveFromPCL (pcl::PCLPointCloud2 &pcl_pc2, sensor_msgs::PointCloud2 &pc2)
void  moveToPCL (sensor_msgs::Image &image, pcl::PCLImage &pcl_image)
void  moveToPCL (sensor_msgs::PointCloud2 &pc2, pcl::PCLPointCloud2 &pcl_pc2)
void  moveToPCL (pcl_msgs::ModelCoefficients &mc, pcl::ModelCoefficients &pcl_mc)
void  toPCL (const sensor_msgs::Image &image, pcl::PCLImage &pcl_image)
void  toPCL (const sensor_msgs::PointCloud2 &pc2, pcl::PCLPointCloud2 &pcl_pc2)

总结出来就是

void fromPCL(const <PCL Type> &, <ROS Message type> &);
void moveFromPCL(<PCL Type> &, <ROS Message type> &);
void toPCL(const <ROS Message type> &, <PCL Type> &);
void moveToPCL(<ROS Message type> &, <PCL Type> &);

PCL类型必须被替换成先前指定的PCL类型和ROS里面相应的类型。sensor_msgs::PointCloud2有一个特定的函数集去执行转换

void toROSMsg(const pcl::PointCloud<T> &, sensor_msgs::PointCloud2 &);                     转换为ROS的点云sensor_msgs::PointCloud2类型
void fromROSMsg(const sensor_msgs::PointCloud2 &, pcl::PointCloud<T>&);                 转为PCL中的pcl::PointCloud<T>类型
void moveFromROSMsg(sensor_msgs::PointCloud2 &, pcl::PointCloud<T> &);               转换为pcl::PointCloud<T> 类型

**************

有兴趣者可以关注微信公众号或者加入QQ群中

   

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_34306446/article/details/85872771

智能推荐

分布式光纤传感器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告_预计2026年中国分布式传感器市场规模有多大-程序员宅基地

文章浏览阅读3.2k次。本文研究全球与中国市场分布式光纤传感器的发展现状及未来发展趋势,分别从生产和消费的角度分析分布式光纤传感器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。主要生产商包括:FISO TechnologiesBrugg KabelSensor HighwayOmnisensAFL GlobalQinetiQ GroupLockheed MartinOSENSA Innovati_预计2026年中国分布式传感器市场规模有多大

07_08 常用组合逻辑电路结构——为IC设计的延时估计铺垫_基4布斯算法代码-程序员宅基地

文章浏览阅读1.1k次,点赞2次,收藏12次。常用组合逻辑电路结构——为IC设计的延时估计铺垫学习目的:估计模块间的delay,确保写的代码的timing 综合能给到多少HZ,以满足需求!_基4布斯算法代码

OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版-程序员宅基地

文章浏览阅读3.3k次,点赞3次,收藏5次。OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版

关于美国计算机奥赛USACO,你想知道的都在这_usaco可以多次提交吗-程序员宅基地

文章浏览阅读2.2k次。USACO自1992年举办,到目前为止已经举办了27届,目的是为了帮助美国信息学国家队选拔IOI的队员,目前逐渐发展为全球热门的线上赛事,成为美国大学申请条件下,含金量相当高的官方竞赛。USACO的比赛成绩可以助力计算机专业留学,越来越多的学生进入了康奈尔,麻省理工,普林斯顿,哈佛和耶鲁等大学,这些同学的共同点是他们都参加了美国计算机科学竞赛(USACO),并且取得过非常好的成绩。适合参赛人群USACO适合国内在读学生有意向申请美国大学的或者想锻炼自己编程能力的同学,高三学生也可以参加12月的第_usaco可以多次提交吗

MySQL存储过程和自定义函数_mysql自定义函数和存储过程-程序员宅基地

文章浏览阅读394次。1.1 存储程序1.2 创建存储过程1.3 创建自定义函数1.3.1 示例1.4 自定义函数和存储过程的区别1.5 变量的使用1.6 定义条件和处理程序1.6.1 定义条件1.6.1.1 示例1.6.2 定义处理程序1.6.2.1 示例1.7 光标的使用1.7.1 声明光标1.7.2 打开光标1.7.3 使用光标1.7.4 关闭光标1.8 流程控制的使用1.8.1 IF语句1.8.2 CASE语句1.8.3 LOOP语句1.8.4 LEAVE语句1.8.5 ITERATE语句1.8.6 REPEAT语句。_mysql自定义函数和存储过程

半导体基础知识与PN结_本征半导体电流为0-程序员宅基地

文章浏览阅读188次。半导体二极管——集成电路最小组成单元。_本征半导体电流为0

随便推点

【Unity3d Shader】水面和岩浆效果_unity 岩浆shader-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏18次。游戏水面特效实现方式太多。咱们这边介绍的是一最简单的UV动画(无顶点位移),整个mesh由4个顶点构成。实现了水面效果(左图),不动代码稍微修改下参数和贴图可以实现岩浆效果(右图)。有要思路是1,uv按时间去做正弦波移动2,在1的基础上加个凹凸图混合uv3,在1、2的基础上加个水流方向4,加上对雾效的支持,如没必要请自行删除雾效代码(把包含fog的几行代码删除)S..._unity 岩浆shader

广义线性模型——Logistic回归模型(1)_广义线性回归模型-程序员宅基地

文章浏览阅读5k次。广义线性模型是线性模型的扩展,它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系。广义线性模型拟合的形式为:其中g(μY)是条件均值的函数(称为连接函数)。另外,你可放松Y为正态分布的假设,改为Y 服从指数分布族中的一种分布即可。设定好连接函数和概率分布后,便可以通过最大似然估计的多次迭代推导出各参数值。在大部分情况下,线性模型就可以通过一系列连续型或类别型预测变量来预测正态分布的响应变量的工作。但是,有时候我们要进行非正态因变量的分析,例如:(1)类别型.._广义线性回归模型

HTML+CSS大作业 环境网页设计与实现(垃圾分类) web前端开发技术 web课程设计 网页规划与设计_垃圾分类网页设计目标怎么写-程序员宅基地

文章浏览阅读69次。环境保护、 保护地球、 校园环保、垃圾分类、绿色家园、等网站的设计与制作。 总结了一些学生网页制作的经验:一般的网页需要融入以下知识点:div+css布局、浮动、定位、高级css、表格、表单及验证、js轮播图、音频 视频 Flash的应用、ul li、下拉导航栏、鼠标划过效果等知识点,网页的风格主题也很全面:如爱好、风景、校园、美食、动漫、游戏、咖啡、音乐、家乡、电影、名人、商城以及个人主页等主题,学生、新手可参考下方页面的布局和设计和HTML源码(有用点赞△) 一套A+的网_垃圾分类网页设计目标怎么写

C# .Net 发布后,把dll全部放在一个文件夹中,让软件目录更整洁_.net dll 全局目录-程序员宅基地

文章浏览阅读614次,点赞7次,收藏11次。之前找到一个修改 exe 中 DLL地址 的方法, 不太好使,虽然能正确启动, 但无法改变 exe 的工作目录,这就影响了.Net 中很多获取 exe 执行目录来拼接的地址 ( 相对路径 ),比如 wwwroot 和 代码中相对目录还有一些复制到目录的普通文件 等等,它们的地址都会指向原来 exe 的目录, 而不是自定义的 “lib” 目录,根本原因就是没有修改 exe 的工作目录这次来搞一个启动程序,把 .net 的所有东西都放在一个文件夹,在文件夹同级的目录制作一个 exe._.net dll 全局目录

BRIEF特征点描述算法_breif description calculation 特征点-程序员宅基地

文章浏览阅读1.5k次。本文为转载,原博客地址:http://blog.csdn.net/hujingshuang/article/details/46910259简介 BRIEF是2010年的一篇名为《BRIEF:Binary Robust Independent Elementary Features》的文章中提出,BRIEF是对已检测到的特征点进行描述,它是一种二进制编码的描述子,摈弃了利用区域灰度..._breif description calculation 特征点

房屋租赁管理系统的设计和实现,SpringBoot计算机毕业设计论文_基于spring boot的房屋租赁系统论文-程序员宅基地

文章浏览阅读4.1k次,点赞21次,收藏79次。本文是《基于SpringBoot的房屋租赁管理系统》的配套原创说明文档,可以给应届毕业生提供格式撰写参考,也可以给开发类似系统的朋友们提供功能业务设计思路。_基于spring boot的房屋租赁系统论文