48 using Goal =
typename ActionT::Goal;
51 using Result =
typename ActionT::Result;
75 const std::chrono::seconds server_timeout = std::chrono::seconds{ 3 },
76 const std::chrono::seconds response_timeout = std::chrono::seconds{ 3 });
87 bool syncCancelLastGoal(
const std::chrono::seconds response_timeout = std::chrono::seconds{ 3 });
112 const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface_ptr_;
113 const rclcpp::Logger logger_;
114 const std::string action_name_;
115 typename rclcpp_action::Client<ActionT>::SharedPtr client_ptr_;
116 typename ClientGoalHandle::SharedPtr goal_handle_ptr_;
117 std::shared_ptr<const Feedback> feedback_ptr_;
122 : node_base_interface_ptr_{ node.get_node_base_interface() }
123 , logger_{ node.get_logger() }
124 , action_name_{ action_name }
126 client_ptr_ = rclcpp_action::create_client<ActionT>(&node, action_name_);
132 const std::chrono::seconds server_timeout,
133 const std::chrono::seconds response_timeout)
135 auto promise_ptr = std::make_shared<std::promise<WrappedResultSharedPtr>>();
136 if (!client_ptr_->wait_for_action_server(server_timeout))
138 throw std::runtime_error(
"Action server '" + action_name_ +
"' is not available");
142 _options.goal_response_callback = options.goal_response_callback;
143 _options.feedback_callback =
144 [
this, feedback_callback = options.feedback_callback](
typename ClientGoalHandle::SharedPtr client_goal_handle,
145 const std::shared_ptr<const Feedback> feedback) {
146 feedback_ptr_ = feedback;
147 if (feedback_callback)
149 feedback_callback(client_goal_handle, feedback);
152 _options.result_callback = [
this, promise_ptr, result_callback = options.result_callback](
153 const typename ClientGoalHandle::WrappedResult& wr) {
158 promise_ptr->set_value(std::make_shared<typename ClientGoalHandle::WrappedResult>(wr));
159 goal_handle_ptr_ =
nullptr;
162 auto goal_response_future = client_ptr_->async_send_goal(goal, _options);
164 switch (rclcpp::spin_until_future_complete(node_base_interface_ptr_, goal_response_future, response_timeout))
166 case rclcpp::FutureReturnCode::SUCCESS:
168 case rclcpp::FutureReturnCode::TIMEOUT:
169 throw std::runtime_error(
"No goal response due to timeout");
170 case rclcpp::FutureReturnCode::INTERRUPTED:
171 throw std::runtime_error(
"No goal response due to interruption");
174 auto client_goal_handle_ptr = goal_response_future.get();
175 if (!client_goal_handle_ptr)
177 promise_ptr->set_value(
nullptr);
178 return promise_ptr->get_future();
181 goal_handle_ptr_ = client_goal_handle_ptr;
182 return promise_ptr->get_future();
188 if (!goal_handle_ptr_)
190 throw std::runtime_error(
"Cannot cancel goal because goal_handle_ptr_ is nullptr");
194 auto cancel_response_future = client_ptr_->async_cancel_goal(goal_handle_ptr_);
195 switch (rclcpp::spin_until_future_complete(node_base_interface_ptr_, cancel_response_future, response_timeout))
197 case rclcpp::FutureReturnCode::SUCCESS:
199 case rclcpp::FutureReturnCode::TIMEOUT:
200 throw std::runtime_error(
"No cancel response due to timeout");
201 case rclcpp::FutureReturnCode::INTERRUPTED:
202 throw std::runtime_error(
"No cancel response due to interruption");
206 switch (cancel_response_future.get()->return_code)
208 case action_msgs::srv::CancelGoal::Response::ERROR_NONE:
210 case action_msgs::srv::CancelGoal::Response::ERROR_REJECTED:
212 case action_msgs::srv::CancelGoal::Response::ERROR_UNKNOWN_GOAL_ID:
213 RCLCPP_WARN(logger_,
"Cancel response ERROR_UNKNOWN_GOAL_ID");
215 case action_msgs::srv::CancelGoal::Response::ERROR_GOAL_TERMINATED:
216 RCLCPP_WARN(logger_,
"Cancel response ERROR_GOAL_TERMINATED");