17 #include "nav2_util/controller_utils.hpp"
18 #include "nav2_util/geometry_utils.hpp"
22 geometry_msgs::msg::Point circleSegmentIntersection(
23 const geometry_msgs::msg::Point & p1,
24 const geometry_msgs::msg::Point & p2,
42 double dr2 = dx * dx + dy * dy;
43 double D = x1 * y2 - x2 * y1;
46 double d1 = x1 * x1 + y1 * y1;
47 double d2 = x2 * x2 + y2 * y2;
50 geometry_msgs::msg::Point p;
51 double sqrt_term = std::sqrt(r * r * dr2 - D * D);
52 p.x = (D * dy + std::copysign(1.0, dd) * dx * sqrt_term) / dr2;
53 p.y = (-D * dx + std::copysign(1.0, dd) * dy * sqrt_term) / dr2;
57 geometry_msgs::msg::Point linearInterpolation(
58 const geometry_msgs::msg::Point & p1,
59 const geometry_msgs::msg::Point & p2,
60 const double target_dist)
62 geometry_msgs::msg::Point result;
64 double dx = p2.x - p1.x;
65 double dy = p2.y - p1.y;
66 double d_dist = std::hypot(dx, dy);
68 double target_ratio = target_dist / d_dist;
70 result.x = p1.x + target_ratio * dx;
71 result.y = p1.y + target_ratio * dy;
75 geometry_msgs::msg::PoseStamped getLookAheadPoint(
76 double & lookahead_dist,
77 const nav_msgs::msg::Path & transformed_plan,
78 const bool interpolate_after_goal)
82 const auto & poses = transformed_plan.poses;
83 auto goal_pose_it = poses.begin();
84 double path_dist = 0.0;
85 double interpolation_dist = 0.0;
87 bool pose_found =
false;
88 for (
size_t i = 1; i < poses.size(); i++) {
89 const auto & prev_pose = poses[i - 1].pose.position;
90 const auto & curr_pose = poses[i].pose.position;
92 const double d = std::hypot(curr_pose.x - prev_pose.x, curr_pose.y - prev_pose.y);
93 if (path_dist + d >= lookahead_dist) {
94 goal_pose_it = poses.begin() + i;
102 interpolation_dist = lookahead_dist - path_dist;
104 goal_pose_it = poses.end();
108 if (goal_pose_it == transformed_plan.poses.end()) {
109 if (interpolate_after_goal) {
110 auto last_pose_it = std::prev(transformed_plan.poses.end());
111 auto prev_last_pose_it = std::prev(last_pose_it);
113 double end_path_orientation = atan2(
114 last_pose_it->pose.position.y - prev_last_pose_it->pose.position.y,
115 last_pose_it->pose.position.x - prev_last_pose_it->pose.position.x);
119 auto projected_position = last_pose_it->pose.position;
120 projected_position.x += cos(end_path_orientation) * lookahead_dist;
121 projected_position.y += sin(end_path_orientation) * lookahead_dist;
125 const auto interpolated_position = linearInterpolation(
126 last_pose_it->pose.position, projected_position, interpolation_dist);
128 geometry_msgs::msg::PoseStamped interpolated_pose;
129 interpolated_pose.header = last_pose_it->header;
130 interpolated_pose.pose.position = interpolated_position;
132 return interpolated_pose;
134 lookahead_dist = path_dist;
135 goal_pose_it = std::prev(transformed_plan.poses.end());
137 }
else if (goal_pose_it != transformed_plan.poses.begin()) {
143 auto prev_pose_it = std::prev(goal_pose_it);
144 auto point = linearInterpolation(
145 prev_pose_it->pose.position,
146 goal_pose_it->pose.position, interpolation_dist);
151 point.y - prev_pose_it->pose.position.y,
152 point.x - prev_pose_it->pose.position.x);
154 geometry_msgs::msg::PoseStamped pose;
155 pose.header.frame_id = prev_pose_it->header.frame_id;
156 pose.header.stamp = goal_pose_it->header.stamp;
157 pose.pose.position = point;
158 pose.pose.orientation = geometry_utils::orientationAroundZAxis(yaw);
162 return *goal_pose_it;