Skip to content

Commit 687057f

Browse files
Add new interfaces to enable introspection for action (#2743)
* Add new interfaces to enable intropsection for action Signed-off-by: Barry Xu <barry.xu@sony.com> * Correct some comments Signed-off-by: Barry Xu <barry.xu@sony.com> --------- Signed-off-by: Barry Xu <barry.xu@sony.com>
1 parent 9db7fa2 commit 687057f

File tree

7 files changed

+135
-2
lines changed

7 files changed

+135
-2
lines changed

rclcpp_action/include/rclcpp_action/client.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@
3030
#include "rcl/event_callback.h"
3131

3232
#include "rclcpp/exceptions.hpp"
33+
#include "rclcpp/clock.hpp"
3334
#include "rclcpp/macros.hpp"
3435
#include "rclcpp/node_interfaces/node_base_interface.hpp"
3536
#include "rclcpp/node_interfaces/node_logging_interface.hpp"
3637
#include "rclcpp/node_interfaces/node_graph_interface.hpp"
3738
#include "rclcpp/logger.hpp"
39+
#include "rclcpp/qos.hpp"
3840
#include "rclcpp/time.hpp"
3941
#include "rclcpp/waitable.hpp"
4042

rclcpp_action/include/rclcpp_action/client_base.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,22 @@ class ClientBase : public rclcpp::Waitable
177177
// End Waitables API
178178
// -----------------
179179

180+
/// Configure action client introspection.
181+
/**
182+
* \param[in] clock clock to use to generate introspection timestamps
183+
* \param[in] qos_service_event_pub QoS settings to use when creating the introspection publisher
184+
* \param[in] introspection_state the state to set introspection to
185+
*
186+
* \throws std::invalid_argument if clock is nullptr
187+
* \throws rclcpp::exceptions::throw_from_rcl_error if rcl error occurs.
188+
*/
189+
RCLCPP_ACTION_PUBLIC
190+
void
191+
configure_introspection(
192+
rclcpp::Clock::SharedPtr clock,
193+
const rclcpp::QoS & qos_service_event_pub,
194+
rcl_service_introspection_state_t introspection_state);
195+
180196
protected:
181197
RCLCPP_ACTION_PUBLIC
182198
ClientBase(

rclcpp_action/include/rclcpp_action/server.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@
2828
#include "rcl_action/action_server.h"
2929
#include "rosidl_runtime_c/action_type_support_struct.h"
3030
#include "rosidl_typesupport_cpp/action_type_support.hpp"
31+
#include "rclcpp/clock.hpp"
3132
#include "rclcpp/node_interfaces/node_base_interface.hpp"
3233
#include "rclcpp/node_interfaces/node_clock_interface.hpp"
3334
#include "rclcpp/node_interfaces/node_logging_interface.hpp"
35+
#include "rclcpp/qos.hpp"
3436
#include "rclcpp/waitable.hpp"
3537

3638
#include "rclcpp_action/visibility_control.hpp"
@@ -187,6 +189,22 @@ class ServerBase : public rclcpp::Waitable
187189
// End Waitables API
188190
// -----------------
189191

192+
/// Configure action server introspection
193+
/**
194+
* \param[in] clock clock to use to generate introspection timestamps
195+
* \param[in] qos_service_event_pub QoS settings to use when creating the introspection publisher
196+
* \param[in] introspection_state the state to set introspection to
197+
*
198+
* \throw std::invalid_argument if clock is nullptr
199+
* \throw rclcpp::exceptions::throw_from_rcl_error if rcl error occurs.
200+
*/
201+
RCLCPP_ACTION_PUBLIC
202+
void
203+
configure_introspection(
204+
rclcpp::Clock::SharedPtr clock,
205+
const rclcpp::QoS & qos_service_event_pub,
206+
rcl_service_introspection_state_t introspection_state);
207+
190208
protected:
191209
RCLCPP_ACTION_PUBLIC
192210
ServerBase(

rclcpp_action/src/client_base.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ class ClientBaseImpl
103103
const rcl_action_client_options_t & client_options)
104104
: node_graph_(node_graph),
105105
node_handle(node_base->get_shared_rcl_node_handle()),
106+
action_type_support_(type_support),
106107
logger(node_logging->get_logger().get_child("rclcpp_action")),
107108
random_bytes_generator(std::random_device{}())
108109
{
@@ -165,6 +166,7 @@ class ClientBaseImpl
165166
// node_handle must be destroyed after client_handle to prevent memory leak
166167
std::shared_ptr<rcl_node_t> node_handle{nullptr};
167168
std::shared_ptr<rcl_action_client_t> client_handle{nullptr};
169+
const rosidl_action_type_support_t * action_type_support_;
168170
rclcpp::Logger logger;
169171

170172
using ResponseCallback = std::function<void (std::shared_ptr<void> response)>;
@@ -801,4 +803,31 @@ ClientBase::execute(const std::shared_ptr<void> & data_in)
801803
}, data_ptr->data);
802804
}
803805

