15 #ifndef NAV2_BEHAVIORS__TIMED_BEHAVIOR_HPP_
16 #define NAV2_BEHAVIORS__TIMED_BEHAVIOR_HPP_
28 #include "rclcpp/rclcpp.hpp"
29 #include "tf2_ros/transform_listener.hpp"
30 #include "tf2_ros/create_timer_ros.hpp"
31 #include "geometry_msgs/msg/twist.hpp"
32 #include "nav2_util/robot_utils.hpp"
33 #include "nav2_util/twist_publisher.hpp"
34 #include "nav2_ros_common/simple_action_server.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),
78 transform_tolerance_(0.0)
87 virtual ResultStatus onRun(
const std::shared_ptr<const typename ActionT::Goal> command) = 0;
99 virtual void onConfigure()
105 virtual void onCleanup()
110 virtual void onActionCompletion(std::shared_ptr<typename ActionT::Result>)
116 const nav2::LifecycleNode::WeakPtr & parent,
117 const std::string & name, std::shared_ptr<tf2_ros::Buffer> tf,
118 std::shared_ptr<nav2_costmap_2d::CostmapTopicCollisionChecker> local_collision_checker,
119 std::shared_ptr<nav2_costmap_2d::CostmapTopicCollisionChecker> global_collision_checker)
123 auto node = node_.lock();
124 logger_ = node->get_logger();
125 clock_ = node->get_clock();
127 RCLCPP_INFO(logger_,
"Configuring %s", name.c_str());
129 behavior_name_ = name;
132 node->get_parameter(
"cycle_frequency", cycle_frequency_);
133 node->get_parameter(
"local_frame", local_frame_);
134 node->get_parameter(
"global_frame", global_frame_);
135 node->get_parameter(
"robot_base_frame", robot_base_frame_);
136 node->get_parameter(
"transform_tolerance", transform_tolerance_);
138 action_server_ = node->create_action_server<ActionT>(
140 std::bind(&TimedBehavior::execute,
this),
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();
178 nav2::LifecycleNode::WeakPtr node_;
180 std::string behavior_name_;
181 std::unique_ptr<nav2_util::TwistPublisher> vel_pub_;
182 typename ActionServer::SharedPtr action_server_;
183 std::shared_ptr<nav2_costmap_2d::CostmapTopicCollisionChecker> local_collision_checker_;
184 std::shared_ptr<nav2_costmap_2d::CostmapTopicCollisionChecker> global_collision_checker_;
185 std::shared_ptr<tf2_ros::Buffer> tf_;
187 double cycle_frequency_;
189 std::string local_frame_;
190 std::string global_frame_;
191 std::string robot_base_frame_;
192 double transform_tolerance_;
193 rclcpp::Duration elapsed_time_{0, 0};
196 rclcpp::Clock::SharedPtr clock_;
199 rclcpp::Logger logger_{rclcpp::get_logger(
"nav2_behaviors")};
205 RCLCPP_INFO(logger_,
"Running %s", behavior_name_.c_str());
210 "Called while inactive, ignoring request.");
215 auto result = std::make_shared<typename ActionT::Result>();
217 ResultStatus on_run_result = onRun(action_server_->get_current_goal());
218 if (on_run_result.status != Status::SUCCEEDED) {
219 result->error_code = on_run_result.error_code;
220 result->error_msg = on_run_result.error_msg;
221 RCLCPP_INFO(logger_,
"Initial checks failed for %s - %s", behavior_name_.c_str(),
222 on_run_result.error_msg.c_str());
223 action_server_->terminate_current(result);
227 auto start_time = clock_->now();
228 rclcpp::WallRate loop_rate(cycle_frequency_);
230 while (rclcpp::ok()) {
231 elapsed_time_ = clock_->now() - start_time;
233 if (action_server_->is_preempt_requested()) {
235 logger_,
"Received a preemption request for %s,"
236 " however feature is currently not implemented. Aborting and stopping.",
237 behavior_name_.c_str());
239 result->total_elapsed_time = clock_->now() - start_time;
240 onActionCompletion(result);
241 action_server_->terminate_current(result);
245 if (action_server_->is_cancel_requested()) {
246 RCLCPP_INFO(logger_,
"Canceling %s", behavior_name_.c_str());
248 result->total_elapsed_time = elapsed_time_;
249 onActionCompletion(result);
250 action_server_->terminate_all(result);
254 ResultStatus on_cycle_update_result = onCycleUpdate();
255 switch (on_cycle_update_result.status) {
256 case Status::SUCCEEDED:
259 "%s completed successfully", behavior_name_.c_str());
260 result->total_elapsed_time = clock_->now() - start_time;
261 onActionCompletion(result);
262 action_server_->succeeded_current(result);
266 result->error_code = on_cycle_update_result.error_code;
267 result->error_msg = behavior_name_ +
" failed:" + on_cycle_update_result.error_msg;
268 RCLCPP_WARN(logger_, result->error_msg.c_str());
269 result->total_elapsed_time = clock_->now() - start_time;
270 onActionCompletion(result);
271 action_server_->terminate_current(result);
274 case Status::RUNNING:
286 auto cmd_vel = std::make_unique<geometry_msgs::msg::TwistStamped>();
287 cmd_vel->header.frame_id = robot_base_frame_;
288 cmd_vel->header.stamp = clock_->now();
289 cmd_vel->twist.linear.x = 0.0;
290 cmd_vel->twist.linear.y = 0.0;
291 cmd_vel->twist.angular.z = 0.0;
293 vel_pub_->publish(std::move(cmd_vel));
An action server wrapper to make applications simpler using Actions.
void configure(const nav2::LifecycleNode::WeakPtr &parent, const std::string &name, std::shared_ptr< tf2_ros::Buffer > tf, std::shared_ptr< nav2_costmap_2d::CostmapTopicCollisionChecker > local_collision_checker, std::shared_ptr< nav2_costmap_2d::CostmapTopicCollisionChecker > global_collision_checker) override
TimedBehavior()
A TimedBehavior constructor.
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 cleanup() override
Method to cleanup resources used on shutdown.
Abstract interface for behaviors to adhere to with pluginlib.