chapter2 ROS2 概念理解

ROS2 概念理解

节点

节点(Node): 节点是具有一定功能的模块(如控制机器人手臂电机)。每个节点可通过话题(topic), 服务(service), 动作(action)以及参数(parameter)等来发送(publish)与接收(subscribe)数据,从而实现与其他节点的通信,最终实现机器人的某项能力。

chapter2 ROS2 概念理解

下面我们来看下模拟,打开小乌龟模拟器:

# ros2 run <package_name> <executable_name>
ros2 run turtlesim turtlesim_node

这个命名以后会经常使用: turtlesim 是工作包(package)的名字, turtlesim_node是可以执行的文件名。

小乌龟窗口会弹出来,类似:

chapter2 ROS2 概念理解

使用如下命令即可查看当前的ros 图中有哪些节点:

ros2 node list

返回的结果应该:

/turtlesim

即只有一个节点, 节点名/turtlesim

如果在模拟时,我们想控制小乌龟的移动,可以使用如命令(打开一个新终端)

ros2 run turtlesim turtle_teleop_key

通过这个命令我们就可以使用如方向键等按键来控制小乌龟移动了。然后,我们再查看节点(ros2 node list):

/turtlesim
/teleop_turtle

发现又多了一个节点,即为刚才我们用以控制小乌龟的节点(/teleop_turtle).

可以使用如下命令来查看某一节点的相关信息,比如我们查看/turtlesim节点信息:

# ros2 node info <node_name>
ros2 node info /turtlesim

会显示如下信息:

/my_turtle
  Subscribers:
    /parameter_events: rcl_interfaces/msg/ParameterEvent
    /turtle1/cmd_vel: geometry_msgs/msg/Twist
  Publishers:
    /parameter_events: rcl_interfaces/msg/ParameterEvent
    /rosout: rcl_interfaces/msg/Log
    /turtle1/color_sensor: turtlesim/msg/Color
    /turtle1/pose: turtlesim/msg/Pose
  Services:
    /clear: std_srvs/srv/Empty
    /kill: turtlesim/srv/Kill
    /reset: std_srvs/srv/Empty
    /spawn: turtlesim/srv/Spawn
    /turtle1/set_pen: turtlesim/srv/SetPen
    /turtle1/teleport_absolute: turtlesim/srv/TeleportAbsolute
    /turtle1/teleport_relative: turtlesim/srv/TeleportRelative
    /my_turtle/describe_parameters: rcl_interfaces/srv/DescribeParameters
    /my_turtle/get_parameter_types: rcl_interfaces/srv/GetParameterTypes
    /my_turtle/get_parameters: rcl_interfaces/srv/GetParameters
    /my_turtle/list_parameters: rcl_interfaces/srv/ListParameters
    /my_turtle/set_parameters: rcl_interfaces/srv/SetParameters
    /my_turtle/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically
  Action Servers:
    /turtle1/rotate_absolute: turtlesim/action/RotateAbsolute
  Action Clients:

话题 topic

topic是各节点间传递信息的媒介。使用如下命令可查年当前活动的topics:

ros2 topic list

会显示:

/parameter_events
/rosout
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose

如在后面加上-t,还可以显示各个topic对应的数据类型:

ros2 topic list -t
/parameter_events [rcl_interfaces/msg/ParameterEvent]
/rosout [rcl_interfaces/msg/Log]
/turtle1/cmd_vel [geometry_msgs/msg/Twist]
/turtle1/color_sensor [turtlesim/msg/Color]
/turtle1/pose [turtlesim/msg/Pose]

使用rqt_graph可视化节点及其之间的topic:

rqt_graph

chapter2 ROS2 概念理解

上图展示的是节点/teleop_turtle通过发布数据到 topic/turtle1/cmd_vel,同时, 节点turtlesim订阅此topic来获取相应的数据。

通过如下命令可以实时查看某一topic中正在传输的数据,比如topic/turtle1/cmd_vel:

# ros2 topic echo <topic_name>
ros2 topic echo /turtle1/cmd_vel

每当你按键来操控小乌龟(需让执行ros2 run turtlesim turtle_teleop_key 的终端窗口保持在前面)时, 执行ros2 topic echo /turtle1/cmd_vel就会打印对应的topic中传输的数据:

linear:
  x: 0.0
  y: 0.0
  z: 0.0
angular:
  x: 0.0
  y: 0.0
  z: 2.0
---

使用:

ros2 topic info /turtle1/cmd_vel

