EasyFleet
A simple-by-default framework for multi-robot, multi-capability fleets built on ROS 2
Loading...
Searching...
No Matches
action_server_base.hpp
1// Copyright 2026 Intelligent Robotics Lab
2//
3// This file is part of the project EasyFleet
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16#ifndef EASYFLEET_CORE__ACTION_SERVER_BASE_HPP_
17#define EASYFLEET_CORE__ACTION_SERVER_BASE_HPP_
18
19#include <atomic>
20#include <condition_variable>
21#include <memory>
22#include <mutex>
23#include <string>
24#include <thread>
25#include <vector>
26
27#include "rclcpp/rclcpp.hpp"
28#include "rclcpp_action/rclcpp_action.hpp"
29
30namespace easyfleet_core
31{
32
34
64template<typename ActionT>
65class ActionServerBase
66{
67public:
69 using ActionType = ActionT;
71 using Goal = typename ActionT::Goal;
73 using Feedback = typename ActionT::Feedback;
75 using Result = typename ActionT::Result;
77 using GoalHandle = rclcpp_action::ServerGoalHandle<ActionT>;
79 using GoalHandleSharedPtr = std::shared_ptr<GoalHandle>;
81 using SharedPtr = std::shared_ptr<ActionServerBase<ActionT>>;
82
83 ActionServerBase(const ActionServerBase &) = delete;
84 ActionServerBase & operator=(const ActionServerBase &) = delete;
85
86 virtual ~ActionServerBase();
87
90 const std::string & get_action_name() const noexcept;
91
94 bool is_active() const;
95
99 bool is_preemptable() const noexcept;
100
101protected:
111 template<typename NodeT>
112 explicit ActionServerBase(
113 NodeT & node,
114 const std::string & action_name,
115 bool default_allow_preemption = true)
116 : ActionServerBase(
117 node.get_node_base_interface(),
118 node.get_node_clock_interface(),
119 node.get_node_logging_interface(),
120 node.get_node_parameters_interface(),
121 node.get_node_waitables_interface(),
122 action_name,
123 default_allow_preemption)
124 {
125 }
126
134 virtual rclcpp_action::GoalResponse on_goal_received(
135 const rclcpp_action::GoalUUID & uuid,
136 std::shared_ptr<const Goal> goal) = 0;
137
149 virtual void on_execute(const GoalHandleSharedPtr goal_handle) = 0;
150
155 virtual rclcpp_action::CancelResponse on_cancel_requested(const GoalHandleSharedPtr goal_handle);
156
160 virtual void on_preempted(const GoalHandleSharedPtr & preempted_goal_handle);
161
166 bool is_preempt_requested() const noexcept;
167
172 bool is_shutdown_requested() const noexcept;
173
179 rclcpp::Logger logger() const;
180
181private:
182 ActionServerBase(
183 rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base,
184 rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock,
185 rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging,
186 rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters,
187 rclcpp::node_interfaces::NodeWaitablesInterface::SharedPtr node_waitables,
188 const std::string & action_name,
189 bool default_allow_preemption);
190
191 rclcpp_action::GoalResponse handle_goal(
192 const rclcpp_action::GoalUUID & uuid,
193 std::shared_ptr<const Goal> goal);
194 rclcpp_action::CancelResponse handle_cancel(const GoalHandleSharedPtr goal_handle);
195 void handle_accepted(GoalHandleSharedPtr goal_handle);
196 void on_parameters_set(const std::vector<rclcpp::Parameter> & params);
197 void worker_loop();
198
199 rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_base_;
200 rclcpp::node_interfaces::NodeClockInterface::SharedPtr node_clock_;
201 rclcpp::node_interfaces::NodeLoggingInterface::SharedPtr node_logging_;
202 rclcpp::node_interfaces::NodeParametersInterface::SharedPtr node_parameters_;
203 rclcpp::node_interfaces::NodeWaitablesInterface::SharedPtr node_waitables_;
204
205 std::string action_name_;
206 std::string robot_name_;
207 std::string param_name_;
208 std::atomic_bool allow_preemption_{true};
209
210 typename rclcpp_action::Server<ActionT>::SharedPtr server_;
211 rclcpp::node_interfaces::PostSetParametersCallbackHandle::SharedPtr param_cb_handle_;
212
213 mutable std::mutex mutex_;
214 std::condition_variable cv_;
215 std::atomic_bool shutting_down_{false};
216 std::atomic_bool preempt_requested_{false};
217 GoalHandleSharedPtr active_handle_;
218 GoalHandleSharedPtr pending_handle_;
219 std::thread worker_;
220};
221
222} // namespace easyfleet_core
223
224#include "easyfleet_core/detail/action_server_base_impl.hpp"
225
226#endif // EASYFLEET_CORE__ACTION_SERVER_BASE_HPP_
std::shared_ptr< ActionServerBase< ActionT > > SharedPtr
Shared pointer to an ActionServerBase<ActionT>.
Definition action_server_base.hpp:81
const std::string & get_action_name() const noexcept
Fully-qualified name of the action served by this instance.
Definition action_server_base_impl.hpp:109
virtual void on_execute(const GoalHandleSharedPtr goal_handle)=0
Run an accepted goal to completion.
ActionT ActionType
The wrapped rclcpp_action action type.
Definition action_server_base.hpp:69
typename ActionT::Goal Goal
Goal type of the wrapped action.
Definition action_server_base.hpp:71
rclcpp_action::ServerGoalHandle< ActionT > GoalHandle
rclcpp_action server-side goal handle type of the wrapped action.
Definition action_server_base.hpp:77
typename ActionT::Result Result
Result type of the wrapped action.
Definition action_server_base.hpp:75
virtual rclcpp_action::CancelResponse on_cancel_requested(const GoalHandleSharedPtr goal_handle)
Decide whether a cancel request (via the action's cancel service) should be accepted.
Definition action_server_base_impl.hpp:128
bool is_preempt_requested() const noexcept
Whether a newer goal has been accepted and is waiting to replace the one currently executing.
Definition action_server_base_impl.hpp:140
typename ActionT::Feedback Feedback
Feedback type of the wrapped action.
Definition action_server_base.hpp:73
virtual void on_preempted(const GoalHandleSharedPtr &preempted_goal_handle)
Optional hook invoked (from the accepting thread, not the worker thread) when a new goal is about to ...
Definition action_server_base_impl.hpp:135
std::shared_ptr< GoalHandle > GoalHandleSharedPtr
Shared pointer to a GoalHandle.
Definition action_server_base.hpp:79
virtual rclcpp_action::GoalResponse on_goal_received(const rclcpp_action::GoalUUID &uuid, std::shared_ptr< const Goal > goal)=0
Validate an incoming goal.