【ROS2学习笔记】RViz 三维可视化

前言

本系列博文是本人的学习笔记,自用为主,不是教程,学习请移步其他大佬的相关教程。前几篇学习资源来自鱼香ROS大佬的详细教程,适合深入学习,但对本人这样的初学者不算友好,后续笔记将以@古月居的ROS2入门21讲为主,侵权即删。

一、学习目标

  1. 搞懂 RViz 的核心作用 ------ 把机器人的 "数字数据" 变成 "看得见的图形"(比如摄像头图像、激光点云)
  2. 掌握 RViz 的基础启动方法和界面核心功能(比如Displays窗口的使用)
  3. 学会 3 类常用传感器的 "仿真 + RViz 可视化":彩色相机、三维相机(RGBD)、激光雷达
  4. 彻底分清 RViz 和 Gazebo 的区别(避免混淆两个工具的用途)
  5. 记住可视化的通用流程:启动数据源(仿真/真实传感器)→ 启动RViz → 添加显示项 → 配置话题/参考系

二、先搞懂:RViz 是什么?为什么需要它?

2.1 一句话定义:机器人的 "眼睛"

RViz(Robot Visualization)是 ROS 官方的三维可视化工具,核心功能是把机器人的各种数据(传感器数据、机器人模型、坐标系、路径等)转换成 "人类能看懂的图形",相当于给开发者装了一双 "看机器人数据的眼睛"。

2.2 为什么需要 RViz?(小白必懂的痛点)

没有 RViz 时,你看到的是这样的 "数据":[0,255,0, 0,255,0, ...](一堆数字,不知道是啥)有了 RViz 后,你看到的是这样的 "图形":一片绿色的草地(数字被渲染成图像)

数据类型 无 RViz(数字 / 文本) 有 RViz(图形化)
摄像头数据 一堆 0-255 的 RGB 数值 彩色图像
激光雷达数据 一堆距离数值(0.5m, 1.2m, ...) 二维激光点组成的 "环境轮廓"
三维相机(RGBD)数据 距离 + RGB 数值组合 带颜色的三维点云(能看到物体的立体形状)
机器人坐标系 文字描述 "base_link 在 world 的 x=1m 处" 彩色坐标轴(红色 x、绿色 y、蓝色 z)

结论:RViz 让机器人开发 "看得见、好调试",不用对着数字猜效果。

三、RViz 基础:启动与界面初识

3.1 启动 RViz(1 行命令)

打开终端,输入以下命令,直接启动 RViz:

复制代码
ros2 run rviz2 rviz2
  • 预期效果:弹出 RViz 窗口,默认是 "空界面"(只有网格背景),左侧有Displays窗口(核心,用来添加显示项)。

3.2 RViz 核心界面介绍(小白必看)

重点关注左侧Displays窗口,所有可视化配置都在这里操作:

界面元素 作用 小白操作场景
Fixed Frame 全局参考坐标系(所有数据都基于这个坐标系显示) 可视化传感器时,通常设为odombase_link
Add按钮 添加要显示的数据类型(如图像、点云、激光) 要显示摄像头图像,就点 Add→选 Image
Displays列表 已添加的显示项,可配置话题、颜色等 选中 Image 项,设置 "Topic" 为/image_raw
Status 显示项状态(绿色√= 正常,红色 ×= 有问题) 红色 × 时,检查参考系或话题是否正确

四、实战:传感器的仿真与 RViz 可视化

要在 RViz 中看到传感器数据,需要先有 "数据源"------ 要么是真实传感器(如 USB 相机),要么是 Gazebo 仿真的传感器。下面以 "Gazebo 仿真" 为例,带大家实现 3 类传感器的可视化。

4.1 实战 1:彩色相机(最常用)

场景需求

在 Gazebo 中仿真一个彩色相机,通过 RViz 看到相机拍摄的虚拟图像。

步骤 1:理解相机仿真插件配置(XACRO 代码)

相机的仿真需要用 Gazebo 的libgazebo_ros_camera.so插件,配置文件在learning_gazebo/urdf/sensors/camera_gazebo.xacro,代码带详细注释:

