15 #ifndef RCLCPP_ACTION__CLIENT_HPP_
16 #define RCLCPP_ACTION__CLIENT_HPP_
27 #include <rosidl_runtime_c/action_type_support_struct.h>
28 #include <rosidl_typesupport_cpp/action_type_support.hpp>
71 template<
typename RepT =
int64_t,
typename RatioT = std::milli>
77 std::chrono::duration_cast<std::chrono::nanoseconds>(timeout)
135 rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
136 rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
137 rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
139 const rosidl_action_type_support_t * type_support,
261 template<
typename ActionT>
290 "Use new goal response callback signature "
291 "`std::function<void (Client<ActionT>::GoalHandle::SharedPtr)>` "
292 "instead of the old "
293 "`std::function<void (std::shared_future<Client<ActionT>::GoalHandle::SharedPtr>)>`.\n"
296 "Client<ActionT>::SendGoalOptions options;\n"
297 "options.goal_response_callback = [](Client<ActionT>::GoalHandle::SharedPtr goal) {\n"
298 " // do something with `goal` here\n"
301 : old_callback_(
std::move(old_callback)) {}
304 : new_callback_(
std::move(new_callback)) {}
321 "Cannot call GoalResponseCallback(GoalHandle::SharedPtr) "
322 "if using the old goal response callback signature."};
329 "`void goal_response_callback("
330 " std::shared_future<Client<ActionT>::GoalHandle::SharedPtr> goal_handle_shared_future)`"
336 old_callback_(
std::move(goal_handle_future));
340 new_callback_(
std::move(goal_handle_future).get_future().share());
346 explicit operator bool() const noexcept {
347 return new_callback_ || old_callback_;
354 typename GoalHandle::SharedPtr goal_handle,
362 old_callback_(
std::move(goal_handle_future));
368 NewSignature new_callback_;
369 OldSignature old_callback_;
413 rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
414 rclcpp::node_interfaces::NodeGraphInterface::SharedPtr node_graph,
415 rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
420 node_base, node_graph, node_logging, action_name,
421 rosidl_typesupport_cpp::get_action_type_support_handle<ActionT>(),
445 auto promise = std::make_shared<std::promise<typename GoalHandle::SharedPtr>>();
447 using GoalRequest =
typename ActionT::Impl::SendGoalService::Request;
448 auto goal_request = std::make_shared<GoalRequest>();
450 goal_request->goal = goal;
452 std::static_pointer_cast<void>(goal_request),
455 using GoalResponse =
typename ActionT::Impl::SendGoalService::Response;
456 auto goal_response = std::static_pointer_cast<GoalResponse>(response);
457 if (!goal_response->accepted) {
458 promise->set_value(
nullptr);
459 if (options.goal_response_callback) {
460 options.goal_response_callback(
nullptr, future);
465 goal_info.goal_id.uuid = goal_request->goal_id.uuid;
466 goal_info.stamp = goal_response->stamp;
469 new GoalHandle(goal_info, options.feedback_callback, options.result_callback));
472 goal_handles_[goal_handle->get_goal_id()] = goal_handle;
474 promise->set_value(goal_handle);
475 if (options.goal_response_callback) {
476 options.goal_response_callback(goal_handle, future);
479 if (options.result_callback) {
480 this->make_result_aware(goal_handle);
490 auto goal_handle_it = goal_handles_.begin();
491 while (goal_handle_it != goal_handles_.end()) {
492 if (!goal_handle_it->second.lock()) {
495 "Dropping weak reference to goal handle during send_goal()");
496 goal_handle_it = goal_handles_.erase(goal_handle_it);
516 typename GoalHandle::SharedPtr goal_handle,
520 if (goal_handles_.count(goal_handle->get_goal_id()) == 0) {
523 if (goal_handle->is_invalidated()) {
526 throw goal_handle->invalidate_exception_;
528 if (result_callback) {
530 goal_handle->set_result_callback(result_callback);
532 this->make_result_aware(goal_handle);
533 return goal_handle->async_get_result();
551 typename GoalHandle::SharedPtr goal_handle,
555 if (goal_handles_.count(goal_handle->get_goal_id()) == 0) {
558 auto cancel_request = std::make_shared<CancelRequest>();
560 cancel_request->goal_info.goal_id.uuid = goal_handle->get_goal_id();
561 return async_cancel(cancel_request, cancel_callback);
577 auto cancel_request = std::make_shared<CancelRequest>();
580 cancel_request->goal_info.goal_id.uuid.begin(),
581 cancel_request->goal_info.goal_id.uuid.end(), 0u);
582 return async_cancel(cancel_request, cancel_callback);
601 auto cancel_request = std::make_shared<CancelRequest>();
604 cancel_request->goal_info.goal_id.uuid.begin(),
605 cancel_request->goal_info.goal_id.uuid.end(), 0u);
606 cancel_request->goal_info.stamp = stamp;
607 return async_cancel(cancel_request, cancel_callback);
614 auto it = goal_handles_.begin();
615 while (it != goal_handles_.end()) {
616 typename GoalHandle::SharedPtr goal_handle = it->second.lock();
620 it = goal_handles_.erase(it);
627 create_goal_response()
const override
629 using GoalResponse =
typename ActionT::Impl::SendGoalService::Response;
635 create_result_response()
const override
637 using GoalResultResponse =
typename ActionT::Impl::GetResultService::Response;
643 create_cancel_response()
const override
650 create_feedback_message()
const override
652 using FeedbackMessage =
typename ActionT::Impl::FeedbackMessage;
661 using FeedbackMessage =
typename ActionT::Impl::FeedbackMessage;
662 typename FeedbackMessage::SharedPtr feedback_message =
663 std::static_pointer_cast<FeedbackMessage>(message);
664 const GoalUUID & goal_id = feedback_message->goal_id.uuid;
665 if (goal_handles_.count(goal_id) == 0) {
668 "Received feedback for unknown goal. Ignoring...");
671 typename GoalHandle::SharedPtr goal_handle = goal_handles_[goal_id].lock();
676 "Dropping weak reference to goal handle during feedback callback");
677 goal_handles_.erase(goal_id);
680 auto feedback = std::make_shared<Feedback>();
681 *feedback = feedback_message->feedback;
682 goal_handle->call_feedback_callback(goal_handle, feedback);
687 create_status_message()
const override
689 using GoalStatusMessage =
typename ActionT::Impl::GoalStatusMessage;
698 using GoalStatusMessage =
typename ActionT::Impl::GoalStatusMessage;
699 auto status_message = std::static_pointer_cast<GoalStatusMessage>(message);
700 for (
const GoalStatus & status : status_message->status_list) {
701 const GoalUUID & goal_id = status.goal_info.goal_id.uuid;
702 if (goal_handles_.count(goal_id) == 0) {
705 "Received status for unknown goal. Ignoring...");
708 typename GoalHandle::SharedPtr goal_handle = goal_handles_[goal_id].lock();
713 "Dropping weak reference to goal handle during status callback");
714 goal_handles_.erase(goal_id);
717 goal_handle->set_status(status.status);
723 make_result_aware(
typename GoalHandle::SharedPtr goal_handle)
726 if (goal_handle->set_result_awareness(
true)) {
729 using GoalResultRequest =
typename ActionT::Impl::GetResultService::Request;
730 auto goal_result_request = std::make_shared<GoalResultRequest>();
731 goal_result_request->goal_id.uuid = goal_handle->get_goal_id();
734 std::static_pointer_cast<void>(goal_result_request),
739 using GoalResultResponse =
typename ActionT::Impl::GetResultService::Response;
740 auto result_response = std::static_pointer_cast<GoalResultResponse>(response);
741 wrapped_result.result = std::make_shared<typename ActionT::Result>();
742 *wrapped_result.result = result_response->result;
743 wrapped_result.goal_id = goal_handle->get_goal_id();
744 wrapped_result.code =
static_cast<ResultCode>(result_response->status);
745 goal_handle->set_result(wrapped_result);
747 goal_handles_.erase(goal_handle->get_goal_id());
751 goal_handle->invalidate(exceptions::UnawareGoalHandleError(ex.
message));
758 typename CancelRequest::SharedPtr cancel_request,
762 auto promise = std::make_shared<std::promise<typename CancelResponse::SharedPtr>>();
765 std::static_pointer_cast<void>(cancel_request),
768 auto cancel_response = std::static_pointer_cast<CancelResponse>(response);
769 promise->set_value(cancel_response);
770 if (cancel_callback) {
771 cancel_callback(cancel_response);
782 #endif // RCLCPP_ACTION__CLIENT_HPP_