☰
RViz嵌入Qt的机器人上位机3D可视化界面开发实战
2026/10/24 1:45:24 网站建设 项目流程

简介:机器人上位机开发中,激光雷达点云、地图构建、实时位姿与导航路径等数据的直观呈现,是提升调试与交付效率的关键环节。ROS生态中的RViz作为跨平台3D可视化框架,提供了强大的场景渲染能力,而将其以组件形式嵌入Qt窗口,则能构建出面向业务场景的自定义交互界面。RViz本质上是基于Qt构建的可组合类库,通过VisualizationManager与RenderPanel的协作,开发者可在自有程序中直接管理显示插件、话题订阅与视图交互,无需依赖独立进程。这种嵌入方案缩短了数据链路,保留了RViz完整的显示逻辑,同时支持工具栏、状态栏与业务按钮的灵活定制,广泛应用于机器人产品监控、导航联调及客户演示场景。本文以一个Linux环境下的完整Demo为主线,系统拆解了从环境配置、CMake工程组织到面板封装、动态视角控制的实施细节,为ROS/Qt混合开发提供可复用的工程参考。 做机器人上位机开发,最绕不开的一件事就是看数据。激光雷达的扫描、地图构建的结果、机器人的实时位姿、导航规划的路径,这些东西用文本看毫无意义,必须放到三维场景里才直观。ROS生态里现成的方案就是RViz。但问题来了:你自己调试的时候开一个RViz窗口完全没问题,给客户演示或者做成产品的时候,总不能让人家在一个光秃秃的标准RViz窗口里点来点去吧。所以我做了这个rviz_demo_qt项目,目标很直接:在Linux环境下,把ROS的RViz显示能力完整嵌到Qt自绘的界面里,做一个带自定义工具栏、底栏状态和业务按钮的上位机Demo。本文把这套东西从原理到实现完整拆一遍,适合刚接触ROS和Qt混合开发的人,也适合想快速把RViz集成进自己产品里的老手。

1. 项目设计思路:为什么要把RViz嵌进Qt界面里

1.1 独立RViz窗口的痛点:调试凑合,交付不行

先说这个项目解决的第一个问题。刚开始做机器人开发的同学,往往习惯在终端里敲rosrun rviz rviz打开一个独立窗口,然后手动添加Display、选话题、调视角。这种方式在算法调试阶段完全够用,但一旦进入联调或者产品化阶段,问题马上暴露出来。

第一,信息太分散。一台机器上可能有相机画面、激光点云、导航路径、机械臂关节状态好几路数据,每个数据开一个窗口,屏幕根本摆不下。底下的操作员要在四五个窗口之间来回切,注意力早就被撕碎了。第二,界面无法定制。标准RViz的左边是显示树,上面是工具栏,右边是视图,这是为工程师设计的布局,客户和现场操作员根本看不懂。他们关心的只是"当前小车在哪个位置、有没有撞到障碍物、任务跑完没有"。第三,交互逻辑是写死的。想在RViz里加一个"一键回位"的按钮,或者双击某个区域执行一个动作,原生RViz做不到,你得去改它的源码。

换句话说,独立RViz窗口适合开发期,不适合交付期。这个Demo要做的,就是把RViz变成一个可复用的组件,塞进自己的Qt界面里,让界面长成自己希望的样子。

1.2 方案选型:直接嵌入RViz,而不是另做3D渲染

明确了目标之后,实现方案其实有几种。第一种,外面开一个特殊窗口,通过ROS话题、Service或者Action去控制独立RViz的视角、显示内容和刷新行为。这个方案能做到一定程度的联动,但本质上还是一个单独窗口,界面定制能力有限。第二种,在Qt工程里直接用OSG或者OpenGL把机器人模型和点云重新画一遍。这个方案自由度最高,但工程量巨大,光是处理URDF模型的加载、几何体解析、激光数据转换成点云渲染,就够写几个月的,而且后续ROS版本升级时全部要自己维护。第三种,也就是我最终选的方案:直接把RViz作为Qt库嵌入到自己的程序里。

这个选择背后有一个很多人可能没注意到的点:RViz本身不是独立应用,它是一套基于Qt组件构建的框架。你平时看到的rosrun rviz rviz启动的只是一个入口程序,里面真正干活的是rviz::VisualizationManager、rviz::RenderPanel这一套类。这些类全部是公开的C++ API,可以被任何Qt程序 include 之后直接使用。这样做的好处有三个:数据链路最短,RViz直接订阅你程序里的ROS话题,没有中间转发层;界面复用度最高,RViz里那些Grid、RobotModel、LaserScan的显示逻辑全部保留;第三,学习成本最低,你只需要掌握几个核心类的初始化顺序,其他事情RViz内部帮你做完了。

