UPDATE
As Gijs pointed out, there is already a CMake macro for that:
http://wiki.ros.org/xacro#Building_fr...
The macro is here:
https://github.com/ros/xacro/blob/kin...
It is possible to generate URDF files at compile time thanks to the add_custom_command
and add_custom_target
CMake commands.
In short
- Create a custom command that generates URDF files from XACRO files
- Create a target depending on all your URDF files and that depends on every target of you CMake script
Details
add_custom_command(
OUTPUT
${CMAKE_CURRENT_SOURCE_DIR}/urdf/robot.urdf
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/urdf/box_line_macro.xacro
${CMAKE_CURRENT_SOURCE_DIR}/urdf/box_macro.xacro
${CMAKE_CURRENT_SOURCE_DIR}/urdf/robot.xacro
COMMAND
xacro --inorder robot.xacro -o robot.urdf
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}/urdf/
COMMENT
"Generating ${PROJECT_NAME} robot URDF"
VERBATIM
)
This creates a command that will generate your URDF file, using DEPENDS
makes sure that everytime one of the XACRO file is changed the URDF will be generated.
This means that URDFs are generated only if necessary as long as you list all dependencies correctly. You can multiply this command block to generate multiple URDF files.
add_custom_target(
${PROJECT_NAME}_URDFs_files
ALL
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/urdf/robot.urdf
)
This command creates a CMake target that is built when "make all" is invoked and that depends on the URDF files. This ensures that the custom command will be called.
You should list here all your generated URDF files.
In your launch file instead of something like:
<param name="robot_description" command="$(find xacro)/xacro --inorder $(find xacro_urdf_cmake)/urdf/robot.xacro" />
You now should use:
<param name="robot_description" textfile="$(find xacro_urdf_cmake)/urdf/robot.urdf" />
Instead of generating the URDF at run-time (in the launch file), you can now use the URDF generated at compile time.
Caveats
- It does not work if your xacro files have
($find xacro_urdf_cmake)
because xacro
is invoked by CMake and does not source the workspace you are working in. Use relative paths! - If you are writing some tests, you must manually specify that your test depends on the
${PROJECT_NAME}_URDFs_files
target - URDFs are generated in the source package, you should ignore them with a
.gitignore
file
A demonstration package is available at xacro_urdf_cmake. Checkout the pipeline to see what is does!