Skip to content

使用替换

目标: 了解 ROS 2 launch 文件中的替换(substitutions)。

教程级别: 中级

时间: 15 分钟

Launch 文件用于启动节点、服务以及执行各种进程。这些操作可以带有参数,从而影响其行为。替换(substitution)可以在参数中使用,为编写可复用的 launch 文件提供更大灵活性。替换本质上是一种变量,仅在 launch description 执行期间才会被求值,可用于获取特定信息(如 launch 配置、环境变量),或用于求值任意 Python 表达式。

本教程将展示 ROS 2 launch 文件中替换的使用示例。

本教程使用 turtlesim 包。此外,本教程假设你已经熟悉如何创建包。

和往常一样,每次打开新终端时不要忘记 source ROS 2。

首先,创建一个名为 launch_tutorial 的新包:

创建一个 build_type 为 ament_python 的新包:

Terminal window
$ ros2 pkg create --build-type ament_python --license Apache-2.0 launch_tutorial

在该包内部,创建一个名为 launch 的目录:

Terminal window
$ mkdir launch_tutorial/launch

最后,确保安装 launch 文件:

在包的 setup.py 中做以下修改:

import os
from glob import glob
from setuptools import find_packages, setup
package_name = 'launch_tutorial'
setup(
# Other parameters ...
data_files=[
# ... Other data files
# Include all launch files.
(os.path.join('share', package_name, 'launch'), glob('launch/*'))
]
)

我们来创建一个 launch 文件,用于调用另一个 launch 文件并传递参数。该 launch 文件可以是 YAML、XML 或 Python 格式。

为此,在 launch_tutorial 包的 launch 文件夹中创建以下文件。

将完整代码复制并粘贴到 launch/example_main_launch.xml 文件中:

<?xml version="1.0" encoding="UTF-8"?>
<launch>
<let name="background_r" value="200" />
<include file="$(find-pkg-share launch_tutorial)/launch/example_substitutions_launch.xml">
<let name="turtlesim_ns" value="turtlesim2" />
<let name="use_provided_red" value="True" />
<let name="new_background_r" value="$(var background_r)" />
</include>
</launch>

$(find-pkg-share launch_tutorial) 替换用于查找 launch_tutorial 包的路径。然后将该路径与 example_substitutions_launch.xml 文件名拼接。

<include file="$(find-pkg-share launch_tutorial)/launch/example_substitutions_launch.xml">

background_r 变量以及 turtlesim_ns 和 use_provided_red 参数被传递给 include 操作。$(var background_r) 替换用于将 new_background_r 参数的值定义为 background_r 变量的值。

<let name="turtlesim_ns" value="turtlesim2" />
<let name="use_provided_red" value="True" />
<let name="new_background_r" value="$(var background_r)" />

现在在同一文件夹中创建替换 launch 文件:

创建文件 launch/example_substitutions_launch.xml 并插入以下代码:

<?xml version="1.0" encoding="UTF-8"?>
<launch>
<arg name="turtlesim_ns" default="turtlesim1" />
<arg name="use_provided_red" default="False" />
<arg name="new_background_r" default="200" />
<node pkg="turtlesim" namespace="$(var turtlesim_ns)" exec="turtlesim_node" name="sim" />
<executable cmd="ros2 service call $(var turtlesim_ns)/spawn turtlesim_msgs/srv/Spawn '{x: 5, y: 2, theta: 0.2}'" />
<executable cmd="ros2 param set $(var turtlesim_ns)/sim background_r 120" />
<timer period="2.0">
<executable cmd="ros2 param set $(var turtlesim_ns)/sim background_r $(var new_background_r)"
if="$(eval '$(var new_background_r) == 200 and $(var use_provided_red)')" />
</timer>
</launch>

这里定义了 turtlesim_ns、use_provided_red 和 new_background_r launch 配置。它们用于将 launch 参数的值存储在上述变量中,并传递给所需的操作。之后,可以在 launch description 的任何位置通过 $(var <name>) 替换获取这些 launch 参数的值。

arg 标签用于定义可以从上面的 launch 文件或从控制台传递的 launch 参数。

<arg name="turtlesim_ns" default="turtlesim1" />
<arg name="use_provided_red" default="False" />
<arg name="new_background_r" default="200" />

