【ROS入门】如何在ROS中使用PCL

官方教程:

1.创建一个ROS包

$ catkin_create_pkg my_pcl_tutorial pcl_conversions pcl_ros roscpp sensor_msgs 

修改package.xml 添加

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

2.创建代码框架
创建一个名为src / example.cpp的空文件,并将以下代码粘贴到其中:

 #include 
// PCL specific includes
 #include 
 #include 
 #include 
 #include 
 
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;
 
  // 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 point cloud
   pub = nh.advertise<sensor_msgs::PointCloud2> ("output", 1);
 
   // Spin
   ros::spin ();
}

初始化ROS,为PointCloud2数据创建订阅者和发布者。

3.将源文件添加到CMakeLists.txt
在新创建的功能包中编辑CMakeLists.txt文件,并添加:

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

4.从PCL教程下载源代码
PCL大约有四种表示点云数据的方式,类型是:

sensor_msgs :: PointCloud — ROS消息(不建议使用)
sensor_msgs :: PointCloud2 — ROS消息
pcl :: PCLPointCloud2 — PCL数据结构主要是为了与ROS兼容
pcl :: PointCloud < T> —标准PCL数据结构

重点关注ROS消息(sensor_msgs :: PointCloud2)和标准PCL数据结构(pcl :: PointCloud < T>)。
pcl :: PCLPointCloud2也是一种重要且有用的类型:可以使用该类型直接订阅节点,并且它将自动与sensor_msgs类型进行序列化。pcl :: PCLPointCloud2

- sensor_msgs / PointCloud2

如果您想保存一些复制和粘贴的信息,可以在此处下载此示例的源文件。将文件重命名为example.cpp或编辑CMakeLists.txt即可。

sensor_msgs / PointCloud2格式是一个ROS消息,用于ROS应用的首选。
在下面的示例中,我们使用3D网格对PointCloud2结构进行下采样,从而大大减少了输入数据集中的点数。
要将此功能添加到上面的代码框架中,请执行以下步骤:
请访问http://www.pointclouds.org/documentation/,单击“教程”,然后使用VoxelGrid过滤器教程(http://www.pointclouds.org/documentation/tutorials/voxel_grid.php)导航到对PointCloud进行降采样。

阅读此处提供的代码和说明。该代码主要分为三部分:
加载云(9-19行)
处理云(第20-24行)
保存输出(第25-32行)
由于我们在上面的代码片段中使用了ROS订阅者和发布者,因此可以忽略使用PCD格式加载和保存点云数据。因此,本教程中唯一相关的部分仍然是第20-24行,它们创建PCL对象,传递输入数据并执行实际计算:

 // Create the filtering object
pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
sor.setInputCloud (cloud);
sor.setLeafSize (0.01, 0.01, 0.01);
sor.filter (*cloud_filtered);

在这些行中,输入数据集称为cloud,输出数据集称为cloud_filtered。需要做一些额外的工作才能将 ROS消息转换为PCL类型。修改回调函数,如下所示:

#include  
 ...
 
void 
 cloud_cb (const sensor_msgs::PointCloud2ConstPtr& cloud_msg)
 {
   // Container for original & filtered data
   pcl::PCLPointCloud2* cloud = new pcl::PCLPointCloud2; 
   pcl::PCLPointCloud2ConstPtr cloudPtr(cloud);
   pcl::PCLPointCloud2 cloud_filtered;
 
   // Convert to PCL data type
   pcl_conversions::toPCL(*cloud_msg, *cloud);
 
   // Perform the actual filtering
   pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
   sor.setInputCloud (cloudPtr);
   sor.setLeafSize (0.1, 0.1, 0.1);
   sor.filter (cloud_filtered);
 
   // Convert to ROS data type
   sensor_msgs::PointCloud2 output;
   pcl_conversions::fromPCL(cloud_filtered, output);
 
   // Publish the data
   pub.publish (output);
 }

请注意,我们必须将变量名输入更改为cloud,并将输出名更改为cloud_filtered,以便与我们复制的教程中的代码匹配。
请注意,此处效率略有下降。该fromPCL可以替换moveFromPCL防止复制整个(过滤后)的点云。但是,由于原始输入为const,因此无法以这种方式优化toPCL调用。

保存输出文件,然后构建:

$ cd %TOP_DIR_YOUR_CATKIN_HOME%
$ catkin_make

然后运行:

$ rosrun my_pcl_tutorial example input:=/narrow_stereo_textured/points2