806+
void
807+
ClientBase::configure_introspection(
808+
rclcpp::Clock::SharedPtr clock,
809+
const rclcpp::QoS & qos_service_event_pub,
810+
rcl_service_introspection_state_t introspection_state)
811+
{
812+
rcl_publisher_options_t pub_opts = rcl_publisher_get_default_options();
813+
pub_opts.qos = qos_service_event_pub.get_rmw_qos_profile();
814+
815+
if (clock == nullptr) {
816+
throw std::invalid_argument("clock is nullptr");
817+
}
818+
819+
rcl_ret_t ret = rcl_action_client_configure_action_introspection(
820+
pimpl_->client_handle.get(),
821+
pimpl_->node_handle.get(),
822+
clock->get_clock_handle(),
823+
pimpl_->action_type_support_,
824+
pub_opts,
825+
introspection_state);
826+
827+
if (RCL_RET_OK != ret) {
828+
rclcpp::exceptions::throw_from_rcl_error(
829+
ret, "failed to configure action client introspection");
830+
}
831+
}
832+
804833
} // namespace rclcpp_action

rclcpp_action/src/server.cpp

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,25 @@ class ServerBaseImpl
7474
{
7575
public:
7676
ServerBaseImpl(
77+
rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
78+
const rosidl_action_type_support_t * type_support,
7779
rclcpp::Clock::SharedPtr clock,
7880
rclcpp::Logger logger
7981
)
80-
: clock_(clock), logger_(logger)
82+
: node_handle_(node_base->get_shared_rcl_node_handle()),
83+
action_type_support_(type_support),
84+
clock_(clock),
85+
logger_(logger)
8186
{
8287
}
8388

8489
// Lock for action_server_
8590
std::recursive_mutex action_server_reentrant_mutex_;
8691

92+
std::shared_ptr<rcl_node_t> node_handle_;
93+
94+
const rosidl_action_type_support_t * action_type_support_;
95+
8796
rclcpp::Clock::SharedPtr clock_;
8897

8998
rclcpp::TimerBase::SharedPtr expire_timer_;
@@ -124,7 +133,8 @@ ServerBase::ServerBase(
124133
const rcl_action_server_options_t & options
125134
)
126135
: pimpl_(new ServerBaseImpl(
127-
node_clock->get_clock(), node_logging->get_logger().get_child("rclcpp_action")))
136+
node_base, type_support, node_clock->get_clock(),
137+
node_logging->get_logger().get_child("rclcpp_action")))
128138
{
129139
auto deleter = [node_base](rcl_action_server_t * ptr)
130140
{
@@ -929,3 +939,29 @@ ServerBase::get_timers() const
929939
{
930940
return {pimpl_->expire_timer_};
931941
}
942+
943+
void
944+
ServerBase::configure_introspection(
945+
rclcpp::Clock::SharedPtr clock, const rclcpp::QoS & qos_service_event_pub,
946+
rcl_service_introspection_state_t introspection_state)
947+
{
948+
rcl_publisher_options_t pub_opts = rcl_publisher_get_default_options();
949+
pub_opts.qos = qos_service_event_pub.get_rmw_qos_profile();
950+
951+
if (clock == nullptr) {
952+
throw std::invalid_argument("clock is nullptr");
953+
}
954+
955+
rcl_ret_t ret = rcl_action_server_configure_action_introspection(
956+
pimpl_->action_server_.get(),
957+
pimpl_->node_handle_.get(),
958+
clock->get_clock_handle(),
959+
pimpl_->action_type_support_,
960+
pub_opts,
961+
introspection_state);
962+
963+
if (RCL_RET_OK != ret) {
964+
rclcpp::exceptions::throw_from_rcl_error(
965+
ret, "failed to configure action server introspection");
966+
}
967+
}

rclcpp_action/test/test_client.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,3 +1035,20 @@ TEST_F(TestClientAgainstServer, execute_rcl_errors)
10351035
rclcpp::exceptions::RCLError);
10361036
}
10371037
}
1038+
1039+
TEST_F(TestClientAgainstServer, test_configure_introspection)
1040+
{
1041+
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
1042+
1043+
EXPECT_THROW(
1044+
action_client->configure_introspection(
1045+
nullptr, rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS),
1046+
std::invalid_argument);
1047+
1048+
EXPECT_NO_THROW(
1049+
action_client->configure_introspection(
1050+
client_node->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS));
1051+
1052+
// No method was found to make rcl_action_client_configure_action_introspection return
1053+
// a value other than RCL_RET_OK. mocking_utils::patch_and_return does not work for this function.
1054+
}

rclcpp_action/test/test_server.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,21 @@ class TestBasicServer : public TestServer
10731073
std::shared_ptr<GoalHandle> goal_handle_;
10741074
};
10751075

1076+
TEST_F(TestBasicServer, test_configure_introspection)
1077+
{
1078+
EXPECT_THROW(
1079+
action_server_->configure_introspection(
1080+
nullptr, rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS),
1081+
std::invalid_argument);
1082+
1083+
EXPECT_NO_THROW(
1084+
action_server_->configure_introspection(
1085+
node_->get_clock(), rclcpp::SystemDefaultsQoS(), RCL_SERVICE_INTROSPECTION_CONTENTS));
1086+
1087+
// No method was found to make rcl_action_server_configure_action_introspection return
1088+
// a value other than RCL_RET_OK. mocking_utils::patch_and_return does not work for this function.
1089+
}
1090+
10761091
class TestGoalRequestServer : public TestBasicServer {};
10771092

10781093
TEST_F(TestGoalRequestServer, execute_goal_request_received_take_goal)

0 commit comments

Comments
 (0)