rclcpp_action  master
C++ ROS Action Client Library
server.hpp
Go to the documentation of this file.
1 // Copyright 2018 Open Source Robotics Foundation, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef RCLCPP_ACTION__SERVER_HPP_
16 #define RCLCPP_ACTION__SERVER_HPP_
17 
18 #include <rcl_action/action_server.h>
19 #include <rosidl_runtime_c/action_type_support_struct.h>
20 #include <rosidl_typesupport_cpp/action_type_support.hpp>
24 #include <rclcpp/waitable.hpp>
25 
26 #include <functional>
27 #include <memory>
28 #include <mutex>
29 #include <string>
30 #include <unordered_map>
31 #include <utility>
32 
35 #include "rclcpp_action/types.hpp"
36 
37 namespace rclcpp_action
38 {
39 // Forward declaration
40 class ServerBaseImpl;
41 
43 enum class GoalResponse : int8_t
44 {
46  REJECT = 1,
50  ACCEPT_AND_DEFER = 3,
51 };
52 
54 enum class CancelResponse : int8_t
55 {
57  REJECT = 1,
59  ACCEPT = 2,
60 };
61 
64 
71 {
72 public:
74  virtual ~ServerBase();
75 
76  // -------------
77  // Waitables API
78 
82  size_t
84 
88  size_t
89  get_number_of_ready_timers() override;
90 
94  size_t
95  get_number_of_ready_clients() override;
96 
100  size_t
101  get_number_of_ready_services() override;
102 
106  size_t
108 
112  bool
113  add_to_wait_set(rcl_wait_set_t * wait_set) override;
114 
118  bool
119  is_ready(rcl_wait_set_t *) override;
120 
123  take_data() override;
124 
128  void
129  execute(std::shared_ptr<void> & data) override;
130 
131  // End Waitables API
132  // -----------------
133 
134 protected:
136  ServerBase(
137  rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
138  rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock,
139  rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
140  const std::string & name,
141  const rosidl_action_type_support_t * type_support,
142  const rcl_action_server_options_t & options);
143 
144  // -----------------------------------------------------
145  // API for communication between ServerBase and Server<>
146 
147  // ServerBase will call this function when a goal request is received.
148  // The subclass should convert to the real type and call a user's callback.
151  virtual
154 
155  // ServerBase will determine which goal ids are being cancelled, and then call this function for
156  // each goal id.
157  // The subclass should look up a goal handle and call the user's callback.
160  virtual
162  call_handle_cancel_callback(const GoalUUID & uuid) = 0;
163 
167  virtual
168  GoalUUID
169  get_goal_id_from_goal_request(void * message) = 0;
170 
174  virtual
176  create_goal_request() = 0;
177 
181  virtual
182  void
185  GoalUUID uuid, std::shared_ptr<void> goal_request_message) = 0;
186 
190  virtual
191  GoalUUID
192  get_goal_id_from_result_request(void * message) = 0;
193 
197  virtual
199  create_result_request() = 0;
200 
204  virtual
206  create_result_response(decltype(action_msgs::msg::GoalStatus::status) status) = 0;
207 
210  void
211  publish_status();
212 
215  void
217 
220  void
221  publish_result(const GoalUUID & uuid, std::shared_ptr<void> result_msg);
222 
225  void
227 
228  // End API for communication between ServerBase and Server<>
229  // ---------------------------------------------------------
230 
231 private:
235  void
236  execute_goal_request_received(std::shared_ptr<void> & data);
237 
241  void
242  execute_cancel_request_received(std::shared_ptr<void> & data);
243 
247  void
248  execute_result_request_received(std::shared_ptr<void> & data);
249 
253  void
254  execute_check_expired_goals();
255 
259 };
260 
262 
271 template<typename ActionT>
272 class Server : public ServerBase, public std::enable_shared_from_this<Server<ActionT>>
273 {
274 public:
276 
277 
284 
286 
312  rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
313  rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock,
314  rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
315  const std::string & name,
316  const rcl_action_server_options_t & options,
317  GoalCallback handle_goal,
318  CancelCallback handle_cancel,
319  AcceptedCallback handle_accepted
320  )
321  : ServerBase(
322  node_base,
323  node_clock,
324  node_logging,
325  name,
326  rosidl_typesupport_cpp::get_action_type_support_handle<ActionT>(),
327  options),
328  handle_goal_(handle_goal),
329  handle_cancel_(handle_cancel),
330  handle_accepted_(handle_accepted)
331  {
332  }
333 
334  virtual ~Server() = default;
335 
336 protected:
337  // -----------------------------------------------------
338  // API for communication between ServerBase and Server<>
339 
343  {
344  auto request = std::static_pointer_cast<
345  typename ActionT::Impl::SendGoalService::Request>(message);
346  auto goal = std::shared_ptr<typename ActionT::Goal>(request, &request->goal);
347  GoalResponse user_response = handle_goal_(uuid, goal);
348 
349  auto ros_response = std::make_shared<typename ActionT::Impl::SendGoalService::Response>();
350  ros_response->accepted = GoalResponse::ACCEPT_AND_EXECUTE == user_response ||
351  GoalResponse::ACCEPT_AND_DEFER == user_response;
352  return std::make_pair(user_response, ros_response);
353  }
354 
357  call_handle_cancel_callback(const GoalUUID & uuid) override
358  {
360  {
361  std::lock_guard<std::mutex> lock(goal_handles_mutex_);
362  auto element = goal_handles_.find(uuid);
363  if (element != goal_handles_.end()) {
364  goal_handle = element->second.lock();
365  }
366  }
367 
369  if (goal_handle) {
370  resp = handle_cancel_(goal_handle);
371  if (CancelResponse::ACCEPT == resp) {
372  try {
373  goal_handle->_cancel_goal();
374  } catch (const rclcpp::exceptions::RCLError & ex) {
375  RCLCPP_DEBUG(
376  rclcpp::get_logger("rclcpp_action"),
377  "Failed to cancel goal in call_handle_cancel_callback: %s", ex.what());
378  return CancelResponse::REJECT;
379  }
380  }
381  }
382  return resp;
383  }
384 
386  void
389  GoalUUID uuid, std::shared_ptr<void> goal_request_message) override
390  {
392  std::weak_ptr<Server<ActionT>> weak_this = this->shared_from_this();
393 
394  std::function<void(const GoalUUID &, std::shared_ptr<void>)> on_terminal_state =
395  [weak_this](const GoalUUID & goal_uuid, std::shared_ptr<void> result_message)
396  {
397  std::shared_ptr<Server<ActionT>> shared_this = weak_this.lock();
398  if (!shared_this) {
399  return;
400  }
401  // Send result message to anyone that asked
402  shared_this->publish_result(goal_uuid, result_message);
403  // Publish a status message any time a goal handle changes state
404  shared_this->publish_status();
405  // notify base so it can recalculate the expired goal timer
406  shared_this->notify_goal_terminal_state();
407  // Delete data now (ServerBase and rcl_action_server_t keep data until goal handle expires)
408  std::lock_guard<std::mutex> lock(shared_this->goal_handles_mutex_);
409  shared_this->goal_handles_.erase(goal_uuid);
410  };
411 
412  std::function<void(const GoalUUID &)> on_executing =
413  [weak_this](const GoalUUID & goal_uuid)
414  {
415  std::shared_ptr<Server<ActionT>> shared_this = weak_this.lock();
416  if (!shared_this) {
417  return;
418  }
419  (void)goal_uuid;
420  // Publish a status message any time a goal handle changes state
421  shared_this->publish_status();
422  };
423 
426  {
427  std::shared_ptr<Server<ActionT>> shared_this = weak_this.lock();
428  if (!shared_this) {
429  return;
430  }
431  shared_this->publish_feedback(std::static_pointer_cast<void>(feedback_msg));
432  };
433 
434  auto request = std::static_pointer_cast<
435  const typename ActionT::Impl::SendGoalService::Request>(goal_request_message);
436  auto goal = std::shared_ptr<const typename ActionT::Goal>(request, &request->goal);
437  goal_handle.reset(
439  rcl_goal_handle, uuid, goal, on_terminal_state, on_executing, publish_feedback));
440  {
441  std::lock_guard<std::mutex> lock(goal_handles_mutex_);
442  goal_handles_[uuid] = goal_handle;
443  }
444  handle_accepted_(goal_handle);
445  }
446 
448  GoalUUID
449  get_goal_id_from_goal_request(void * message) override
450  {
451  return
452  static_cast<typename ActionT::Impl::SendGoalService::Request *>(message)->goal_id.uuid;
453  }
454 
458  {
459  return std::shared_ptr<void>(new typename ActionT::Impl::SendGoalService::Request());
460  }
461 
463  GoalUUID
464  get_goal_id_from_result_request(void * message) override
465  {
466  return
467  static_cast<typename ActionT::Impl::GetResultService::Request *>(message)->goal_id.uuid;
468  }
469 
473  {
474  return std::shared_ptr<void>(new typename ActionT::Impl::GetResultService::Request());
475  }
476 
479  create_result_response(decltype(action_msgs::msg::GoalStatus::status) status) override
480  {
481  auto result = std::make_shared<typename ActionT::Impl::GetResultService::Response>();
482  result->status = status;
483  return std::static_pointer_cast<void>(result);
484  }
485 
486  // End API for communication between ServerBase and Server<>
487  // ---------------------------------------------------------
488 
489 private:
490  GoalCallback handle_goal_;
491  CancelCallback handle_cancel_;
492  AcceptedCallback handle_accepted_;
493 
494  using GoalHandleWeakPtr = std::weak_ptr<ServerGoalHandle<ActionT>>;
498  std::mutex goal_handles_mutex_;
499 };
500 } // namespace rclcpp_action
501 #endif // RCLCPP_ACTION__SERVER_HPP_
node_logging_interface.hpp
rclcpp_action::ServerBase::publish_feedback
RCLCPP_ACTION_PUBLIC void publish_feedback(std::shared_ptr< void > feedback_msg)
std::weak_ptr::lock
T lock(T... args)
rclcpp_action::ServerBase::create_goal_request
virtual RCLCPP_ACTION_PUBLIC std::shared_ptr< void > create_goal_request()=0
rclcpp_action::GoalResponse
GoalResponse
A response returned by an action server callback when a goal is requested.
Definition: server.hpp:43
std::string
std::shared_ptr< void >
rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE
@ ACCEPT_AND_EXECUTE
The server accepts the goal, and is going to begin execution immediately.
rclcpp::exceptions::RCLError
std::pair
rclcpp_action::ServerBase::notify_goal_terminal_state
RCLCPP_ACTION_PUBLIC void notify_goal_terminal_state()
rclcpp_action::ServerBase::get_number_of_ready_timers
RCLCPP_ACTION_PUBLIC size_t get_number_of_ready_timers() override
rclcpp_action::ServerBase::call_handle_cancel_callback
virtual RCLCPP_ACTION_PUBLIC CancelResponse call_handle_cancel_callback(const GoalUUID &uuid)=0
node_clock_interface.hpp
types.hpp
rclcpp_action::Server::~Server
virtual ~Server()=default
rclcpp_action::ServerBase::publish_status
RCLCPP_ACTION_PUBLIC void publish_status()
rclcpp::get_logger
Logger get_logger(const std::string &name)
std::lock_guard
rclcpp_action::CancelResponse::REJECT
@ REJECT
The server will not try to cancel the goal.
node_base_interface.hpp
rclcpp_action::Server::create_result_request
std::shared_ptr< void > create_result_request() override
Definition: server.hpp:472
rclcpp_action::ServerBase::call_handle_goal_callback
virtual RCLCPP_ACTION_PUBLIC std::pair< GoalResponse, std::shared_ptr< void > > call_handle_goal_callback(GoalUUID &, std::shared_ptr< void > request)=0
std::function< GoalResponse(const GoalUUID &, std::shared_ptr< const typename ActionT::Goal >)>
rclcpp_action::Server::create_goal_request
std::shared_ptr< void > create_goal_request() override
Definition: server.hpp:457
rclcpp_action::ServerBase::is_ready
RCLCPP_ACTION_PUBLIC bool is_ready(rcl_wait_set_t *) override
rclcpp::Waitable
rclcpp_action
Definition: client.hpp:46
rclcpp_action::Server::get_goal_id_from_goal_request
GoalUUID get_goal_id_from_goal_request(void *message) override
Definition: server.hpp:449
std::shared_ptr::reset
T reset(T... args)
rclcpp_action::Server::create_result_response
std::shared_ptr< void > create_result_response(decltype(action_msgs::msg::GoalStatus::status) status) override
Definition: server.hpp:479
rclcpp_action::ServerBase::create_result_request
virtual RCLCPP_ACTION_PUBLIC std::shared_ptr< void > create_result_request()=0
rclcpp_action::ServerBase::get_goal_id_from_goal_request
virtual RCLCPP_ACTION_PUBLIC GoalUUID get_goal_id_from_goal_request(void *message)=0
rclcpp_action::ServerBase::get_number_of_ready_guard_conditions
RCLCPP_ACTION_PUBLIC size_t get_number_of_ready_guard_conditions() override
std::enable_shared_from_this< Server< ActionT > >::shared_from_this
T shared_from_this(T... args)
rclcpp_action::Server::Server
Server(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base, rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock, rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging, const std::string &name, const rcl_action_server_options_t &options, GoalCallback handle_goal, CancelCallback handle_cancel, AcceptedCallback handle_accepted)
Construct an action server.
Definition: server.hpp:311
rclcpp_action::GoalResponse::REJECT
@ REJECT
The goal is rejected and will not be executed.
waitable.hpp
rclcpp_action::ServerBase::~ServerBase
virtual RCLCPP_ACTION_PUBLIC ~ServerBase()
std::static_pointer_cast
T static_pointer_cast(T... args)
std::array
std::enable_shared_from_this
rclcpp_action::Server::CancelCallback
std::function< CancelResponse(std::shared_ptr< ServerGoalHandle< ActionT > >)> CancelCallback
Signature of a callback that accepts or rejects requests to cancel a goal.
Definition: server.hpp:281
rcl_wait_set_t
rclcpp_action::ServerBase::execute
RCLCPP_ACTION_PUBLIC void execute(std::shared_ptr< void > &data) override
RCLCPP_DEBUG
#define RCLCPP_DEBUG(logger,...)
rclcpp_action::ServerBase::take_data
RCLCPP_ACTION_PUBLIC std::shared_ptr< void > take_data() override
rclcpp_action::ServerBase::call_goal_accepted_callback
virtual RCLCPP_ACTION_PUBLIC void call_goal_accepted_callback(std::shared_ptr< rcl_action_goal_handle_t > rcl_goal_handle, GoalUUID uuid, std::shared_ptr< void > goal_request_message)=0
rclcpp_action::ServerBase::create_result_response
virtual RCLCPP_ACTION_PUBLIC std::shared_ptr< void > create_result_response(decltype(action_msgs::msg::GoalStatus::status) status)=0
std::weak_ptr
rclcpp_action::Server
Action Server.
Definition: server.hpp:272
rclcpp_action::ServerBase::get_number_of_ready_clients
RCLCPP_ACTION_PUBLIC size_t get_number_of_ready_clients() override
rclcpp_action::Server::call_handle_cancel_callback
CancelResponse call_handle_cancel_callback(const GoalUUID &uuid) override
Definition: server.hpp:357
rclcpp_action::Server::GoalCallback
std::function< GoalResponse(const GoalUUID &, std::shared_ptr< const typename ActionT::Goal >)> GoalCallback
Signature of a callback that accepts or rejects goal requests.
Definition: server.hpp:279
rclcpp_action::CancelResponse::ACCEPT
@ ACCEPT
The server has agreed to try to cancel the goal.
rclcpp_action::GoalResponse::ACCEPT_AND_DEFER
@ ACCEPT_AND_DEFER
The server accepts the goal, and is going to execute it later.
server_goal_handle.hpp
visibility_control.hpp
rclcpp_action::ServerBase::get_number_of_ready_subscriptions
RCLCPP_ACTION_PUBLIC size_t get_number_of_ready_subscriptions() override
rclcpp_action::CancelResponse
CancelResponse
A response returned by an action server callback when a goal has been asked to be canceled.
Definition: server.hpp:54
RCLCPP_ACTION_PUBLIC
#define RCLCPP_ACTION_PUBLIC
Definition: visibility_control.hpp:50
rclcpp_action::ServerBase::get_goal_id_from_result_request
virtual RCLCPP_ACTION_PUBLIC GoalUUID get_goal_id_from_result_request(void *message)=0
rclcpp_action::ServerBase::get_number_of_ready_services
RCLCPP_ACTION_PUBLIC size_t get_number_of_ready_services() override
std::mutex
RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE
#define RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(...)
std::make_pair
T make_pair(T... args)
rclcpp_action::Server::call_goal_accepted_callback
void call_goal_accepted_callback(std::shared_ptr< rcl_action_goal_handle_t > rcl_goal_handle, GoalUUID uuid, std::shared_ptr< void > goal_request_message) override
Definition: server.hpp:387
rclcpp_action::Server::get_goal_id_from_result_request
GoalUUID get_goal_id_from_result_request(void *message) override
Definition: server.hpp:464
std::unique_ptr< ServerBaseImpl >
rclcpp_action::ServerBase
Definition: server.hpp:70
std::unordered_map
rclcpp_action::Server::call_handle_goal_callback
std::pair< GoalResponse, std::shared_ptr< void > > call_handle_goal_callback(GoalUUID &uuid, std::shared_ptr< void > message) override
Definition: server.hpp:342
rclcpp_action::ServerBase::add_to_wait_set
RCLCPP_ACTION_PUBLIC bool add_to_wait_set(rcl_wait_set_t *wait_set) override
rclcpp_action::ServerBase::ServerBase
RCLCPP_ACTION_PUBLIC ServerBase(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base, rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock, rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging, const std::string &name, const rosidl_action_type_support_t *type_support, const rcl_action_server_options_t &options)
rclcpp_action::ServerBase::publish_result
RCLCPP_ACTION_PUBLIC void publish_result(const GoalUUID &uuid, std::shared_ptr< void > result_msg)
std::runtime_error::what
T what(T... args)
rcl_action_server_options_t
rclcpp_action::Server::AcceptedCallback
std::function< void(std::shared_ptr< ServerGoalHandle< ActionT > >)> AcceptedCallback
Signature of a callback that is used to notify when the goal has been accepted.
Definition: server.hpp:283
rclcpp_action::ServerGoalHandle
Class to interact with goals on a server.
Definition: server_goal_handle.hpp:135