Loading and saving point clouds to the disk

PCL provides a standard file format to load and store point clouds to the disk as it is a common practice among researchers to share interesting datasets for other people to experiment with. This format is named PCD, and it has been designed to support PCL-specific extensions.

The format is very simple; it starts with a header containing information about the point type and the number of elements in the point cloud, followed by a list of points conforming to the specified type. The following lines are an example of a PCD file header:

# .PCD v.5 - Point Cloud Data file format 
FIELDS x y z intensity distance sid 
SIZE 4 4 4 4 4 4 
TYPE F F F F F F 
COUNT 1 1 1 1 1 1 
WIDTH 460400 
HEIGHT 1 
POINTS 460400 
DATA ascii 

Reading PCD files can be done through the PCL API, which makes it a very straightforward process. The following example can be found in chapter10_tutorials/src, and it is named pcl_read.cpp. The following example shows how to load a PCD file and publish the resulting point cloud as a ROS message:

#include <ros/ros.h> 
#include <pcl/point_cloud.h> 
#include <pcl_conversions/pcl_conversions.h> 
#include <sensor_msgs/PointCloud2.h> 
#include <pcl/io/pcd_io.h> 
 
main(int argc, char **argv) 
{ 
    ros::init (argc, argv, "pcl_read"); 
 
    ros::NodeHandle nh; 
    ros::Publisher pcl_pub = 
nh.advertise<sensor_msgs::PointCloud2> ("pcl_output", 1); sensor_msgs::PointCloud2 output; pcl::PointCloud<pcl::PointXYZ> cloud; pcl::io::loadPCDFile ("test_pcd.pcd", cloud); pcl::toROSMsg(cloud, output); output.header.frame_id = "odom";
    ros::Rate loop_rate(1); 
    while (ros::ok()) 
    { 
        pcl_pub.publish(output); 
        ros::spinOnce(); 
        loop_rate.sleep(); 
    } 
 
    return 0; 
} 

As always, the first step is to include the required header files. In this particular case, the only new header file that has been added is pcl/io/pcd_io.h, which contains the required definitions to load and store point clouds to PCD and other file formats.

The main difference between the previous example and this new one is simply the mechanism used to obtain the point cloud. While in the first example, we manually filled the point cloud with random points, in this case, we just load them from the disk:

pcl::io::loadPCDFile ("test_pcd.pcd", cloud); 

As we can see, the process of loading a PCD file has no complexity whatsoever. Further versions of the PCD file format also allow reading and writing of the current origin and orientation of the point cloud.

In order to run the previous example, we need to access the data directory in the package provided, which includes an example PCD file containing a point cloud that will be used further in this chapter:

    $ roscd chapter10_tutorials/data
    $ rosrun chapter10_tutorials pcl_read

As in the previous example, the point cloud can be easily visualized through the RViz visualizer:

Obvious though it may sound, the second interesting operation when dealing with PCD files is creating them. In the following example, our goal is to subscribe to a sensor_msgs/PointCloud2 topic and store the received point clouds into a file.
The code can be found in chapter10_tutorials, and it is named pcl_write.cpp:

#include <ros/ros.h> 
#include <pcl/point_cloud.h> 
#include <pcl_conversions/pcl_conversions.h> 
#include <sensor_msgs/PointCloud2.h> 
#include <pcl/io/pcd_io.h> 
 
void cloudCB(const sensor_msgs::PointCloud2 &input) 
{ 
    pcl::PointCloud<pcl::PointXYZ> cloud; 
    pcl::fromROSMsg(input, cloud); 
    pcl::io::savePCDFileASCII ("write_pcd_test.pcd", cloud); 
} 
 
main (int argc, char **argv) 
{ 
    ros::init (argc, argv, "pcl_write"); 
 
    ros::NodeHandle nh; 
    ros::Subscriber bat_sub = nh.subscribe("pcl_output", 10, 
cloudCB); ros::spin(); return 0; }

The topic subscribed to is the same used in the two previous examples, namely
pcl_output, so they can be linked together for testing:

ros::Subscriber bat_sub = nh.subscribe("pcl_output", 10, cloudCB); 

When a message is received, the callback function is called. The first step in this callback function is to define a PCL cloud and convert PointCloud2 that is received, using the pcl_conversions function fromROSMsg. Finally, the point cloud is saved to the disk in the ASCII format, but it could also be saved in the binary format, which will generate smaller PCD files:

void cloudCB(const sensor_msgs::PointCloud2 &input) 
{ 
    pcl::PointCloud<pcl::PointXYZ> cloud; 
    pcl::fromROSMsg(input, cloud); 
    pcl::io::savePCDFileASCII ("write_pcd_test.pcd", cloud); 
} 

In order to be able to run this example, it is necessary to have a publisher providing point clouds through the pcl_output topic. In this particular case, we will use the pcl_read example shown earlier, which fits this requirement. In three different terminals, we will run the roscore, pcl_read, and pcl_write node:

    $ roscore
    $ roscd chapter10_tutorials/data && rosrun chapter10_tutorials pcl_read
    $ roscd chapter10_tutorials/data && rosrun chapter10_tutorials pcl_write
  

If everything worked properly, after the first (or second) message is produced, the pcl_write node should have created a file named write_pcd_test.pcd in the data directory of the chapter10_tutorials package.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.181.144