15 #ifndef NAV2_BEHAVIORS__TIMED_BEHAVIOR_HPP_
16 #define NAV2_BEHAVIORS__TIMED_BEHAVIOR_HPP_
28 #include "rclcpp/rclcpp.hpp"
29 #include "nav2_ros_common/tf2_factories.hpp"
30 #include "geometry_msgs/msg/twist.hpp"
31 #include "nav2_util/robot_utils.hpp"
32 #include "nav2_util/twist_publisher.hpp"
33 #include "nav2_ros_common/simple_action_server.hpp"
34 #include "nav2_ros_common/rate.hpp"
35 #include "nav2_core/behavior.hpp"
36 #pragma GCC diagnostic push
37 #pragma GCC diagnostic ignored "-Wpedantic"
38 #include "tf2/utils.hpp"
39 #pragma GCC diagnostic pop
42 namespace nav2_behaviors
45 enum class Status : int8_t
55 uint16_t error_code{0};
56 std::string error_msg;
59 using namespace std::chrono_literals;
65 template<
typename ActionT>
75 : action_server_(nullptr),
76 cycle_frequency_(10.0),
86 virtual ResultStatus onRun(
const std::shared_ptr<const typename ActionT::Goal> command) = 0;
98 virtual void onConfigure()
104 virtual void onCleanup()
109 virtual void onActionCompletion(std::shared_ptr<typename ActionT::Result>)
115 const nav2::LifecycleNode::WeakPtr & parent,
116 const std::string & name, nav2::TransformBuffer::SharedPtr tf,
117 std::shared_ptr<nav2_costmap_2d::CostmapTopicCollisionChecker> local_collision_checker,
118 std::shared_ptr<nav2_costmap_2d::CostmapTopicCollisionChecker> global_collision_checker)
122 auto node = node_.lock();
123 logger_ = node->get_logger();
124 clock_ = node->get_clock();
126 RCLCPP_INFO(logger_,
"Configuring %s", name.c_str());
128 behavior_name_ = name;
131 node->get_parameter(
"cycle_frequency", cycle_frequency_);
132 node->get_parameter(
"local_frame", local_frame_);
133 node->get_parameter(
"global_frame", global_frame_);
134 node->get_parameter(
"robot_base_frame", robot_base_frame_);
135 transform_staleness_threshold_ = node->declare_or_get_parameter(
136 "transform_staleness_threshold", 0.0);
138 action_server_ = node->create_action_server<ActionT>(
140 std::bind(&TimedBehavior::execute,
this),
nullptr,
nullptr, std::chrono::milliseconds(
143 local_collision_checker_ = local_collision_checker;
144 global_collision_checker_ = global_collision_checker;
146 vel_pub_ = std::make_unique<nav2_util::TwistPublisher>(node,
"cmd_vel");
154 action_server_.reset();
162 RCLCPP_INFO(logger_,
"Activating %s", behavior_name_.c_str());
164 vel_pub_->on_activate();
165 action_server_->activate();
172 vel_pub_->on_deactivate();
173 action_server_->deactivate();
185 if (!nav2_util::getFreshPose(
186 *tf_, local_frame_, robot_base_frame_, clock_->now(),
187 transform_staleness_threshold_, pose))
194 nav2::LifecycleNode::WeakPtr node_;
196 std::string behavior_name_;
197 std::unique_ptr<nav2_util::TwistPublisher> vel_pub_;
198 typename ActionServer::SharedPtr action_server_;
199 std::shared_ptr<nav2_costmap_2d::CostmapTopicCollisionChecker> local_collision_checker_;
200 std::shared_ptr<nav2_costmap_2d::CostmapTopicCollisionChecker> global_collision_checker_;
201 nav2::TransformBuffer::SharedPtr tf_;
203 double cycle_frequency_;
205 std::string local_frame_;
206 std::string global_frame_;
207 std::string robot_base_frame_;
208 double transform_staleness_threshold_{0.0};
209 rclcpp::Duration elapsed_time_{0, 0};
212 rclcpp::Clock::SharedPtr clock_;
215 rclcpp::Logger logger_{rclcpp::get_logger(
"nav2_behaviors")};
221 RCLCPP_INFO(logger_,
"Running %s", behavior_name_.c_str());
226 "Called while inactive, ignoring request.");
231 auto result = std::make_shared<typename ActionT::Result>();
233 ResultStatus on_run_result = onRun(action_server_->get_current_goal());
234 if (on_run_result.status != Status::SUCCEEDED) {
235 result->error_code = on_run_result.error_code;
236 result->error_msg = on_run_result.error_msg;
238 logger_,
"Initial checks failed for %s - %s", behavior_name_.c_str(),
239 on_run_result.error_msg.c_str());
240 action_server_->terminate_current(result);
244 auto start_time = clock_->now();
245 auto node = node_.lock();
249 "Failed to run %s because the parent node is no longer available.",
250 behavior_name_.c_str());
251 result->error_msg = behavior_name_ +
" failed: parent node expired";
252 result->total_elapsed_time = clock_->now() - start_time;
253 onActionCompletion(result);
254 action_server_->terminate_current(result);
259 while (rclcpp::ok()) {
260 elapsed_time_ = clock_->now() - start_time;
262 if (action_server_->is_preempt_requested()) {
264 logger_,
"Received a preemption request for %s,"
265 " however feature is currently not implemented. Aborting and stopping.",
266 behavior_name_.c_str());
268 result->total_elapsed_time = clock_->now() - start_time;
269 onActionCompletion(result);
270 action_server_->terminate_current(result);
274 if (action_server_->is_cancel_requested()) {
275 RCLCPP_INFO(logger_,
"Canceling %s", behavior_name_.c_str());
277 result->total_elapsed_time = elapsed_time_;
278 onActionCompletion(result);
279 action_server_->terminate_all(result);
283 ResultStatus on_cycle_update_result = onCycleUpdate();
284 switch (on_cycle_update_result.status) {
285 case Status::SUCCEEDED:
288 "%s completed successfully", behavior_name_.c_str());
289 result->total_elapsed_time = clock_->now() - start_time;
290 onActionCompletion(result);
291 action_server_->succeeded_current(result);
295 result->error_code = on_cycle_update_result.error_code;
296 result->error_msg = behavior_name_ +
" failed:" + on_cycle_update_result.error_msg;
297 RCLCPP_WARN(logger_,
"%s", result->error_msg.c_str());
298 result->total_elapsed_time = clock_->now() - start_time;
299 onActionCompletion(result);
300 action_server_->terminate_current(result);
303 case Status::RUNNING:
315 auto cmd_vel = std::make_unique<geometry_msgs::msg::TwistStamped>();
316 cmd_vel->header.frame_id = robot_base_frame_;
317 cmd_vel->header.stamp = clock_->now();
318 cmd_vel->twist.linear.x = 0.0;
319 cmd_vel->twist.linear.y = 0.0;
320 cmd_vel->twist.angular.z = 0.0;
322 vel_pub_->publish(std::move(cmd_vel));
A sim-time-aware rate for Nav2 loops.
An action server wrapper to make applications simpler using Actions.
TimedBehavior()
A TimedBehavior constructor.
bool getCurrentPoseChecked(geometry_msgs::msg::PoseStamped &pose)
Get one checked robot pose in the local frame, preserving the TF timestamp.
void deactivate() override
Method to deactivate Behavior and any threads involved in execution.
void activate() override
Method to active Behavior and any threads involved in execution.
void configure(const nav2::LifecycleNode::WeakPtr &parent, const std::string &name, nav2::TransformBuffer::SharedPtr tf, std::shared_ptr< nav2_costmap_2d::CostmapTopicCollisionChecker > local_collision_checker, std::shared_ptr< nav2_costmap_2d::CostmapTopicCollisionChecker > global_collision_checker) override
void cleanup() override
Method to cleanup resources used on shutdown.
Abstract interface for behaviors to adhere to with pluginlib.