ROS2学习
ROS 2 依赖于使用 shell 环境组合工作区。 “工作区”是一个 ROS 术语,表示您使用 ROS 2 进行开发的系统上的位置。 核心 ROS 2 工作区称为底层。 随后的本地工作区称为叠加层。 使用 ROS 2 进行开发时,您通常会有多个工作区同时处于活动状态。
结合工作区可以更轻松地针对不同版本的 ROS 2 或不同的软件包集进行开发。 它还允许在同一台计算机上安装多个 ROS 2 发行版(或“发行版”,例如 Dashing 和 Eloquent)并在它们之间切换。
这是通过在每次打开新 shell 时获取安装文件,或通过将 source 命令添加到 shell 启动脚本一次来实现的。 如果不获取安装文件,您将无法访问 ROS 2 命令,也无法找到或使用 ROS 2 包。 换句话说,您将无法使用 ROS 2。
1. 环境配置
需要在打开的每个新 shell 上运行此命令才能访问 ROS 2 命令,如下所示:
source /opt/ros/foxy/setup.bash
如果您不想在每次打开新 shell 时都获取安装文件的源代码(跳过任务 1),那么您可以将命令添加到您的 shell 启动脚本中:
$ echo "source /opt/ros/foxy/setup.bash" >> ~/.bashrc
添加 colcon_cd到你的 shell 启动脚本
命令 colcon_cd
允许您快速将 shell 的当前工作目录更改为包目录。 举个例子 colcon_cd some_ros_package
会很快带你到目录 ~/ros2_install/src/some_ros_package
echo "source /usr/share/colcon_cd/function/colcon_cd.sh" >> ~/.bashrc
echo "export _colcon_cd_root=~/ros2_install" >> ~/.bashrc
检查环境变量⽅法如下:
$ printenv | grep -i ROS
2. turtlesim和rqt
Turtlesim 是一个用于学习 ROS 2 的轻量级模拟器。 它说明了 ROS 2 在最基本的层面上的作用,让您了解稍后将使用真实机器人或机器人模拟来做什么。
rqt 是 ROS 2 的 GUI 工具。 在 rqt 中所做的一切都可以在命令行上完成,但它提供了一种更简单、更用户友好的方式来操作 ROS 2 元素。
要启动turtlesim,请在终端中输入以下命令:
ros2 run turtlesim turtlesim_node
运行一个新节点来控制第一个节点中的海龟:
ros2 run turtlesim turtle_teleop_key
# 列出⽬前正在运⾏的节点
$ ros2 node list
# 列出⽬前所有的topic
$ ros2 topic list
# 列出⽬前所有的service
$ ros2 service list
# 列出⽬前所有的action
$ ros2 action list
2.1 rqt
rqt
使用 rqt 来调用 /spawn服务。 从它的名字就可以猜到 /spawn将在turtlesim 窗口中创建另一只海龟。
给新乌龟一个唯一的名字,比如 turtle2通过在“ 的空单引号之间双击 表达式” 列中 。 您可以看到该表达式对应于 name 值,并且是 类型 string 。
输入海龟生成的新坐标,例如 x = 1.0和 y = 1.0.
要生成turtle2,您必须通过单击 右上角的 Call 按钮来调用该服务。
/set_pen服务可以修改颜色,粗细
2.2 重映射
重新映射 允许您将默认节点属性(如节点名称、主题名称、服务名称等)重新分配给自定义值。
ros2 run turtlesim turtle_teleop_key --ros-args --remap turtle1/cmd_vel:=turtle2/cmd_vel
将话题turtle1/cmd_vel进⾏重映射,使得turtle_teleop_key节点发送消息的对象变成了 turtle2/cmd_vel。
3. 节点node
ROS图是同时处理数据的ROS2元素组成的网络。
ROS 中的每个节点都应负责一个单一的模块用途(例如,一个节点用于控制车轮电机,一个节点用于控制激光测距仪等)。 每个节点都可以通过主题、服务、动作或参数向其他节点发送和接收数据。
一个完整的机器人系统由许多协同工作的节点组成。 在 ROS 2 中,单个可执行文件(C++ 程序、Python 程序等)可以包含一个或多个节点。
知道节点的名称,您可以通过以下方式访问有关它们的更多信息:
ros2 node info <node_name>
4. topic
主题是 ROS 图的重要元素,充当节点交换消息的总线。 一个节点可以向任意数量的主题发布数据并同时订阅任意数量的主题。
同ROS1,利用rqt_graph
查看节点与主题的连接关系。
ros2 topic list
命令将返回系统中当前活动的所有被订阅和发布的主题。
ros2 topic list -t
将主题类型附加在括号中。
ros2 topic echo <topic_name>
查 看关于某个主题发布的数据。
ros2 topic info /turtle1/cmd_vel
⽤来查看给定topic的数据类型以及其订阅者和发布者的数量。
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
ros2 topic pub
向给定话题发送消息。
ros2 topic pub --once /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}}"
–once是一个可选参数,意思是“发布一条消息然后退出”。
ros2 topic pub --rate 1 /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}}"
–rate 1告诉 ros2 topic pub以 1 Hz 的稳定流发布命令。
ros2 topic hz /turtle1/pose
查看数据发布的速度
5. 服务
服务是 ROS 图中节点的另一种通信方式。 服务基于调用和响应模型,而不是主题的发布者-订阅者模型。 虽然主题允许节点订阅数据流并获得持续更新,但服务仅在客户端专门调用时才提供数据。
同ROS1,
ros2 service list
返回系统中当前活动的所有服务的列表;
服务的类型描述了服务的请求和响应数据的结构。 服务类型的定义与主题类型类似,但服务类型有两个部分:一个用于请求的消息,另一个用于响应的消息。
ros2 service type <service_name>
返回服务的类型;
ros2 service list -t
同时查看所有活动服务的类型;
ros2 service find <type_name>
查找特定类型的所有服务
ros2 interface show <type_name>.srv
查看详细信息
$ 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
---
将请求结构(上)与响应结构(下)分开。
调用服务
ros2 service call /clear std_srvs/srv/Empty
此命令将清除乌龟绘制的任何线条的turtlesim 窗口。
现在让我们通过调用生成一个新的海龟 /spawn并输入参数。 输入 在来自命令行的服务调用中需要使用 YAML 语法。
ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"
6. ROS2 参数
同ROS1,
ros2 param set 设置参数
ros2 param get 获取参数
ros2 param load 从文件中加载参数
ros2 param dump 转储参数到文件
ros2 param list 列出参数名称
7. ROS2的actions
actions是 ROS 2 中的一种通信类型,用于长时间运行的任务。 它们由三部分组成:目标、反馈和结果。
actions建立在主题和服务上。 它们的功能类似于服务,除了actions是可抢占的(您可以在执行时取消它们)。 它们还提供稳定的反馈,而不是返回单一响应的服务。
actions使用客户端-服务器模型,类似于发布者-订阅者模型。 “actions客户端”节点向“actions服务器”节点发送目标,该节点确认目标并返回反馈流和结果。
要查看 /turtlesim节点的actions,打开一个新终端并运行命令:
$ ros2 node info /turtlesim
/turtlesim
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
/turtlesim/describe_parameters: rcl_interfaces/srv/DescribeParameters
/turtlesim/get_parameter_types: rcl_interfaces/srv/GetParameterTypes
/turtlesim/get_parameters: rcl_interfaces/srv/GetParameters
/turtlesim/list_parameters: rcl_interfaces/srv/ListParameters
/turtlesim/set_parameters: rcl_interfaces/srv/SetParameters
/turtlesim/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically
Action Servers:
/turtle1/rotate_absolute: turtlesim/action/RotateAbsolute
Action Clients:
/ turtlesim的/ turtle1 / rotate_absolute动作在动作服务器下。 这意味着/ turtlesim响应并提供了/ turtle1 / rotate_absolute行动的反馈。
可以发现/turtlesim节点是Action服务器端。对/teleop_turtle调⽤同样的指令可以得知/teleop_turtle是客户端。
- 要识别 ROS 图中的所有操作,请运行以下命令:
ros2 action list
/turtle1/rotate_absolute
这是目前 ROS 图中的唯一操作。 正如您之前看到的,它控制着海龟的旋转。 您也已经知道有一个动作客户端( /teleop_turtle) 和一个动作服务器(部分 /turtlesim) 。
- 顺便查看动作类型
ros2 action list -t
/turtle1/rotate_absolute [turtlesim/action/RotateAbsolute]
- 查看细节
ros2 action info /turtle1/rotate_absolute
可以查看Action客户端和服务器端分别是哪些节点
- 查看动作类型细节
$ ros2 interface show turtlesim/action/RotateAbsolute
# 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
第一部分是目标请求的结构(数据类型和名称)。 下一部分是结果的结构。 最后一部分是反馈的结构。
- 发送动作
ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"
Waiting for an action server to become available...
Sending goal:
theta: 1.57
Goal accepted with ID: 13595dd64e6a430ca02e67166ca4c1c9
Result:
delta: -1.5520002841949463
Goal finished with status: SUCCEEDED
所有目标都有一个唯一的 ID,显示在返回消息中。 您还可以看到结果,一个带有名称的字段 delta,这是到起始位置的位移。
要查看此目标的反馈,请添加 --feedback到您运行的最后一个命令。
ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: -1.57}" --feedback
Waiting for an action server to become available...
Sending goal:
theta: -1.57
Goal accepted with ID: b5c60e460d904feebff355ac75f5f290
Feedback:
remaining: -3.122000217437744
Feedback:
remaining: -3.1060004234313965
......
Feedback:
remaining: -0.017999649047851562
Result:
delta: 3.1040005683898926
Goal finished with status: SUCCEEDED
持续收到反馈,直到目标完成。
8. rqt_console
用于自省日志消息的工具。
启动:ros2 run rqt_console rqt_console
用法与ROS1相同。
9. 启动文件
随着创建具有越来越多同时运行的节点的更复杂的系统,打开终端和重新输入配置细节变得乏味。
启动文件允许同时启动和配置多个包含 ROS 2 节点的可执行文件。
运行单个启动文件 ros2 launch命令将立即启动的整个系统 - 所有节点及其配置。
编写启动文件:
mkdir launch
cd launch
gedit 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'),
]
)
])
LaunchDescription是一个由三个节点组成的系统,全部来自 turtlesim包。 该系统的目标是启动两个海龟窗口,让一只海龟模仿另一只海龟的运动。
前两个操作启动两个turtlesim窗口,两个节点之间的唯一区别是它们的命名空间值。 唯一的命名空间允许系统启动两个模拟器而不会发生节点名称或主题名称冲突。
该系统中的两只海龟都接收关于同一主题的命令,并在同一主题上发布它们的姿势。 如果没有唯一的命名空间,就无法区分针对一只乌龟或另一只乌龟的消息。
最后一个节点以重映射的形式添加了配置详细信息。令turtlesim2 模仿 turtlesim1的动作。
启动:
cd launch
ros2 launch turtlesim_mimic_launch.py
10. 记录和回放数据
记录发布在某个topic上的数据,以便您可以随时回放和检查它。 ros2 bag工具可以根据
所记录topic的时间信息进行回放以重现当时的行为,但是由于存在⼀些系统上的误差,无法进行⼀模⼀样的重现。
mkdir bag_files
cd bag_files
ros2 bag只能记录来自已发布主题的数据。 要查看系统主题列表,请打开一个新终端并运行以下命令:
ros2 topic list
/parameter_events
/rosout
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
查看topic
ros2 topic echo /turtle1/cmd_vel
打开一个新终端并进入 bag_files您之前创建的目录,因为 rosbag 文件将保存在您运行它的目录中。
- 运行命令记录数据:
$ ros2 bag record /turtle1/cmd_vel
[INFO] [1632876475.878238382] [rosbag2_storage]: Opened database 'rosbag2_2021_09_29-08_47_55/rosbag2_2021_09_29-08_47_55_0.db3' for READ_WRITE.
[INFO] [1632876475.888124622] [rosbag2_transport]: Listening for topics...
[INFO] [1632876475.888779987] [rosbag2_transport]: Subscribed to topic '/turtle1/cmd_vel'
[INFO] [1632876475.888914026] [rosbag2_transport]: All requested topics are subscribed. Stopping discovery...
发布在/turtle1/cmd_vel的消息被记录下来,数据将被累积在一个包文件中,其名称的模式为 rosbag2_year_month_day-hour_minute_second。
$ ros2 bag record -o subset /turtle1/cmd_vel /turtle1/pose
可以记录/turtle1/cmd_vel和turtle1/pose两个topic,并将其存储在名为subset的bag file中。
- 查看记录的信息:
$ ros2 bag info subset
Files: subset_0.db3
Bag size: 73.2 KiB
Storage id: sqlite3
Duration: 14.943s
Start: Sep 29 2021 08:56:15.651 (1632876975.651)
End: Sep 29 2021 08:56:30.595 (1632876990.595)
Messages: 938
Topic information: Topic: /turtle1/pose | Type: turtlesim/msg/Pose | Count: 935 | Serialization Format: cdr
Topic: /turtle1/cmd_vel | Type: geometry_msgs/msg/Twist | Count: 3 | Serialization Format: cdr
- 复现记录
$ ros2 bag play subset
[INFO] [1632877268.219079978] [rosbag2_storage]: Opened database 'subset/subset_0.db3' for READ_ONLY.
海龟将遵循在录制时输入的相同路径进行复现(虽然不是 100% 准确;turtlesim 对系统时间的微小变化很敏感)