Robotics StackExchange | Archived questions

ROS 2 Variables Substitution Inside YAML

Hi,

in ROS1, I was able to use $(arg variable) inside the YAML if the attribute subst_value was set to true in the Launch file.

However, in ROS 2 (using KUbuntu 20 LTS + ROS 2 Foxy), there seems to be no alternative to do that.

Although setting the parameter in the launch file could be an alternative, I am uses environment variable to set the namespace of the nodes. And that is not possible to properly define the parameters in the YAML without putting in plain text the variable's value.

launch.py

import os

import yaml

from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.launch_context import LaunchContext
from launch.substitutions import EnvironmentVariable, LaunchConfiguration



def generate_launch_description():

  context = LaunchContext()



  robot_id = LaunchConfiguration('robot_id')

  robot_id_launch_arg = DeclareLaunchArgument(
    name='robot_id',
    default_value=EnvironmentVariable(
      name='ROBOT_ID',
      default_value='unnamed_robot'
    )
  )



  sdpo_hangfaq2_driver_param_path = os.path.join(
    FindPackageShare('sdpo_hangfaq2_driver').perform(context),
    'config','sdpo_hangfaq2_driver.yaml'
  )

  with open(sdpo_hangfaq2_driver_param_path, 'r') as param_file:

    sdpo_hangfaq2_driver_param = yaml.load(
      stream=param_file,
      Loader=yaml.SafeLoader
    )



  sdpo_hangfaq2_driver_node = Node(
    namespace=robot_id,
    package='sdpo_hangfaq2_driver',
    executable='sdpo_hangfaq2_driver',
    name='sdpo_hangfaq2_driver',
    parameters=[sdpo_hangfaq2_driver_param]
  )


  return LaunchDescription([
    robot_id_launch_arg,
    sdpo_hangfaq2_driver_node
  ])

yaml

/$(var robot_id):
  sdpo_hangfaq2_driver:
    ros__parameters:
      encoder_res: 48.06666
      gear_reduction: 64.06666
      serial_port_name: "/dev/ttyACM06666"

Best regards,

Ricardo

Asked by Ricardo B. Sousa on 2023-07-20 05:09:56 UTC

Comments

Answers

I'm not sure if doing a substitution in the yaml parameters file is possible. However, you should be able to load a default parameters files and then replace an element of the loaded dict with your LaunchConfiguration variable. This should enable setting the robot_id at runtime.

Asked by jdlangs on 2023-07-20 10:15:29 UTC

Comments

The problem is that /$(var robot_id): in the YAML file is a key of the dictionary, not a parameters' value... only if we pop the variable, change the key accordingly, and then push again the variable to the dictionary...

Asked by Ricardo B. Sousa on 2023-07-20 11:37:10 UTC

Isn't that key a node namespace? Why not use the namespace argument for launch_ros.actions.Node (which can be substituted) and then load parameters as a plain dict?

Asked by jdlangs on 2023-07-20 15:32:35 UTC

Although I did not find a way to substitute values inside YAML similar to ROS 1, launch.xml format allows nested parameters and use the substitution:

<launch>

  <arg name="robot_id" default="$(env ROBOT_ID 'unnamed_robot')"/>



  <node pkg="vineslam_ros" exec="slam_node"
      name="slam_node"
      namespace="$(var robot_id)">

    <remap from="/odom_topic" to ="odom"/>
    <remap from="/scan_topic" to ="scan"/>



    <param name="world_frame_id" value="$(var robot_id)/map"/>
    <param name="odom_frame_id" value="$(var robot_id)/odom"/>
    <param name="base_frame_id" value="$(var robot_id)/base_footprint"/>
    <param name="lidar_sensor_frame" value="$(var robot_id)/rslidar"/>

    <param name="use_semantic_features" value="False"/>
    <param name="use_lidar_features" value="True"/>
    <param name="use_vertical_planes" value="False"/>
    <param name="use_ground_plane" value="False"/>
    <param name="use_imu" value="False"/>
    <param name="use_gyroscope" value="False"/>
    <param name="use_gps" value="False"/>
    <param name="use_gps_altitude" value="False"/>
    <param name="use_gps_heading" value="False"/>

    <param name="publish_level" value="2"/>

    <param name="robot_dimensions">
      <param name="x" value="0.42"/>
      <param name="y" value="0.32"/>
      <param name="z" value="0.37"/>
    </param>

    <param name="multilayer_mapping">

      <param name="datum">
        <param name="latitude" value="45.706199"/>
        <param name="longitude" value="7.2495435"/>
        <param name="altitude" value="668.63"/>
      </param>

      <param name="topological_map">
        <param name="autogen_topological_map" value="True"/>
        <param name="folder" value="/home/sousarbarb/.ros/vineslam/"/>

        <param name="dimensions">
          <param name="x" value="100.0"/>
          <param name="y" value="100.0"/>
          <param name="square_size" value="20.0"/>
        </param>
      </param>

      <param name="grid_map">
        <param name="origin">
          <param name="z" value="0.0"/>
        </param>

        <param name="height" value="30.0"/>
        <param name="resolution" value="0.25"/>
      </param>

    </param>

    <param name="pf">
      <param name="n_particles" value="300"/>
      <param name="sigma_xx" value="0.3"/>
      <param name="sigma_yy" value="0.3"/>
      <param name="sigma_zz" value="0.2"/>
      <param name="sigma_RR" value="0.1"/>
      <param name="sigma_PP" value="0.1"/>
      <param name="sigma_YY" value="0.2"/>
    </param>

  </node>

</launch>

Asked by Ricardo B. Sousa on 2023-07-26 03:49:37 UTC

Comments