复制代码
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro">
    <!-- 彩色相机仿真插件配置:挂载到某个link(如camera_link) -->
    <xacro:macro name="camera_gazebo" params="prefix">
        <!-- gazebo标签:关联到相机连杆(prefix_link,比如camera_link) -->
        <gazebo reference="${prefix}_link">
            <!-- 1. sensor标签:定义传感器基本信息 -->
            <sensor type="camera" name="${prefix}_camera">
                <update_rate>30.0</update_rate> <!-- 传感器更新频率:30Hz(每秒拍30张图) -->
                <always_on>true</always_on>     <!-- 始终开启传感器 -->

                <!-- 2. camera标签:配置相机参数(类似真实相机的参数) -->
                <camera name="head">
                    <horizontal_fov>1.3962634</horizontal_fov> <!-- 水平视场角:80度(1.396弧度≈80°) -->
                    <image> <!-- 图像分辨率和格式 -->
                        <width>1280</width>  <!-- 宽度:1280像素 -->
                        <height>720</height> <!-- 高度:720像素(720P) -->
                        <format>R8G8B8</format> <!-- 格式:RGB三通道,每个通道8位(256色) -->
                    </image>
                    <clip> <!-- 相机可视范围(近/远裁剪面) -->
                        <near>0.02</near>  <!-- 最近能拍0.02米(2厘米)内的物体 -->
                        <far>300</far>     <!-- 最远能拍300米内的物体 -->
                    </clip>
                    <noise> <!-- 仿真图像噪声(模拟真实相机的噪点) -->
                        <type>gaussian</type> <!-- 高斯噪声(最常见的噪声类型) -->
                        <mean>0.0</mean>      <!-- 噪声均值:0 -->
                        <stddev>0.007</stddev> <!-- 噪声标准差:0.007(值越小越清晰) -->
                    </noise>
                </camera>

                <!-- 3. plugin标签:加载Gazebo相机插件(核心,让相机发布ROS话题) -->
                <plugin name="gazebo_camera" filename="libgazebo_ros_camera.so">
                    <ros>
                        <!-- 话题重映射:把插件默认的"~/image_raw"重映射为"image_raw"(简化话题名) -->
                        <remapping>~/image_raw:=image_raw</remapping>
                        <!-- 相机内参话题:发布相机参数(如焦距、分辨率,RViz显示图像需要) -->
                        <remapping>~/camera_info:=camera_info</remapping>
                    </ros>
                    <camera_name>${prefix}</camera_name> <!-- 相机名称(标识用) -->
                    <frame_name>${prefix}_link</frame_name> <!-- 相机的坐标系(关联到相机连杆) -->
                    <hack_baseline>0.2</hack_baseline> <!-- 基线(用于立体视觉,单目相机可忽略) -->
                </plugin>
            </sensor>
        </gazebo>
    </xacro:macro>
</robot>
步骤 2:启动相机仿真环境
  1. 打开终端,执行启动命令(加载带相机的机器人模型到 Gazebo):

    复制代码
    ros2 launch learning_gazebo load_mbot_camera_into_gazebo.launch.py
  2. 验证相机话题是否发布(新终端):

    复制代码
    ros2 topic list | grep image  # 查看是否有/image_raw话题
    • 预期输出:/image_raw(相机图像话题)、/camera_info(相机内参话题)。
步骤 3:RViz 可视化相机图像(详细步骤)
  1. 启动 RViz:

    复制代码
    ros2 run rviz2 rviz2
  2. 配置 RViz 显示图像:

    • 第一步:设置Fixed Frame(全局参考系):在Displays窗口顶部,把Fixed Framemap改成odom(或base_link,避免坐标系不匹配导致红色 ×)。
    • 第二步:添加 "Image" 显示项:点击Displays窗口左下角的Add→在弹出的窗口中选Image→点击OK
    • 第三步:配置图像话题:在Displays列表中找到新增的Image项→展开Image→点击Topic右侧的下拉框→选择/image_raw
  3. 预期效果:RViz 窗口中显示相机拍摄的 Gazebo 虚拟环境图像(如地面、障碍物)。

4.2 实战 2:三维相机(RGBD,如 Kinect)

场景需求

仿真一个能输出 "彩色图像 + 深度信息" 的三维相机,在 RViz 中看点云(用无数带颜色的点组成的三维图像)。

步骤 1:三维相机仿真插件配置(核心代码)

三维相机用的还是libgazebo_ros_camera.so插件,但配置更复杂(需输出深度和点云),文件在learning_gazebo/urdf/sensors/kinect_gazebo.xacro

