Skip to content

Commit 5253423

Browse files
Merge pull request #12 from hsrn24/10-mppi-pull-4621
10 mppi pull 4621
2 parents a1b0669 + 68f7d65 commit 5253423

File tree

68 files changed

+2039
-4945
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+2039
-4945
lines changed
Lines changed: 378 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,378 @@
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.h"
25+
#include "rclcpp/rclcpp.hpp"
26+
#include "rclcpp_lifecycle/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+
33+
/**
34+
* @struct FeedbackUtils
35+
* @brief Navigator feedback utilities required to get transforms and reference frames.
36+
*/
37+
struct FeedbackUtils
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+
45+
/**
46+
* @class NavigatorMuxer
47+
* @brief A class to control the state of the BT navigator by allowing only a single
48+
* plugin to be processed at a time.
49+
*/
50+
class NavigatorMuxer
51+
{
52+
public:
53+
/**
54+
* @brief A Navigator Muxer constructor
55+
*/
56+
NavigatorMuxer()
57+
: current_navigator_(std::string("")) {}
58+
59+
/**
60+
* @brief Get the navigator muxer state
61+
* @return bool If a navigator is in progress
62+
*/
63+
bool isNavigating()
64+
{
65+
std::scoped_lock l(mutex_);
66+
return !current_navigator_.empty();
67+
}
68+
69+
/**
70+
* @brief Start navigating with a given navigator
71+
* @param string Name of the navigator to start
72+
*/
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+
86+
/**
87+
* @brief Stop navigating with a given navigator
88+
* @param string Name of the navigator ending task
89+
*/
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+
109+
/**
110+
* @class NavigatorBase
111+
* @brief Navigator interface to allow navigators to be stored in a vector and
112+
* accessed via pluginlib due to templates. These functions will be implemented
113+
* by BehaviorTreeNavigator, not the user. The user should implement the virtual
114+
* methods from BehaviorTreeNavigator to implement their navigator action.
115+
*/
116+
class NavigatorBase
117+
{
118+
public:
119+
NavigatorBase() = default;
120+
virtual ~NavigatorBase() = default;
121+
122+
/**
123+
* @brief Configuration of the navigator's backend BT and actions
124+
* @return bool If successful
125+
*/
126+
virtual bool on_configure(
127+
rclcpp_lifecycle::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+
133+
/**
134+
* @brief Activation of the navigator's backend BT and actions
135+
* @return bool If successful
136+
*/
137+
virtual bool on_activate() = 0;
138+
139+
/**
140+
* @brief Deactivation of the navigator's backend BT and actions
141+
* @return bool If successful
142+
*/
143+
virtual bool on_deactivate() = 0;
144+
145+
/**
146+
* @brief Cleanup a navigator
147+
* @return bool If successful
148+
*/
149+
virtual bool on_cleanup() = 0;
150+
};
151+
152+
/**
153+
* @class BehaviorTreeNavigator
154+
* @brief Navigator interface that acts as a base class for all BT-based Navigator action's plugins
155+
* All methods from NavigatorBase are marked as final so they may not be overrided by derived
156+
* methods - instead, users should use the appropriate APIs provided after BT Action handling.
157+
*/
158+
template<class ActionT>
159+
class BehaviorTreeNavigator : public NavigatorBase
160+
{
161+
public:
162+
using Ptr = std::shared_ptr<nav2_core::BehaviorTreeNavigator<ActionT>>;
163+
164+
/**
165+
* @brief A Navigator constructor
166+
*/
167+
BehaviorTreeNavigator()
168+
: NavigatorBase()
169+
{
170+
plugin_muxer_ = nullptr;
171+
}
172+
173+
/**
174+
* @brief Virtual destructor
175+
*/
176+
virtual ~BehaviorTreeNavigator() = default;
177+
178+
/**
179+
* @brief Configuration to setup the navigator's backend BT and actions
180+
* @param parent_node The ROS parent node to utilize
181+
* @param plugin_lib_names a vector of plugin shared libraries to load
182+
* @param feedback_utils Some utilities useful for navigators to have
183+
* @param plugin_muxer The muxing object to ensure only one navigator
184+
* can be active at a time
185+
* @param odom_smoother Object to get current smoothed robot's speed
186+
* @return bool If successful
187+
*/
188+
bool on_configure(
189+
rclcpp_lifecycle::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+
// Create the Behavior Tree Action Server for this navigator
205+
bt_action_server_ = std::make_unique<nav2_behavior_tree::BtActionServer<ActionT>>(
206+
node,
207+
getName(),
208+
plugin_lib_names,
209+
default_bt_xml_filename,
210+
std::bind(&BehaviorTreeNavigator::onGoalReceived, this, std::placeholders::_1),
211+
std::bind(&BehaviorTreeNavigator::onLoop, this),
212+
std::bind(&BehaviorTreeNavigator::onPreempt, this, std::placeholders::_1),
213+
std::bind(
214+
&BehaviorTreeNavigator::onCompletion, this,
215+
std::placeholders::_1, std::placeholders::_2));
216+
217+
bool ok = true;
218+
if (!bt_action_server_->on_configure()) {
219+
ok = false;
220+
}
221+
222+
BT::Blackboard::Ptr blackboard = bt_action_server_->getBlackboard();
223+
blackboard->set("tf_buffer", feedback_utils.tf); // NOLINT
224+
blackboard->set("initial_pose_received", false); // NOLINT
225+
blackboard->set("number_recoveries", 0); // NOLINT
226+
blackboard->set("odom_smoother", odom_smoother); // NOLINT
227+
228+
return configure(parent_node, odom_smoother) && ok;
229+
}
230+
231+
/**
232+
* @brief Activation of the navigator's backend BT and actions
233+
* @return bool If successful
234+
*/
235+
bool on_activate() final
236+
{
237+
bool ok = true;
238+
239+
if (!bt_action_server_->on_activate()) {
240+
ok = false;
241+
}
242+
243+
return activate() && ok;
244+
}
245+
246+
/**
247+
* @brief Deactivation of the navigator's backend BT and actions
248+
* @return bool If successful
249+
*/
250+
bool on_deactivate() final
251+
{
252+
bool ok = true;
253+
if (!bt_action_server_->on_deactivate()) {
254+
ok = false;
255+
}
256+
257+
return deactivate() && ok;
258+
}
259+
260+
/**
261+
* @brief Cleanup a navigator
262+
* @return bool If successful
263+
*/
264+
bool on_cleanup() final
265+
{
266+
bool ok = true;
267+
if (!bt_action_server_->on_cleanup()) {
268+
ok = false;
269+
}
270+
271+
bt_action_server_.reset();
272+
273+
return cleanup() && ok;
274+
}
275+
276+
virtual std::string getDefaultBTFilepath(rclcpp_lifecycle::LifecycleNode::WeakPtr node) = 0;
277+
278+
/**
279+
* @brief Get the action name of this navigator to expose
280+
* @return string Name of action to expose
281+
*/
282+
virtual std::string getName() = 0;
283+
284+
protected:
285+
/**
286+
* @brief An intermediate goal reception function to mux navigators.
287+
*/
288+
bool onGoalReceived(typename ActionT::Goal::ConstSharedPtr goal)
289+
{
290+
if (plugin_muxer_->isNavigating()) {
291+
RCLCPP_ERROR(
292+
logger_,
293+
"Requested navigation from %s while another navigator is processing,"
294+
" rejecting request.", getName().c_str());
295+
return false;
296+
}
297+
298+
bool goal_accepted = goalReceived(goal);
299+
300+
if (goal_accepted) {
301+
plugin_muxer_->startNavigating(getName());
302+
}
303+
304+
return goal_accepted;
305+
}
306+
307+
/**
308+
* @brief An intermediate completion function to mux navigators
309+
*/
310+
void onCompletion(
311+
typename ActionT::Result::SharedPtr result,
312+
const nav2_behavior_tree::BtStatus final_bt_status)
313+
{
314+
plugin_muxer_->stopNavigating(getName());
315+
goalCompleted(result, final_bt_status);
316+
}
317+
318+
/**
319+
* @brief A callback to be called when a new goal is received by the BT action server
320+
* Can be used to check if goal is valid and put values on
321+
* the blackboard which depend on the received goal
322+
*/
323+
virtual bool goalReceived(typename ActionT::Goal::ConstSharedPtr goal) = 0;
324+
325+
/**
326+
* @brief A callback that defines execution that happens on one iteration through the BT
327+
* Can be used to publish action feedback
328+
*/
329+
virtual void onLoop() = 0;
330+
331+
/**
332+
* @brief A callback that is called when a preempt is requested
333+
*/
334+
virtual void onPreempt(typename ActionT::Goal::ConstSharedPtr goal) = 0;
335+
336+
/**
337+
* @brief A callback that is called when a the action is completed; Can fill in
338+
* action result message or indicate that this action is done.
339+
*/
340+
virtual void goalCompleted(
341+
typename ActionT::Result::SharedPtr result,
342+
const nav2_behavior_tree::BtStatus final_bt_status) = 0;
343+
344+
/**
345+
* @param Method to configure resources.
346+
*/
347+
virtual bool configure(
348+
rclcpp_lifecycle::LifecycleNode::WeakPtr /*node*/,
349+
std::shared_ptr<nav2_util::OdomSmoother>/*odom_smoother*/)
350+
{
351+
return true;
352+
}
353+
354+
/**
355+
* @brief Method to cleanup resources.
356+
*/
357+
virtual bool cleanup() {return true;}
358+
359+
/**
360+
* @brief Method to activate any threads involved in execution.
361+
*/
362+
virtual bool activate() {return true;}
363+
364+
/**
365+
* @brief Method to deactivate and any threads involved in execution.
366+
*/
367+
virtual bool deactivate() {return true;}
368+
369+
std::unique_ptr<nav2_behavior_tree::BtActionServer<ActionT>> bt_action_server_;
370+
rclcpp::Logger logger_{rclcpp::get_logger("Navigator")};
371+
rclcpp::Clock::SharedPtr clock_;
372+
FeedbackUtils feedback_utils_;
373+
NavigatorMuxer * plugin_muxer_;
374+
};
375+
376+
} // namespace nav2_core
377+
378+
#endif // NAV2_CORE__BEHAVIOR_TREE_NAVIGATOR_HPP_

0 commit comments

Comments
 (0)