查看对应的topic的数据类型以及发布与订阅情况:

Type: geometry_msgs/msg/Twist
Publisher count: 1
Subscription count: 1

我们把在topic中传输的数据称为信息(message),message传输需要一定的数据类型,对某一topic发布与订阅均需要使用完全一致的message类型. 回想上面使用ros2 topic list -t命令输出的信息,如: /turtle1/cmd_vel [geometry_msgs/msg/Twist], 中括号内的含义是工作包geometry_msgs有一个msg叫做Twist:

# ros2 interface show <msg type>
ros2 interface show geometry_msgs/msg/Twist

显示:

This expresses velocity in free space broken into its linear and angular parts.

    Vector3  linear
    Vector3  angular

表明/turtlesim节点的message是两个向量,每个向量均包含三个元素。

服务 service

service是ROS图的另一种通信方式,相比于topic的持续性信息流,service仅在客户端调用时提供数据。

使用如下命令即可查看当前活跃的服务列表:

ros2 service list

显示:

/clear
/kill
/reset
/spawn
/teleop_turtle/describe_parameters
/teleop_turtle/get_parameter_types
/teleop_turtle/get_parameters
/teleop_turtle/list_parameters
/teleop_turtle/set_parameters
/teleop_turtle/set_parameters_atomically
/turtle1/set_pen
/turtle1/teleport_absolute
/turtle1/teleport_relative
/turtlesim/describe_parameters
/turtlesim/get_parameter_types
/turtlesim/get_parameters
/turtlesim/list_parameters
/turtlesim/set_parameters
/turtlesim/set_parameters_atomically

使用如下命令可以查看服务类型, 比如查看/spawn的服务类型:

# ros2 service type <service_name>
ros2 service type /clear

会显示:

turtlesim/srv/Spawn

类似上面topic的列表命令,加上-t可以查看所有服务类型:

ros2 service list -t

会显示:

/clear [std_srvs/srv/Empty]
/kill [turtlesim/srv/Kill]
/reset [std_srvs/srv/Empty]
/spawn [turtlesim/srv/Spawn]
...
/turtle1/set_pen [turtlesim/srv/SetPen]
/turtle1/teleport_absolute [turtlesim/srv/TeleportAbsolute]
/turtle1/teleport_relative [turtlesim/srv/TeleportRelative]
...

使用如下命令可以查看某一服务类型的数据结构,比如/spawn:

# ros2 interface show <service_type_name>
ros2 interface show turtlesim/srv/Spawn

将返回:

float32 x
float32 y
float32 theta
string name # Optional.  A unique name will be created and returned if this is empty
---
string name

请求结构(上)与响应结构(下)由---分开。

参数 parameter

参数是节点的配置,其数据类型可以是整型、浮点数、布尔值、字符串和列表。在ROS2中 所参数都可通过服务来动态配置。

使用如下命令查看当前ROS图中节目的参数:

/teleop_turtle:
  scale_angular
  scale_linear
  use_sim_time
/turtlesim:
  background_b
  background_g
  background_r
  use_sim_time

使用如下命令获取参数的数据类型与当前值,比如/turtlesimbackground_r:

# ros2 param get /turtlesim background_r

显示:

Integer value is: 69

background_r的值是整型69

动作 action

另一种通信类型是action, 它适用于运行周期较长的任务,它有目标、反馈与结果三部分组成。相比于service,动作在结果返回之前会一直提供反馈,并且客户端可以根据反馈情况决定是否继续等待结果产生还是中途取消。

当我们使用ros2 run turtlesim turtle_teleop_key命令时,注意到其显示:

Reading from keyboard
---------------------------
Use arrow keys to move the turtle.
Use G|B|V|C|D|E|R|T keys to rotate to absolute orientations. 'F' to cancel a rotation.
'Q' to quit.

其中Use G|B|V|C...这句对应一个让小包龟旋转的动作。如果将F想象成小乌龟,那么围绕F一圈字母表示的正好是希望旋转的方向,比如C表示旋转小乌龟让其方向朝向左下角,当我们按下C时(确保此时活跃窗口为ros2 run turtlesim turtle_teleop_key), 小如乌龟就会自动旋转向左下角,其间如果没有其他操作,当小乌龟旋转完成时,在ros2 run turtlesim turtlesim_node命令窗口中会显示类似如下信息:

[INFO] [1630279564.023316728] [turtlesim]: Rotation goal completed successfully

如果在其旋转时按下F, 小乌龟就会停止,然后上面的窗口会反馈:

