Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
behavior_tree_navigator.hpp
1 // Copyright (c) 2021-2023 Samsung Research America
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef NAV2_CORE__BEHAVIOR_TREE_NAVIGATOR_HPP_
16 #define NAV2_CORE__BEHAVIOR_TREE_NAVIGATOR_HPP_
17 
18 #include <memory>
19 #include <string>
20 #include <vector>
21 #include <mutex>
22 
23 #include "nav2_util/odometry_utils.hpp"
24 #include "tf2_ros/buffer.hpp"
25 #include "rclcpp/rclcpp.hpp"
26 #include "nav2_ros_common/lifecycle_node.hpp"
27 #include "pluginlib/class_loader.hpp"
28 #include "nav2_behavior_tree/bt_action_server.hpp"
29 
30 namespace nav2_core
31 {
32 
38 {
39  std::string robot_frame;
40  std::string global_frame;
41  double transform_tolerance;
42  std::shared_ptr<tf2_ros::Buffer> tf;
43 };
44 
51 {
52 public:
57  : current_navigator_(std::string("")) {}
58 
63  bool isNavigating()
64  {
65  std::scoped_lock l(mutex_);
66  return !current_navigator_.empty();
67  }
68 
73  void startNavigating(const std::string & navigator_name)
74  {
75  std::scoped_lock l(mutex_);
76  if (!current_navigator_.empty()) {
77  RCLCPP_ERROR(
78  rclcpp::get_logger("NavigatorMutex"),
79  "Major error! Navigation requested while another navigation"
80  " task is in progress! This likely occurred from an incorrect"
81  "implementation of a navigator plugin.");
82  }
83  current_navigator_ = navigator_name;
84  }
85 
90  void stopNavigating(const std::string & navigator_name)
91  {
92  std::scoped_lock l(mutex_);
93  if (current_navigator_ != navigator_name) {
94  RCLCPP_ERROR(
95  rclcpp::get_logger("NavigatorMutex"),
96  "Major error! Navigation stopped while another navigation"
97  " task is in progress! This likely occurred from an incorrect"
98  "implementation of a navigator plugin.");
99  } else {
100  current_navigator_ = std::string("");
101  }
102  }
103 
104 protected:
105  std::string current_navigator_;
106  std::mutex mutex_;
107 };
108 
117 {
118 public:
119  NavigatorBase() = default;
120  virtual ~NavigatorBase() = default;
121 
126  virtual bool on_configure(
127  nav2::LifecycleNode::WeakPtr parent_node,
128  const std::vector<std::string> & plugin_lib_names,
129  const FeedbackUtils & feedback_utils,
130  nav2_core::NavigatorMuxer * plugin_muxer,
131  std::shared_ptr<nav2_util::OdomSmoother> odom_smoother) = 0;
132 
137  virtual bool on_activate() = 0;
138 
143  virtual bool on_deactivate() = 0;
144 
149  virtual bool on_cleanup() = 0;
150 };
151 
158 template<class ActionT>
160 {
161 public:
162  using Ptr = std::shared_ptr<nav2_core::BehaviorTreeNavigator<ActionT>>;
163 
168  : NavigatorBase()
169  {
170  plugin_muxer_ = nullptr;
171  }
172 
176  virtual ~BehaviorTreeNavigator() = default;
177 
189  nav2::LifecycleNode::WeakPtr parent_node,
190  const std::vector<std::string> & plugin_lib_names,
191  const FeedbackUtils & feedback_utils,
192  nav2_core::NavigatorMuxer * plugin_muxer,
193  std::shared_ptr<nav2_util::OdomSmoother> odom_smoother) final
194  {
195  auto node = parent_node.lock();
196  logger_ = node->get_logger();
197  clock_ = node->get_clock();
198  feedback_utils_ = feedback_utils;
199  plugin_muxer_ = plugin_muxer;
200 
201  // get the default behavior tree for this navigator
202  std::string default_bt_xml_filename = getDefaultBTFilepath(parent_node);
203 
204  auto search_directories = node->declare_or_get_parameter(
205  "bt_search_directories",
206  std::vector<std::string>{ament_index_cpp::get_package_share_directory(
207  "nav2_bt_navigator") + "/behavior_trees"}
208  );
209 
210  // Create the Behavior Tree Action Server for this navigator
211  bt_action_server_ =
212  std::make_unique<nav2_behavior_tree::BtActionServer<ActionT, nav2::LifecycleNode>>(
213  node,
214  getName(),
215  plugin_lib_names,
216  default_bt_xml_filename,
217  std::bind(&BehaviorTreeNavigator::onGoalReceived, this, std::placeholders::_1),
218  std::bind(&BehaviorTreeNavigator::onLoop, this),
219  std::bind(&BehaviorTreeNavigator::onPreempt, this, std::placeholders::_1),
220  std::bind(
222  std::placeholders::_1, std::placeholders::_2),
223  search_directories);
224 
225  bool ok = true;
226  if (!bt_action_server_->on_configure()) {
227  ok = false;
228  }
229 
230  BT::Blackboard::Ptr blackboard = bt_action_server_->getBlackboard();
231  blackboard->set("tf_buffer", feedback_utils.tf); // NOLINT
232  blackboard->set("initial_pose_received", false); // NOLINT
233  blackboard->set("number_recoveries", 0); // NOLINT
234  blackboard->set("odom_smoother", odom_smoother); // NOLINT
235 
236  return configure(parent_node, odom_smoother) && ok;
237  }
238 
243  bool on_activate() final
244  {
245  bool ok = true;
246 
247  if (!bt_action_server_->on_activate()) {
248  ok = false;
249  }
250 
251  return activate() && ok;
252  }
253 
258  bool on_deactivate() final
259  {
260  bool ok = true;
261  if (!bt_action_server_->on_deactivate()) {
262  ok = false;
263  }
264 
265  return deactivate() && ok;
266  }
267 
272  bool on_cleanup() final
273  {
274  bool ok = true;
275  if (!bt_action_server_->on_cleanup()) {
276  ok = false;
277  }
278 
279  bt_action_server_.reset();
280 
281  return cleanup() && ok;
282  }
283 
284  virtual std::string getDefaultBTFilepath(nav2::LifecycleNode::WeakPtr node) = 0;
285 
290  virtual std::string getName() = 0;
291 
292 protected:
296  bool onGoalReceived(typename ActionT::Goal::ConstSharedPtr goal)
297  {
298  if (plugin_muxer_->isNavigating()) {
299  RCLCPP_ERROR(
300  logger_,
301  "Requested navigation from %s while another navigator is processing,"
302  " rejecting request.", getName().c_str());
303  return false;
304  }
305 
306  bool goal_accepted = goalReceived(goal);
307 
308  if (goal_accepted) {
309  plugin_muxer_->startNavigating(getName());
310  }
311 
312  return goal_accepted;
313  }
314 
319  typename ActionT::Result::SharedPtr result,
320  const nav2_behavior_tree::BtStatus final_bt_status)
321  {
322  plugin_muxer_->stopNavigating(getName());
323  goalCompleted(result, final_bt_status);
324  }
325 
331  virtual bool goalReceived(typename ActionT::Goal::ConstSharedPtr goal) = 0;
332 
337  virtual void onLoop() = 0;
338 
342  virtual void onPreempt(typename ActionT::Goal::ConstSharedPtr goal) = 0;
343 
348  virtual void goalCompleted(
349  typename ActionT::Result::SharedPtr result,
350  const nav2_behavior_tree::BtStatus final_bt_status) = 0;
351 
355  virtual bool configure(
356  nav2::LifecycleNode::WeakPtr /*node*/,
357  std::shared_ptr<nav2_util::OdomSmoother>/*odom_smoother*/)
358  {
359  return true;
360  }
361 
365  virtual bool cleanup() {return true;}
366 
370  virtual bool activate() {return true;}
371 
375  virtual bool deactivate() {return true;}
376 
377  std::unique_ptr<nav2_behavior_tree::BtActionServer<ActionT, nav2::LifecycleNode>>
378  bt_action_server_;
379  rclcpp::Logger logger_{rclcpp::get_logger("Navigator")};
380  rclcpp::Clock::SharedPtr clock_;
381  FeedbackUtils feedback_utils_;
382  NavigatorMuxer * plugin_muxer_;
383 };
384 
385 } // namespace nav2_core
386 
387 #endif // NAV2_CORE__BEHAVIOR_TREE_NAVIGATOR_HPP_
Navigator interface that acts as a base class for all BT-based Navigator action's plugins All methods...
virtual void goalCompleted(typename ActionT::Result::SharedPtr result, const nav2_behavior_tree::BtStatus final_bt_status)=0
A callback that is called when a the action is completed; Can fill in action result message or indica...
virtual void onPreempt(typename ActionT::Goal::ConstSharedPtr goal)=0
A callback that is called when a preempt is requested.
BehaviorTreeNavigator()
A Navigator constructor.
virtual ~BehaviorTreeNavigator()=default
Virtual destructor.
virtual std::string getName()=0
Get the action name of this navigator to expose.
bool onGoalReceived(typename ActionT::Goal::ConstSharedPtr goal)
An intermediate goal reception function to mux navigators.
bool on_cleanup() final
Cleanup a navigator.
void onCompletion(typename ActionT::Result::SharedPtr result, const nav2_behavior_tree::BtStatus final_bt_status)
An intermediate completion function to mux navigators.
virtual bool deactivate()
Method to deactivate and any threads involved in execution.
virtual void onLoop()=0
A callback that defines execution that happens on one iteration through the BT Can be used to publish...
virtual bool activate()
Method to activate any threads involved in execution.
bool on_deactivate() final
Deactivation of the navigator's backend BT and actions.
virtual bool cleanup()
Method to cleanup resources.
virtual bool configure(nav2::LifecycleNode::WeakPtr, std::shared_ptr< nav2_util::OdomSmoother >)
virtual bool goalReceived(typename ActionT::Goal::ConstSharedPtr goal)=0
A callback to be called when a new goal is received by the BT action server Can be used to check if g...
bool on_activate() final
Activation of the navigator's backend BT and actions.
bool on_configure(nav2::LifecycleNode::WeakPtr parent_node, const std::vector< std::string > &plugin_lib_names, const FeedbackUtils &feedback_utils, nav2_core::NavigatorMuxer *plugin_muxer, std::shared_ptr< nav2_util::OdomSmoother > odom_smoother) final
Configuration to setup the navigator's backend BT and actions.
Navigator interface to allow navigators to be stored in a vector and accessed via pluginlib due to te...
virtual bool on_cleanup()=0
Cleanup a navigator.
virtual bool on_deactivate()=0
Deactivation of the navigator's backend BT and actions.
virtual bool on_activate()=0
Activation of the navigator's backend BT and actions.
virtual bool on_configure(nav2::LifecycleNode::WeakPtr parent_node, const std::vector< std::string > &plugin_lib_names, const FeedbackUtils &feedback_utils, nav2_core::NavigatorMuxer *plugin_muxer, std::shared_ptr< nav2_util::OdomSmoother > odom_smoother)=0
Configuration of the navigator's backend BT and actions.
A class to control the state of the BT navigator by allowing only a single plugin to be processed at ...
void startNavigating(const std::string &navigator_name)
Start navigating with a given navigator.
void stopNavigating(const std::string &navigator_name)
Stop navigating with a given navigator.
bool isNavigating()
Get the navigator muxer state.
NavigatorMuxer()
A Navigator Muxer constructor.
Navigator feedback utilities required to get transforms and reference frames.