当然,嵌入方案也有代价。最典型的代价是工程构建变复杂了,catkin、Qt、rviz三套依赖要理顺,版本之间还有兼容性问题。后面第3节会专门讲怎么把这些坑填平。

2. 核心原理解读:RViz其实是站在Qt肩膀上的一套组件

2.1 RViz不是独立应用,而是一套可组合的Qt类库

如果你看过RViz的源码结构,你会发现它本质上是一个Qt Widget集合。打开/opt/ros/noetic/include/rviz目录,里面躺着几十个类,分工非常明确。

最顶层的是VisualizationFrame,它就是我们平时看到的那个RViz主窗口,负责组合菜单栏、工具栏、显示树面板、视图面板和中间的渲染视图。VisualizationFrame内部有两个核心对象:VisualizationManager负责管理所有Display的创建、配置、更新,是实际的大脑;RenderPanel则是一个继承自QWidget的3D渲染视图,把所有三维内容画在里面。此外还有DisplayGroupPanel、DisplaysPanel这些面板类,负责在左侧显示"Display"树和"Tool"树。

这个结构意味着,如果你只想嵌入一个3D视图,不想要左边的显示树,那么完全可以不实例化DisplaysPanel,只拿RenderPanel和VisualizationManager就行。反过来,如果你想完整保留RViz的显示树配置能力,也可以把DisplaysPanel加进你的布局。这就是我在项目里采取的做法:主界面是自己画的 Qt Widget,中间是一个RvizPanel,左侧保留了一个可折叠的显示树面板。

2.2 嵌入的关键:VisualizationManager和RenderPanel如何协作

把RViz嵌入Qt界面的核心,就是理清VisualizationManager、RenderPanel、QApplication三者之间的关系。

RenderPanel是一个渲染窗口,它内部封装了OGRE(三维渲染引擎)的场景管理对象和渲染窗口,对外提供initialize(sceneManager, visualizationManager)方法完成绑定。VisualizationManager则是所有Display的逻辑管理者,它不直接负责渲染,而是管理一个场景树,然后通知RenderPanel去刷新。两者是互相引用、协作运转的关系。

初始化顺序很关键,一旦搞反,界面会黑屏或者直接崩溃。标准顺序是:

render_panel_ = new rviz::RenderPanel(this); visualization_manager_ = new rviz::VisualizationManager(render_panel_); render_panel_->initialize(visualization_manager_->getSceneManager(), visualization_manager_); visualization_manager_->initialize(); visualization_manager_->startUpdate();

第三步里,getSceneManager()返回的是OGRE的场景管理器,RenderPanel拿到它之后才能知道要渲染什么场景。完成这四步之后,RenderPanel就会进入持续刷新的状态,ROS话题里过来的数据会自动更新到画面上。

这里有个细节值得注意:startUpdate()必须在initialize()之后调用,否则Display对象可能在被添加到场景时找不到有效的渲染上下文。我自己刚开始写的时候就把startUpdate放到了initialize前面,结果整个窗口一片漆黑,一点报错都没有,排查了很久才反应过来。

2.3 版本选型:ROS1还是ROS2,Qt5还是Qt6

做这个Demo之前,先要确认你机器上的ROS和Qt版本,因为这会直接影响代码里 include 的头文件和类名。

如果你用的是 ROS1(比如 Noetic),那嵌入的头文件是rviz/visualization_manager.h、rviz/render_panel.h,命名空间是rviz。ROS1的RViz是绑定Qt5的,所以工程里必须用 Qt5 的 CMake 模块,也就是Qt5Widgets、Qt5Core这一组。如果你用Qt6去编译ROS1的rviz,会直接报一堆头文件不兼容的错误,这条路不用试,行不通。

如果你用的是 ROS2(比如 Humble),那嵌入的是 RViz2,头文件变成rviz_common/visualization_manager.hpp、rviz_common/render_panel.hpp,命名空间是rviz_common。RViz2底层虽然还是一样的架构,但类名和初始化流程做了一些调整,直接照搬ROS1的代码编不过。

