迁移 Launch 文件
虽然 ROS 1 中的 launch 文件始终使用 XML 文件指定,但 ROS 2 同时支持 XML 和 YAML 文件。 ROS 2 还支持 Python launch 脚本以实现更大的灵活性(参见 launch 软件包)。 但是,对于典型的用例,应优先使用 XML 和 YAML 而非 Python。
本指南描述了如何编写 ROS 2 XML launch 文件,以便从 ROS 1 轻松迁移。
有关 ROS 2 launch 系统的描述可在 Launch 系统教程 中找到。
launch
Section titled “launch”- 在 ROS 1 中可用。
launch是任何 ROS 2 launch XML 文件的根元素。
-
启动一个新节点。
-
与 ROS 1 的差异:
type属性现在是exec。ns属性现在是namespace。required="true"现在是on_exit="shutdown"。- 以下属性不再可用:
machine、respawn_delay、clear_params。
<launch> <node pkg="demo_nodes_cpp" exec="talker"/> <node pkg="demo_nodes_cpp" exec="listener"/></launch>- 在 ROS 1 中可用。
- 用于向节点传递参数。
- ROS 2 中没有全局参数概念。
因此,它只能嵌套在
node标签中使用。 ROS 2 中不支持某些属性:type、textfile、binfile、executable。 command属性现在是value="$(command '...' )"。
<launch> <node pkg="demo_nodes_cpp" exec="parameter_event"> <param name="foo" value="5"/> </node></launch>类型推断规则
Section titled “类型推断规则”以下是一些如何编写参数的示例:
<node pkg="my_package" exec="my_executable" name="my_node"> <!--值为 "1" 的字符串参数--> <param name="a_string" value="'1'"/> <!--值为 1 的整数参数--> <param name="an_int" value="1"/> <!--值为 1.0 的浮点数参数--> <param name="a_float" value="1.0"/> <!--值为 "asd" 的字符串参数--> <param name="another_string" value="asd"/> <!--另一个值为 "asd" 的字符串参数--> <param name="string_with_same_value_as_above" value="'asd'"/> <!--另一个值为 "'asd'" 的字符串参数--> <param name="quoted_string" value="\'asd\'"/> <!--值为 ["asd", "bsd", "csd"] 的字符串列表--> <param name="list_of_strings" value="asd, bsd, csd" value-sep=", "/> <!--值为 [1, 2, 3] 的整数列表--> <param name="list_of_ints" value="1,2,3" value-sep=","/> <!--另一个值为 ["1", "2", "3"] 的字符串列表--> <param name="another_list_of_strings" value="'1';'2';'3'" value-sep=";"/> <!--使用特殊分隔符的字符串列表,值为 ["1", "2", "3"]--> <param name="strange_separator" value="'1'//'2'//'3'" value-sep="//"/></node>在 ROS 2 中,param 标签允许嵌套。
例如:
<node pkg="my_package" exec="my_executable" name="my_node" namespace="/an_absoulute_ns"> <param name="group1"> <param name="group2"> <param name="my_param" value="1"/> </param> <param name="another_param" value="2"/> </param></node>这将创建两个参数:
- 值为
1的group1.group2.my_param,由节点/an_absolute_ns/my_node托管。 - 值为
2的group1.another_param,由节点/an_absolute_ns/my_node托管。
也可以使用完整的参数名称:
<node pkg="my_package" exec="my_executable" name="my_node" namespace="/an_absoulute_ns"> <param name="group1.group2.my_param" value="1"/> <param name="group1.another_param" value="2"/></node>rosparam
Section titled “rosparam”- 在 ROS 1 中可用。
- 从 yaml 文件加载参数。
- 已被
param标签中的from属性替代。
<node pkg="my_package" exec="my_executable" name="my_node" namespace="/an_absoulute_ns"> <param from="/path/to/file"/></node>- 在 ROS 1 中可用。
- 用于向节点传递重映射规则。
- 只能在
node标签内使用。
<launch> <node pkg="demo_nodes_cpp" exec="talker"> <remap from="chatter" to="my_topic"/> </node> <node pkg="demo_nodes_cpp" exec="listener"> <remap from="chatter" to="my_topic"/> </node></launch>include
Section titled “include”-
允许包含另一个 launch 文件。
-
与 ROS 1 的差异:
- 在 ROS 1 中,包含的内容是有作用域的。
在 ROS 2 中则不是。
这意味着
arg标签的值会传播到包含的 launch 文件中,就像在 ROS 1 中使用了pass_all_args="true"一样。 但是,此传播仅适用于有默认值的参数(在被包含的 launch 文件中)。 必需参数必须显式传递。 将 include 嵌套在group标签中以限定其作用域(另请参阅group属性scoped和forwarding)。 - 不支持
ns属性。 参见push_ros_namespace标签的示例以了解替代方案。 - 嵌套在
include标签中的arg标签现在是let。 但是,arg目前仍然受支持。 - 嵌套在
include标签中的let标签不支持条件判断(if、unless)或description属性。 - 不支持嵌套的
env标签。 可以改用set_env和unset_env。 clear_params和pass_all_args属性都不受支持。 ROS 2 launch 的行为就好像pass_all_args被设置为 true 一样(见上文)。
- 在 ROS 1 中,包含的内容是有作用域的。
在 ROS 2 中则不是。
这意味着
参见下文的替换 include 标签。
-
arg用于声明 launch 参数,或在使用include标签时传递参数。 -
与 ROS 1 的差异:
-
不允许
value属性。 请使用let标签。 -
doc现在是description。 -
当嵌套在
include标签内时:- 使用
let代替arg。 - 不允许
if、unless和description属性。
- 使用
-
<launch> <arg name="topic_name" default="chatter"/> <node pkg="demo_nodes_cpp" exec="talker"> <remap from="chatter" to="$(var topic_name)"/> </node> <node pkg="demo_nodes_cpp" exec="listener"> <remap from="chatter" to="$(var topic_name)"/> </node></launch>向 launch 文件传递参数
Section titled “向 launch 文件传递参数”在上面的 XML launch 文件中,topic_name 默认为 chatter,但可以在命令行上配置。
假设上述 launch 配置在一个名为 mylaunch.xml 的文件中,可以通过以下方式启动来使用不同的 topic 名称:
ros2 launch mylaunch.xml topic_name:=custom_topic_name有关传递命令行参数的更多信息,请参阅使用替换(Substitutions)。
-
设置环境变量。
-
已被
env、set_env和unset_env替代:env只能嵌套在node或executable标签中使用。 不支持if和unless标签。set_env可以嵌套在根标签launch或group标签中。 它接受与env相同的属性,以及if和unless标签。unset_env取消设置环境变量。 它接受name属性和条件判断。
<launch> <set_env name="MY_ENV_VAR" value="MY_VALUE" if="CONDITION_A"/> <set_env name="ANOTHER_ENV_VAR" value="ANOTHER_VALUE" unless="CONDITION_B"/> <set_env name="SOME_ENV_VAR" value="SOME_VALUE"/> <node pkg="MY_PACKAGE" exec="MY_EXECUTABLE" name="MY_NODE"> <env name="NODE_ENV_VAR" value="SOME_VALUE"/> </node> <unset_env name="MY_ENV_VAR" if="CONDITION_A"/> <node pkg="ANOTHER_PACKAGE" exec="ANOTHER_EXECUTABLE" name="ANOTHER_NODE"/> <unset_env name="ANOTHER_ENV_VAR" unless="CONDITION_B"/> <unset_env name="SOME_ENV_VAR"/></launch>-
允许限制 launch 配置的作用域。 通常与
let、include和push_ros_namespace标签一起使用。 -
与 ROS 1 的差异:
- 没有
ns属性。 参见新的push_ros_namespace标签作为替代方案。 clear_params属性不可用。- 它不接受
remap或param标签作为子元素。 - 它有两个新属性:
scoped和forwarding(两者默认为 true)。 如果scoped为 false,则该组不引入新的变量作用域,因此对组内变量所做的操作也会影响外部变量。 如果forwarding为 false,则组内不可使用外部的 launch 配置(arg)。 这可用于隔离被包含的 launch 文件,从而防止参数名称冲突。
- 没有
launch-prefix 配置会影响 executable 和 node 标签的操作。
如果 use_time_prefix_in_talker 参数为 1,此示例将仅对 talker 使用 time 作为前缀。
<launch> <arg name="use_time_prefix_in_talker" default="0"/> <group> <let name="launch-prefix" value="time" if="$(var use_time_prefix_in_talker)"/> <node pkg="demo_nodes_cpp" exec="talker"/> </group> <node pkg="demo_nodes_cpp" exec="listener"/></launch>machine
Section titled “machine”目前不支持。
目前不支持。
ROS 2 中的新标签
Section titled “ROS 2 中的新标签”set_env 和 unset_env
Section titled “set_env 和 unset_env”参见上文 env 标签的描述。
push_ros_namespace
Section titled “push_ros_namespace”include 和 group 标签不接受 ns 属性。
此操作可以用作替代方案:
<!--其他标签--><group> <push_ros_namespace namespace="my_ns"/> <!--这里的节点使用 "my_ns" 作为命名空间。--> <!--如果此处有 include 操作,其节点也将被命名空间化。--> <push_ros_namespace namespace="another_ns"/> <!--这里的节点使用 "another_ns/my_ns" 作为命名空间。--> <push_ros_namespace namespace="/absolute_ns"/> <!--这里的节点使用 "/absolute_ns" 作为命名空间。--> <!--以下节点接收绝对命名空间,因此它将忽略之前推送的其他命名空间。--> <!--节点的完整路径将为 /asd/my_node。--> <node pkg="my_pkg" exec="my_executable" name="my_node" namespace="/asd"/></group><!--group 操作之外的节点不会被命名空间化。--><!--其他标签-->它是带有 value 属性的 arg 标签的替代品。
<let name="foo" value="asd"/>let 和 arg 在 ROS 2 中有两个不同的用途:
let设置 launch 配置值。arg声明一个 launch 参数/配置,并可选地提供默认值。 该值可以单独从 CLI 设置,或在包含给定 launch 文件时设置。 如果未设置任何值,则使用提供的默认值(如果有),否则报告错误。
executable
Section titled “executable”它允许运行任何可执行文件。
<executable cmd="ls -las" cwd="/var/log" name="my_exec" launch-prefix="something" output="screen" shell="true"> <env name="LD_LIBRARY" value="/lib/some.so"/></executable>替换 include 标签
Section titled “替换 include 标签”为了像 ROS 1 那样在命名空间下包含 launch 文件,include 标签必须嵌套在 group 标签中。
<group> <include file="another_launch_file"/></group>然后,不要使用 ns 属性,而是添加 push_ros_namespace 操作标签来指定命名空间:
<group> <push_ros_namespace namespace="my_ns"/> <include file="another_launch_file"/></group>仅在指定命名空间时才需要将 include 标签嵌套在 group 标签下。
替换(Substitutions)
Section titled “替换(Substitutions)”有关 ROS 1 替换的文档可以在 roslaunch XML wiki 中找到。
替换语法没有改变,即仍然遵循 $(substitution-name arg1 arg2 ...) 模式。
但是,相对于 ROS 1 有一些变化:
env和optenv标签已被env标签替代。 如果环境变量不存在,$(env <NAME>)将失败。$(env <NAME> '')的作用与 ROS 1 的$(optenv <NAME>)相同。$(env <NAME> <DEFAULT>)的作用与 ROS 1 的$(env <NAME> <DEFAULT>)或$(optenv <NAME> <DEFAULT>)相同。find已被find-pkg-share替代(替换已安装软件包的 share 目录)。 或者,find-pkg-prefix将返回已安装软件包的根目录。- 新增了
exec-in-pkg替换。 例如:$(exec-in-pkg <exec_name> <package_name>)。 - 新增了
find-exec替换。 arg已被var替代。 它查看由arg或let标签定义的配置。eval和dirname替换需要为字符串值使用转义字符,例如if="$(eval '\'$(var variable)\' == \'val1\'')"。 也可以使用 HTML 转义,如"。- 布尔谓词也可以直接用
equals、not-equals、and、or、any和all替换来表示。 例如,if="$(equals $(var variable) val1)"等价于if="$(eval '\'$(var variable)\' == \'val1\'')"。 eval不会将配置(arg)作为局部 Python 变量传递。 必须通过$(var name)访问它们。- 在 ROS 2 中,
eval的参数必须是带引号的字符串。 这也是表达式内的引号必须被转义的原因。
类型推断规则
Section titled “类型推断规则”在 param 标签的「类型推断规则」小节中展示的规则适用于任何属性。
例如:
<!--将字符串值设置到期望 int 的属性会引发错误。--><tag1 attr-expecting-an-int="'1'"/><!--正确版本。--><tag1 attr-expecting-an-int="1"/><!--将整数设置到期望字符串的属性会引发错误。--><tag2 attr-expecting-a-str="1"/><!--正确版本。--><tag2 attr-expecting-a-str="'1'"/><!--将字符串列表设置到期望字符串的属性会引发错误。--><tag3 attr-expecting-a-str="asd, bsd" str-attr-sep=", "/><!--正确版本。--><tag3 attr-expecting-a-str="don't use a separator"/>某些属性接受多种类型,例如 param 标签的 value 属性。
对于类型为 int(或 float)的参数,通常也接受 str 类型,该字符串随后将被替换并由操作尝试转换为 int(或 float)。