15 #ifndef NAV2_ROUTE__CORNER_SMOOTHING_HPP_
16 #define NAV2_ROUTE__CORNER_SMOOTHING_HPP_
22 #include "nav2_route/types.hpp"
23 #include "nav2_route/utils.hpp"
45 float minimum_radius,
float angle_threshold)
47 start_edge_length_ = hypotf(corner.x - start.x, corner.y - start.y);
48 end_edge_length_ = hypotf(end.x - corner.x, end.y - corner.y);
51 if (start_edge_length_ == 0.0 || end_edge_length_ == 0.0) {
return;}
57 if (std::abs(angle) < 1E-6 || std::abs(angle) > angle_threshold) {
return;}
59 float tangent_length = minimum_radius / (std::tan(std::fabs(angle) / 2));
61 if (tangent_length < start_edge_length_ && tangent_length < end_edge_length_) {
62 std::vector<float> start_edge_unit_tangent =
63 {(start.x - corner.x) / start_edge_length_, (start.y - corner.y) / start_edge_length_};
64 std::vector<float> end_edge_unit_tangent =
65 {(end.x - corner.x) / end_edge_length_, (end.y - corner.y) / end_edge_length_};
67 float bisector_x = start_edge_unit_tangent[0] + end_edge_unit_tangent[0];
68 float bisector_y = start_edge_unit_tangent[1] + end_edge_unit_tangent[1];
69 float bisector_magnitude = std::sqrt(bisector_x * bisector_x + bisector_y * bisector_y);
71 std::vector<float> unit_bisector =
72 {bisector_x / bisector_magnitude, bisector_y / bisector_magnitude};
74 start_coordinate_.x = corner.x + start_edge_unit_tangent[0] * tangent_length;
75 start_coordinate_.y = corner.y + start_edge_unit_tangent[1] * tangent_length;
77 end_coordinate_.x = corner.x + end_edge_unit_tangent[0] * tangent_length;
78 end_coordinate_.y = corner.y + end_edge_unit_tangent[1] * tangent_length;
80 float bisector_length = minimum_radius / std::sin(angle / 2);
82 circle_center_coordinate_.x = corner.x + unit_bisector[0] * bisector_length;
83 circle_center_coordinate_.y = corner.y + unit_bisector[1] * bisector_length;
100 const float & max_angle_resolution,
101 std::vector<geometry_msgs::msg::PoseStamped> & poses)
103 std::vector<float> r_start{start_coordinate_.x - circle_center_coordinate_.x,
104 start_coordinate_.y - circle_center_coordinate_.y};
105 std::vector<float> r_end{end_coordinate_.x - circle_center_coordinate_.x,
106 end_coordinate_.y - circle_center_coordinate_.y};
107 float cross = r_start[0] * r_end[1] - r_start[1] * r_end[0];
108 float dot = r_start[0] * r_end[0] + r_start[1] * r_end[1];
109 float signed_angle = std::atan2(cross, dot);
111 int N = std::max(1,
static_cast<int>(std::ceil(std::abs(signed_angle) / max_angle_resolution)));
112 float angle_resolution = signed_angle / N;
115 for (
int i = 0; i < N; i++) {
116 float angle = i * angle_resolution;
117 x = circle_center_coordinate_.x +
118 (r_start[0] * std::cos(angle) - r_start[1] * std::sin(angle));
119 y = circle_center_coordinate_.y +
120 (r_start[0] * std::sin(angle) + r_start[1] * std::cos(angle));
121 poses.push_back(utils::toMsg(x, y));
155 float start_dx = start.x - corner.x;
156 float start_dy = start.y - corner.y;
158 float end_dx = end.x - corner.x;
159 float end_dy = end.y - corner.y;
162 acos((start_dx * end_dx + start_dy * end_dy) / (start_edge_length_ * end_edge_length_));
168 bool valid_corner_{
false};
169 float start_edge_length_;
170 float end_edge_length_;
171 Coordinates start_coordinate_;
172 Coordinates end_coordinate_;
173 Coordinates circle_center_coordinate_;
A class used to smooth corners defined by the edges and nodes of the route graph. Used with path conv...
bool isCornerValid() const
return if a valid corner arc (one that doesn't overrun the edge lengths) is generated
void interpolateArc(const float &max_angle_resolution, std::vector< geometry_msgs::msg::PoseStamped > &poses)
interpolates the arc for a path of certain density
Coordinates getCornerStart() const
return the start coordinate of the corner arc
~CornerArc()=default
A destructor for nav2_route::CornerArc.
float getAngleBetweenEdges(const Coordinates &start, const Coordinates &corner, const Coordinates &end)
find the unsigned angle between a corner generated by 3 points
CornerArc(const Coordinates &start, const Coordinates &corner, const Coordinates &end, float minimum_radius, float angle_threshold)
A constructor for nav2_route::CornerArc.
Coordinates getCornerEnd() const
return the end coordinate of the corner arc
An object to store Node coordinates in different frames.