我建议,想快速体验嵌入开发的朋友优先选 ROS1 Noetic + Ubuntu 20.04,因为网上资料多、API稳定、踩坑记录齐全。如果你已经装了 Ubuntu 22.04,那就用 ROS2 Humble + Qt5,也完全可以跑通,只是个别API要自己对照官方文档改一改。项目名里的"rviz_demo"这个名字其实透露了作者的版本倾向——经典RViz,也就是ROS1那边的东西。

3. 实操过程:从空工程到可运行的RViz+Qt混合界面

3.1 环境准备:Ubuntu上的ROS和Qt安装

先说环境。我用的是一台Ubuntu 22.04的机器,装了ROS2 Humble。如果你还没有ROS环境,最快的办法是用网上常见的一键安装脚本,它会帮你处理源、密钥、依赖这些繁琐步骤,装完之后source /opt/ros/humble/setup.bash就能用。当然,手动安装也不难,官方文档写得很清楚,按步骤执行就行。

Qt这边,我用了Qt 5.15.2,因为ROS系的rviz跟Qt5绑得最稳。安装方式可以直接用Qt官方在线安装器,不过在国内网络环境下下载速度很慢,建议在安装器里配置国内的镜像源,把https://download.qt.io替换成国内镜像地址。装的时候只需要勾选gcc_64这个桌面套件,不需要Android和iOS那些。装完之后,在CMake里通过CMAKE_PREFIX_PATH指向你的Qt安装目录,或者直接把 Qt 的bin目录加进PATH。

装完这两样,先做一个最基本的验证:在终端执行rviz2(或者ROS1时代的rviz),如果能正常弹出窗口,说明RViz本身没毛病,后面嵌入式开发才有的搞。这里建议顺手检查一下显卡渲染能力,执行glxinfo | grep renderer,看看输出的是你的真实显卡还是llvmpipe(软件渲染)。如果是llvmpipe,说明图形加速没开,嵌入之后大概率会卡顿,后面第4节会专门说这个问题。

3.2 用CMake+catkin组织工程

嵌入RViz的程序,工程构建不建议用纯 qmake,因为要链接ROS的库和消息头文件,用catkin系列工具会更顺手。这里我以ROS2 Humble为例,给出一个能跑的CMakeLists.txt,ROS1用户把rclcpp换成roscpp即可。

cmake_minimum_required(VERSION 3.8) project(rviz_demo_qt) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) if(CMAKE_COMPILER_IS_GNUCXX) add_compile_options(-Wall -Wextra) endif() find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(rviz_common REQUIRED) find_package(rviz_rendering REQUIRED) find_package(Qt5 REQUIRED COMPONENTS Core Widgets) add_executable(rviz_demo_qt src/main.cpp src/main_window.cpp src/rviz_panel.cpp ) target_include_directories(rviz_demo_qt PRIVATE src ${Qt5Widgets_INCLUDE_DIRS} ) # 关键:让Qt的moc工具处理含 Q_OBJECT 的头文件 set_target_properties(rviz_demo_qt PROPERTIES AUTOMOC ON ) target_link_libraries(rviz_demo_qt rclcpp::rclcpp rviz_common::rviz_common rviz_rendering::rviz_rendering Qt5::Widgets ) install(TARGETS rviz_demo_qt RUNTIME DESTINATION lib/${PROJECT_NAME} ) ament_package()

这里有一个特别容易踩的坑:AUTOMOC必须打开。因为我们在main_window.h和rviz_panel.h里用了Q_OBJECT宏,这个宏需要Qt的元对象编译器(moc)生成额外的代码,如果不开启AUTOMOC,编译会报一堆vtable for MainWindow之类的链接错误。新手第一次从纯Qt转到ROS工程里,最容易在这个地方卡半小时。

3.3 写嵌入面板:封装一个RvizPanel类

嵌入的核心代码我封装在RvizPanel类里,这样主窗口只用关心布局,不用关心RViz初始化细节。先看头文件:

// rviz_panel.h #ifndef RVIZ_PANEL_H #define RVIZ_PANEL_H #include <QWidget> namespace rviz_common { class VisualizationManager; } namespace rviz_common { class RenderPanel; } class RvizPanel : public QWidget { Q_OBJECT public: explicit RvizPanel(QWidget* parent = nullptr); ~RvizPanel() override; void setFixedFrame(const QString& frame); void setViewType(const QString& type); rviz_common::VisualizationManager* manager() const { return manager_; } private: rviz_common::RenderPanel* render_panel_; rviz_common::VisualizationManager* manager_; }; #endif

