# pcl_tutorials **Repository Path**: gwmunan/pcl_tutorials ## Basic Information - **Project Name**: pcl_tutorials - **Description**: pcl基本介绍和使用教程样例 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 5 - **Forks**: 0 - **Created**: 2024-07-05 - **Last Updated**: 2025-08-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ![输入图片说明](https://foruda.gitee.com/images/1720076877673526823/b38377ab_506465.png "屏幕截图") [PCL](https://pcl.readthedocs.io/projects/tutorials/en/master/index.html)(Point Cloud Library)ROS接口库, ![输入图片说明](https://foruda.gitee.com/images/1720076774053173798/21bcb516_506465.png "Screenshot from 2024-07-04 15-04-49.png") pcl_ros的介绍 PCL_ROS是在ROS中涉及n维点云和3D几何处理的3D应用的首选桥梁。 这个包提供运行ROS和PCL的接口和工具,包括nodelets、nodes和c++接口 输入图片说明 ![输入图片说明](Screenshot%20from%202024-07-04%2015-08-27.png) **bag_to_pcd:** 读取ROS包里面的数据,按照指定Topic存入PCD格式的文件中。 ``` $ rosrun pcl_ros bag_to_pcd ``` 说明: input_file.bag:加载的bag文件路径 topic:bag中指定的topic,通常是点云的topic output_directory: 输出的PCD文件路径 样例: ``` $ rosrun pcl_ros bag_to_pcd data.bag /laser_tilt_cloud ./pointclouds ``` ----- **pcd_to_pointcloud:** 加载指定的PCD文件,转换为ROS中的PointCloud格式发布出来 ``` $ rosrun pcl_ros pcd_to_pointcloud [ ] ``` 说明: file.pcd :pcd文件路径 interval :时间间隔,单位 s 样例: ``` $ rosrun pcl_ros pcd_to_pointcloud /home/wilson/fast_livo_ws/src/pcl_tutorials/pcd/scans.pcd 1 ``` ---- **pointcloud_to_pcd:** 订阅点云的topic,并保存点云数据到PCD文件中,每个topic消息保存为一个独立的PCD文件 ``` $ rosrun pcl_ros pointcloud_to_pcd input:= ``` 说明: PointCloudTopic :订阅的点云话题 样例: ``` $ rosrun pcl_ros pointcloud_to_pcd input:=/cloud_pcd ``` 以上是pcl_ros节点中各个节点的使用方法,接下来我们看一下接口的使用 以读取PCD文件,发布为ROS中标准的PointCloud2话题为例: ``` #include #include #include #include #include int main(int argc, char** argv) { // 初始化ROS节点 ros::init(argc, argv, "pcd_to_pointcloud_pub"); ros::NodeHandle nh; // 创建一个ROS发布者,用于发布点云消息 ros::Publisher pub = nh.advertise("/cloud_pcd", 1); // 读取PCD文件 pcl::PointCloud::Ptr cloud(new pcl::PointCloud); if (pcl::io::loadPCDFile("/home/wilson/fast_livo_ws/src/pcl_tutorials/pcd/scans.pcd", *cloud) == -1) { PCL_ERROR("Failed to read PCD file\n"); return -1; } // 创建一个ROS点云消息 sensor_msgs::PointCloud2 output; pcl::toROSMsg(*cloud, output); output.header.frame_id = "base_link"; // 设置点云消息的坐标系 ros::Rate loop_rate(1); while (ros::ok()) { // 发布ROS点云消息 pub.publish(output); std::cout << "Published a point cloud." << std::endl; ros::spinOnce(); loop_rate.sleep(); } return 0; } ``` 对应的订阅节点为: ``` #include #include #include void cloudCallback(const sensor_msgs::PointCloud2ConstPtr& msg) { pcl::PointCloud::Ptr cloud(new pcl::PointCloud); pcl::fromROSMsg(*msg, *cloud); // 获取点云数据的大小(字节数) size_t pointCloudSize = msg->data.size(); ROS_WARN("Received point cloud size: %zu bytes", pointCloudSize); } int main(int argc, char** argv) { ros::init(argc, argv, "pcd_to_pointcloud_sub"); ros::NodeHandle nh; ros::Subscriber sub = nh.subscribe("/cloud_pcd", 1, cloudCallback); ros::spin(); return 0; } ``` 以上是PCD文件与PointCloud2的转换 接下来我们延伸一下,看一下PCL中的过滤功能,这个在ROS的点云处理中也是经常使用 1.直通滤波: 过滤出指定范围内(坐标系的x轴,y轴,z轴)的点云集合 原始点云数据: ![输入图片说明](https://foruda.gitee.com/images/1720079820179007607/12f25838_506465.png "Screenshot from 2024-07-04 15-56-20.png") 滤波之后: ![输入图片说明](https://foruda.gitee.com/images/1720079989854202613/e3549765_506465.png "Screenshot from 2024-07-04 15-59-18.png") 样例如下: 新建一个pointcloud_filter_passthrough.cpp文件,内容如下: ``` #include // PCL specific includes #include #include #include #include // 添加引用 #include #include #include ros::Publisher pub; 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::PassThrough pass; // build the filter pass.setInputCloud(cloudPtr); pass.setFilterFieldName("x"); pass.setFilterLimits(1, 2); // pass.setFilterFieldName("y"); // pass.setFilterLimits(0, 2); // pass.setFilterFieldName("z"); // pass.setFilterLimits(0, 2); // apply filter pass.filter(cloud_filtered); // Convert to ROS data type sensor_msgs::PointCloud2 cloud_pt; pcl_conversions::moveFromPCL(cloud_filtered, cloud_pt); // Publish the data pub.publish(cloud_pt); } int main(int argc, char **argv) { // Initialize ROS ros::init(argc, argv, "pointcloud_filter_pub"); ros::NodeHandle nh; // Create a ROS subscriber for the input point cloud 输入 ros::Subscriber sub = nh.subscribe("/cloud_pcd", 1, cloud_cb); // Create a ROS publisher for the output point cloud 输出 pub = nh.advertise("/cloud_pcd/filter", 1); // Spin ros::spin(); } ``` 说明: 这里我们在X轴方向,过滤范围为:0~2m,只取X轴方向上原点到2m范围内的点云集合,其他都会被过滤掉 输出topic为:“/cloud_pcd”的点云数据,频率为 1 HZ 2.体素滤波 其实就是对点云集合进行降采样,降低点云密度,提示传输或加载效率 原始点云数据: ![输入图片说明](https://foruda.gitee.com/images/1720079820179007607/12f25838_506465.png "Screenshot from 2024-07-04 15-56-20.png") 过滤后效果: ![输入图片说明](https://foruda.gitee.com/images/1720080138591582539/f368342d_506465.png "Screenshot from 2024-07-04 16-01-24.png") 样例如下: 新建名为pointcloud_filter_volex.cpp的文件 ``` #include // PCL specific includes #include #include #include #include // 添加引用 #include #include #include ros::Publisher pub; 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); pcl::VoxelGrid sor; // build the filter sor.setInputCloud(cloudPtr); // 通过 lx, ly, lz 分别设置体素栅格在 XYZ 3个方向上的尺寸 sor.setLeafSize(0.5, 0.5, 0.5); // apply filter sor.filter(cloud_filtered); // Convert to ROS data type sensor_msgs::PointCloud2 cloud_vog; pcl_conversions::moveFromPCL(cloud_filtered, cloud_vog); // Publish the data pub.publish(cloud_vog); } int main(int argc, char **argv) { // Initialize ROS ros::init(argc, argv, "pointcloud_filter_pub"); ros::NodeHandle nh; // Create a ROS subscriber for the input point cloud 输入 ros::Subscriber sub = nh.subscribe("/cloud_pcd", 1, cloud_cb); // Create a ROS publisher for the output point cloud 输出 pub = nh.advertise("/cloud_pcd/filter", 1); // Spin ros::spin(); } ``` 说明: 这个样例中,我们订阅了名称为"/cloud_pcd"的点云数据,通过体素滤波器,设置x,y,z轴上的尺寸:0.5,0.5,0.5 3.点云投影 样例如下: 新建名为pointcloud_filter_coefficients.cpp的文件 ``` #include // PCL specific includes #include #include #include #include // 添加引用 #include #include #include #include #include #include #include #include #include using namespace std; using namespace pcl; int main(int argc, char **argv) { // 读取文件 PCDReader reader; PCDWriter writer; PointCloud::Ptr cloud(new PointCloud); PointCloud::Ptr cloud_f(new PointCloud); reader.read("/home/wilson/fast_livo_ws/src/pcl_tutorials/pcd/scans.pcd", *cloud); // 我们使用平面模型,其中ax + by + cz + d = 0,其中a = b = d = 0,并且c = 1,或者换句话说,XY平面。 pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients()); coefficients->values.resize(4); coefficients->values[0] = 0; coefficients->values[1] = 0; coefficients->values[2] = 1.0; coefficients->values[3] = 0; // 我们创建投影对象,并使用上面定义的模型作为投影模型 pcl::ProjectInliers proj; proj.setModelType(pcl::SACMODEL_PLANE); proj.setInputCloud(cloud); proj.setModelCoefficients(coefficients); proj.filter(*cloud_f); // Initialize ROS ros::init(argc, argv, "pointcloud_filter_pub"); ros::NodeHandle nh; // 创建一个ROS发布者,用于发布点云消息 ros::Publisher pub = nh.advertise("/cloud_pcd_coefficients", 1); // 创建一个ROS点云消息 sensor_msgs::PointCloud2 output; pcl::toROSMsg(*cloud_f, output); output.header.frame_id = "base_link"; // 设置点云消息的坐标系 ros::Rate loop_rate(1); while (ros::ok()) { // 发布ROS点云消息 pub.publish(output); std::cout << "Published a point cloud." << std::endl; ros::spinOnce(); loop_rate.sleep(); } return (0); } ``` 说明: 我们使用投影模型对象ModelCoefficients对从PCD文件中读取的点云数据,进行平面投影处理,可以打开rviz查看投影后的具体效果 原始数据: ![输入图片说明](https://foruda.gitee.com/images/1720079820179007607/12f25838_506465.png "Screenshot from 2024-07-04 15-56-20.png") 投影后数据: ![输入图片说明](https://foruda.gitee.com/images/1720079725047865328/7e4980bf_506465.png "Screenshot from 2024-07-04 15-55-05.png") 当然,除此之外PCL还有很多其他功能,感兴趣的可以去官网查看:https://pointclouds.org/