使用替换
目标: 了解 ROS 2 启动文件中的替换。
教程级别: 中级
时间: 15 分钟
背景
启动文件用于启动节点、服务和执行进程。 这组操作可能具有影响其行为的参数。 替换可用于参数中,以便在描述可重复使用的启动文件时提供更大的灵活性。 替换是仅在执行启动描述期间评估的变量,可用于获取特定信息,如启动配置、环境变量或评估任意 Python 表达式。
本教程展示了 ROS 2 启动文件中替换的使用示例。
先决条件
本教程使用 turtlesim 包。 本教程还假设您熟悉 creating packages。
与往常一样,不要忘记在 每次打开新终端 中获取 ROS 2。
使用替换
1 创建并设置包
首先,创建一个名为 launch_tutorial
的新包:
Create a new package of build_type ament_python
:
ros2 pkg create --build-type ament_python --license Apache-2.0 launch_tutorial
Create a new package of build_type ament_cmake
:
ros2 pkg create --build-type ament_cmake --license Apache-2.0 launch_tutorial
在该包内,创建一个名为“launch”的目录:
mkdir launch_tutorial/launch
mkdir launch_tutorial/launch
md launch_tutorial/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(os.path.join('launch', '*launch.[pxy][yma]*')))
]
)
将以下代码附加到“CMakeLists.txt”中,紧接着“ament_package()”之前:
install(DIRECTORY
launch
DESTINATION share/${PROJECT_NAME}/
)
2 父启动文件
让我们创建一个启动文件,它将调用另一个启动文件并将参数传递给它。
此启动文件可以是 Python 或 YAML。
为此,请在“launch_tutorial”包的“launch”文件夹中创建以下文件。
将完整代码复制并粘贴到“launch/example_main.launch.py”文件中:
from launch_ros.substitutions import FindPackageShare
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import PathJoinSubstitution, TextSubstitution
def generate_launch_description():
colors = {
'background_r': '200'
}
return LaunchDescription([
IncludeLaunchDescription(
PythonLaunchDescriptionSource([
PathJoinSubstitution([
FindPackageShare('launch_tutorial'),
'launch',
'example_substitutions.launch.py'
])
]),
launch_arguments={
'turtlesim_ns': 'turtlesim2',
'use_provided_red': 'True',
'new_background_r': TextSubstitution(text=str(colors['background_r']))
}.items()
)
])
FindPackageShare
替换用于查找 launch_tutorial
包的路径。
然后使用 PathJoinSubstitution
替换将该包路径的路径与 example_substitutions.launch.py
文件名连接起来。
PathJoinSubstitution([
FindPackageShare('launch_tutorial'),
'launch',
'example_substitutions.launch.py'
])
带有“turtlesim_ns”和“use_provided_red”参数的“launch_arguments”字典被传递给“IncludeLaunchDescription”操作。 “TextSubstitution”替换用于使用“colors”字典中“background_r”键的值来定义“new_background_r”参数。
launch_arguments={
'turtlesim_ns': 'turtlesim2',
'use_provided_red': 'True',
'new_background_r': TextSubstitution(text=str(colors['background_r']))
}.items()
将完整代码复制并粘贴到“launch/example_main.launch.yaml”文件中:
launch:
- let:
name: 'background_r'
value: '200'
- include:
file: '$(find-pkg-share launch_tutorial)/launch/example_substitutions.launch.yaml'
arg:
- name: 'turtlesim_ns'
value: 'turtlesim2'
- name: 'use_provided_red'
value: 'True'
- name: 'new_background_r'
value: '$(var background_r)'
$(find-pkg-share launch_tutorial)
替换用于查找 launch_tutorial
包的路径。
然后将路径替换与 example_substitutions.launch.yaml
文件名连接起来。
file: '$(find-pkg-share launch_tutorial)/launch/example_substitutions.launch.yaml'
带有“turtlesim_ns”和“use_provided_red”参数的“background_r”变量被传递给“include”操作。 “$(var background_r)”替换用于使用“background_r”变量的值定义“new_background_r”参数。
arg:
- name: 'turtlesim_ns'
value: 'turtlesim2'
- name: 'use_provided_red'
value: 'True'
- name: 'new_background_r'
value: '$(var background_r)'
3 替换示例启动文件
现在在同一文件夹中创建替换启动文件:
创建文件“launch/example_substitutions.launch.py”并插入以下代码:
from launch_ros.actions import Node
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, ExecuteProcess, TimerAction
from launch.conditions import IfCondition
from launch.substitutions import LaunchConfiguration, PythonExpression
def generate_launch_description():
turtlesim_ns = LaunchConfiguration('turtlesim_ns')
use_provided_red = LaunchConfiguration('use_provided_red')
new_background_r = LaunchConfiguration('new_background_r')
turtlesim_ns_launch_arg = DeclareLaunchArgument(
'turtlesim_ns',
default_value='turtlesim1'
)
use_provided_red_launch_arg = DeclareLaunchArgument(
'use_provided_red',
default_value='False'
)
new_background_r_launch_arg = DeclareLaunchArgument(
'new_background_r',
default_value='200'
)
turtlesim_node = Node(
package='turtlesim',
namespace=turtlesim_ns,
executable='turtlesim_node',
name='sim'
)
spawn_turtle = ExecuteProcess(
cmd=[[
'ros2 service call ',
turtlesim_ns,
'/spawn ',
'turtlesim/srv/Spawn ',
'"{x: 2, y: 2, theta: 0.2}"'
]],
shell=True
)
change_background_r = ExecuteProcess(
cmd=[[
'ros2 param set ',
turtlesim_ns,
'/sim background_r ',
'120'
]],
shell=True
)
change_background_r_conditioned = ExecuteProcess(
condition=IfCondition(
PythonExpression([
new_background_r,
' == 200',
' and ',
use_provided_red
])
),
cmd=[[
'ros2 param set ',
turtlesim_ns,
'/sim background_r ',
new_background_r
]],
shell=True
)
return LaunchDescription([
turtlesim_ns_launch_arg,
use_provided_red_launch_arg,
new_background_r_launch_arg,
turtlesim_node,
spawn_turtle,
change_background_r,
TimerAction(
period=2.0,
actions=[change_background_r_conditioned],
)
])
定义了 turtlesim_ns
、use_provided_red
和 new_background_r
启动配置。
它们用于将启动参数的值存储在上述变量中,并将它们传递给所需的操作。
这些 LaunchConfiguration
替换允许我们在启动描述的任何部分获取启动参数的值。
DeclareLaunchArgument
用于定义可以从上述启动文件或控制台传递的启动参数。
turtlesim_ns = LaunchConfiguration('turtlesim_ns')
use_provided_red = LaunchConfiguration('use_provided_red')
new_background_r = LaunchConfiguration('new_background_r')
turtlesim_ns_launch_arg = DeclareLaunchArgument(
'turtlesim_ns',
default_value='turtlesim1'
)
use_provided_red_launch_arg = DeclareLaunchArgument(
'use_provided_red',
default_value='False'
)
new_background_r_launch_arg = DeclareLaunchArgument(
'new_background_r',
default_value='200'
)
定义了将“namespace”设置为“turtlesim_ns”的“LaunchConfiguration”替换的“turtlesim_node”节点。
turtlesim_node = Node(
package='turtlesim',
namespace=turtlesim_ns,
executable='turtlesim_node',
name='sim'
)
随后,使用相应的“cmd”参数定义名为“spawn_turtle”的“ExecuteProcess”操作。 此命令调用 turtlesim 节点的 spawn 服务。 此外,“LaunchConfiguration”替换用于获取“turtlesim_ns”启动参数的值以构造命令字符串。
spawn_turtle = ExecuteProcess(
cmd=[[
'ros2 service call ',
turtlesim_ns,
'/spawn ',
'turtlesim/srv/Spawn ',
'"{x: 2, y: 2, theta: 0.2}"'
]],
shell=True
)
相同的方法也用于改变 turtlesim 背景的红色参数的“change_background_r”和“change_background_r_condition”操作。 不同之处在于,只有当提供的“new_background_r”参数等于“200”并且“use_provided_red”启动参数设置为“True”时,才会执行“change_background_r_condition”操作。 “IfCondition”中的评估是使用“PythonExpression”替换完成的。
change_background_r = ExecuteProcess(
cmd=[[
'ros2 param set ',
turtlesim_ns,
'/sim background_r ',
'120'
]],
shell=True
)
change_background_r_conditioned = ExecuteProcess(
condition=IfCondition(
PythonExpression([
new_background_r,
' == 200',
' and ',
use_provided_red
])
),
cmd=[[
'ros2 param set ',
turtlesim_ns,
'/sim background_r ',
new_background_r
]],
shell=True
)
创建文件“launch/example_substitutions.launch.yaml”并插入以下代码:
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/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
children:
- 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)")'
定义了 turtlesim_ns
、use_provided_red
和 new_background_r
启动配置。
它们用于将启动参数的值存储在上述变量中,并将它们传递给所需的操作。
启动配置参数稍后可以与 $(var <name>)
替换一起使用,以获取启动描述任何部分中的启动参数的值。
arg
标签用于定义可以从上述启动文件或控制台传递的启动参数。
- arg:
name: 'turtlesim_ns'
default: 'turtlesim1'
- arg:
name: 'use_provided_red'
default: 'False'
- arg:
name: 'new_background_r'
default: '200'
使用“$(var <name>)”替换将“namespace”设置为“turtlesim_ns”启动配置值的“turtlesim_node”节点定义。
- node:
pkg: 'turtlesim'
namespace: '$(var turtlesim_ns)'
exec: 'turtlesim_node'
name: 'sim'
随后,使用相应的“cmd”标签定义一个“可执行”操作。 此命令调用 turtlesim 节点的 spawn 服务。
此外,使用“$(var <name>)”替换来获取“turtlesim_ns”启动参数的值以构造命令字符串。
- executable:
cmd: 'ros2 service call $(var turtlesim_ns)/spawn turtlesim/srv/Spawn "{x: 5, y: 2, theta: 0.2}"'
相同的方法也用于改变 turtlesim 背景红色参数的“ros2 param”“可执行”操作。 不同之处在于,只有当提供的“new_background_r”参数等于“200”且“use_provided_red”启动参数设置为“True”时,才会执行计时器内的第二个操作。 使用“$(eval <python-expression>)”替换来评估“if”谓词。
- executable:
cmd: 'ros2 param set $(var turtlesim_ns)/sim background_r 120'
- timer:
period: 2.0
children:
- 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)")'
4 构建包
转到工作区的根目录,然后构建包:
colcon build
还要记住在构建后获取工作区。
启动示例
现在您可以使用“ros2 launch”命令启动。
ros2 launch launch_tutorial example_main.launch.py
ros2 launch launch_tutorial example_main.launch.yaml
这将执行以下操作:
启动具有蓝色背景的 turtlesim 节点
生成第二只海龟
将颜色更改为紫色
如果提供的
background_r
参数为200
且use_provided_red
参数为True
,则在两秒后将颜色更改为粉红色
修改启动参数
如果您想更改提供的启动参数,您可以在“example_main.launch.py”中的“launch_arguments”字典中更新它们,或者使用首选参数启动“example_substitutions.launch.py”。 要查看可能提供给启动文件的参数,请运行以下命令:
ros2 launch launch_tutorial example_substitutions.launch.py --show-args
如果您想更改提供的启动参数,您可以更新“example_main.launch.yaml”中的“background_r”变量,或者使用首选参数启动“example_substitutions.launch.yaml”。 要查看可能提供给启动文件的参数,请运行以下命令:
ros2 launch launch_tutorial example_substitutions.launch.yaml --show-args
这将显示可能提供给启动文件的参数及其默认值。
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')
现在您可以将所需的参数传递给启动文件,如下所示:
ros2 launch launch_tutorial example_substitutions.launch.py turtlesim_ns:='turtlesim3' use_provided_red:='True' new_background_r:=200
ros2 launch launch_tutorial example_substitutions.launch.yaml turtlesim_ns:='turtlesim3' use_provided_red:='True' new_background_r:=200
文档
The launch documentation provides detailed information about available substitutions.
摘要
在本教程中,您了解了如何在启动文件中使用替换。
您了解了它们创建可重复使用的启动文件的可能性和功能。
您现在可以了解有关 在启动文件中使用事件处理程序 的更多信息,这些事件处理程序用于定义一组复杂的规则,可用于动态修改启动文件。