实现文件:

// rviz_panel.cpp #include "rviz_panel.h" #include <QHBoxLayout> #include <rviz_common/render_panel.hpp> #include <rviz_common/visualization_manager.hpp> #include <rviz_common/display.hpp> #include <rviz_common/view_manager.hpp> #include <rviz_common/view_controller.hpp> RvizPanel::RvizPanel(QWidget* parent) : QWidget(parent) , render_panel_(nullptr) , manager_(nullptr) { auto* layout = new QHBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); render_panel_ = new rviz_common::RenderPanel(this); layout->addWidget(render_panel_); manager_ = new rviz_common::VisualizationManager(render_panel_); render_panel_->initialize(manager_->getSceneManager(), manager_); manager_->initialize(); manager_->startUpdate(); } RvizPanel::~RvizPanel() { delete manager_; delete render_panel_; } void RvizPanel::setFixedFrame(const QString& frame) { manager_->setFixedFrame(frame); } void RvizPanel::setViewType(const QString& type) { auto* view_controller = manager_->getViewManager()->getCurrent(); if (view_controller && view_controller->getClassId() != type) { manager_->getViewManager()->setCurrentViewControllerType(type); } }

这段代码是整个Demo的地基。它的核心逻辑就三件事:创建RenderPanel并加入布局;创建VisualizationManager并让两者互相绑定;启动更新循环。做完这三步,你就拥有了一个能实时反映ROS话题数据的3D窗口。

析构函数里的顺序要特别小心,必须是先删manager_,再删render_panel_。因为RenderPanel内部引用着OGRE的渲染上下文,而VisualizationManager在析构时会释放Display和场景节点,如果釜底抽薪先把渲染面板删了,manager析构时访问的场景指针就成了悬空指针,Segmentation fault就来了。

3.4 主窗口布局和视角控制

有了RvizPanel,主窗口就简单了。我搭了一个QMainWindow,中间放RvizPanel,上面自己画了一个QToolBar,左侧加了几个按钮用来切换视角和添加显示项。窗口结构如下:

// main_window.cpp(节选) #include "main_window.h" #include <QToolBar> #include <QStatusBar> #include <QMenuBar> #include <QMessageBox> MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { setWindowTitle("Robot Monitor - rviz_demo_qt"); resize(1280, 800); rviz_panel_ = new RvizPanel(this); setCentralWidget(rviz_panel_); // 自定义工具栏 auto* toolbar = addToolBar("View"); toolbar->setMovable(false); QAction* top_action = toolbar->addAction("Top View"); connect(top_action, &QAction::triggered, this, [this]() { rviz_panel_->setViewType("rviz/TopViewOrtho"); }); QAction* orbit_action = toolbar->addAction("Orbit View"); connect(orbit_action, &QAction::triggered, this, [this]() { rviz_panel_->setViewType("rviz/Orbit"); }); // 左侧显示树面板(可选) addDockWidget(Qt::LeftDockWidgetArea, createDisplaysDock()); statusBar()->showMessage("Ready"); } QWidget* MainWindow::createDisplaysDock() { // RViz2中也可以直接使用 rviz_common::DisplaysPanel 类 // 这里为了控制篇幅,demo里简化成先不显示树,只保留中间视图 return nullptr; }

关于视角控制,代码里用的是getViewManager()->setCurrentViewControllerType(),它的作用是切换当前的视图控制器类型。TopViewOrtho是俯视的正交视图,适合看导航地图;Orbit是轨道相机,适合看机器人模型和传感器数据。这两个类型名称是RViz内置的,不需要额外注册。

如果你希望鼠标在3D视图里能正常旋转、平移、缩放,需要在VisualizationManager初始化之后设置当前的工具(Tool)。默认情况下管理器可能没有选中任何工具,这时候鼠标在视图里是不响应的。可以在RvizPanel构造函数末尾加一行:

manager_->getToolManager()->setCurrentTool( manager_->getToolManager()->getTool("Move Camera"));

这样鼠标左键拖动就是旋转视角,右键拖动就是缩放,中键拖动就是平移。这个细节不写的话,你运行起来会发现窗口是黑的或者画面不动,容易误以为程序卡死了。

3.5 添加机器人显示和传感器话题

窗口和工具准备好之后,下一步是往场景里添加数据。RViz中一切可见元素都是Display对象,通过VisualizationManager的createDisplay()创建,你可以把它理解为"往场景里添加一个图层"。

