PCL提供了几种方法来可视化点云,其中最简单的方法是通过点云查看器。
目的
创建一个节点用来订阅sensor_msgs/PointCloud2
,这个节点会使用库中的cloud_viewer
(basic)来显示sensor_msgs/PointCloud2
。
代码
源文件pcl_visualize.cpp:
#include <iostream>
#include <ros/ros.h>
#include <pcl/visualization/cloud_viewer.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl_conversions/pcl_conversions.h>
class cloudHandler
{
public:
cloudHandler()
: viewer("Cloud Viewer")
{
pcl_sub = nh.subscribe("pcl_output", 10, &cloudHandler::cloudCB, this);
viewer_timer = nh.createTimer(ros::Duration(0.1), &cloudHandler::timerCB, this);
}
void cloudCB(const sensor_msgs::PointCloud2 &input)
{
pcl::PointCloud<pcl::PointXYZ> cloud;
pcl::fromROSMsg(input, cloud);
viewer.showCloud(cloud.makeShared());
}
void timerCB(const ros::TimerEvent&)
{
if (viewer.wasStopped())
{
ros::shutdown();
}
}
protected:
ros::NodeHandle nh;
ros::Subscriber pcl_sub;
pcl::visualization::CloudViewer viewer;
ros::Timer viewer_timer;
};
main (int argc, char **argv)
{
ros::init (argc, argv, "pcl_visualize");
cloudHandler handler;
ros::spin();
return 0;
}
解析
本实例中,不同于使用全局变量,所有的函数都封装在一个类中,这样能提供一个使用回调函数分享变量的简洁方式。
通过默认的构造函数隐式地初始化节点句柄,它可以自动调用初始化列表中遗漏的对象。
初始化完成后,用一个与窗口名字相对应的字符串来初始化云句柄的显示。
设置订阅者接收pcl_output
主题。
设置一个定时器,它每隔100ms会触发一次回调函数,用来周期性地检查窗口是否已经关闭,如果已经关闭,则终止代码的运行。
cloudHandler()
: viewer("Cloud Viewer")
{
pcl_sub = nh.subscribe("pcl_output", 10, &cloudHandler::cloudCB, this);
viewer_timer = nh.createTimer(ros::Duration(0.1), &cloudHandler::timerCB, this);
}
回调函数,PCL点云通过showCloud
函数直接传递给查看器,查看器会自动更新显示:
void cloudCB(const sensor_msgs::PointCloud2 &input)
{
pcl::PointCloud<pcl::PointXYZ> cloud;
pcl::fromROSMsg(input, cloud);
viewer.showCloud(cloud.makeShared());
}
回调函数通过一个ROS定时器每隔100ms调用一次,如果查看器关闭了,则终止节点:
void timerCB(const ros::TimerEvent&)
{
if (viewer.wasStopped())
{
ros::shutdown();
}
}
运行
roscore
roscd chapter6_tutorials/data
rosrun chapter6_tutorials pcl_read
rosrun chapter6_tutorials pcl_visualize
启动的窗口如下:
鼠标可以用来在3D视图中移动;组合shift键可以缩放图像,组合control键,可以旋转图像;按下h键可在当前终端打印帮助文档。