21 #include "behaviortree_cpp/decorator_node.h"
22 #include "geometry_msgs/msg/pose_stamped.hpp"
23 #include "nav2_util/geometry_utils.hpp"
24 #include "nav2_util/robot_utils.hpp"
25 #include "nav_msgs/msg/path.hpp"
26 #include "rclcpp/rclcpp.hpp"
27 #include "tf2/LinearMath/Quaternion.hpp"
28 #include "nav2_ros_common/tf2_factories.hpp"
30 #include "nav2_behavior_tree/plugins/action/truncate_path_local_action.hpp"
32 namespace nav2_behavior_tree
36 const std::string & name,
37 const BT::NodeConfiguration & conf)
38 : BT::ActionNodeBase(name, conf)
41 config().blackboard->template get<nav2::TransformBuffer::SharedPtr>(
43 auto node = config().blackboard->get<nav2::LifecycleNode::SharedPtr>(
"node");
44 clock_ = node->get_clock();
45 transform_staleness_threshold_ = node->declare_or_get_parameter(
46 "transform_staleness_threshold", 0.0);
49 inline BT::NodeStatus TruncatePathLocal::tick()
51 setStatus(BT::NodeStatus::RUNNING);
53 double distance_forward, distance_backward;
54 geometry_msgs::msg::PoseStamped pose;
55 double angular_distance_weight;
56 double max_robot_pose_search_dist;
58 getInput(
"distance_forward", distance_forward);
59 getInput(
"distance_backward", distance_backward);
60 getInput(
"angular_distance_weight", angular_distance_weight);
61 getInput(
"max_robot_pose_search_dist", max_robot_pose_search_dist);
63 bool path_pruning = std::isfinite(max_robot_pose_search_dist);
64 if (distance_forward < 0.0) {
65 distance_forward = std::numeric_limits<double>::max();
67 nav_msgs::msg::Path new_path;
68 getInput(
"input_path", new_path);
69 if (!path_pruning || new_path != path_) {
71 closest_pose_detection_begin_ = path_.poses.begin();
74 if (!getRobotPose(path_.header.frame_id, pose)) {
75 return BT::NodeStatus::FAILURE;
78 if (path_.poses.empty()) {
79 setOutput(
"output_path", path_);
80 return BT::NodeStatus::SUCCESS;
83 auto closest_pose_detection_end = path_.poses.end();
85 closest_pose_detection_end = nav2_util::geometry_utils::first_after_integrated_distance(
86 closest_pose_detection_begin_, path_.poses.end(), max_robot_pose_search_dist);
90 auto current_pose = nav2_util::geometry_utils::min_by(
91 closest_pose_detection_begin_, closest_pose_detection_end,
92 [&pose, angular_distance_weight](
const geometry_msgs::msg::PoseStamped & ps) {
93 return poseDistance(pose, ps, angular_distance_weight);
97 closest_pose_detection_begin_ = current_pose;
101 auto forward_pose_it = nav2_util::geometry_utils::first_after_integrated_distance(
102 current_pose, path_.poses.end(), distance_forward);
106 auto backward_pose_it = nav2_util::geometry_utils::first_after_integrated_distance(
107 std::reverse_iterator(current_pose + 1), path_.poses.rend(), distance_backward);
109 nav_msgs::msg::Path output_path;
110 output_path.header = path_.header;
111 output_path.poses = std::vector<geometry_msgs::msg::PoseStamped>(
112 backward_pose_it.base(), forward_pose_it);
113 setOutput(
"output_path", output_path);
115 return BT::NodeStatus::SUCCESS;
118 inline bool TruncatePathLocal::getRobotPose(
119 std::string path_frame_id, geometry_msgs::msg::PoseStamped & pose)
121 if (!getInput(
"pose", pose)) {
122 auto node = config().blackboard->get<nav2::LifecycleNode::SharedPtr>(
"node");
123 std::string robot_frame = BT::deconflictPortAndParamFrame<std::string>(
124 node,
"robot_base_frame",
this);
125 if (robot_frame.empty()) {
128 "Neither pose nor robot_base_frame specified for %s", name().c_str());
131 if (!nav2_util::getFreshPose(
132 *tf_buffer_, path_frame_id, robot_frame, clock_->now(), transform_staleness_threshold_,
137 "Failed to lookup current robot pose for %s", name().c_str());
145 TruncatePathLocal::poseDistance(
146 const geometry_msgs::msg::PoseStamped & pose1,
147 const geometry_msgs::msg::PoseStamped & pose2,
148 const double angular_distance_weight)
150 double dx = pose1.pose.position.x - pose2.pose.position.x;
151 double dy = pose1.pose.position.y - pose2.pose.position.y;
155 tf2::convert(pose1.pose.orientation, q1);
157 tf2::convert(pose2.pose.orientation, q2);
158 double da = angular_distance_weight * std::abs(q1.angleShortestPath(q2));
159 return std::sqrt(dx * dx + dy * dy + da * da);
164 #include "behaviortree_cpp/bt_factory.h"
165 BT_REGISTER_NODES(factory) {
167 "TruncatePathLocal");
A BT::ActionNodeBase to shorten path to some distance around robot.
TruncatePathLocal(const std::string &xml_tag_name, const BT::NodeConfiguration &conf)
A nav2_behavior_tree::TruncatePathLocal constructor.