@@ -122,6 +122,62 @@ class ClientBaseImpl
122122 std::default_random_engine, 8 , unsigned int > random_bytes_generator;
123123};
124124
125+ struct ClientBaseData
126+ {
127+ struct FeedbackReadyData
128+ {
129+ FeedbackReadyData (rcl_ret_t retIn, std::shared_ptr<void > msg)
130+ : ret(retIn), feedback_message(msg) {}
131+ rcl_ret_t ret;
132+ std::shared_ptr<void > feedback_message;
133+ };
134+ struct StatusReadyData
135+ {
136+ StatusReadyData (rcl_ret_t retIn, std::shared_ptr<void > msg)
137+ : ret(retIn), status_message(msg) {}
138+ rcl_ret_t ret;
139+ std::shared_ptr<void > status_message;
140+ };
141+ struct GoalResponseData
142+ {
143+ GoalResponseData (rcl_ret_t retIn, rmw_request_id_t header, std::shared_ptr<void > response)
144+ : ret(retIn), response_header(header), goal_response(response) {}
145+ rcl_ret_t ret;
146+ rmw_request_id_t response_header;
147+ std::shared_ptr<void > goal_response;
148+ };
149+ struct CancelResponseData
150+ {
151+ CancelResponseData (rcl_ret_t retIn, rmw_request_id_t header, std::shared_ptr<void > response)
152+ : ret(retIn), response_header(header), cancel_response(response) {}
153+ rcl_ret_t ret;
154+ rmw_request_id_t response_header;
155+ std::shared_ptr<void > cancel_response;
156+ };
157+ struct ResultResponseData
158+ {
159+ ResultResponseData (rcl_ret_t retIn, rmw_request_id_t header, std::shared_ptr<void > response)
160+ : ret(retIn), response_header(header), result_response(response) {}
161+ rcl_ret_t ret;
162+ rmw_request_id_t response_header;
163+ std::shared_ptr<void > result_response;
164+ };
165+
166+ std::variant<FeedbackReadyData, StatusReadyData, GoalResponseData, CancelResponseData,
167+ ResultResponseData> data;
168+
169+ explicit ClientBaseData (FeedbackReadyData && dataIn)
170+ : data(std::move(dataIn)) {}
171+ explicit ClientBaseData (StatusReadyData && dataIn)
172+ : data(std::move(dataIn)) {}
173+ explicit ClientBaseData (GoalResponseData && dataIn)
174+ : data(std::move(dataIn)) {}
175+ explicit ClientBaseData (CancelResponseData && dataIn)
176+ : data(std::move(dataIn)) {}
177+ explicit ClientBaseData (ResultResponseData && dataIn)
178+ : data(std::move(dataIn)) {}
179+ };
180+
125181ClientBase::ClientBase (
126182 rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
127183 rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
@@ -551,43 +607,53 @@ std::shared_ptr<void>
551607ClientBase::take_data ()
552608{
553609 if (pimpl_->is_feedback_ready ) {
610+ pimpl_->is_feedback_ready = false ;
554611 std::shared_ptr<void > feedback_message = this ->create_feedback_message ();
555612 rcl_ret_t ret = rcl_action_take_feedback (
556613 pimpl_->client_handle .get (), feedback_message.get ());
557614 return std::static_pointer_cast<void >(
558- std::make_shared<std::tuple<rcl_ret_t , std::shared_ptr<void >>>(
559- ret, feedback_message));
615+ std::make_shared<ClientBaseData>(
616+ ClientBaseData::FeedbackReadyData (
617+ ret, feedback_message)));
560618 } else if (pimpl_->is_status_ready ) {
619+ pimpl_->is_status_ready = false ;
561620 std::shared_ptr<void > status_message = this ->create_status_message ();
562621 rcl_ret_t ret = rcl_action_take_status (
563622 pimpl_->client_handle .get (), status_message.get ());
564623 return std::static_pointer_cast<void >(
565- std::make_shared<std::tuple<rcl_ret_t , std::shared_ptr<void >>>(
566- ret, status_message));
624+ std::make_shared<ClientBaseData>(
625+ ClientBaseData::StatusReadyData (
626+ ret, status_message)));
567627 } else if (pimpl_->is_goal_response_ready ) {
628+ pimpl_->is_goal_response_ready = false ;
568629 rmw_request_id_t response_header;
569630 std::shared_ptr<void > goal_response = this ->create_goal_response ();
570631 rcl_ret_t ret = rcl_action_take_goal_response (
571632 pimpl_->client_handle .get (), &response_header, goal_response.get ());
572633 return std::static_pointer_cast<void >(
573- std::make_shared<std::tuple<rcl_ret_t , rmw_request_id_t , std::shared_ptr<void >>>(
574- ret, response_header, goal_response));
634+ std::make_shared<ClientBaseData>(
635+ ClientBaseData::GoalResponseData (
636+ ret, response_header, goal_response)));
575637 } else if (pimpl_->is_result_response_ready ) {
638+ pimpl_->is_result_response_ready = false ;
576639 rmw_request_id_t response_header;
577640 std::shared_ptr<void > result_response = this ->create_result_response ();
578641 rcl_ret_t ret = rcl_action_take_result_response (
579642 pimpl_->client_handle .get (), &response_header, result_response.get ());
580643 return std::static_pointer_cast<void >(
581- std::make_shared<std::tuple<rcl_ret_t , rmw_request_id_t , std::shared_ptr<void >>>(
582- ret, response_header, result_response));
644+ std::make_shared<ClientBaseData>(
645+ ClientBaseData::ResultResponseData (
646+ ret, response_header, result_response)));
583647 } else if (pimpl_->is_cancel_response_ready ) {
648+ pimpl_->is_cancel_response_ready = false ;
584649 rmw_request_id_t response_header;
585650 std::shared_ptr<void > cancel_response = this ->create_cancel_response ();
586651 rcl_ret_t ret = rcl_action_take_cancel_response (
587652 pimpl_->client_handle .get (), &response_header, cancel_response.get ());
588653 return std::static_pointer_cast<void >(
589- std::make_shared<std::tuple<rcl_ret_t , rmw_request_id_t , std::shared_ptr<void >>>(
590- ret, response_header, cancel_response));
654+ std::make_shared<ClientBaseData>(
655+ ClientBaseData::CancelResponseData (
656+ ret, response_header, cancel_response)));
591657 } else {
592658 throw std::runtime_error (" Taking data from action client but nothing is ready" );
593659 }
@@ -619,71 +685,54 @@ ClientBase::take_data_by_entity_id(size_t id)
619685}
620686
621687void
622- ClientBase::execute (std::shared_ptr<void > & data )
688+ ClientBase::execute (std::shared_ptr<void > & dataIn )
623689{
624- if (!data ) {
690+ if (!dataIn ) {
625691 throw std::runtime_error (" 'data' is empty" );
626692 }
627693
628- if (pimpl_->is_feedback_ready ) {
629- auto shared_ptr = std::static_pointer_cast<std::tuple<rcl_ret_t , std::shared_ptr<void >>>(data);
630- auto ret = std::get<0 >(*shared_ptr);
631- pimpl_->is_feedback_ready = false ;
632- if (RCL_RET_OK == ret) {
633- auto feedback_message = std::get<1 >(*shared_ptr);
634- this ->handle_feedback_message (feedback_message);
635- } else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
636- rclcpp::exceptions::throw_from_rcl_error (ret, " error taking feedback" );
637- }
638- } else if (pimpl_->is_status_ready ) {
639- auto shared_ptr = std::static_pointer_cast<std::tuple<rcl_ret_t , std::shared_ptr<void >>>(data);
640- auto ret = std::get<0 >(*shared_ptr);
641- pimpl_->is_status_ready = false ;
642- if (RCL_RET_OK == ret) {
643- auto status_message = std::get<1 >(*shared_ptr);
644- this ->handle_status_message (status_message);
645- } else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
646- rclcpp::exceptions::throw_from_rcl_error (ret, " error taking status" );
647- }
648- } else if (pimpl_->is_goal_response_ready ) {
649- auto shared_ptr = std::static_pointer_cast<
650- std::tuple<rcl_ret_t , rmw_request_id_t , std::shared_ptr<void >>>(data);
651- auto ret = std::get<0 >(*shared_ptr);
652- pimpl_->is_goal_response_ready = false ;
653- if (RCL_RET_OK == ret) {
654- auto response_header = std::get<1 >(*shared_ptr);
655- auto goal_response = std::get<2 >(*shared_ptr);
656- this ->handle_goal_response (response_header, goal_response);
657- } else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
658- rclcpp::exceptions::throw_from_rcl_error (ret, " error taking goal response" );
659- }
660- } else if (pimpl_->is_result_response_ready ) {
661- auto shared_ptr = std::static_pointer_cast<
662- std::tuple<rcl_ret_t , rmw_request_id_t , std::shared_ptr<void >>>(data);
663- auto ret = std::get<0 >(*shared_ptr);
664- pimpl_->is_result_response_ready = false ;
665- if (RCL_RET_OK == ret) {
666- auto response_header = std::get<1 >(*shared_ptr);
667- auto result_response = std::get<2 >(*shared_ptr);
668- this ->handle_result_response (response_header, result_response);
669- } else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
670- rclcpp::exceptions::throw_from_rcl_error (ret, " error taking result response" );
671- }
672- } else if (pimpl_->is_cancel_response_ready ) {
673- auto shared_ptr = std::static_pointer_cast<
674- std::tuple<rcl_ret_t , rmw_request_id_t , std::shared_ptr<void >>>(data);
675- auto ret = std::get<0 >(*shared_ptr);
676- pimpl_->is_cancel_response_ready = false ;
677- if (RCL_RET_OK == ret) {
678- auto response_header = std::get<1 >(*shared_ptr);
679- auto cancel_response = std::get<2 >(*shared_ptr);
680- this ->handle_cancel_response (response_header, cancel_response);
681- } else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != ret) {
682- rclcpp::exceptions::throw_from_rcl_error (ret, " error taking cancel response" );
683- }
684- } else {
685- throw std::runtime_error (" Executing action client but nothing is ready" );
686- }
694+ std::shared_ptr<ClientBaseData> dataPtr = std::static_pointer_cast<ClientBaseData>(dataIn);
695+
696+
697+ std::visit (
698+ [&](auto && data) -> void {
699+ using T = std::decay_t <decltype (data)>;
700+ if constexpr (std::is_same_v<T, ClientBaseData::FeedbackReadyData>) {
701+ if (RCL_RET_OK == data.ret ) {
702+ this ->handle_feedback_message (data.feedback_message );
703+ } else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != data.ret ) {
704+ rclcpp::exceptions::throw_from_rcl_error (data.ret , " error taking feedback" );
705+ }
706+ }
707+ if constexpr (std::is_same_v<T, ClientBaseData::StatusReadyData>) {
708+ if (RCL_RET_OK == data.ret ) {
709+ this ->handle_status_message (data.status_message );
710+ } else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != data.ret ) {
711+ rclcpp::exceptions::throw_from_rcl_error (data.ret , " error taking status" );
712+ }
713+ }
714+ if constexpr (std::is_same_v<T, ClientBaseData::GoalResponseData>) {
715+ if (RCL_RET_OK == data.ret ) {
716+ this ->handle_goal_response (data.response_header , data.goal_response );
717+ } else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != data.ret ) {
718+ rclcpp::exceptions::throw_from_rcl_error (data.ret , " error taking goal response" );
719+ }
720+ }
721+ if constexpr (std::is_same_v<T, ClientBaseData::ResultResponseData>) {
722+ if (RCL_RET_OK == data.ret ) {
723+ this ->handle_result_response (data.response_header , data.result_response );
724+ } else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != data.ret ) {
725+ rclcpp::exceptions::throw_from_rcl_error (data.ret , " error taking result response" );
726+ }
727+ }
728+ if constexpr (std::is_same_v<T, ClientBaseData::CancelResponseData>) {
729+ if (RCL_RET_OK == data.ret ) {
730+ this ->handle_cancel_response (data.response_header , data.cancel_response );
731+ } else if (RCL_RET_ACTION_CLIENT_TAKE_FAILED != data.ret ) {
732+ rclcpp::exceptions::throw_from_rcl_error (data.ret , " error taking cancel response" );
733+ }
734+ }
735+ }, dataPtr->data );
687736}
688737
689738} // namespace rclcpp_action
0 commit comments