情况说明
使用以下命令,一般情况下,是可以直接从bag包中将指定的点云话题数据按时间戳保存成pcd的:
rosrun pcl_ros bag_to_pcd <input_file.bag> <topic> <output_directory>
过程:
结果:
但是我在通过pcl_viewer命令查看点云时,遇到了奇怪的问题:该命令执行时,命令行窗口并无报错,但是可视化窗口没有弹出来,无法查看点云。
情况分析
首先,将pcd在VsCode中打开,查看其具体内容:
这里选择open anyway继续即可, 然后得到以下内容:
在这里发现FIELDS字段有些奇怪,速腾的点云应该是XYZIRT格式,但这里自动保存的PCD多出了好几个“_”的字段。
接下来,我查找了速腾的github仓库中发布点云话题时所做的具体改动,发现他们是这样做的:
即在sensor_msgs::PointCloud2类型中又添加了几个需要的字段。
而bag_to_pcd命令在提取指定话题的点云进行保存时,是这样做的(可以在官网的bag_to_pcd查看):
这也对应上了bag_to_pcd保存时,输出的Got xxx Data points in frame xxx on topic xxx with the following fields: x y z intensity ring timestamp, 说明读取字段时没有问题。那么推测可能是在保存时出现了问题。
验证
为了验证是不是保存时的问题,我写了一段C++ 读取bag包指定点云话题并进行保存的代码,
关键内容如下:
rosbag::Bag bag;
bag.open(file_path);
rosbag::View view(bag, rosbag::TopicQuery(topic));
std::cout << "frame of "<< topic <<" is "<< view.size() << std::endl;
auto it = view.begin();
sensor_msgs::PointCloud2ConstPtr msg = it->instantiate<sensor_msgs::PointCloud2>();
std::cout << "msg time = " << msg->header.stamp << std::endl;
sensor_msgs::PointCloud2 cloud_t;
std::cout << "get cloud size = "<< cloud->size() << std::endl;
cloud_t = *msg;
pcl::io::savePCDFile (save_name, cloud_t //Eigen::Vector4f::Zero (), Eigen::Quaternionf::Identity (), true
);
这里对官网的读取和保存方式简化了下,验证的结论是:==当pcl::io::savePCDFile
中,加上//Eigen::Vector4f::Zero (), Eigen::Quaternionf::Identity (), true
时, 保存下来的pcd中FIELDS中就会多出来几个“_”的字段。将true改为false,或者直接pcl::io::savePCDFile (save_name, cloud_t
, 保存下来的pcd则是正常的,如下所示:
pcl_viewer 也能打开该pcd了:
结论
根据对pcl::io::savePCDFile用法的查阅,该参数的含义为:
如果为true,则PCD文件将以二进制格式保存。如果为false,则默认为ASCII格式(默认)。
但是,bag_to_pcd的用法中,似乎还没有参数可以指定pcd的保存格式,看其源码中,这部分是写死为true的。
所以目前我的解决办法是写一个c++代码来实现速腾XYZIRT格式点云的提取。当然,也可以考虑改掉自己环境中bag_to_pcd.cpp源码中相关的部分,然后重新编译。
如果小伙伴们有更好的方式来简便地解决这个问题,欢迎交流哈!