ROS2-006-Communication Mechanisms: Action Communication Extra: How to Implement a Custom Action Interface Message
Introduction
The flow for implementing a custom action interface message is similar to that of implementing a custom topic interface message, the main steps being:
- Create and write the
.actionfile; - Edit the configuration files;
- Build;
- Test.
So now, in the interface package base_interfaces_demo we created before, let's try writing an .action file. That file contains the request data (two integer fields) and the response data (one integer field).
Creating and editing the .action file
In the base_interfaces_demo package create a new action folder, and in the action folder create a new Progress.action file, then enter the following into it:
int64 num
---
int64 sum
---
float64 progressEditing the configuration files
1. The package.xml file
In package.xml we need to add some dependency packages, specifically:
<!-- build dependency -->
<buildtool_depend>rosidl_default_generators</buildtool_depend>
<!-- dependency -->
<depend>action_msgs</depend>
<!-- declare the package group this package belongs to -->
<member_of_group>rosidl_interface_packages</member_of_group>Looks a bit like a repeat?
The dependency packages the action file needs are basically the same as the ones the msg file needed in implementing a custom interface message above. If you're adding an action file to a newly created package, then some of the dependencies can just refer to the package.xml configuration from when the msg file was defined.
If, when you implemented the custom interface message earlier, you already created the base_interfaces_demo package and already configured the dependency packages for the msg file, then the package.xml here only needs the following code added:
<!-- build dependency -->
<buildtool_depend>rosidl_default_generators</buildtool_depend>
<!-- dependency -->
<depend>action_msgs</depend>Note it's <buildtool_depend> and not the earlier <build_depend>!
2. The CMakeLists.txt file
To turn the .action file into the corresponding C++ and Python code, you also need to add the following configuration to CMakeLists.txt:
find_package(rosidl_default_generators REQUIRED)
# generate source code for the interface file
rosidl_generate_interfaces(${PROJECT_NAME}
"action/Progress.action"
)Looks a bit like a repeat again?
The new CMakeLists.txt configuration the action file needs is basically the same as the configuration for CMakeLists.txt in implementing a custom interface message above. If you're adding the new CMakeLists.txt configuration to a newly created package, then just refer to the configuration above.
If, when you implemented the custom interface message earlier, you already applied this configuration to CMakeLists.txt, then here you only need to add one more parameter to the rosidl_generate_interfaces function, like this:
# generate source code for the interface file
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/Student.msg"
"action/Progress.action"
)Build
In a terminal, go into the current workspace and build the package:
colcon build --packages-select base_interfaces_demoTest
Once the build is done, the C++ and Python files corresponding to Progress.action will be generated in the install directory under the workspace. We can also go into the workspace from the terminal and use the following command to check the file definition and whether the build went fine:
. install/setup.bash
ros2 interface show base_interfaces_demo/action/Progress.actionAnd with that the creation work is done.
Including a custom interface file may throw an error
Once the creation work is done, you'll need to include the headers related to the custom message in your C++ file. At that point VSCode may throw an exception. You can open the c_cpp_properties.json file in VSCode and add one more path line under the includePath property:
"${workspaceFolder}/install/base_interfaces_demo/include/**"
Once that's added, the exception won't be thrown when you include the related headers. The same goes for using other interface files or interface packages.
Custom Python import paths
When importing the packages related to a custom message in a Python file, for convenience you can configure the settings.json file in VSCode and add one more line under the python.autoComplete.extraPaths and python.analysis.extraPaths properties:
"${workspaceFolder}/install/base_interfaces_demo/lib/python3.12/site-packages"
Once that's added, the code gets highlighted and auto-completes; the same goes for using other interface files or interface packages.
(Note: the ROS2 version used here is Jazzy and Python is 3.12, so the path structure is not necessarily the same — please adjust as needed based on the file tree)
Tips
If you came here from ROS2-006-Communication Mechanisms: Action Communication, you can navigate back from here.
Important
This article was translated by Hermes Agent; the original text can be found at here. The translation is for reference only. Translation time: 2026-11-05