定义了 turtlesim_node 节点,其 namespace 通过 $(var <name>) 替换设置为 turtlesim_ns launch 配置的值。

<node pkg="turtlesim" namespace="$(var turtlesim_ns)" exec="turtlesim_node" name="sim" />

随后定义了一个 executable 操作及对应的 cmd 标签。该命令调用 turtlesim 节点的 spawn 服务。此外,使用 $(var <name>) 替换获取 turtlesim_ns launch 参数的值来构造命令字符串。

<executable cmd="ros2 service call $(var turtlesim_ns)/spawn turtlesim_msgs/srv/Spawn '{x: 5, y: 2, theta: 0.2}'" />

ros2 param executable 操作同样用于更改 turtlesim 背景的红色颜色参数。区别在于,timer 内的第二个操作仅在提供的 new_background_r 参数等于 200 且 use_provided_red launch 参数设置为 True 时才执行。if 谓词的求值使用 $(eval <python-expression>) 替换完成。

<executable cmd="ros2 param set $(var turtlesim_ns)/sim background_r 120" />
<timer period="2.0">
<executable cmd="ros2 param set $(var turtlesim_ns)/sim background_r $(var new_background_r)"
if="$(eval '$(var new_background_r) == 200 and $(var use_provided_red)')" />
</timer>

进入 workspace 根目录,构建包:

Terminal window
$ colcon build

构建后还要记得 source workspace。

现在你可以使用 ros2 launch 命令来启动。

Terminal window
$ ros2 launch launch_tutorial example_main_launch.yaml

这将会执行以下操作:

  1. 启动一个蓝色背景的 turtlesim 节点
  2. 生成第二只海龟
  3. 将颜色更改为紫色
  4. 如果提供的 background_r 参数为 200 且 use_provided_red 参数为 True,则两秒后将颜色更改为粉色

如果你想更改提供的 launch 参数,可以更新 example_main_launch.yaml 中的 background_r 变量,或者带上你想要的参数启动 example_substitutions_launch.yaml。要查看可以传递给 launch 文件的参数,运行以下命令:

Terminal window
$ ros2 launch launch_tutorial example_substitutions_launch.yaml --show-args

这将显示可以传递给 launch 文件的参数及其默认值。

Arguments (pass arguments as '<name>:=<value>'):
'turtlesim_ns':
no description given
(default: 'turtlesim1')
'use_provided_red':
no description given
(default: 'False')
'new_background_r':
no description given
(default: '200')

现在你可以按如下方式向 launch 文件传递所需参数:

Terminal window
$ ros2 launch launch_tutorial example_substitutions_launch.yaml turtlesim_ns:='turtlesim3' use_provided_red:='True' new_background_r:=200

除了 $(eval <python-expression>) 之外,还有一组专用的布尔替换可用于比较值和组合结果。它们可以在任何允许使用替换的地方使用,包括任何操作的 if 和 unless 属性。

注意:比较是在每个参数的字符串表示上进行的。

XML / YAML 名称Python 类描述
$(equals A B)EqualsSubstitution如果 A 等于 B 则解析为 'true',否则为 'false'。
$(not-equals A B)NotEqualsSubstitution如果 A 不等于 B 则解析为 'true',否则为 'false'。
$(and A B)AndSubstitution两个布尔替换的逻辑与。
$(or A B)OrSubstitution两个布尔替换的逻辑或。
$(any A B ...)AnySubstitution如果任意参数为 true 则解析为 'true'。
$(all A B ...)AllSubstitution仅当所有参数都为 true 时才解析为 'true'。

上一节中的 if 谓词也可以使用布尔替换而非 Python 表达式来表达:

<executable cmd="ros2 param set /turtlesim background_r $(var new_background_r)"
if="$(and $(equals $(var new_background_r) 200) $(var use_provided_red))"/>

launch 文档提供了有关可用替换的详细信息。

在本教程中,你了解了如何在 launch 文件中使用替换,以及如何借助它们编写可复用的 launch 文件。

接下来可以进一步了解如何在 launch 文件中使用事件处理器——事件处理器用于定义一组复杂的规则,从而动态地修改 launch 文件。