You're reading the documentation for a development version. For the latest released version, please have a look at Jazzy.
Configure action introspection
Goal: Configure action introspection for an action client and an action server.
Tutorial level: Advanced
Time: 15 minutes
Overview
ROS 2 applications usually consist of actions to execute specific long-running procedures or work in remote nodes. It is possible to introspect action data communication with action introspection.
ROS 2 actions are built on topics and services, so action introspection is based on Service Introspection.
In this demo, we’ll be highlighting how to configure action introspection state for an action client and an action server and monitor action communication with ros2 action echo
.
Installing the demo
See the installation instructions for details on installing ROS 2.
If you’ve installed ROS 2 binary packages, ensure that you have ros-rolling-demo-nodes-cpp
and ros-rolling-demo-nodes-py
installed.
If you downloaded the archive or built ROS 2 from source, it will already be part of the installation.
Introspection Configuration State
There are three configuration states for action introspection that are the same states as service introspection.
RCL_SERVICE_INTROSPECTION_OFF |
Disabled |
RCL_SERVICE_INTROSPECTION_METADATA |
Only metadata without any user data contents |
RCL_SERVICE_INTROSPECTION_CONTENTS |
User data contents with metadata |
Introspection demo
This demo shows how to manage action introspection and monitor the action data communication with using ros2 action echo
.
Action server
You can find the source code here: fibonacci_action_server.py.
FibonacciActionServer
has a parameter named action_server_configure_introspection
to configure the action introspection state.
class FibonacciActionServer(Node):
...
def on_post_set_parameters_callback(self, parameter_list):
for param in parameter_list:
if param.name != 'action_server_configure_introspection':
continue
introspection_state = ServiceIntrospectionState.OFF
if param.value == 'disabled':
introspection_state = ServiceIntrospectionState.OFF
elif param.value == 'metadata':
introspection_state = ServiceIntrospectionState.METADATA
elif param.value == 'contents':
introspection_state = ServiceIntrospectionState.CONTENTS
self._action_server.configure_introspection(self.get_clock(),
qos_profile_system_default,
introspection_state)
break
...
If you want to try the C++ version, you can find the source code here: fibonacci_action_server.cpp.
Action introspection is disabled by default, so users need to enable it with action_server_configure_introspection
parameter when the server starts up.
In this demo, FibonacciActionServer
enables action introspection when the value of the action_server_configure_introspection
parameter is contents
.
ros2 run action_tutorials_py fibonacci_action_server --ros-args -p action_server_configure_introspection:=contents
To change action introspection state, we need to set the action_server_configure_introspection
parameter as follows.
### User data contents with metadata
$ ros2 param set /fibonacci_action_server action_server_configure_introspection contents
### Or only metadata
$ ros2 param set /fibonacci_action_server action_server_configure_introspection metadata
### To disable
$ ros2 param set /fibonacci_action_server action_server_configure_introspection disabled
Action client
You can find the source code here: fibonacci_action_client.cpp.
FibonacciActionClient
has a parameter named action_client_configure_introspection
to configure the action introspection state.
namespace action_tutorials_cpp
{
class FibonacciActionClient : public rclcpp::Node
...
auto post_set_parameter_callback =
[this](const std::vector<rclcpp::Parameter> & parameters) {
for (const rclcpp::Parameter & param : parameters) {
if (param.get_name() != "action_client_configure_introspection") {
continue;
}
rcl_service_introspection_state_t introspection_state = RCL_SERVICE_INTROSPECTION_OFF;
if (param.as_string() == "disabled") {
introspection_state = RCL_SERVICE_INTROSPECTION_OFF;
} else if (param.as_string() == "metadata") {
introspection_state = RCL_SERVICE_INTROSPECTION_METADATA;
} else if (param.as_string() == "contents") {
introspection_state = RCL_SERVICE_INTROSPECTION_CONTENTS;
}
this->client_ptr_->configure_introspection(
this->get_clock(), rclcpp::SystemDefaultsQoS(), introspection_state);
break;
}
};
...
If you want to try the Python version, you can find the source code here: fibonacci_action_client.py.
And then, we start and configure FibonacciActionClient
in the same way.
ros2 run action_tutorials_cpp fibonacci_action_client --ros-args -p action_client_configure_introspection:=contents
To change action introspection state, we need to set the action_client_configure_introspection
parameter as follows.
Note that FibonacciActionClient
only runs in short time, so it is recommended to set the parameter before running the client as above.
### User data contents with metadata
$ ros2 param set /fibonacci_action_client action_client_configure_introspection contents
### Or only metadata
$ ros2 param set /fibonacci_action_client action_client_configure_introspection metadata
### To disable
$ ros2 param set /fibonacci_action_client action_client_configure_introspection disabled
Introspect
In this tutorial, the following is an example output with action introspection state contents
on both FibonacciActionServer
and FibonacciActionClient
.
To monitor action communication between FibonacciActionServer
and FibonacciActionClient
, let’s run it:
$ ros2 action echo /fibonacci example_interfaces/action/Fibonacci --flow-style
interface: GOAL_SERVICE
info:
event_type: REQUEST_SENT
stamp:
sec: 1742070798
nanosec: 400435819
client_gid: [1, 15, 165, 231, 194, 197, 167, 157, 0, 0, 0, 0, 0, 0, 20, 4]
sequence_number: 1
request: [{goal_id: {uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]}, goal: {order: 10}}]
response: []
---
interface: GOAL_SERVICE
info:
event_type: REQUEST_RECEIVED
stamp:
sec: 1742070798
nanosec: 400706446
client_gid: [1, 15, 165, 231, 194, 197, 167, 157, 0, 0, 0, 0, 0, 0, 20, 4]
sequence_number: 1
request: [{goal_id: {uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]}, goal: {order: 10}}]
response: []
---
interface: RESULT_SERVICE
info:
event_type: REQUEST_SENT
stamp:
sec: 1742070798
nanosec: 401486678
client_gid: [1, 15, 165, 231, 194, 197, 167, 157, 0, 0, 0, 0, 0, 0, 24, 4]
sequence_number: 1
request: [{goal_id: {uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]}}]
response: []
---
interface: FEEDBACK_TOPIC
goal_id:
uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]
feedback:
sequence: [0, 1, 1]
---
interface: STATUS_TOPIC
status_list: [{goal_info: {goal_id: {uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]}, stamp: {sec: 1742070798, nanosec: 401146752}}, status: 2}]
---
interface: GOAL_SERVICE
info:
event_type: RESPONSE_SENT
stamp:
sec: 1742070798
nanosec: 401109161
client_gid: [1, 15, 165, 231, 194, 197, 167, 157, 0, 0, 0, 0, 0, 0, 20, 4]
sequence_number: 1
request: []
response: [{accepted: true, stamp: {sec: 0, nanosec: 0}}]
---
interface: RESULT_SERVICE
info:
event_type: REQUEST_RECEIVED
stamp:
sec: 1742070798
nanosec: 401579875
client_gid: [1, 15, 165, 231, 194, 197, 167, 157, 0, 0, 0, 0, 0, 0, 24, 4]
sequence_number: 1
request: [{goal_id: {uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]}}]
response: []
---
interface: GOAL_SERVICE
info:
event_type: RESPONSE_RECEIVED
stamp:
sec: 1742070798
nanosec: 401234269
client_gid: [1, 15, 165, 231, 194, 197, 167, 157, 0, 0, 0, 0, 0, 0, 20, 4]
sequence_number: 1
request: []
response: [{accepted: true, stamp: {sec: 0, nanosec: 0}}]
---
interface: FEEDBACK_TOPIC
goal_id:
uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]
feedback:
sequence: [0, 1, 1, 2]
---
interface: FEEDBACK_TOPIC
goal_id:
uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]
feedback:
sequence: [0, 1, 1, 2, 3]
---
interface: FEEDBACK_TOPIC
goal_id:
uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]
feedback:
sequence: [0, 1, 1, 2, 3, 5]
---
interface: FEEDBACK_TOPIC
goal_id:
uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]
feedback:
sequence: [0, 1, 1, 2, 3, 5, 8]
---
interface: FEEDBACK_TOPIC
goal_id:
uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]
feedback:
sequence: [0, 1, 1, 2, 3, 5, 8, 13]
---
interface: FEEDBACK_TOPIC
goal_id:
uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]
feedback:
sequence: [0, 1, 1, 2, 3, 5, 8, 13, 21]
---
interface: FEEDBACK_TOPIC
goal_id:
uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]
feedback:
sequence: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
---
interface: FEEDBACK_TOPIC
goal_id:
uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]
feedback:
sequence: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
---
interface: RESULT_SERVICE
info:
event_type: RESPONSE_SENT
stamp:
sec: 1742070807
nanosec: 402339670
client_gid: [1, 15, 165, 231, 194, 197, 167, 157, 0, 0, 0, 0, 0, 0, 24, 4]
sequence_number: 1
request: []
response: [{status: 4, result: {sequence: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]}}]
---
interface: RESULT_SERVICE
info:
event_type: RESPONSE_RECEIVED
stamp:
sec: 1742070807
nanosec: 402698784
client_gid: [1, 15, 165, 231, 194, 197, 167, 157, 0, 0, 0, 0, 0, 0, 24, 4]
sequence_number: 1
request: []
response: [{status: 4, result: {sequence: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]}}]
---
interface: STATUS_TOPIC
status_list: [{goal_info: {goal_id: {uuid: [230, 96, 12, 6, 100, 69, 69, 70, 220, 205, 135, 251, 210, 2, 231, 110]}, stamp: {sec: 1742070798, nanosec: 401146752}}, status: 4}]
---
...
You can see the interface: GOAL_SERVICE
and interface: RESULT_SERVICE
, those introspection service events take place in both FibonacciActionServer
and FibonacciActionClient
.
And you can also see interface: FEEDBACK_TOPIC
and interface: STATUS_TOPIC
data, those topics are published by FibonacciActionServer
and subscribed by FibonacciActionClient
.
Now you can see the action communication between FibonacciActionServer
and FibonacciActionClient
with ros2 action echo
.