20 #include "nav2_bt_navigator/navigators/navigate_through_poses.hpp"
22 namespace nav2_bt_navigator
27 rclcpp_lifecycle::LifecycleNode::WeakPtr parent_node,
28 std::shared_ptr<nav2_util::OdomSmoother> odom_smoother)
30 start_time_ = rclcpp::Time(0);
31 auto node = parent_node.lock();
33 if (!node->has_parameter(
"goals_blackboard_id")) {
34 node->declare_parameter(
"goals_blackboard_id", std::string(
"goals"));
37 goals_blackboard_id_ = node->get_parameter(
"goals_blackboard_id").as_string();
39 if (!node->has_parameter(
"path_blackboard_id")) {
40 node->declare_parameter(
"path_blackboard_id", std::string(
"path"));
43 path_blackboard_id_ = node->get_parameter(
"path_blackboard_id").as_string();
46 odom_smoother_ = odom_smoother;
53 rclcpp_lifecycle::LifecycleNode::WeakPtr parent_node)
55 std::string default_bt_xml_filename;
56 auto node = parent_node.lock();
58 if (!node->has_parameter(
"default_nav_through_poses_bt_xml")) {
59 std::string pkg_share_dir =
60 ament_index_cpp::get_package_share_directory(
"nav2_bt_navigator");
61 node->declare_parameter<std::string>(
62 "default_nav_through_poses_bt_xml",
64 "/behavior_trees/navigate_through_poses_w_replanning_and_recovery.xml");
67 node->get_parameter(
"default_nav_through_poses_bt_xml", default_bt_xml_filename);
69 return default_bt_xml_filename;
75 auto bt_xml_filename = goal->behavior_tree;
77 if (!bt_action_server_->loadBehaviorTree(bt_xml_filename)) {
79 logger_,
"Error loading XML file: %s. Navigation canceled.",
80 bt_xml_filename.c_str());
91 typename ActionT::Result::SharedPtr ,
92 const nav2_behavior_tree::BtStatus )
99 using namespace nav2_util::geometry_utils;
103 auto feedback_msg = std::make_shared<ActionT::Feedback>();
105 auto blackboard = bt_action_server_->getBlackboard();
108 blackboard->get<Goals>(goals_blackboard_id_, goal_poses);
110 if (goal_poses.size() == 0) {
111 bt_action_server_->publishFeedback(feedback_msg);
115 geometry_msgs::msg::PoseStamped current_pose;
116 nav2_util::getCurrentPose(
117 current_pose, *feedback_utils_.tf,
118 feedback_utils_.global_frame, feedback_utils_.robot_frame,
119 feedback_utils_.transform_tolerance);
123 nav_msgs::msg::Path current_path;
124 blackboard->get<nav_msgs::msg::Path>(path_blackboard_id_, current_path);
127 auto find_closest_pose_idx =
128 [¤t_pose, ¤t_path]() {
129 size_t closest_pose_idx = 0;
130 double curr_min_dist = std::numeric_limits<double>::max();
131 for (
size_t curr_idx = 0; curr_idx < current_path.poses.size(); ++curr_idx) {
132 double curr_dist = nav2_util::geometry_utils::euclidean_distance(
133 current_pose, current_path.poses[curr_idx]);
134 if (curr_dist < curr_min_dist) {
135 curr_min_dist = curr_dist;
136 closest_pose_idx = curr_idx;
139 return closest_pose_idx;
143 double distance_remaining =
144 nav2_util::geometry_utils::calculate_path_length(current_path, find_closest_pose_idx());
147 rclcpp::Duration estimated_time_remaining = rclcpp::Duration::from_seconds(0.0);
150 geometry_msgs::msg::Twist current_odom = odom_smoother_->getTwist();
151 double current_linear_speed = std::hypot(current_odom.linear.x, current_odom.linear.y);
155 if ((std::abs(current_linear_speed) > 0.01) && (distance_remaining > 0.1)) {
156 estimated_time_remaining =
157 rclcpp::Duration::from_seconds(distance_remaining / std::abs(current_linear_speed));
160 feedback_msg->distance_remaining = distance_remaining;
161 feedback_msg->estimated_time_remaining = estimated_time_remaining;
166 int recovery_count = 0;
167 blackboard->get<
int>(
"number_recoveries", recovery_count);
168 feedback_msg->number_of_recoveries = recovery_count;
169 feedback_msg->current_pose = current_pose;
170 feedback_msg->navigation_time = clock_->now() - start_time_;
171 feedback_msg->number_of_poses_remaining = goal_poses.size();
173 bt_action_server_->publishFeedback(feedback_msg);
179 RCLCPP_INFO(logger_,
"Received goal preemption request");
181 if (goal->behavior_tree == bt_action_server_->getCurrentBTFilename() ||
182 (goal->behavior_tree.empty() &&
183 bt_action_server_->getCurrentBTFilename() == bt_action_server_->getDefaultBTFilename()))
192 "Preemption request was rejected since the requested BT XML file is not the same "
193 "as the one that the current goal is executing. Preemption with a new BT is invalid "
194 "since it would require cancellation of the previous goal instead of true preemption."
195 "\nCancel the current goal and send a new action request if you want to use a "
196 "different BT XML file. For now, continuing to track the last goal until completion.");
197 bt_action_server_->terminatePendingGoal();
204 if (goal->poses.size() > 0) {
206 logger_,
"Begin navigating from current location through %zu poses to (%.2f, %.2f)",
207 goal->poses.size(), goal->poses.back().pose.position.x, goal->poses.back().pose.position.y);
211 start_time_ = clock_->now();
212 auto blackboard = bt_action_server_->getBlackboard();
213 blackboard->set<
int>(
"number_recoveries", 0);
216 blackboard->set<Goals>(goals_blackboard_id_, goal->poses);
bool configure(rclcpp_lifecycle::LifecycleNode::WeakPtr node, std::shared_ptr< nav2_util::OdomSmoother > odom_smoother) override
A configure state transition to configure navigator's state.
void onPreempt(ActionT::Goal::ConstSharedPtr goal) override
A callback that is called when a preempt is requested.
void initializeGoalPoses(ActionT::Goal::ConstSharedPtr goal)
Goal pose initialization on the blackboard.
bool goalReceived(ActionT::Goal::ConstSharedPtr goal) override
A callback to be called when a new goal is received by the BT action server Can be used to check if g...
void goalCompleted(typename ActionT::Result::SharedPtr result, const nav2_behavior_tree::BtStatus final_bt_status) override
A callback that is called when a the action is completed, can fill in action result message or indica...
std::string getDefaultBTFilepath(rclcpp_lifecycle::LifecycleNode::WeakPtr node) override
Get navigator's default BT.
void onLoop() override
A callback that defines execution that happens on one iteration through the BT Can be used to publish...