Migrating launch files from ROS 1 to ROS 2
Table of Contents
This guide describes how to write XML launch files for an easy migration from ROS 1.
Background
A description of the ROS 2 launch system and its Python API can be found in Launch System tutorial.
Migrating tags from ROS 1 to ROS 2
launch
launch
is the root element of any ROS 2 launch XML file.
node
Launches a new node.
Differences from ROS 1:
type
attribute is nowexec
.ns
attribute is nownamespace
.The following attributes aren’t available:
machine
,respawn_delay
,clear_params
.
Example
<launch>
<node pkg="demo_nodes_cpp" exec="talker"/>
<node pkg="demo_nodes_cpp" exec="listener"/>
</launch>
param
Used for passing a parameter to a node.
There’s no global parameter concept in ROS 2. For that reason, it can only be used nested in a
node
tag. Some attributes aren’t supported in ROS 2:type
,textfile
,binfile
,executable
,command
.
Example
<launch>
<node pkg="demo_nodes_cpp" exec="parameter_event">
<param name="foo" value="5"/>
</node>
</launch>
Type inference rules
Here are some examples of how to write parameters:
<node pkg="my_package" exec="my_executable" name="my_node">
<!--A string parameter with value "1"-->
<param name="a_string" value="'1'"/>
<!--A integer parameter with value 1-->
<param name="an_int" value="1"/>
<!--A float parameter with value 1.0-->
<param name="a_float" value="1.0"/>
<!--A string parameter with value "asd"-->
<param name="another_string" value="asd"/>
<!--Another string parameter, with value "asd"-->
<param name="string_with_same_value_as_above" value="'asd'"/>
<!--Another string parameter, with value "'asd'"-->
<param name="quoted_string" value="\'asd\'"/>
<!--A list of strings, with value ["asd", "bsd", "csd"]-->
<param name="list_of_strings" value="asd, bsd, csd" value-sep=", "/>
<!--A list of ints, with value [1, 2, 3]-->
<param name="list_of_ints" value="1,2,3" value-sep=","/>
<!--Another list of strings, with value ["1", "2", "3"]-->
<param name="another_list_of_strings" value="'1';'2';'3'" value-sep=";"/>
<!--A list of strings using an strange separator, with value ["1", "2", "3"]-->
<param name="strange_separator" value="'1'//'2'//'3'" value-sep="//"/>
</node>
Parameter grouping
In ROS 2, param
tags are allowed to be nested.
For example:
<node pkg="my_package" exec="my_executable" name="my_node" ns="/an_absoulute_ns">
<param name="group1">
<param name="group2">
<param name="my_param" value="1"/>
</param>
<param name="another_param" value="2"/>
</param>
</node>
That will create two parameters:
A
group1.group2.my_param
of value1
, hosted by node/an_absolute_ns/my_node
.A
group1.another_param
of value2
hosted by node/an_absolute_ns/my_node
.
It’s also possible to use full parameter names:
<node pkg="my_package" exec="my_executable" name="my_node" ns="/an_absoulute_ns">
<param name="group1.group2.my_param" value="1"/>
<param name="group1.another_param" value="2"/>
</node>
rosparam
Loads parameters from a yaml file.
It has been replaced with a
from
attribute inparam
tags.
Example
<node pkg="my_package" exec="my_executable" name="my_node" ns="/an_absoulute_ns">
<param from="/path/to/file"/>
</node>
remap
Used to pass remapping rules to a node.
It can only be used within
node
tags.
Example
<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
Allows including another launch file.
Differences from ROS 1:
Available in ROS 1, included content was scoped. In ROS 2, it’s not. Nest includes in
group
tags to scope them.ns
attribute is not supported. See example ofpush_ros_namespace
tag for a workaround.arg
tags nested in aninclude
tag don’t support conditionals (if
orunless
).There is no support for nested
env
tags.set_env
andunset_env
can be used instead.Both
clear_params
andpass_all_args
attributes aren’t supported.
Examples
arg
arg
is used for declaring a launch argument, or to pass an argument when usinginclude
tags.Differences from ROS 1:
value
attribute is not allowed. Uselet
tag for this.doc
is nowdescription
.When nested within an
include
tag,if
andunless
attributes aren’t allowed.
Example
<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>
Passing an argument to the launch file
In the XML launch file above, the topic_name
defaults to the name chatter
, but can be configured on the command-line.
Assuming the above launch configuration is in a file named mylaunch.xml
, a different topic name can be used by launching it with the following:
ros2 launch mylaunch.xml topic_name:=custom_topic_name
There is some additional information about passing command-line arguments in Using Substitutions.
env
Sets an environment variable.
It has been replaced with
env
,set_env
andunset_env
:env
can only be used nested in anode
orexecutable
tag.if
andunless
tags aren’t supported.set_env
can be nested within the root taglaunch
or ingroup
tags. It accepts the same attributes asenv
, and alsoif
andunless
tags.unset_env
unsets an environment variable. It accepts aname
attribute and conditionals.
Example
<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>
group
Allows limiting the scope of launch configurations. Usually used together with
let
,include
andpush_ros_namespace
tags.Differences from ROS 1:
There is no
ns
attribute. See the newpush_ros_namespace
tag as a workaround.clear_params
attribute isn’t available.It doesn’t accept
remap
norparam
tags as children.
Example
launch-prefix
configuration affects both executable
and node
tags’ actions.
This example will use time
as a prefix if use_time_prefix_in_talker
argument is 1
, only for the talker.
<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
It is not supported at the moment.
test
It is not supported at the moment.
New tags in ROS 2
push_ros_namespace
include
and group
tags don’t accept an ns
attribute.
This action can be used as a workaround:
<!-Other tags-->
<group>
<push_ros_namespace namespace="my_ns"/>
<!--Nodes here are namespaced with "my_ns".-->
<!--If there is an include action here, its nodes will also be namespaced.-->
<push_ros_namespace namespace="another_ns"/>
<!--Nodes here are namespaced with "another_ns/my_ns".-->
<push_ros_namespace namespace="/absolute_ns"/>
<!--Nodes here are namespaced with "/absolute_ns".-->
<!--The following node receives an absolute namespace, so it will ignore the others previously pushed.-->
<!--The full path of the node will be /asd/my_node.-->
<node pkg="my_pkg" exec="my_executable" name="my_node" ns="/asd"/>
</group>
<!--Nodes outside the group action won't be namespaced.-->
<!-Other tags-->
Replacing an include tag
In order to include a launch file under a namespace as in ROS 1 then the include
tags must be nested in a group
tag.
<group>
<include file="another_launch_file"/>
</group>
Then, instead of using the ns
attribute, add the push_ros_namespace
action tag to specify the namespace:
<group>
<push_ros_namespace namespace="my_ns"/>
<include file="another_launch_file"/>
</group>
Nesting include
tags under a group
tag is only required when specifying a namespace
Substitutions
Documentation about ROS 1’s substitutions can be found in roslaunch XML wiki.
Substitutions syntax hasn’t changed, i.e. it still follows the $(substitution-name arg1 arg2 ...)
pattern.
There are, however, some changes w.r.t. ROS 1:
env
andoptenv
tags have been replaced by theenv
tag.$(env <NAME>)
will fail if the environment variable doesn’t exist.$(env <NAME> '')
does the same as ROS 1’s$(optenv <NAME>)
.$(env <NAME> <DEFAULT>)
does the same as ROS 1’s$(env <NAME> <DEFAULT>)
or$(optenv <NAME> <DEFAULT>)
.find
has been replaced withfind-pkg-share
(substituting the share directory of an installed package). Alternativelyfind-pkg-prefix
will return the root of an installed package.There is a new
exec-in-pkg
substitution. e.g.:$(exec-in-pkg <package_name> <exec_name>)
.There is a new
find-exec
substitution.arg
has been replaced withvar
. It looks at configurations defined either witharg
orlet
tag.eval
anddirname
substitutions haven’t changed.anon
substitution is not supported.
Type inference rules
The rules that were shown in Type inference rules
subsection of param
tag applies to any attribute.
For example:
<!--Setting a string value to an attribute expecting an int will raise an error.-->
<tag1 attr-expecting-an-int="'1'"/>
<!--Correct version.-->
<tag1 attr-expecting-an-int="1"/>
<!--Setting an integer in an attribute expecting a string will raise an error.-->
<tag2 attr-expecting-a-str="1"/>
<!--Correct version.-->
<tag2 attr-expecting-a-str="'1'"/>
<!--Setting a list of strings in an attribute expecting a string will raise an error.-->
<tag3 attr-expecting-a-str="asd, bsd" str-attr-sep=", "/>
<!--Correct version.-->
<tag3 attr-expecting-a-str="don't use a separator"/>
Some attributes accept more than a single type, for example value
attribute of param
tag.
It’s usual that parameters that are of type int
(or float
) also accept an str
, that will be later substituted and tried to convert to an int
(or float
) by the action.