PCL中点云数据格式之间的转化

本文涉及的产品
资源编排,不限时长
简介: (1) 关于pcl::PCLPointCloud2::Ptr和pcl::PointCloud两中数据结构的区别pcl::PointXYZ::PointXYZ ( float_x, float_y, float_z ...

(1) 关于pcl::PCLPointCloud2::Ptr和pcl::PointCloud<pcl::PointXYZ>两中数据结构的区别

pcl::PointXYZ::PointXYZ ( float_x,
                  float_y,
                  float_z
                    ) 

区别:    

 struct PCLPointCloud2
 {
  PCLPointCloud2 () : header (), height (0), width (0), fields (),
 is_bigendian (false), point_step (0), row_step (0),
  data (), is_dense (false)
  {
 #if defined(BOOST_BIG_ENDIAN)
  is_bigendian = true;
 #elif defined(BOOST_LITTLE_ENDIAN)
  is_bigendian = false;
 #else
 #error "unable to determine system endianness"
 #endif
  }
 
  ::pcl::PCLHeader header;
 
  pcl::uint32_t height;
  pcl::uint32_t width;
 
  std::vector< ::pcl::PCLPointField> fields;
 
  pcl::uint8_t is_bigendian;
  pcl::uint32_t point_step;
  pcl::uint32_t row_step;
 
  std::vector<pcl::uint8_t> data;
 
  pcl::uint8_t is_dense;
 
  public:
  typedef boost::shared_ptr< ::pcl::PCLPointCloud2> Ptr;
  typedef boost::shared_ptr< ::pcl::PCLPointCloud2 const> ConstPtr;
  }; // struct PCLPointCloud2

那么要实现它们之间的数据转换,

举个例子

 pcl::PCLPointCloud2::Ptr cloud_blob (new pcl::PCLPointCloud2), cloud_filtered_blob (new pcl::PCLPointCloud2);//申明滤波前后的点云
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>), cloud_p (new pcl::PointCloud<pcl::PointXYZ>), cloud_f (new pcl::PointCloud<pcl::PointXYZ>);

  // 读取PCD文件
  pcl::PCDReader reader;
  reader.read ("table_scene_lms400.pcd", *cloud_blob);
   //统计滤波前的点云个数
  std::cerr << "PointCloud before filtering: " << cloud_blob->width * cloud_blob->height << " data points." << std::endl;

  // 创建体素栅格下采样: 下采样的大小为1cm
  pcl::VoxelGrid<pcl::PCLPointCloud2> sor;  //体素栅格下采样对象
  sor.setInputCloud (cloud_blob);             //原始点云
  sor.setLeafSize (0.01f, 0.01f, 0.01f);    // 设置采样体素大小
  sor.filter (*cloud_filtered_blob);        //保存

  // 转换为模板点云
  pcl::fromPCLPointCloud2 (*cloud_filtered_blob, *cloud_filtered);

  std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl;

  // 保存下采样后的点云
  pcl::PCDWriter writer;
  writer.write<pcl::PointXYZ> ("table_scene_lms400_downsampled.pcd", *cloud_filtered, false);

程序中红色部分就是一句实现两者之间的数据转化的我们可以看出

cloud_filtered_blob 声明的数据格式为pcl::PCLPointCloud2::Ptr  cloud_filtered_blob (new pcl::PCLPointCloud2);
cloud_filtered 申明的数据格式  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>)

那么依照这种的命名风格我们可以查看到更多的关于的数据格式之间的转换的类的成员

(1)

   void pcl::fromPCLPointCloud(const pcl:PCLPointCloud2 & msg

                                                   pcl::PointCloud<PointT>  & cloud

                                                     const MsgFieldMap & filed_map

                                                     )

函数使用field_map实现将一个pcl::pointcloud2二进制数据blob到PCL::PointCloud<pointT>对象

使用 PCLPointCloud2 (PCLPointCloud2, PointCloud<T>)生成自己的 MsgFieldMap

MsgFieldMap field_map;
createMapping<PointT> (msg.fields, field_map);

(2)

void pcl::fromPCLPointCloud2(const pcl::PCLPointCloud & msg

                                                  pcl::PointCloud<pointT> &cloud

                                                  )

把pcl::PCLPointCloud数据格式的点云转化为pcl::PointCloud<pointT>格式

(3)

 void pcl::fromROSMsg(const pcl:PCLPointCloud2 & msg

                                 pcl::PointCloud<PointT>  & cloud

                                  const MsgFieldMap & filed_map

                                     )

(4)

 void pcl::fromROSMsg(const pcl:PCLPointCloud2 & msg

                                  pcl::PointCloud<PointT>  & cloud

                                     )

在使用fromROSMsg是一种在ROS 下的一种数据转化的作用,我们举个例子实现订阅使用kinect发布   /camera/depth/points  从程序中我们可以看到如何使用该函数实现数据的转换。并且我在程序中添加了如果使用PCL的库实现在ROS下调用并且可视化,

/************************************************
关于如何使用PCL在ROS 中,实现简单的数据转化
时间:2017.3.31

****************************************************/


#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>

#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/cloud_viewer.h>

ros::Publisher pub;
  

  pcl::visualization::CloudViewer viewer("Cloud Viewer");

void 
cloud_cb (const sensor_msgs::PointCloud2ConstPtr& input)
{
 // 创建一个输出的数据格式
  sensor_msgs::PointCloud2 output;  //ROS中点云的数据格式
  //对数据进行处理
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB>);

  output = *input;

    pcl::fromROSMsg(output,*cloud);

    
     //blocks until the cloud is actually rendered
    viewer.showCloud(cloud);
    

  pub.publish (output);
}



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);
   ros::Rate loop_rate(100);
  // Create a ROS publisher for the output point cloud
  pub = nh.advertise<sensor_msgs::PointCloud2> ("output", 1);
    

  

  // Spin
  ros::spin ();
