在rviz中可视化通过RGBD图像合成的点云,并存储成pcd文件

近期,我参考高翔博士的“一起学RGBD-SLAM”教程入门视觉slam。

我合成点云的方法与高博不同。高博是通过存放在本地的彩色图和深度图合成点云;我是通过realsense D435在线采集彩色图和深度图,再合成点云,然后通过/topic把点云发布出来。

代码编译成功后,打开rviz添加pointcloud2选项卡,当我订阅合成点云时,可视化失败,选项卡报错:

1)throw up 292485 points;

解读:通过  rostopic echo /pointcloud_topic  读取相机节点发布的原始点云的相关数据,可以发现每一帧原始点云的点数量为307200。可以猜测由于某种原因,系统把每一帧合成点云的数据都丢弃了。

原因:我事先给定合成点云的大小为,height = 480,width = 640. 然而在合成点云的过程中,剔除了部分违法值(深度数值无穷大或无穷小或不存在),由此导致合成点云的点数量与指定的点数量不匹配,合成点云的数据因此被丢弃。

2)transform xxxxx;

解读:通过  rostopic echo /pointcloud_topic  ,发现原始点云数据具有如下信息,

header: 
  seq: 50114
  stamp: 
    secs: 1528439158
    nsecs: 557543003
  frame_id: "camera_color_optical_frame"

由此推断,合成点云缺失参考坐标系header.frame_id。点云中点的XYZ属性是相对于某个坐标系来描述的,因此,需要指定点云的参考坐标系。

经过上述分析后,着手用代码解决问题。以下为main函数内的代码片段,仅供参考。  

  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
sensor_msgs::PointCloud2 pub_pointcloud;


// 合成点云的代码与高博一致 while (ros::ok()) { // 遍历深度图 for (int m = 0; m < depth_pic.rows; m++){ for (int n = 0; n < depth_pic.cols; n++){ // 获取深度图中(m,n)处的值 float d = depth_pic.ptr<float>(m)[n]; //ushort d = depth_pic.ptr<ushort>(m)[n]; // d 可能没有值,若如此,跳过此点 if (d == 0) continue; // d 存在值,则向点云增加一个点 pcl::PointXYZRGB p; // 计算这个点的空间坐标 p.z = double(d) / camera_factor; p.x = (n - camera_cx) * p.z / camera_fx; p.y = (m - camera_cy) * p.z / camera_fy; // 从rgb图像中获取它的颜色 // rgb是三通道的BGR格式图,所以按下面的顺序获取颜色 p.b = color_pic.ptr<uchar>(m)[n*3]; p.g = color_pic.ptr<uchar>(m)[n*3+1]; p.r = color_pic.ptr<uchar>(m)[n*3+2]; // 把p加入到点云中 cloud->points.push_back( p ); } } // 设置点云属性,采用无序的排列方法存储点云 cloud->height = 1; cloud->width = cloud->points.size(); ROS_INFO("point cloud size = %d",cloud->width); cloud->is_dense = false;

// pcl::toROSMsg()将pcl数据类型转换成ros数据类型 pcl::toROSMsg(
*cloud,pub_pointcloud);
// 给定参考坐标系,在已有的相机tf中选取一个 pub_pointcloud.header.frame_id
= "camera_color_optical_frame"; pub_pointcloud.header.stamp = ros::Time::now();

// 用pcd存储合成点云 pcl::io::savePCDFile(
"./pointcloud.pcd", pub_pointcloud);
// 发布合成点云 pointcloud_publisher.publish(pub_pointcloud);
}

我参照高博的代码,将合成点云存储成pcd文件时遇到如下报错:

[ INFO] [1528442016.931874649]: point cloud size = 0
terminate called after throwing an instance of 'pcl::IOException'
  what():  : [pcl::PCDWriter::writeASCII] Input point cloud has no data!
Aborted (core dumped)

经过多方查找,摸索了一步trick,分享给大家。真实报错原因仍未查明,期待前辈的指点

高博的源代码如下所示,里面的cloud是pcl的数据类型,

pcl::io::savePCDFile( "./pointcloud.pcd", *cloud );  。

我的源代码如以上所示,先通过 pcl::toROSMsg() 将pcl的数据类型转换成ros的数据类型,再写入pcd中,即可跳过报错。

猜你喜欢

转载自www.cnblogs.com/gdut-gordon/p/9155662.html