ROS Launch 文件中的替换参数详解
ROS Launch 文件中的替换参数详解
roslaunch 以单次遍历方式处理 XML 文件。包含文件按深度优先顺序处理。标签按顺序解析,最后设置的参数值生效。因此,若某参数存在多次赋值,最终将采用最后一次指定的参数值。
ROS launch 文件支持多种替换参数(substitution args),这些参数在文件被解析时会被替换为实际值。以下是所有可用的替换参数及其详细说明:
基本替换参数
-
$(arg name)
- 用于替换由
<arg>
标签定义的参数值 - 示例:
<arg name="resolution" default="0.1" /> <param name="resolution" value="$(arg resolution)" />
- 用于替换由
-
$(env ENVIRONMENT_VARIABLE)
- 用当前环境中的变量值进行替换。若环境变量未设置,启动将失败。
- 如果环境变量未设置,会抛出错误
- 示例:
<param name="home_dir" value="$(env HOME)" />
-
$(optenv ENVIRONMENT_VARIABLE default_value)
- 若环境变量已设置则替换其值。若提供 default_value 参数,当环境变量未设置时将使用该值。若未提供 default_value 参数,则使用空字符串。 default_value 可以是多个由空格分隔的单词。
- 示例:
<param name="foo" value="$(optenv NUM_CPUS 1)" /> <param name="foo" value="$(optenv CONFIG_PATH /home/marvin/ros_workspace)" /> <param name="foo" value="$(optenv VARIABLE ros rocks)" />
文件路径相关替换参数
-
$(find pkg)
- 例如 $(find rospy)/manifest.xml 。指定一个相对于软件包的路径。软件包目录的文件系统路径将被内联替换。强烈建议使用相对于软件包的路径,因为硬编码路径会降低启动配置的可移植性。正斜杠和反斜杠将被解析为本地文件系统约定。
- 最常用的替换参数之一
- 示例:
<param name="config_file" textfile="$(find my_package)/config/config.yaml" />
-
$(anon name)
- 例如 $(anon rviz-1) 。基于 name 生成一个匿名 ID。 name 本身是一个唯一标识符:多次使用 $(anon foo) 将创建相同的"匿名化"名称。这用于 name 属性,以便创建具有匿名名称的节点,因为 ROS 要求节点具有唯一名称。例如:
- 示例:
<node name="$(anon foo)" pkg="rospy_tutorials" type="talker.py" />
-
$(dirname) Lunar 版本新增功能
- 返回当前launch文件所在目录的绝对路径
- 示例:
<param name="local_config" value="$(dirname)/local_config.yaml" />
条件与评估替换参数
-
$(eval expression) Kinetic 版本新增功能
- 评估Python表达式
- 允许评估任意复杂的 Python 表达式
- 示例:
<param name="circumference" value="$(eval 2.*3.1415*arg('radius'))" />
- 注意!
- 存在一个限制,$(eval) 表达式需要占据整个属性字符串。无法在单个字符串中混合使用其他替换参数与 eval ,比如说:
<param name="foo" value="$(arg foo)$(eval 6*7)bar"/>
- 为了解决这一限制,所有替换命令在eval中也可以作为函数使用:
"$(eval arg('foo') + env('PATH') + 'bar' + find('pkg')"
- 为方便起见,参数也会被隐式解析,即以下两个表达式是等价的:
"$(eval arg('foo'))" "$(eval foo)"
-
$(eval environment_variable)
- 评估环境变量
- 示例:
<param name="path_count" value="$(eval int(env('PATH').count(':'))+1)" />
替换参数目前仅在本地机器上解析。也就是说,即使对于远程启动的进程,环境变量和 ROS 软件包路径也将设置为当前环境中的值。
if 和 unless 属性
所有标签都支持 if 和 unless 属性,这些属性根据值的评估结果来包含或排除标签。"1"和"true"被视为真值,"0"和"false"被视为假值。其他值将导致错误。
- if属性
- if=value (optional) if=value (可选)
若 value 值为真,则包含该标签及其内容。 - unless=value (optional) unless=value (可选)
除非 value 值为真(即当 value 值为假时),否则包含该标签及其内容。 -
<group if="$(arg foo)"><!-- stuff that will only be evaluated if foo is true --></group><param name="foo" value="bar" unless="$(arg foo)" /> <!-- This param won't be set when "unless" condition is met -->
组合使用示例
这些替换参数可以组合使用以实现更复杂的功能:
<launch><arg name="sensor_type" default="lidar" /><!-- 使用find获取包路径,dirname获取当前目录 --><param name="config_path" value="$(find my_robot)/config/$(arg sensor_type)_config.yaml" /><!-- 使用eval进行数学计算 --><param name="scaled_value" value="$(eval arg('base_value') * env('SCALE_FACTOR', 1.0))" /><!-- 使用anon生成唯一节点名 --><node name="$(anon sensor_processor)" pkg="sensor_processing" type="processor_node" output="screen"><!-- 使用optenv获取环境变量,带默认值 --><param name="log_level" value="$(optenv LOG_LEVEL INFO)" /></node>
</launch>
注意事项
- 替换参数在launch文件解析时被处理,不是在运行时
- 复杂的替换逻辑可能会降低launch文件的可读性
- 某些替换参数(如
$(command)
)可能有安全风险,应谨慎使用 - 替换参数不能嵌套使用(如
$(arg $(env VAR))
是不允许的)
掌握这些替换参数可以让你编写更加灵活和强大的ROS launch文件。