/*
while (!viewer.wasStopped ())
    {

    } 
*/

 
}

那么对于这一段小程序实现了从发布的节点中转化为可以使用PCL的可视化函数实现可视化,并不一定要用RVIZ来实现,所以我们分析以下其中的步骤,在订阅话题的回调函数中,

void  cloud_cb (const sensor_msgs::PointCloud2ConstPtr& input)        //这里面设置了一个数据类型为sensor_msgs::PointCloud2ConstPtr& input形参
{
  sensor_msgs::PointCloud2 output;                                //ROS中点云的数据格式(或者说是发布话题点云的数据类型)
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB>);     //对数据转换后存储的类型
  output = *input;
   pcl::fromROSMsg(output,*cloud);   //最重要的一步骤实现从ROS到PCL中的数据的转化,同时也可以直接使用PCL库实现可视化

  viewer.showCloud(cloud);  //PCL库的可视化
  pub.publish (output);     //那么原来的output的类型仍然是sensor_msgs::PointCloud2,可以通过RVIZ来可视化
}

那么也可以使用

  pcl::PCDWriter writer;
  writer.write<pcl::PointXYZ> ("ros_to_PCL.pcd", *cloud, false);

这一段代码来实现保存的作用。那么见到那看一下可视化的结果

使用pcl_viewer 可视化保存的PCD文件

可能写的比较乱,但是有用到关于PCL中点云数据类型的转换以及可视化等功能可以参考,同时欢迎有兴趣者扫描下方二维码或者QQ群

与我交流并且投稿,大家一起学习,共同进步与分享

  

相关实践学习
使用ROS创建VPC和VSwitch
本场景主要介绍如何利用阿里云资源编排服务,定义资源编排模板,实现自动化创建阿里云专有网络和交换机。
阿里云资源编排ROS使用教程
资源编排(Resource Orchestration)是一种简单易用的云计算资源管理和自动化运维服务。用户通过模板描述多个云计算资源的依赖关系、配置等,并自动完成所有资源的创建和配置,以达到自动化部署、运维等目的。编排模板同时也是一种标准化的资源和应用交付方式,并且可以随时编辑修改,使基础设施即代码(Infrastructure as Code)成为可能。 产品详情:https://www.aliyun.com/product/ros/
相关文章
|
NoSQL Cloud Native 关系型数据库
阿里云RDS云数据库详解(三分钟)
阿里云RDS云数据库详解(三分钟),阿里云RDS关系型数据库如MySQL版、PolarDB、PostgreSQL、SQL Server和MariaDB等
241 1
|
4月前
|
运维 数据库 数据库管理
云数据库问题之阿里云在运营商领域数据库替换的整体解决方案要如何实现
云数据库问题之阿里云在运营商领域数据库替换的整体解决方案要如何实现
|
2月前
|
缓存 弹性计算 NoSQL
新一期陪跑班开课啦!阿里云专家手把手带你体验高并发下利用云数据库缓存实现极速响应
新一期陪跑班开课啦!阿里云专家手把手带你体验高并发下利用云数据库缓存实现极速响应
|
5月前
|
NoSQL Cloud Native Redis
|
7月前
|
Cloud Native 自动驾驶 NoSQL
亚太唯一,阿里云连续4年入选Gartner®云数据库管理系统魔力象限领导者象限
国际市场研究机构Gartner®日前公布2023年度全球《云数据库管理系统魔力象限》报告,阿里云成为亚太区唯一入选该报告“领导者(LEADERS)”象限的科技公司,同时也是唯一一家连续4年入选“领导者”象限的中国企业。
亚太唯一,阿里云连续4年入选Gartner®云数据库管理系统魔力象限领导者象限
|
7月前
|
弹性计算 关系型数据库 MySQL
阿里云MySQL云数据库优惠价格、购买和使用教程分享!
阿里云数据库使用流程包括购买和管理。首先,选购支持MySQL、SQL Server、PostgreSQL等的RDS实例,如选择2核2GB的MySQL,设定地域和可用区。购买后,等待实例创建。接着,创建数据库和账号,设置DB名称、字符集及账号权限。最后,通过DMS登录数据库,填写账号和密码。若ECS在同一地域和VPC内,可内网连接,记得将ECS IP加入白名单。
908 2
|
7月前
|
存储 弹性计算 NoSQL
阿里云突发!上百种云产品大规模降价,云服务器、云数据库、存储价格下调
阿里云突发!上百种云产品大规模降价,云服务器、云数据库、存储价格下调
188 2
|
7月前
|
关系型数据库 Serverless 分布式数据库
碧桂园服务使用阿里云PolarDB Serverless云数据库实现降本增效。
碧桂园集团,即碧桂园控股有限公司新型城镇化住宅开发商,采用集中及标准化的运营模式,业务包含物业发展、建安、装修、物业管理、物业投资、酒店开发和管理、以及现代农业、机器人。
|
7月前
|
SQL 关系型数据库 MySQL
阿里云——云数据库管理与数据迁移
阿里云——云数据库管理与数据迁移
229 0
|
7月前
|
Cloud Native 关系型数据库 分布式数据库
凭安征信引入阿里云PolarDB云数据库支撑企业征信核心业务系统
凭安征信是国家中小企业公共服务示范平台,主营信用管理服务包括信用管家、水滴信用及可信认证。通过采用阿里云PolarDB云原生数据库替代RDS数据库帮助客户全面实现业务系统性能提升1-2倍,通过PolarDB企业级能力的加持下,运维更加简便,操作更加简单,数据安全能力更强。

热门文章

最新文章