复制代码
<xacro:macro name="kinect_gazebo" params="prefix">
    <gazebo reference="${prefix}_link">
        <!-- 传感器类型设为depth(深度相机) -->
        <sensor type="depth" name="${prefix}_depth_cam">
            <update_rate>15.0</update_rate> <!-- 深度相机更新慢一点:15Hz(节省算力) -->
            <pose>0 0 0 0 0 0</pose> <!-- 相机在连杆上的位置(无偏移) -->

            <camera name="kinect"> <!-- 相机参数类似彩色相机,但分辨率低(640×480,实时性更好) -->
                <horizontal_fov>${60.0*M_PI/180.0}</horizontal_fov> <!-- 60度视场角(转成弧度) -->
                <image>
                    <format>R8G8B8</format>
                    <width>640</width>
                    <height>480</height>
                </image>
                <clip>
                    <near>0.05</near> <!-- 最近5厘米,比彩色相机远 -->
                    <far>8.0</far>    <!-- 最远8米(深度相机通常近距精度高) -->
                </clip>
            </camera>

            <!-- 加载插件,发布深度图像和点云 -->
            <plugin name="${prefix}_controller" filename="libgazebo_ros_camera.so">
                <ros>
                    <!-- 话题重映射:彩色图像→/rgb/image_raw,深度图像→/depth/image_raw -->
                    <remapping>${prefix}/image_raw:=rgb/image_raw</remapping>
                    <remapping>${prefix}/image_depth:=depth/image_raw</remapping>
                    <!-- 相机内参:彩色内参→/rgb/camera_info,深度内参→/depth/camera_info -->
                    <remapping>${prefix}/camera_info:=rgb/camera_info</remapping>
                    <remapping>${prefix}/camera_info_depth:=depth/camera_info</remapping>
                    <!-- 点云话题:深度+彩色→/depth/points(RViz要显示的点云话题) -->
                    <remapping>${prefix}/points:=depth/points</remapping>
                </ros>
                <camera_name>${prefix}</camera_name>
                <frame_name>${prefix}_frame_optical</frame_name> <!-- 光学坐标系(更精准) -->
                <min_depth>0.001</min_depth> <!-- 最小深度值 -->
                <max_depth>300.0</max_depth> <!-- 最大深度值 -->
            </plugin>
        </sensor>
    </gazebo>
</xacro:macro>
步骤 2:启动三维相机仿真
  1. 启动命令:

    复制代码
    ros2 launch learning_gazebo load_mbot_rgbd_into_gazebo.launch.py
  2. 验证点云话题(新终端):

    复制代码
    ros2 topic list | grep points  # 查看是否有/depth/points话题
    • 预期输出:/depth/points(点云话题)。
步骤 3:RViz 可视化点云
  1. 启动 RViz,设置Fixed Frameodom
  2. 添加 "PointCloud2" 显示项:点击Add→选PointCloud2OK
  3. 配置点云话题:展开PointCloud2Topic下拉选/depth/points→勾选Use Fixed Frame(确保用 odom 坐标系)。
  4. 预期效果:RViz 中显示三维点云,能看到 Gazebo 环境中物体的立体形状(比如立方体的三个面,带颜色)。

4.3 实战 3:激光雷达(如 RPLIDAR)

场景需求

仿真一个激光雷达,在 RViz 中看 "激光扫描的环境轮廓"(二维激光点)。

步骤 1:激光雷达仿真插件配置

激光雷达用 Gazebo 的libgazebo_ros_ray_sensor.so插件,文件在learning_gazebo/urdf/sensors/lidar_gazebo.xacro

复制代码
<xacro:macro name="lidar_gazebo" params="prefix">
    <gazebo reference="${prefix}_link">
        <!-- 传感器类型设为ray(激光雷达本质是"射线传感器") -->
        <sensor type="ray" name="${prefix}_lidar">
            <update_rate>20</update_rate> <!-- 激光雷达更新频率:20Hz(每秒扫20次) -->

            <!-- ray标签:配置激光扫描参数 -->
            <ray>
                <scan> <!-- 扫描范围和精度 -->
                    <horizontal> <!-- 水平扫描(2D激光雷达,只扫水平方向) -->
                        <samples>360</samples> <!-- 每圈采样数:360个点(1度1个点,精度高) -->
                        <resolution>1</resolution> <!-- 分辨率:1(每个采样点都保留) -->
                        <min_angle>-3</min_angle> <!-- 最小角度:-3弧度(≈-171.9度) -->
                        <max_angle>3</max_angle>  <!-- 最大角度:3弧度(≈171.9度) → 总视场角≈343.8度(接近360度) -->
                    </horizontal>
                </scan>
                <range> <!-- 激光测距范围 -->
                    <min>0.10</min>  <!-- 最近10厘米 -->
                    <max>30.0</max>  <!-- 最远30米(符合常见激光雷达参数) -->
                    <resolution>0.01</resolution> <!-- 测距精度:1厘米 -->
                </range>
                <noise> <!-- 激光噪声(模拟真实雷达的测量误差) -->
                    <type>gaussian</type>
                    <mean>0.0</mean>
                    <stddev>0.01</stddev> <!-- 误差1厘米 -->
                </noise>
            </ray>

            <!-- 加载激光雷达插件,发布LaserScan话题 -->
            <plugin name="gazebo_rplidar" filename="libgazebo_ros_ray_sensor.so">
                <ros>
                    <namespace>/</namespace> <!-- 命名空间(根目录,话题直接在/下) -->
                    <remapping>~/out:=scan</remapping> <!-- 把插件默认话题重映射为/scan(ROS激光雷达标准话题) -->
                </ros>
                <output_type>sensor_msgs/LaserScan</output_type> <!-- 输出消息类型(固定为LaserScan) -->
            </plugin>
        </sensor>
    </gazebo>
