Skip to content

Instantly share code, notes, and snippets.

@clalancette
Created December 5, 2019 18:45
Show Gist options
  • Save clalancette/5d15df1f54a1e01946659dbfa6c46c30 to your computer and use it in GitHub Desktop.
Save clalancette/5d15df1f54a1e01946659dbfa6c46c30 to your computer and use it in GitHub Desktop.
Using xacro with ROS 2 python launch
The goal here is to be able to use the ROS 2 python launch system to generate URDF files from xacro files, utilizing substitution. All of the comments below are an attempt to solve this problem.
# Robot state publisher
In order to make this work, it is easiest to use the refactored robot_state_publisher branch https://github.com/ros/robot_state_publisher/tree/ros2-refactor . The reason for this is that the refactor takes the `robot_description` as a parameter rather than as an argument on the command-line. This branch isn't currently reviewed or released into any ROS 2 distribution, so it needs to be built from source. (I'll note that it is probably *possible* to make all of this work with the version of robot_state_publisher released into Eloquent, but the rest of this comment will assume you are using the ros2-refactor branch).
```
source /opt/ros/eloquent/setup.bash
mkdir -p rsp_ws/src
cd rsp_ws/src
git clone https://github.com/ros/robot_state_publisher -b ros2-refactor
cd ..
colcon build
```
# Xacro file
The rest of the comments will assume the simple xacro file as follows. More complex ones will probably work but have not been tested:
```
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="test">
<xacro:arg name="length" default="0.6"/>
<xacro:property name="length" value="$(arg length)"/>
<xacro:arg name="radius" default="0.2"/>
<xacro:property name="radius" value="$(arg radius)"/>
<link name="base_link">
<visual>
<geometry>
<cylinder length="${length}" radius="${radius}"/>
</geometry>
<material name="blue"/>
</visual>
</link>
</robot>
```
# Launch file
Now we can put the above together and create a launch file that will take the xacro file, create a URDF file from it (incorporating any mappings from the user):
```
import launch
import launch_ros.actions
import xacro
def generate_launch_description():
doc = xacro.process_file('/home/ubuntu/rsp_ws/test-desc.urdf.xacro', mappings={'radius': '0.9'})
robot_desc = doc.toprettyxml(indent=' ')
params = {'robot_description': robot_desc}
rsp = launch_ros.actions.Node(package='robot_state_publisher',
node_executable='robot_state_publisher_node',
output='both',
parameters=[params])
return launch.LaunchDescription([rsp])
```
Note that the mappings parameter is a dictionary of keys to values, so as many mapping as necessary can be substituted in.
# Output
The output will be as follows:
```
<?xml version=\"1.0\" ?>
<!-- =================================================================================== -->
<!-- | This document was autogenerated by xacro from /home/ubuntu/rsp_ws/test-desc.urdf.xacro | -->
<!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | -->
<!-- =================================================================================== -->
<robot name="test">
<link name="base_link">
<visual>
<geometry>
<cylinder length="0.6" radius="0.9"/>
</geometry>
<material name="blue"/>
</visual>
</link>
</robot>
```
@superseppl
Copy link

Thanks for the detailed explanation. One question, how can I pass LaunchArguments to the xacro files?

@MrBlenny
Copy link

@shrinivas96
Copy link

There is a property in my xacro file that I would like to retrieve the value of inside the python launch file. Any idea how I could achieve that? (Yes, I know the other option is to pass that propery value as arguments into the xacro file.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment