queued_action_server.h
Go to the documentation of this file.
1 #pragma once
2 
6 
9 #include <ros/ros.h>
10 
11 #include <chrono>
12 #include <condition_variable>
13 #include <memory>
14 #include <mutex>
15 #include <queue>
16 #include <string>
17 #include <thread>
18 
25 template <class ActionSpec>
27 {
28 public:
29  ACTION_DEFINITION(ActionSpec)
30  using GoalHandle = typename actionlib::ActionServer<ActionSpec>::GoalHandle;
31 
32  using ExecuteCallback = ensenso::std::function<void(GoalConstPtr const&)>;
33 
34 public:
36  bool autoStart = false)
38  {
39  actionServer = ensenso::std::make_unique<actionlib::ActionServer<ActionSpec>>(nh, name, false);
40  actionServer->registerGoalCallback(ensenso::std::bind(&QueuedActionServer::onGoalReceived, this, _1));
41  actionServer->registerCancelCallback(ensenso::std::bind(&QueuedActionServer::onCancelReceived, this, _1));
42 
43  if (autoStart)
44  {
45  start();
46  }
47  }
48 
50  {
51  shutdown();
52  }
53 
54  void start()
55  {
56  actionServer->start();
57  loopThread = std::thread([this] { loop(); }); // NOLINT
58  }
59 
61  {
62  return preemptRequested;
63  }
64 
65  void setSucceeded(Result result = Result())
66  {
67  std::lock_guard<std::mutex> lock(mutex);
68 
69  ENSENSO_DEBUG_NAMED(getLoggerName(), "Setting the current goal as succeeded.");
70  currentGoal.setSucceeded(result);
71  }
72 
73  void setAborted(Result result = Result())
74  {
75  std::lock_guard<std::mutex> lock(mutex);
76 
77  ENSENSO_DEBUG_NAMED(getLoggerName(), "Setting the current goal as aborted.");
78  currentGoal.setAborted(result);
79  }
80 
81  void setPreempted(Result result = Result())
82  {
83  std::lock_guard<std::mutex> lock(mutex);
84 
85  ENSENSO_DEBUG_NAMED(getLoggerName(), "Setting the current goal as canceled.");
86  currentGoal.setCanceled(result);
87  }
88 
89  void publishFeedback(FeedbackConstPtr const& feedback)
90  {
91  currentGoal.publishFeedback(*feedback);
92  }
93 
94  void publishFeedback(Feedback const& feedback)
95  {
96  currentGoal.publishFeedback(feedback);
97  }
98 
99 private:
100  void shutdown()
101  {
102  if (loopThread.joinable())
103  {
104  shutdownRequested = true;
105  loopThread.join();
106  }
107  }
108 
109  std::string getLoggerName()
110  {
111  return ros::this_node::getName() + "/QueuedActionServer/" + name;
112  }
113 
115  {
116  ENSENSO_DEBUG_NAMED(getLoggerName(), "Received a new goal.");
117  std::lock_guard<std::mutex> lock(mutex);
118 
119  goalQueue.push(goal);
120  loopCondition.notify_one();
121  }
122 
124  {
125  ENSENSO_DEBUG_NAMED(getLoggerName(), "Received a cancel request.");
126  std::lock_guard<std::mutex> lock(mutex);
127 
128  if (goal == currentGoal)
129  {
130  // The goal is already being executed. We set the preemption flag and the user is responsible for polling it with
131  // isPreemptRequested() and canceling his action handler with setPreempted().
132  preemptRequested = true;
133  }
134  else
135  {
136  // The goal is in the queue. We cancel it and ignore it later, when we extract new goals from the queue.
137  goal.setCanceled(Result(), "Goal was canceled by the user.");
138  }
139  }
140 
141  void loop()
142  {
143  std::unique_lock<std::mutex> lock(mutex);
144 
145  while (nh.ok() && !shutdownRequested)
146  {
147  if (!goalQueue.empty())
148  {
149  currentGoal = goalQueue.front();
150  goalQueue.pop();
151 
152  if (!currentGoal.getGoal())
153  {
154  continue;
155  }
156  else if (currentGoal.getGoalStatus().status == actionlib_msgs::GoalStatus::RECALLING)
157  {
158  currentGoal.setCanceled(Result(), "Goal was canceled by the user.");
159  }
160  else if (currentGoal.getGoalStatus().status != actionlib_msgs::GoalStatus::PENDING)
161  {
162  // The goal might have already been canceled by the cancel callback above.
163  continue;
164  }
165  else
166  {
167  ENSENSO_DEBUG_NAMED(getLoggerName(), "Accepting a new goal.");
168  currentGoal.setAccepted();
169 
170  preemptRequested = false;
171 
172  lock.unlock();
173  callback(currentGoal.getGoal());
174  lock.lock();
175 
176  if (currentGoal.getGoalStatus().status == actionlib_msgs::GoalStatus::ACTIVE ||
177  currentGoal.getGoalStatus().status == actionlib_msgs::GoalStatus::PREEMPTING)
178  {
180  "Your action handler did not set the goal to a terminal state. Aborting it for now.");
181  setAborted(Result());
182  }
183  }
184  }
185 
186  loopCondition.wait_for(lock, std::chrono::milliseconds(100));
187  }
188  }
189 
190 private:
192  std::string name;
193  std::unique_ptr<actionlib::ActionServer<ActionSpec>> actionServer;
194 
195  std::thread loopThread;
196 
197  std::mutex mutex;
198  std::condition_variable loopCondition;
199 
201 
203  std::queue<GoalHandle> goalQueue;
204 
205  // Whether the user canceled the goal that is currently being executed.
206  bool preemptRequested = false;
207 
208  volatile bool shutdownRequested = false;
209 };
QueuedActionServer::name
std::string name
Definition: queued_action_server.h:192
QueuedActionServer::onCancelReceived
void onCancelReceived(GoalHandle goal)
Definition: queued_action_server.h:123
QueuedActionServer::setAborted
void setAborted(Result result=Result())
Definition: queued_action_server.h:73
QueuedActionServer::callback
ExecuteCallback callback
Definition: queued_action_server.h:200
ACTION_DEFINITION
#define ACTION_DEFINITION(ActionSpec)
ros
ros.h
QueuedActionServer::shutdown
void shutdown()
Definition: queued_action_server.h:100
action_definition.h
QueuedActionServer::mutex
std::mutex mutex
Definition: queued_action_server.h:197
ensenso
Definition: point_cloud_utilities.h:5
QueuedActionServer::shutdownRequested
volatile bool shutdownRequested
Definition: queued_action_server.h:208
ENSENSO_DEBUG_NAMED
void ENSENSO_DEBUG_NAMED(std::string name, T... args)
Definition: logging.h:87
QueuedActionServer::loop
void loop()
Definition: queued_action_server.h:141
QueuedActionServer::publishFeedback
void publishFeedback(FeedbackConstPtr const &feedback)
Definition: queued_action_server.h:89
QueuedActionServer::ExecuteCallback
ensenso::std::function< void(GoalConstPtr const &)> ExecuteCallback
Definition: queued_action_server.h:32
QueuedActionServer::publishFeedback
void publishFeedback(Feedback const &feedback)
Definition: queued_action_server.h:94
QueuedActionServer::loopCondition
std::condition_variable loopCondition
Definition: queued_action_server.h:198
QueuedActionServer::start
void start()
Definition: queued_action_server.h:54
ensenso::ros::NodeHandle
::ros::NodeHandle NodeHandle
Definition: node.h:215
QueuedActionServer::GoalHandle
typename actionlib::ActionServer< ActionSpec >::GoalHandle GoalHandle
Definition: queued_action_server.h:30
QueuedActionServer::currentGoal
GoalHandle currentGoal
Definition: queued_action_server.h:202
QueuedActionServer::isPreemptRequested
bool isPreemptRequested()
Definition: queued_action_server.h:60
QueuedActionServer::onGoalReceived
void onGoalReceived(GoalHandle goal)
Definition: queued_action_server.h:114
action_server.h
ros::this_node::getName
const ROSCPP_DECL std::string & getName()
QueuedActionServer::getLoggerName
std::string getLoggerName()
Definition: queued_action_server.h:109
ENSENSO_WARN_NAMED
void ENSENSO_WARN_NAMED(std::string name, T... args)
Definition: logging.h:223
QueuedActionServer::setPreempted
void setPreempted(Result result=Result())
Definition: queued_action_server.h:81
QueuedActionServer::nh
ensenso::ros::NodeHandle nh
Definition: queued_action_server.h:191
std
logging.h
actionlib
QueuedActionServer::~QueuedActionServer
~QueuedActionServer()
Definition: queued_action_server.h:49
QueuedActionServer::setSucceeded
void setSucceeded(Result result=Result())
Definition: queued_action_server.h:65
core.h
QueuedActionServer::preemptRequested
bool preemptRequested
Definition: queued_action_server.h:206
node_handle.h
QueuedActionServer::loopThread
std::thread loopThread
Definition: queued_action_server.h:195
QueuedActionServer
Definition: queued_action_server.h:26
QueuedActionServer::goalQueue
std::queue< GoalHandle > goalQueue
Definition: queued_action_server.h:203
QueuedActionServer::actionServer
std::unique_ptr< actionlib::ActionServer< ActionSpec > > actionServer
Definition: queued_action_server.h:193


ensenso_camera
Author(s): Ensenso
autogenerated on Wed Apr 2 2025 02:37:46