57 using Goal =
typename ActionT::Goal;
58 using SendGoalOptions =
typename rclcpp_action::Client<ActionT>::SendGoalOptions;
59 using Feedback =
typename ActionT::Feedback;
60 using Result =
typename ActionT::Result;
61 using ClientGoalHandle = rclcpp_action::ClientGoalHandle<ActionT>;
62 using WrappedResultSharedPtr = std::shared_ptr<typename ClientGoalHandle::WrappedResult>;
63 using ResultFuture = std::shared_future<WrappedResultSharedPtr>;
84 const Goal & goal = Goal{},
const SendGoalOptions & options = SendGoalOptions{},
85 const std::chrono::seconds server_timeout = std::chrono::seconds{3},
86 const std::chrono::seconds response_timeout = std::chrono::seconds{3});
97 bool syncCancelLastGoal(
const std::chrono::seconds response_timeout = std::chrono::seconds{3});
122 const rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_interface_ptr_;
123 const rclcpp::Logger logger_;
124 const std::string action_name_;
125 typename rclcpp_action::Client<ActionT>::SharedPtr client_ptr_;
126 typename ClientGoalHandle::SharedPtr goal_handle_ptr_;
127 std::shared_ptr<const Feedback> feedback_ptr_;
132: node_base_interface_ptr_{node_ptr->get_node_base_interface()},
133 logger_{node_ptr->get_logger()},
134 action_name_{action_name}
136 client_ptr_ = rclcpp_action::create_client<ActionT>(node_ptr, action_name_);
141 const Goal & goal,
const SendGoalOptions & options,
const std::chrono::seconds server_timeout,
142 const std::chrono::seconds response_timeout)
144 auto promise_ptr = std::make_shared<std::promise<WrappedResultSharedPtr>>();
145 if (!client_ptr_->wait_for_action_server(server_timeout)) {
146 throw std::runtime_error(
"Action server '" + action_name_ +
"' is not available");
149 SendGoalOptions _options;
150 _options.goal_response_callback = options.goal_response_callback;
151 _options.feedback_callback = [
this, feedback_callback = options.feedback_callback](
152 typename ClientGoalHandle::SharedPtr client_goal_handle,
153 const std::shared_ptr<const Feedback> feedback) {
154 feedback_ptr_ = feedback;
155 if (feedback_callback) {
156 feedback_callback(client_goal_handle, feedback);
159 _options.result_callback = [
this, promise_ptr, result_callback = options.result_callback](
160 const typename ClientGoalHandle::WrappedResult & wr) {
161 if (result_callback) {
164 promise_ptr->set_value(std::make_shared<typename ClientGoalHandle::WrappedResult>(wr));
165 goal_handle_ptr_ =
nullptr;
168 auto goal_response_future = client_ptr_->async_send_goal(goal, _options);
170 switch (rclcpp::spin_until_future_complete(node_base_interface_ptr_, goal_response_future, response_timeout)) {
171 case rclcpp::FutureReturnCode::SUCCESS:
173 case rclcpp::FutureReturnCode::TIMEOUT:
174 throw std::runtime_error(
"No goal response due to timeout");
175 case rclcpp::FutureReturnCode::INTERRUPTED:
176 throw std::runtime_error(
"No goal response due to interruption");
179 auto client_goal_handle_ptr = goal_response_future.get();
180 if (!client_goal_handle_ptr) {
181 promise_ptr->set_value(
nullptr);
182 return promise_ptr->get_future();
185 goal_handle_ptr_ = client_goal_handle_ptr;
186 return promise_ptr->get_future();
192 if (!goal_handle_ptr_) {
193 throw std::runtime_error(
"Cannot cancel goal because goal_handle_ptr_ is nullptr");
197 auto cancel_response_future = client_ptr_->async_cancel_goal(goal_handle_ptr_);
198 switch (rclcpp::spin_until_future_complete(node_base_interface_ptr_, cancel_response_future, response_timeout)) {
199 case rclcpp::FutureReturnCode::SUCCESS:
201 case rclcpp::FutureReturnCode::TIMEOUT:
202 throw std::runtime_error(
"No cancel response due to timeout");
203 case rclcpp::FutureReturnCode::INTERRUPTED:
204 throw std::runtime_error(
"No cancel response due to interruption");
208 switch (cancel_response_future.get()->return_code) {
209 case action_msgs::srv::CancelGoal::Response::ERROR_NONE:
211 case action_msgs::srv::CancelGoal::Response::ERROR_REJECTED:
213 case action_msgs::srv::CancelGoal::Response::ERROR_UNKNOWN_GOAL_ID:
214 RCLCPP_WARN(logger_,
"Cancel response ERROR_UNKNOWN_GOAL_ID");
216 case action_msgs::srv::CancelGoal::Response::ERROR_GOAL_TERMINATED:
217 RCLCPP_WARN(logger_,
"Cancel response ERROR_GOAL_TERMINATED");