或者,如果您正在运行兼容OpenNI的深度传感器,请尝试:

$ roslaunch openni_launch openni.launch
$ rosrun my_pcl_tutorial example input:=/camera/depth/points

您可以通过运行RViz可视化结果:

$ rosrun rviz rviz

添加“ PointCloud2 ”显示。选择camera_depth_frame的固定框架(或任何框架适合您的传感器),并选择输出为PointCloud2话题。您应该会看到高度降采样的点云。为了进行比较,您可以查看/ camera / depth / points主题,并查看已被缩减采样的数量。

- pcl/PointCloud< T>

与前面的示例一样,如果要跳过一些步骤,则可以在此处下载此示例的源文件。

所述pcl/PointCloud< T>格式表示内部PCL点云格式。
出于模块化和效率的原因,该格式在点类型上进行了模板化,并且PCL提供了与SSE对齐的模板化常见类型的列表。

以下示例中,估计在一个场景中的最大平面的平面系数。

要将此功能添加到上面的代码框架中,请执行以下步骤:

请访问http://www.pointclouds.org/documentation/,单击“教程”,然后导航至“ 平面模型细分”教程(http://www.pointclouds.org/documentation/tutorials/planar_segmentation.php)

阅读此处提供的代码和说明。该代码主要分为三部分:
创建一个云并为其填充值(第12-30行)
处理云(38-56)
写系数(58-68)
由于我们在上面的代码片段中使用ROS订阅,因此我们可以忽略第一步,而直接处理在回调中接收到的云。因此,本教程中唯一相关的部分仍然是第38-56行,它们创建PCL对象,传递输入数据并执行实际计算:

  pcl::ModelCoefficients coefficients;
  pcl::PointIndices inliers;
  // Create the segmentation object 创建细分对象
  pcl::SACSegmentation<pcl::PointXYZ> seg;
  // Optional
  seg.setOptimizeCoefficients (true);
  // Mandatory
  seg.setModelType (pcl::SACMODEL_PLANE);
  seg.setMethodType (pcl::SAC_RANSAC);
  seg.setDistanceThreshold (0.01);

  seg.setInputCloud (cloud.makeShared ());
  seg.segment (inliers, coefficients);

输入数据集名为cloud,类型为pcl :: PointCloud < pcl :: PointXYZ>,输出由一组点索引表示,这些点索引包含平面以及平面系数。cloud.makeShared()创建了一个提升的shared_ptr的对象物体云(PCL ::点云API文档)。

通过如下修改回调函数,在上面的代码片段中复制这些行:

#include 
#include 
#include 
 ...
  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;
   // Create the segmentation object
   pcl::SACSegmentation<pcl::PointXYZ> seg;
   // Optional
   seg.setOptimizeCoefficients (true);
   // Mandatory
   seg.setModelType (pcl::SACMODEL_PLANE);
   seg.setMethodType (pcl::SAC_RANSAC);
   seg.setDistanceThreshold (0.01);
 
   seg.setInputCloud (cloud.makeShared ());
   seg.segment (inliers, coefficients);
 
   // Publish the model coefficients发布模型系数
   pcl_msgs::ModelCoefficients ros_coefficients;
   pcl_conversions::fromPCL(coefficients, ros_coefficients);
   pub.publish (ros_coefficients);
  }

注意,我们添加了两个转换步骤:从sensor_msgs / PointCloud2到pcl / PointCloud < T>和从pcl :: ModelCoefficients到pcl_msgs :: ModelCoefficients。将发布的变量从输出更改为系数。

此外,由于我们现在要发布找到的平面模型系数而不是点云数据,因此我们必须将发布者类型从以下更改:

 // Create a ROS publisher for the output point cloud,为输出点云创建ROS发布器
  pub = nh.advertise<sensor_msgs::PointCloud2> ("output", 1);
  // Create a ROS publisher for the output model coefficients,为输出模型系数创建ROS发布器
  pub = nh.advertise<pcl_msgs::ModelCoefficients> ("output", 1);

保存输出文件,然后编译并运行上面的代码:

$ rosrun my_pcl_tutorial example input:=/narrow_stereo_textured/points2

或者,如果您正在运行兼容OpenNI的深度传感器,请尝试:

$ rosrun my_pcl_tutorial example input:=/camera/depth/points

查看输出

$ rostopic echo output

你可能感兴趣的:(ROS入门,linux,c++)