[INFO] [1630279898.183500953] [turtlesim]: Rotation goal canceled

如果在其旋转时按下其它旋转方向, 比如R,那么小乌龟会立即向右上方旋转,然后上面的窗口会发出警告:

[WARN] [1630279914.102848944] [turtlesim]: Rotation goal received before a previous goal finished. Aborting previous goal

使用如下命令可以查看活跃的所有action

ros2 action list -t

返回:

/turtle1/rotate_absolute [turtlesim/action/RotateAbsolute]

使用如下命令可以查看动作的信息:

# ros2 action info <action_name>
ros2 action info /turtle1/rotate_absolute

显示:

Action: /turtle1/rotate_absolute
Action clients: 1
    /teleop_turtle
Action servers: 1
    /turtlesim

即action服务器只有/turtlesim, 客户端也只有一个/teleop_turtle.

使用如下命令查看相应action服务器的数据结构:

ros2 interface show turtlesim/action/RotateAbsolute

显示:

Absolute
# The desired heading in radians
float32 theta
---
# The angular displacement in radians to the starting position
float32 delta
---
# The remaining rotation in radians
float32 remaining

---分隔的上面是目标请求结构, 中间是反馈结构,下面是结果返回结构。

rqt_console

rqt_console可用于查看日志消息,通常相关日志会在对应的终端显示。 不过使用rqt_console会更加方便。

在新的终端中打开:

ros2 run rqt_console rqt_console

会弹出一个对话框:

chapter2 ROS2 概念理解

如果此时我们操控小乌龟让其不断的撞墙,在rqt_console容口中就会产生如下消息:

chapter2 ROS2 概念理解

ROS2 提供如下消息等级:

Fatal
Error
Warn
Info
Debug

默认是Info,如果想要修改, 可以在启动时设置记录级别,比如:

ros2 run turtlesim turtlesim_node --ros-args --log-level WARN

launch 启动

一般来说,机器人系统不只一个节点,而是多个节点的复杂系统。如果每个节点都要分别打开,会非常麻烦,而使用launch 文件可以同时启动和配置多个节点。

先关闭上面的所有窗口,然后,创建一个文件夹并在其中创建如下文件:

mkdir launch
touch launch/turtlesim_mimic_launch.py

turtlesim_mimic_launch.py的内容:

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        Node(
            package='turtlesim',
            namespace='turtlesim1',
            executable='turtlesim_node',
            name='sim'
        ),
        Node(
            package='turtlesim',
            namespace='turtlesim2',
            executable='turtlesim_node',
            name='sim'
        ),
        Node(
            package='turtlesim',
            executable='mimic',
            name='mimic',
            remappings=[
                ('/input/pose', '/turtlesim1/turtle1/pose'),
                ('/output/cmd_vel', '/turtlesim2/turtle1/cmd_vel'),
            ]
        )
    ])

其中:

def generate_launch_description():
   return LaunchDescription([...])

返回一个三节点结成的启动系统, 节点均来自包turtlesim

首先启动文件中,前两个节点表明是两个小乌龟,仔细查看,发现两只小乌龟的设置几乎一致,只不过namespace不同(否则会冲突)。最后的节点代表可执行文件mimicmimic/input/posetopic被重新映射到/turtlesim1/turtle1/pose并且它的/output/cmd_veltopic被重新映射到/turtlesim2/turtle1/cmd_vel。这意味着mimic将订阅/turtlesim1/sim的姿势topic并重新发布它以供/turtlesim2/sim订阅的速度命令主题。换句话说,turtlesim2将模仿turtlesim1的动作。

使用如下命令执行launch文件:

cd launch
ros2 launch turtlesim_mimic_launch.py

窗口会显示类似如下信息:

[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [turtlesim_node-1]: process started with pid [18346]
[INFO] [turtlesim_node-2]: process started with pid [18348]
[INFO] [mimic-3]: process started with pid [18350]

可以使用如下命令发布信息,让小乌龟动起来:

ros2 topic pub -r 1 /turtlesim1/turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: -1.8}}"

这样两只小乌龟就开始画圈了。

chapter2 ROS2 概念理解

查看ROS图(如果信息与下面差别较大,可以点击窗口中左上角的刷新(蓝色的旋转箭头)试一下):

rqt_graph

chapter2 ROS2 概念理解

记录与回放数据

ROS2 bag 是一个用于记录topic数据的命令行工具,这些被记录的数据可以回放以便产生记录时一致的实验结果。

关闭上面所有窗口并重新打开:

ros2 run turtlesim turtlesim_node
ros2 run turtlesim turtle_teleop_key

然后为bag创建文件夹以便存储记录的topic数据:

mkdir bag_files
cd bag_files

比如要记录发布于/turtle1/cmd_veltopic上面的数据:

# ros2 bag record <topic_name>
ros2 bag record /turtle1/cmd_vel

会看到类似如下信息:

[INFO] [1630367261.235190016] [rosbag2_storage]: Opened database 'rosbag2_2021_08_31-07_47_41/rosbag2_2021_08_31-07_47_41_0.db3' for READ_WRITE.
[INFO] [1630367261.242226479] [rosbag2_transport]: Listening for topics...
[INFO] [1630367261.242821059] [rosbag2_transport]: Subscribed to topic '/turtle1/cmd_vel'
[INFO] [1630367261.242918703] [rosbag2_transport]: All requested topics are subscribed. Stopping discovery...

使用Ctrl+C停止记录,数据将被累积在一个包文件中,其名称格式: rosbag2_year_month_day-hour_minute_second. 可以使用参数-o 设置文件名称,也可以记录多个topic,如:

ros2 bag record -o subset /turtle1/cmd_vel /turtle1/pose

上面这条命令是将数据保存在subset文件中, 且本次记录的是两个topic的数据。

使用下面命令查看bag信息:

# ros2 bag info <bag_file_name>
ros2 bag info subset

显示类型似:


Files:             subset_0.db3
Bag size:          121.3 KiB
Storage id:        sqlite3
Duration:          24.224s
Start:             Aug 31 2021 07:51:29.372 (1630367489.372)
End:               Aug 31 2021 07:51:53.597 (1630367513.597)
Messages:          1673
Topic information: Topic: /turtle1/cmd_vel | Type: geometry_msgs/msg/Twist | Count: 158 | Serialization Format: cdr
                   Topic: /turtle1/pose | Type: turtlesim/msg/Pose | Count: 1515 | Serialization Format: cdr

接下来,我们回放记录的topic数据, 在这之前,关闭teleop窗口,但小乌龟要保留,然后:

ros2 bag play subset

终端会显示类似如下信息:

[INFO] [1630367914.850719273] [rosbag2_storage]: Opened database 'subset/subset_0.db3' for READ_ONLY.

然后,小乌龟会开始按记录时的数据移动(但不是 100% 准确;turtlesim 对系统时间的微小变化很敏感)。

总结,以上通过小乌龟模拟器熟悉ROS2相关概念及常用命令。上面涉及的命令以后一定会经常用到,汇总如下:

命令 解释
rqt ROS2 的GUI, 其可以查看ROS2中的非常多信息,后面会慢慢介绍
ros2 node list 列出当前所有节点
ros2 node info <node_name> 查看某节点的相关信息
rqt_graph 可以查看相应的ROS2节点图
ros2 topic list 列出当前所有主题,加上-t还可以查看对应的信息类型
ros2 topic echo <topic_name> 可查看某一topic当前正在传输的数据
ros2 topic info <topic_name> 查看某节点的节点信息
ros2 interface show <msg_type> 查看信息类型的具体数据结构
ros2 topic hz <topic_name> 查看topic 发布频率
ros2 service list 列出当前所有服务,加上-t还可以查看对应的信息类型
ros2 service type <service_name> 查看服务类型
ros2 service find <type_name> 查看哪些服务使用某一服务类型
ros2 interface show <type_name> 查看服务类型的具体数据结构
ros2 param list 查看各节点对应的参数配置
ros2 param get <node_name> <parameter_name> 获取某一节点的某一参数类型及取值
ros2 param set <node_name> <parameter_name> 设置某一节点的某一参数取值
ros2 param dump <node_name> 保存某一节点的参数配置
ros2 param load <node_name> <parameter_file> 为某一节点加载参数配置
ros2 action list 列出当前所有动作,加上-t还可以查看对应的信息类型
ros2 action info <action_name> 查看某一action的相关信息
ros2 interface show <action_type> 查看action类型的具体数据结构
ros2 run rqt_console rqt_console 日志查看器
ros2 launch <package_name> <launch_file_name> 启动launch文件
ros2 bag record <topic_name> 记录某一topic的数据,加 -o可设置保存文件名称
ros2 bag info <bag_file_name> 查看某一bag信息
ros2 bag play <bag_file_name> 回放数据
上一篇:数据结构与算法--链表的定义


下一篇:(八)数学问题【C++刷题】