ROS中从摄像头获取PCL点云数据,并滤波后在Rviz中显示

一、点云简介

    通过测量仪器得到的产品外观表面的点数据集合也称之为点云,通常使用三维坐标测量机所得到的点数量比较少,点与点的间距也比较大,叫稀疏点云;而使用三维激光扫描仪或照相式扫描仪得到的点云,点数量比较大并且比较密集,叫密集点云。

        经过几十年的发展,机器人传感器领域已经发生了巨大的变化:从基于声呐的简单测距功能到现在的视觉传感器和激光扫描仪。由视觉传感器和激光扫描仪提供的大量3D数据已经变得实用起来,像DAPAR无人汽车挑战赛已经可以实用高质量的3D点云来感知世界。近年来,一些3D传感器价格已经普遍为大家接受,像微软公司提供的Xbox360游戏机附带的传感器Kinect,价格在1000元左右。Kinect可以提供3D点云,使得机器人可以看到3D世界。

        那么如何有效处理3D点云数据,PCL(point cloud library)给出了一个很好的解决方案。PCL是一个独立的、大规模开源点云处理软件包,现在已经完全集成到ROS中。PCL被设计用于感知3D世界,可以处理实时感知设备的数据,像激光扫描仪、双目立体视觉系统和ToF(Time of Flight)摄像机。

        下面我们给出一个案例,在ROS中实现从摄像头获取PCL点云数据,并滤波后在Rviz中显示。

二、安装摄像头驱动等基础程序

    经过测试,由于Openni2驱动程序无法对华硕的某型摄像头(ASUSTek)产生的点云消息进行发布,因此,安装Open你驱动程序,命令如下:

apt-get install ros-kinetic-openni-camera ros-kinetic-openni-launch

        安装完,通过如下命令测试

roslaunch openni_launch openni.launch

        注意:如果提示    “USB interface is not supported!”,则通过如下命令继续安装一个驱动,问题即可解决

sudo apt-get install libopenni-dev libopenni-sensor-primesense-dev

三、创建ROS package

catkin_create_pkg my_pcl_tutorial pcl_conversions pcl_ros roscpp sensor_msgs

然后,在package.xml中增加如下代码

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

四、创建源代码文件src/example.cpp,将下面的代码粘贴到里边

#include <ros/ros.h>
// PCL specific includes 。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& 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中的点云的数据格式
  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);  //设置滤波时创建的体素大小为1cm立方体
  sor.filter (cloud_filtered);//执行滤波处理,存储输出cloud_filtered

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

  // 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<sensor_msgs::PointCloud2> ("input", 1, cloud_cb);

  // Create a ROS publisher for the output point cloud
//创建ROS的发布节点
  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})

六、编译工作空间

$ cd ~/catkin_ws
$ catkin_make

七、运行roscore

roscore
八、将华硕摄像头连接到USB接口,新的Terminal中运行摄像头驱动及消息发布程序
roslaunch openni_launch openni.launch

九、新的Terminal中运行我们编写的摄像头点云数据降采样程序

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

十、新的Terminal中运行Rviz,查看滤波前后的点云数据

rosrun rviz rviz

Rviz中,Global Options中的Fixed Frame选择camera_depth_frame;通过Add按钮可以添加camera图像数据以及降采样前后的点云数据到Displays面板中,从而查看运行效果,如下图所示。第一幅为降采样前的点云数据显示,第二幅为降采样后的点云数据显示。

















      

ROS,可以使用PointCloud2消息类型来表示点云数据。要将PCL点云转换为ROS点云,可以按照以下步骤操作: 1. 创建一个PointCloud2消息对象,设置其header和fields属性。Header属性包含一些元数据,如时间戳、坐标系等,而Fields属性定义了每个点的数据类型和名称。 2. 将PCL点云数据转换为一个ROS消息的二进制数据数组。这可以通过将PCL点云数据复制到ROS消息的二进制数据数组来完成。 3. 将二进制数据数组设置为PointCloud2消息对象的data属性。 4. 将PointCloud2消息对象发布到ROS话题,以便其他节点可以接收和处理该点云数据。 下面是一个示例代码,可以将一个PCL点云转换为ROS点云并发布到ROS话题: ``` #include <ros/ros.h> #include <pcl_conversions/pcl_conversions.h> #include <sensor_msgs/PointCloud2.h> #include <pcl/point_cloud.h> #include <pcl/point_types.h> int main(int argc, char **argv) { // 初始化ROS节点 ros::init(argc, argv, "pcl_to_ros_node"); ros::NodeHandle nh; // 创建一个PCL点云对象 pcl::PointCloud<pcl::PointXYZ> pcl_cloud; // 填充点云数据(省略) // 创建一个ROS消息对象 sensor_msgs::PointCloud2 ros_cloud; // 将PCL点云数据转换为ROS消息的二进制数据数组 pcl::toROSMsg(pcl_cloud, ros_cloud); // 设置ROS消息对象的header和fields属性 ros_cloud.header.frame_id = "pcl_frame"; ros_cloud.header.stamp = ros::Time::now(); ros_cloud.fields.resize(3); ros_cloud.fields[0].name = "x"; ros_cloud.fields[0].offset = 0; ros_cloud.fields[0].datatype = sensor_msgs::PointField::FLOAT32; ros_cloud.fields[0].count = 1; ros_cloud.fields[1].name = "y"; ros_cloud.fields[1].offset = 4; ros_cloud.fields[1].datatype = sensor_msgs::PointField::FLOAT32; ros_cloud.fields[1].count = 1; ros_cloud.fields[2].name = "z"; ros_cloud.fields[2].offset = 8; ros_cloud.fields[2].datatype = sensor_msgs::PointField::FLOAT32; ros_cloud.fields[2].count = 1; // 设置ROS消息对象的data属性 ros_cloud.data = std::vector<uint8_t>(ros_cloud.point_step * pcl_cloud.size()); memcpy(&ros_cloud.data[0], pcl_cloud.points.data(), ros_cloud.data.size()); // 创建一个ROS话题发布者,并发布ROS消息对象 ros::Publisher pub = nh.advertise<sensor_msgs::PointCloud2>("ros_cloud_topic", 1); pub.publish(ros_cloud); // 进入ROS循环 ros::spin(); return 0; } ```
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值