RViz2可视化传感器数据系列教程之一:在RViz2中显示相机视频图像数据
【编者注】本文由深圳季连科技有限公司kenny wang创作,知识产权归深圳季连科技有限公司所有。如需转载,敬请注明原文出处。
在RViz2中,可以对相机的视频图像数据进行可视化显示,但前提是必须以话题这种ROS的通信方式对相机视频图像数据进行了发布。因此,首先需要通过ROS 2节点发布相机视频图像数据。
可以使用ROS 2的内建相机视频图像发布节点,即v4l2_camera软件包的v4l2_camera_node节点,具体运行命令如下:
ros2 run v4l2_camera v4l2_camera_node
运行上述命令后,会发布以下几个与相机视频图像相关的话题:
/camera_info
/image_raw
/image_raw/compressed
/image_raw/compressedDepth
/image_raw/theora
从中可以看出,v4l2_camera_node节点不仅可以发布一般的视频图像数据(即/image_raw话题),还可以发布压缩的视频数据和压缩的深度相机视频数据(发布压缩视频数据需要安装ros-perception/vision_opencv和image_transport_plugins等依赖包)。在无人机、无人船、远程控制机器人等应用场景下,压缩视频数据传输对于减轻网络负荷非常有用,但在显示视频图像数据前,需要对这类话题发布的视频图像数据进行解压缩。此时,需要通过运行ROS 2的软件包image_transport的republish节点对视频数据解压缩并进行重新发布,解压缩后视频数据话题名称为image_raw/uncompressed:
ros2 run image_transport republish compressed in/compressed:=image_raw/compressed out:=image_raw/uncompressed
当然,也可以使用用户自定义的软件包及其节点进行相机视频图像发布,例如可以使用spreader_camera_pubsub软件包(该软件包用于进行集装箱吊具相机视频图像数据发布、订阅、角件/锁孔目标检测、目标特征点吊具参考坐标系转换计算与发布)的images_publisher节点进行吊具相机视频图像数据发布,具体命令为:
ros2 run spreader_camera_pubsub images_publisher
这样,会发布以下两个与吊具相机视频图像相关的话题:
/camera_info
/image_raw
注意:如果使用用户自定义的软件包及其节点进行相机视频图像发布,必须在发布的类型为sensor_msgs/msgs/Image消息变量(如image_msg)中填充其header字段的相关信息,包括时间戳(stamp)和坐标系名称(frame_id),如下Python代码所示:
image_msg.header.stamp = self. get_clock().now().to_msg()
image_msg.header.frame_id = 'camera'
如果不填充这两个头信息,由于发布的消息其frame_id为空,也没有时间戳,就不能正确配置其固定坐标系,也就不能在RViz2中显示该话题发布的视频图像数据了。
其次,运行RViz2并进行相关配置。可以使用以下命令来运行RViz2:
ros2 run rviz2 rviz2
或者直接运行命令:
rviz2
这样就会打开RViz2图形用户界面。点击该界面左下角的“Add”按钮,可以添加需要进行可视化显示的话题。在选中“Image”话题并点击“Ok”按钮后,会在左侧“Displays”面板底部的“Image”话题对话框中出现的“No Image”字样,如下图所示。
为解决这个问题,需要对该视频图像话题的固定坐标系(Fixed Frame)和话题名称(Topic Name)进行配置。对于该话题的固定坐标系,可以通过两种方式进行配置:一是直接将“Displays”面板顶部固定坐标系(Fixed Frame)的值由默认的“map”修改为“camera”。注意,对于使用自定义软件包节点发布的视频图像话题来说,坐标系名称有可能并不是“camera”,而是其它frame_id,这就需要运行以下命令来查看该视频图像话题的frame_id:
ros2 topic echo /image_raw --no-arr
这样就会看到如下所示的消息:
header:
stamp:
sec: 1639564328
nanosec: 59671685
frame_id: camera
height: 480
width: 640
encoding: rgb8
is_bigendian: 0
step: 1920
data: '<sequence type: uint8, length: 921600>'
其中在header下的frame_id的值就是所需的坐标系名称。
二是可以通过运行ROS 2的坐标变换软件包tf2_ros的静态坐标变换发布者节点,发布RViz2中默认固定坐标系map到该视频图像话题坐标系名称(frame_id)的静态坐标变换。具体命令为:
ros2 run tf2_ros static_transform_publisher 0 0 0 0 0 0 map camera
也要注意,如果该视频图像话题的坐标系名称不是默认的camera,则需将camera替换成正确的坐标系名称。
这样,点击“Displays”面板顶部固定坐标系(Fixed Frame)字段的值(map所在之处),就会出现下拉列表,可以从中选择正确的坐标系名称。此时,如果话题名称配置正确的话,就会开始显示相机视频图像数据了。
但有的时候,话题名称可能也不能直接配置好,需要手动对其进行配置。如果“Image”话题下面的“Topic”字段的值为空,则需要手动输入话题的正确名称,如/image_raw或者其它名称。
当固定坐标系和话题名称被正确配置后,就可以在“Displays”面板底部的“Image”窗口中正常显示相机视频图像了,如下图所示。
除了上述在RViz2图形用户界面中进行手动配置的方式外,还可以直接在RViz2的配置文件*.rviz中进行配置,以便可以在启动RViz2后直接显示相机视频图像数据。下面就是一个这样的示例.rviz文件:
Panels:
- Class: rviz_common/Displays
Help Height: 78
Name: Displays
Property Tree Widget:
Expanded:
- /Global Options1
- /Status1
- /Grid1
- /Image1
- /Image1/Topic1
Splitter Ratio: 0.5
Tree Height: 478
- Class: rviz_common/Selection
Name: Selection
- Class: rviz_common/Tool Properties
Expanded:
- /2D Goal Pose1
- /Publish Point1
Name: Tool Properties
Splitter Ratio: 0.5886790156364441
- Class: rviz_common/Views
Expanded:
- /Current View1
Name: Views
Splitter Ratio: 0.5
- Class: rviz_common/Time
Experimental: false
Name: Time
SyncMode: 0
SyncSource: ""
Visualization Manager:
Class: ""
Displays:
- Alpha: 0.5
Cell Size: 1
Class: rviz_default_plugins/Grid
Color: 160; 160; 164
Enabled: true
Line Style:
Line Width: 0.029999999329447746
Value: Lines
Name: Grid
Normal Cell Count: 0
Offset:
X: 0
Y: 0
Z: 0
Plane: XY
Plane Cell Count: 10
Reference Frame: <Fixed Frame>
Value: true
- Class: rviz_default_plugins/Image
Enabled: true
Max Value: 1
Median window: 5
Min Value: 0
Name: Image
Normalize Range: true
Topic:
Depth: 5
Durability Policy: Volatile
Filter size: 10
History Policy: Keep Last
Reliability Policy: Reliable
Value: /image_raw/ur_camera
Value: true
Enabled: true
Global Options:
Background Color: 48; 48; 48
Fixed Frame: camera
Frame Rate: 30
Name: root
Tools:
- Class: rviz_default_plugins/Interact
Hide Inactive Objects: true
- Class: rviz_default_plugins/MoveCamera
- Class: rviz_default_plugins/Select
- Class: rviz_default_plugins/FocusCamera
- Class: rviz_default_plugins/Measure
Line color: 128; 128; 0
- Class: rviz_default_plugins/SetInitialPose
Covariance x: 0.25
Covariance y: 0.25
Covariance yaw: 0.06853891909122467
Topic:
Depth: 5
Durability Policy: Volatile
History Policy: Keep Last
Reliability Policy: Reliable
Value: /initialpose
- Class: rviz_default_plugins/SetGoal
Topic:
Depth: 5
Durability Policy: Volatile
History Policy: Keep Last
Reliability Policy: Reliable
Value: /goal_pose
- Class: rviz_default_plugins/PublishPoint
Single click: true
Topic:
Depth: 5
Durability Policy: Volatile
History Policy: Keep Last
Reliability Policy: Reliable
Value: /clicked_point
Transformation:
Current:
Class: rviz_default_plugins/TF
Value: true
Views:
Current:
Class: rviz_default_plugins/Orbit
Distance: 10
Enable Stereo Rendering:
Stereo Eye Separation: 0.05999999865889549
Stereo Focal Distance: 1
Swap Stereo Eyes: false
Value: false
Focal Point:
X: 0
Y: 0
Z: 0
Focal Shape Fixed Size: true
Focal Shape Size: 0.05000000074505806
Invert Z Axis: false
Name: Current View
Near Clip Distance: 0.009999999776482582
Pitch: 0.785398006439209
Target Frame: <Fixed Frame>
Value: Orbit (rviz)
Yaw: 0.785398006439209
Saved: ~
Window Geometry:
Displays:
collapsed: false
Height: 1016
Hide Left Dock: false
Hide Right Dock: false
Image:
collapsed: false
QMainWindow State: 000000ff00000000fd0000000400000000000001560000035afc0200000009fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d00000269000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261fb0000000a0049006d00610067006501000002ac000000eb0000002800ffffff000000010000010f0000035afc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000003d0000035a000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000007380000003efc0100000002fb0000000800540069006d0065010000000000000738000002eb00fffffffb0000000800540069006d00650100000000000004500000000000000000000004c70000035a00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
Selection:
collapsed: false
Time:
collapsed: false
Tool Properties:
collapsed: false
Views:
collapsed: false
Width: 1848
X: 72
Y: 27
与没有添加任何话题时RViz2提供的默认default.rviz文件相比,上面这个.rviz文件中添加的内容用字体加粗进行了标注。从中可以看出,由于要添加Image类型的话题,该.rviz文件在4个地方进行了内容添加或修改:
首先,在“Property Tree Widget”元素的“Expended”子元素中添加了以下两行,用于实例化Image及其Topic:
- /Image1
- /Image1/Topic1
其次,在“Visualization Manager”元素的子元素“displays”中添加了Image插件类及其所有相关属性,包括其话题名称(这里的话题名称为/image_raw/ur_camera),如下所示:
- Class: rviz_default_plugins/Image
Enabled: true
Max Value: 1
Median window: 5
Min Value: 0
Name: Image
Normalize Range: true
Topic:
Depth: 5
Durability Policy: Volatile
Filter size: 10
History Policy: Keep Last
Reliability Policy: Reliable
Value: /image_raw/ur_camera
Value: true
第三,将“Displays”元素的“Global Options”子元素中的固定坐标系“Fixed Frame”子元素值由默认的“map”修改成“camera”。
最后,在“Window Geometry”元素中、“QMainWindow State”子元素之前添加了以下两行:
Image:
collapsed: false
这样,就可以将这个.rviz文件保存到包含相机视频图像话题发布者节点的软件包中源代码子目录下的rviz子目录中,并创建一个launch文件(保存在软件包中源代码子目录下的launch子目录中)来同时启动该发布者节点和rviz2节点,以便发布相机视频图像话题并打开RViz2以直接显示该视频图像话题的数据。下面是一个这样的示例launch文件:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.conditions import IfCondition
from launch_ros.actions import Node
def generate_launch_description():
pkg_camera_pubsub = get_package_share_directory('spreader_camera_pubsub')
return LaunchDescription([
DeclareLaunchArgument('rviz', default_value='true',
description='Open RViz.'),
Node(
package='spreader_camera_pubsub',
executable='images_publisher',
name='spreader_camera_images_publisher',
emulate_tty = True,
parameters=[
{'video_source': 0}
],
output='screen'
),
# RViz
Node(
package='rviz2',
executable='rviz2',
arguments=['-d', os.path.join(pkg_camera_pubsub, 'rviz', 'my_image.rviz')],
condition=IfCondition(LaunchConfiguration('rviz'))
),
])
评论(0)
您还未登录,请登录后发表或查看评论