综述
本文通过参考librviz tutorial,在ubuntu20+ros noetic上开发传感器数据可视化的RVIZ+QT程序。
诚然,可以通过RVIZ上的panel插件功能实现RVIZ和QT的融合,但是只能实现一些简单的QT,并且在一些场合,QT应该是主角,RVIZ只能起到可视化传感器数据的作用,在这种情形下,以RVIZ为主体开发UI会有许多冗余的功能,导致程序灵活性欠缺。
其实,RVIZ可视化传感器数据的功能可以通过librviz直接在程序中实现。
这样,以QT为主体进行开发,可以实现所有QT的功能的同时,调用RVIZ来可视化传感器数据。
QT部分开发
这部分主要讲述关于QT部分的开发。
main函数
由于是以QT为主体,所以主函数里面的主线程应该是QT
#include <QApplication>
#include <ros/ros.h>
#include "myviz.h"
int main(int argc, char **argv)
{
if( !ros::isInitialized() )
{
ros::init( argc, argv, "myviz", ros::init_options::AnonymousName );
}
QApplication app( argc, argv );
MyViz* myviz = new MyViz();
myviz->setGeometry(0, 0, 2000, 1000);
myviz->show();
app.exec();
delete myviz;
}
其中
if( !ros::isInitialized() )
{
ros::init( argc, argv, "myviz", ros::init_options::AnonymousName );
}
是初始化ROS,也是所有的ROS程序都需要的初始化操作。
QApplication app( argc, argv );
MyViz* myviz = new MyViz();
myviz->setGeometry(0, 0, 2000, 1000);
myviz->show();
app.exec();
delete myviz;
第一句是所有QT程序都需要的语句,中间是实例化一个MyViz类,也就是用户自己构建的一个Qt类,用于实现QT功能,app.exec()是把主线程的控制权交给QT,这个也是QT-ROS和ROS-QT的一个很大的区别,前者的主控权在QT,后者的主控权在ROS。
MyViz类开发
这个类包含实现所有功能的代码,包含QT界面开发,RVIZ显示界面的开发,ROS订阅者、发布者开发。
QT界面开发
QLabel* thickness_label = new QLabel( "Line Thickness" );
QSlider* thickness_slider = new QSlider( Qt::Horizontal );
thickness_slider->setMinimum( 1 );
thickness_slider->setMaximum( 100 );
QLabel* cell_size_label = new QLabel( "Cell Size" );
QSlider* cell_size_slider = new QSlider( Qt::Horizontal );
cell_size_slider->setMinimum( 1 );
cell_size_slider->setMaximum( 100 );
QLabel* Topic=new QLabel("TOPIC:");
QLineEdit* Topic_text=new QLineEdit();
QGridLayout* controls_layout = new QGridLayout();
QLabel* Size=new QLabel("Cloud Size");
QSpinBox* size=new QSpinBox();
controls_layout->addWidget( thickness_label, 0, 0 );
controls_layout->addWidget( thickness_slider, 0, 1 );
controls_layout->addWidget( cell_size_label, 0, 2 );
controls_layout->addWidget( cell_size_slider, 0, 3 );
controls_layout->addWidget(Topic,0,4);
controls_layout->addWidget(Topic_text,0,5);
controls_layout->addWidget(Size,0,6);
controls_layout->addWidget(size,0,7);
RVIZ显示模块开发
RVIZ开发主要涉及对librviz几个类的调用,包含rviz::RenderPanel(),rviz::VisualizationManager(),前者是RVIZ在QT上显示的类,后者是实现rviz功能的类。
render_panel_ = new rviz::RenderPanel();
QVBoxLayout* main_layout = new QVBoxLayout;
main_layout->addLayout( controls_layout );
main_layout->addWidget( render_panel_ );
...
manager_ = new rviz::VisualizationManager( render_panel_ );
render_panel_->initialize( manager_->getSceneManager(), manager_ );
manager_->setFixedFrame("world");
manager_->initialize();
manager_->startUpdate();
// Create a Grid display.
grid_ = manager_->createDisplay( "rviz/Grid", "adjustable grid", true );
ROS_ASSERT( grid_ != NULL );
cloud = manager_->createDisplay( "rviz/PointCloud2", "point cloud", true );
ROS_ASSERT( cloud != NULL );
cloud->subProp("Topic")->setValue("/pose_graph/octree");
cloud->subProp("Style")->setValue("Points");
cloud->subProp("Size (Pixels)")->setValue("2");
cloud->subProp("Color Transformer")->setValue("Intensity");
cloud->subProp("Invert Rainbow")->setValue("true");
cloud->subProp("Decay Time")->setValue("1");
// Configure the GridDisplay the way we like it.
grid_->subProp( "Line Style" )->setValue( "Billboards" );
grid_->subProp( "Color" )->setValue( QColor( Qt::yellow ) );
ROS订阅者、发布者实现
即使主线程是QT,这里的订阅者仍然可以像一般的ROS类一样定义回调函数就可以;而发布者的实现需要定义一个线程,在线程中实现发布的功能。
全部代码
链接:https://pan.baidu.com/s/13dxGFnBNy0pGr_uI3WC9hw
提取码:nzze
–来自百度网盘超级会员V4的分享
后记
其实我觉得这部分最让我头疼的不是QT或者librviz代码的书写(当然我的QT水平有限),而是CMakeLists文件的书写,但是好在官文有指导,直接搬下来,看懂之后加上自己的东西就可以。
对于详细的话题能包含什么样的subProp的属性,开发人员可以自己开一个rviz,看看你的话题支持什么样的选项,比如对于sensor_msgs::PointCloud2,它的话题就是"Topic",对于sensor_msgs::Image,它的话题名称就是"Image Topic",如果你写代码的过程中遇到类似于"root->subProp->Topic"的报错,可以考虑看看是不是你的话题对应的消息类型在rviz中的属性名称。