</xacro:macro>
步骤 2:启动激光雷达仿真
  1. 启动命令:

    复制代码
    ros2 launch learning_gazebo load_mbot_laser_into_gazebo.launch.py
  2. 验证激光话题(新终端):

    复制代码
    ros2 topic list | grep scan  # 查看是否有/scan话题
    • 预期输出:/scan(激光雷达标准话题)。
步骤 3:RViz 可视化激光扫描
  1. 启动 RViz,设置Fixed Frameodom
  2. 添加 "LaserScan" 显示项:点击Add→选LaserScanOK
  3. 配置激光话题:展开LaserScanTopic下拉选/scanSize设为0.1(激光点大一点,看得清楚)。
  4. 预期效果:RViz 中显示一圈激光点,勾勒出 Gazebo 环境中障碍物的轮廓(比如墙壁、箱子的边缘)。

五、关键:RViz vs Gazebo(小白再也不混淆)

很多初学者会把 RViz 和 Gazebo 搞混,用 "核心功能 + 通俗例子" 彻底区分:

对比维度 RViz(可视化工具) Gazebo(物理仿真工具)
核心功能 显示数据(把已有的 ROS 话题数据转成图形) 生成数据(模拟真实机器人 / 传感器,发布 ROS 话题)
数据来源 依赖外部数据(真实传感器 / Gazebo 仿真) 自己生成数据(虚拟机器人 + 虚拟环境)
关键比喻 "电视"(只显示节目,不制作节目) "电视台"(制作节目,给电视提供内容)
使用场景举例 1. 看真实 USB 相机的图像2. 看真实激光雷达的轮廓3. 看机器人导航路径 1. 没有真实相机,仿真一个相机2. 没有真实机器人,仿真一个移动机器人3. 模拟机器人在客厅环境运动
依赖关系 没有数据时,RViz 是 "空电视"(啥也显示不了) 没有 RViz 时,Gazebo 仍能生成数据(但你看不到图形)

六、复习要点总结(小白必背)

  1. RViz 核心定位:数据可视化工具,"显数据" 不 "造数据"。

  2. RViz 基础操作

    • 启动命令:ros2 run rviz2 rviz2
    • 必设参数:Fixed Frame(通常为odombase_link,避免坐标系错误);
    • 通用流程:Add显示项 → 选对应话题 → 调整参数(如Size、颜色)
  3. 各传感器关键信息

    传感器类型 仿真插件文件名 核心 ROS 话题 RViz 显示项
    彩色相机 libgazebo_ros_camera.so /image_raw Image
    三维相机(RGBD) libgazebo_ros_camera.so /depth/points PointCloud2
    激光雷达 libgazebo_ros_ray_sensor.so /scan LaserScan
  4. Gazebo vs RViz

    • Gazebo:"数据生产者"(仿真机器人 / 传感器,发布话题);
    • RViz:"数据消费者"(订阅话题,显示图形)。

掌握这些,你就能用 RViz 调试大部分机器人功能 ------ 无论是仿真还是真实机器人,RViz 都是你开发中的 "眼睛"!

相关推荐
red_redemption2 小时前
自由学习记录(105)
学习
WWZZ20252 小时前
ORB_SLAM2原理及代码解析:单应矩阵H、基础矩阵F求解
线性代数·算法·计算机视觉·机器人·slam·基础矩阵·单应矩阵
丰锋ff2 小时前
2023 年真题配套词汇单词笔记(考研真相)
学习
Dersun3 小时前
mysql数据库学习之常用函数(五)
数据库·sql·学习·mysql·ai编程
序属秋秋秋4 小时前
《C++进阶之C++11》【智能指针】(下)
c++·笔记·学习·面试·c++11·智能指针·新特性
Mingze03145 小时前
考研408之栈与队列学习
开发语言·c++·学习·考研·算法
丰锋ff5 小时前
2024 年真题配套词汇单词笔记(考研真相)
笔记·考研
从前慢,现在也慢5 小时前
【STL学习】(9)priority_queue
c++·学习
序属秋秋秋5 小时前
《C++进阶之C++11》【智能指针】(上)
c++·笔记·学习·面试·c++11·智能指针·新特性