如何在QTVTK Widget上实时可视化sensor_msgs/PointCloud2而非读取.pcd文件
实时在QTVTK Widget可视化sensor_msgs/PointCloud2数据的修改方案
需求说明
需要将现有读取本地PCD文件的代码,修改为实时可视化已接收到的sensor_msgs/PointCloud2数据,基于QTVTK Widget和PCL库实现。
原代码(读取PCD文件版本)
void MainWindow::imageShowLIDAR( const sensor_msgs::PointCloud2& msg) { //std::cout << "carico file" << std::endl; std::cout << "imageshow lidar initiated" << std::endl; cloud_pcl.reset (new PointCloudT); cloud_pcl->resize (200); red = 128; green = 128; blue = 128; pcl::io::loadPCDFile("/home/rack_dl/RCEDS_V5/Data/pcl1.pcd", *cloud_pcl); //pcl::io::loadPCDFile("/home/rack_dl/RCEDS_V5/Data/Reg.pcd", *cloud_pcl); for (auto& point: *cloud_pcl) { //point.x = 1024 * rand () / (RAND_MAX + 1.0f); //point.y = 1024 * rand () / (RAND_MAX + 1.0f); //point.z = 1024 * rand () / (RAND_MAX + 1.0f); point.r = red; point.g = green; point.b = blue; } viewer_pcl.reset(new pcl::visualization::PCLVisualizer("viewer_pcl", false)); //Set viewer settings viewer_pcl->addCoordinateSystem(3.0, "coordinate"); viewer_pcl->setShowFPS(false); viewer_pcl->setBackgroundColor(0.0, 0.0, 0.0, 0); //viewer_pcl->setCameraPosition(0.0, 0.0, 30.0, 0.0, 1.0, 0.0, 0); ui.LIDAR_Widget->SetRenderWindow(viewer_pcl->getRenderWindow()); viewer_pcl->setupInteractor(ui.LIDAR_Widget->GetInteractor(), ui.LIDAR_Widget->GetRenderWindow()); viewer_pcl->addPointCloud (cloud_pcl, "cloud"); viewer_pcl->resetCamera (); ui.LIDAR_Widget->update(); }
修改步骤与核心要点
- 替换点云来源:用
pcl::fromROSMsg将传入的sensor_msgs/PointCloud2消息转换为PCL格式的点云,替代原有的loadPCDFile读取本地文件逻辑。 - 复用PCLVisualizer:将
viewer_pcl声明为MainWindow类的成员变量,仅在类构造函数中初始化一次可视化窗口、坐标系、背景等基础设置,避免每次回调重复创建导致的性能问题和显示异常。 - 增量更新点云:在回调函数中,检查点云"cloud"是否已存在,存在则调用
updatePointCloud更新数据,不存在再调用addPointCloud添加,提升实时性。 - 保留颜色配置:如果需要统一设置点云颜色,继续保留遍历点云设置RGB的逻辑;若原消息已包含颜色信息,可直接省略该步骤。
修改后的完整代码
1. 在MainWindow类头文件中添加成员变量
class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void imageShowLIDAR(const sensor_msgs::PointCloud2& msg); private: Ui::MainWindow *ui; pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_pcl; boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer_pcl; int red, green, blue; };
2. 在MainWindow构造函数中初始化可视化器
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // 初始化点云指针 cloud_pcl.reset(new pcl::PointCloud<pcl::PointXYZRGB>()); // 初始化可视化器 viewer_pcl.reset(new pcl::visualization::PCLVisualizer("viewer_pcl", false)); // 设置可视化器基础参数 viewer_pcl->addCoordinateSystem(3.0, "coordinate"); viewer_pcl->setShowFPS(false); viewer_pcl->setBackgroundColor(0.0, 0.0, 0.0, 0); // 关联QTVTK Widget ui->LIDAR_Widget->SetRenderWindow(viewer_pcl->getRenderWindow()); viewer_pcl->setupInteractor(ui->LIDAR_Widget->GetInteractor(), ui->LIDAR_Widget->GetRenderWindow()); red = 128; green = 128; blue = 128; }
3. 修改后的imageShowLIDAR回调函数
void MainWindow::imageShowLIDAR(const sensor_msgs::PointCloud2& msg) { std::cout << "imageshow lidar initiated" << std::endl; // 将ROS消息转换为PCL点云 pcl::fromROSMsg(msg, *cloud_pcl); // 统一设置点云颜色(如果不需要可注释) for (auto& point : *cloud_pcl) { point.r = red; point.g = green; point.b = blue; } // 更新点云:存在则更新,不存在则添加 if (viewer_pcl->contains("cloud")) { viewer_pcl->updatePointCloud(cloud_pcl, "cloud"); } else { viewer_pcl->addPointCloud(cloud_pcl, "cloud"); viewer_pcl->resetCamera(); // 仅第一次添加时重置相机视角 } // 刷新QTVTK Widget ui->LIDAR_Widget->update(); }
注意事项
- 确保项目已正确链接PCL库和ROS相关库(如
roscpp、sensor_msgs)。 - 如果点云数据量较大,可考虑在回调中添加线程处理,避免阻塞UI线程。
- 若需要保留相机视角,不要每次回调都调用
resetCamera,仅在首次初始化时调用即可。
内容的提问来源于stack exchange,提问作者Zaid khan
相关产品推荐
相关产品推荐