void MainWindow::addRobotModel() { auto* display = rviz_panel_->manager()->createDisplay( "rviz_common/RobotModelDisplay", "robot model", true); // 设置RobotModel从参数服务器读取的URDF描述名 display->subProp("Robot Description")->setValue("robot_description"); } void MainWindow::addLaserScan(const QString& topic) { auto* display = rviz_panel_->manager()->createDisplay( "rviz_common/LaserScanDisplay", "laser scan", true); display->setTopic(topic, "sensor_msgs/msg/LaserScan"); }

createDisplay的第一个参数是显示类在插件系统中的ID。ROS2里一般写成rviz_common/XXXXDisplay这种形式,ROS1里写成rviz/XXXX。如果类ID写错了,createDisplay会返回nullptr,这时候程序不会报错,但场景里什么都看不到。所以每次创建完Display,建议加一句判空:

if (display) { display->subProp("Topic")->setValue(topic); } else { qWarning() << "Failed to create display, check plugin ID"; }

要验证整个Demo是否工作,最简单的办法是启动一个robot_state_publisher发布机器人的TF和模型,再发布一组模拟激光数据。终端里跑:

source /opt/ros/humble/setup.bash ros2 run robot_state_publisher robot_state_publisher --ros-args -p robot_description:="$(xacro your_robot.urdf.xacro)" ros2 run tf2_ros static_transform_publisher 0 0 0 0 0 0 map base_link ros2 topic pub -r 10 /scan sensor_msgs/msg/LaserScan "{range_min: 0.1, range_max: 10.0, angle_min: 0.0, angle_max: 6.28, angle_increment: 0.01, ranges: [...]}"

话题数据一旦开始流动,嵌入的面板里就能看到小车模型和一圈点云,跟独立RViz里看到的一模一样,但此时它们已经在你自定义的Qt界面里了。

4. 常见问题与排查实录

4.1 CMake或编译阶段的问题

嵌入RViz的常见问题,第一个阶段就卡在编译上。

问题1:find_package找不到rviz相关包。这一般是因为你没有source ROS环境就直接执行了cmake。在终端里source /opt/ros/humble/setup.bash之后再重新配置。还可以检查一下CMAKE_PREFIX_PATH,确认它包含了/opt/ros/humble。

问题2:Qt5::Widgets找不到或者版本不对。Ubuntu上一般执行sudo apt install qtbase5-dev就能解决。如果你是用Qt官方安装器装的Qt5,那需要在CMake里加一行set(CMAKE_PREFIX_PATH "/home/yourname/Qt/5.15.2/gcc_64"),让CMake能找到Qt的CMake配置文件。

问题3:链接阶段报undefined reference to vtable for MainWindow。这是AUTOMOC没开导致的。记住,任何包含Q_OBJECT宏的头文件都要被moc处理。在CMakeLists.txt里打开AUTOMOC ON之后,Qt的moc会自动处理你工程里的头文件,不需要手动跑moc命令。

我见过很多初学者在这类编译问题上花掉一整天,其实根源就一句话:ROS的CMake和Qt的CMake模块混在一起时,顺序和变量要理清楚,缺一个就全乱套。

4.2 界面黑屏和渲染着色器报错

编译过了,运行起来界面却是黑屏,或者终端里刷类似这样的日志:

[error] [1787157672.465148717] [rviz2]: vertex program: rviz/glsl120/indexed_

这个报错非常典型,我在虚拟机和老旧的集成显卡机器上遇到过很多次。它的含义是:RViz的OGRE渲染引擎尝试编译一个GLSL 1.20版本的着色器程序,但当前OpenGL上下文不支持或者驱动实现有问题。GLSL 1.20是OpenGL 2.1时代的着色器语言,按理说现代显卡都支持,问题往往出在渲染环境上。

最常踩的场景是虚拟机。VirtualBox或VMware里默认的显卡驱动是虚拟的,OpenGL支持很弱,跑RViz这种3D应用经常崩。解决办法是给虚拟机开启3D加速,或者在主机上安装真正的显卡驱动后,让虚拟机直通GPU。物理机上黑屏通常是NVIDIA驱动没装对,推荐更新到官方驱动。

如果只是想快速验证代码逻辑,可以用软件渲染临时顶上:

export LIBGL_ALWAYS_SOFTWARE=1 ./rviz_demo_qt

软件渲染能出画面,但帧率很低,转视角会明显卡顿,所以这只适合调试,不适合日常使用。另外,如果你用的是远程桌面或者VNC,也要注意OpenGL上下文是否正常创建,必要时给VNC配置虚拟GL。

仔细看这个问题的本质,它其实不是代码的问题,是运行环境对3D渲染的支持度问题。所以排查顺序应该是:先确认显卡驱动,再确认OpenGL版本,最后才回到代码本身。

4.3 退出崩溃和资源释放顺序

第三个高发问题在程序退出时。你点关闭按钮,界面关了,终端里却报Segmentation fault。

这个崩九成是资源释放顺序没处理好。前面我在RvizPanel的析构函数里特意写了"先删manager_,再删render_panel_",很多人不以为然,觉得析构顺序无所谓,结果就是踩坑。原因是:VisualizationManager内部持有OGRE场景、所有Display对象、ViewManager等资源,它析构时需要访问渲染面板来释放某些渲染资源;如果渲染面板先被销毁,这些资源就成了悬空指针,一碰就崩。

另外还有一个隐藏点:如果主窗口关闭时ROS节点还在跑,也就是rclcpp::shutdown()没有调用,那么析构过程中可能还有回调在访问已经销毁的QWidget,同样会崩。所以合理的关闭逻辑是:

void MainWindow::closeEvent(QCloseEvent* event) { rclcpp::shutdown(); event->accept(); QMainWindow::closeEvent(event); }

这个顺序在Qt里执行得很快,几乎不会让用户感觉到卡顿,但能从根源上避免退出时的悬空访问。如果你在退出时卡了2秒才退出,大概率也是ROS资源没有及时清理。

4.4 一个冷门的坑:QVTKOpenGLWidget的版本冲突

还有一个小众但值得提的问题。RViz底层渲染依赖Qt和OpenGL之间的桥接,ROS1时代的RViz在使用时经常需要设置QVTKOpenGLWidget::setEnableHiDPI(true)之类的高DPI支持选项,否则在2K、4K高分屏上字体会模糊或者画面边缘模糊。ROS2侧虽然做了不少改进,但如果你在Qt工程里同时引入了自己的VTK组件,就要注意VTK版本和RViz内部的VTK版本不能冲突,否则运行时会出现 "Both QVTKOpenGLNativeWidget and QVTKOpenGLWidget ..." 这类OpenGL context冲突。

我的建议是:不要在嵌入RViz的工程里同时混用另一套基于VTK的3D组件。如果确实需要点云以外的二维图表、曲线之类的可视化,优先用Qt自带的QPainter或者QCustomPlot这类纯Qt组件,避免引入第二个3D渲染栈。

5. 扩展方向与个人体会

这个Demo跑通之后,后续能扩展的东西非常多。我在实际项目里做过几个比较有效的改造,分享出来供参考。

第一,把左侧的显示树面板正式加回来。用rviz_common::DisplaysPanel或者其他同类面板,让界面同时具备"自定义外观"和"专业调试入口"两种能力。开启这个面板后,操作人员平时用它看状态,现场调参时可以展开显示树手动调试。第二,在工具栏里加录制和回放按钮,点一下开始录制当前所有话题数据,再点一下停止并保存为rosbag,对现场问题复盘特别管用。第三,对接导航栈,在嵌入的3D视图里用鼠标点击地面,程序发布一个目标点,机器人自动导航过去。RViz原生的"2D Nav Goal"工具就是干这件事的,嵌入后你可以完全控制目标点的发布逻辑,比如加一个确认弹窗或者限定合法区域。

个人实际操作中,我体会最深的一点是:嵌入RViz之后,调试效率不是提升了一点半点。过去调导航算法,要一边开着终端切话题,一边在独立RViz里来回找数据,现在所有数据都集中在同一个界面上,哪里有问题一眼就能看到。尤其是给非技术背景的同事演示的时候,一个干净整洁的自定义界面,比十个标准RViz窗口说服力都强。

最后再分享一个小技巧:如果想让嵌入的RViz启动后自动加载自定义的显示配置,不必像Demo里那样一行行代码创建Display,可以直接把RViz的.rviz配置文件存好,在初始化阶段用manager_->loadDisplayConfig(config_file_path)一键加载,这样你可以在图形界面里把显示效果调到自己满意,保存成文件,然后让代码读这个文件。这也是我建议每个做RViz嵌入开发的人都掌握的方式——先用原生RViz调好,再嵌入程序,不要一上来就写代码配Display,效率差太多了。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询