72 explicit Task(
const std::string& name,
const rclcpp::NodeOptions& options,
81 virtual bool onGoalRequest(std::shared_ptr<const Goal> goal_ptr);
83 virtual void setInitialResult(std::shared_ptr<const Goal> goal_ptr, std::shared_ptr<Result> result_ptr);
85 virtual bool onCancelRequest(std::shared_ptr<const Goal> goal_ptr, std::shared_ptr<Result> result_ptr);
87 virtual Status cancelGoal(std::shared_ptr<const Goal> goal_ptr, std::shared_ptr<Result> result_ptr);
89 virtual Status executeGoal(std::shared_ptr<const Goal> goal_ptr, std::shared_ptr<Feedback> feedback_ptr,
90 std::shared_ptr<Result> result_ptr) = 0;
96 rclcpp_action::GoalResponse handle_goal_(
const rclcpp_action::GoalUUID& uuid, std::shared_ptr<const Goal> goal_ptr);
97 rclcpp_action::CancelResponse handle_cancel_(std::shared_ptr<GoalHandle> goal_handle_ptr);
98 void handle_accepted_(std::shared_ptr<GoalHandle> goal_handle_ptr);
100 void execution_timer_callback_(std::shared_ptr<const Goal> goal_ptr);
110 typename rclcpp_action::Server<ActionT>::SharedPtr action_server_ptr_;
111 rclcpp::TimerBase::SharedPtr execution_timer_ptr_;
112 const std::chrono::milliseconds execution_timer_interval_;
113 std::chrono::steady_clock::time_point last_feedback_ts_;
116template <
class ActionT>
118 std::shared_ptr<ActionContextType> action_context_ptr, std::chrono::milliseconds execution_interval,
119 std::chrono::milliseconds feedback_interval)
120 : node_ptr_{ node_ptr }, action_context_ptr_{ action_context_ptr }, execution_timer_interval_{ execution_interval }
124 using namespace std::placeholders;
125 action_server_ptr_ = rclcpp_action::create_server<ActionT>(
132 rcl_interfaces::msg::ParameterDescriptor param_desc;
133 param_desc.description =
"Rate at which this task publishes feedback.";
137template <
class ActionT>
139 std::chrono::milliseconds execution_interval, std::chrono::milliseconds feedback_interval)
140 :
Task{ name, node_ptr, std::make_shared<
ActionContextType>(node_ptr->get_logger()), execution_interval,
145template <
class ActionT>
147 std::chrono::milliseconds execution_interval, std::chrono::milliseconds feedback_interval)
148 :
Task{ name, std::make_shared<rclcpp::Node>(
"task_" + name +
"_node", options), execution_interval,
153template <
class ActionT>
159template <
class ActionT>
167template <
class ActionT>
168void Task<ActionT>::setInitialResult(std::shared_ptr<const Goal> goal_ptr, std::shared_ptr<Result> result_ptr)
175template <
class ActionT>
176bool Task<ActionT>::onCancelRequest(std::shared_ptr<const Goal> goal_ptr, std::shared_ptr<Result> result_ptr)
184template <
class ActionT>
185TaskStatus Task<ActionT>::cancelGoal(std::shared_ptr<const Goal> goal_ptr, std::shared_ptr<Result> result_ptr)
193template <
class ActionT>
194rclcpp_action::GoalResponse Task<ActionT>::handle_goal_(
const rclcpp_action::GoalUUID& uuid,
195 std::shared_ptr<const Goal> goal_ptr)
197 if (action_context_ptr_->isValid() && action_context_ptr_->getGoalHandlePtr()->is_active())
199 RCLCPP_DEBUG(node_ptr_->get_logger(),
200 "Goal %s was REJECTED because another one is still executing. ID of the executing goal: %s",
201 rclcpp_action::to_string(uuid).c_str(),
202 rclcpp_action::to_string(action_context_ptr_->getGoalHandlePtr()->get_goal_id()).c_str());
203 return rclcpp_action::GoalResponse::REJECT;
206 if (onGoalRequest(goal_ptr))
208 return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
211 RCLCPP_DEBUG(node_ptr_->get_logger(),
"Goal %s was REJECTED because onGoalRequest() returned false",
212 rclcpp_action::to_string(uuid).c_str());
213 return rclcpp_action::GoalResponse::REJECT;
216template <
class ActionT>
217rclcpp_action::CancelResponse Task<ActionT>::handle_cancel_(std::shared_ptr<GoalHandle> goal_handle_ptr)
219 (void)goal_handle_ptr;
221 return onCancelRequest(action_context_ptr_->getGoalHandlePtr()->get_goal(), action_context_ptr_->getResultPtr()) ?
222 rclcpp_action::CancelResponse::ACCEPT :
223 rclcpp_action::CancelResponse::REJECT;
226template <
class ActionT>
227void Task<ActionT>::handle_accepted_(std::shared_ptr<GoalHandle> goal_handle_ptr)
229 action_context_ptr_->setUp(goal_handle_ptr);
230 const auto goal_ptr = action_context_ptr_->getGoalHandlePtr()->get_goal();
231 setInitialResult(goal_ptr, action_context_ptr_->getResultPtr());
232 (void)goal_handle_ptr;
235 execution_timer_ptr_ = node_ptr_->create_wall_timer(
236 execution_timer_interval_, [
this, goal_ptr]() { this->execution_timer_callback_(goal_ptr); });
239 const std::chrono::milliseconds feedback_interval{ node_ptr_->get_parameter(PARAM_NAME_FEEDBACK_INTERVAL).as_int() };
240 last_feedback_ts_ = std::chrono::steady_clock::now() - feedback_interval;
243template <
class ActionT>
244void Task<ActionT>::execution_timer_callback_(std::shared_ptr<const Goal> goal_ptr)
247 if (!action_context_ptr_->getGoalHandlePtr()->is_active())
249 execution_timer_ptr_->cancel();
254 if (action_context_ptr_->getGoalHandlePtr()->is_canceling())
256 switch (cancelGoal(goal_ptr, action_context_ptr_->getResultPtr()))
261 action_context_ptr_->cancel();
264 action_context_ptr_->abort();
270 const auto ret = executeGoal(goal_ptr, action_context_ptr_->getFeedbackPtr(), action_context_ptr_->getResultPtr());
273 const std::chrono::milliseconds feedback_interval{
274 node_ptr_->get_parameter(PARAM_NAME_FEEDBACK_INTERVAL).as_int()
276 if (feedback_interval <= (std::chrono::steady_clock::now() - last_feedback_ts_))
278 action_context_ptr_->publishFeedback();
279 last_feedback_ts_ = std::chrono::steady_clock::now();
287 action_context_ptr_->succeed();
290 action_context_ptr_->abort();