Formula Student Autonomous Systems
The code for the main driverless system
Loading...
Searching...
No Matches
utils.cpp
Go to the documentation of this file.
1#include "utils/utils.hpp"
2
3using namespace common_lib::structures;
4
6 const Position& cg, double orientation, double dist_cg_2_rear_axis) {
7 Position rear_axis;
8 rear_axis.x = cg.x - dist_cg_2_rear_axis * std::cos(orientation);
9 rear_axis.y = cg.y - dist_cg_2_rear_axis * std::sin(orientation);
10 return rear_axis;
11}
12
13
14std::tuple<Position, int, double> get_closest_point(
15 const std::vector<custom_interfaces::msg::PathPoint> &pathpoint_array, const Position& position) {
16 double min_distance = 1e9;
17 double closest_point_velocity = 0;
18 Position closest_point = Position();
19 Position aux_point = Position();
20 int closest_point_id = -1;
21 for (size_t i = 1; i < pathpoint_array.size(); i++) {
22 aux_point = Position(pathpoint_array[i].x, pathpoint_array[i].y);
23 double distance = position.euclidean_distance(aux_point);
24 if (distance < min_distance) {
25 min_distance = distance;
26 closest_point = aux_point;
27 closest_point_id = static_cast<int>(i);
28 closest_point_velocity = pathpoint_array[i].v;
29 }
30 }
31 return std::make_tuple(closest_point, closest_point_id, closest_point_velocity);
32}
33
34
35std::tuple<Position, double, bool> get_lookahead_point(
36 const std::vector<custom_interfaces::msg::PathPoint> &pathpoint_array,
37 int closest_point_id, double lookahead_distance, Position rear_axis_position, double last_to_first_max_dist) {
38
39 if (pathpoint_array.empty()) {
40 RCLCPP_DEBUG(rclcpp::get_logger("control"), "Empty path");
41 return std::make_tuple(Position(), 0.0, true);
42 }
43
44 // Clamp closest_point_id
45 closest_point_id = std::clamp(closest_point_id, 0, static_cast<int>(pathpoint_array.size()) - 1);
46
47 Position rear_axis_point = rear_axis_position;
48
49 for (size_t i = 0; i < pathpoint_array.size(); i++) {
50 size_t index_a = (static_cast<size_t>(closest_point_id) + i) % pathpoint_array.size();
51 size_t index_b = (static_cast<size_t>(closest_point_id) + i + 1) % pathpoint_array.size();
52
53 // We reached the end of the path
54 if (index_b < index_a) {
55 Position first_point(pathpoint_array.front().x, pathpoint_array.front().y);
56 Position last_point(pathpoint_array.back().x, pathpoint_array.back().y);
57 double start_end_distance = first_point.euclidean_distance(last_point);
58
59 // If the path is not a closed track, force last point as lookahead
60 // If the closest point is the first point, then the car is before the path start, so return first point, else return the last point
61 if (start_end_distance > last_to_first_max_dist) {
62 if (closest_point_id == 1) {
63 // Car might be before the first point, return it as lookahead
64 const auto &cp = pathpoint_array[static_cast<size_t>(closest_point_id)];
65 return std::make_tuple(Position(cp.x, cp.y), cp.v, false);
66 } else {
67 RCLCPP_DEBUG(rclcpp::get_logger("control"),
68 "Lookahead extends beyond path end and it is not a closed track, using last "
69 "point of the path as lookahead point");
70 return std::make_tuple(Position(pathpoint_array.back().x, pathpoint_array.back().y),
71 pathpoint_array.back().v, false);
72 }
73 }
74 }
75
76 auto point_a = Position(pathpoint_array[index_a].x, pathpoint_array[index_a].y);
77 auto point_b = Position(pathpoint_array[index_b].x, pathpoint_array[index_b].y);
78
79 if (!(rear_axis_point.euclidean_distance(point_a) < lookahead_distance &&
80 rear_axis_point.euclidean_distance(point_b) > lookahead_distance)) {
81 continue;
82 }
83
84 double result_x;
85 double result_y;
86
87 // Slope of the line is infinite, don't need line equation
88 if (point_a.x == point_b.x) {
89 RCLCPP_DEBUG(rclcpp::get_logger("control"), "Vertical line!!");
90 result_x = point_a.x;
91 double delta = lookahead_distance * lookahead_distance - std::pow(result_x - rear_axis_point.x, 2);
92 if (delta < 0) {
93 continue;
94 }
95 double y1 = rear_axis_point.y + std::sqrt(delta);
96 double y2 = rear_axis_point.y - std::sqrt(delta);
97
98 if (y1 >= std::min(point_a.y, point_b.y) && y1 <= std::max(point_a.y, point_b.y)) {
99 result_y = y1;
100 } else {
101 result_y = y2;
102 }
103
104 } else {
105 // y = mx + c
106 double m = (point_b.y - point_a.y) / (point_b.x - point_a.x);
107 double c = point_a.y - m * point_a.x;
108
109 // (x - x0)^2 + (y - y0)^2 = r^2
110 // with x0 = rear_axis_point.x, y0 = rear_axis_point.y, r = lookahead_distance
111
112 // with this information we can find the intersection point between the circle and the line
113 // and obtain the lookahead point.
114 // Expanded form of the circle equation with y substituted by mx + c gives a quadratic
115 // equation:
116 double A = 1 + m * m;
117 double B = 2 * (m * c - rear_axis_point.x - m * rear_axis_point.y);
118 double C = rear_axis_point.x * rear_axis_point.x + c * c +
119 rear_axis_point.y * rear_axis_point.y - 2 * c * rear_axis_point.y - lookahead_distance * lookahead_distance;
120
121 double delta = B * B - 4 * A * C;
122
123 if (delta < 0) {
124 continue;
125 }
126
127 double x1 = (-B + std::sqrt(delta)) / (2 * A);
128 double x2 = (-B - std::sqrt(delta)) / (2 * A);
129
130 double y1 = m * x1 + c;
131 double y2 = m * x2 + c;
132
133 // solution (x,y) which is within bounds of point_a and point_b
134 if (x1 >= std::min(point_a.x, point_b.x) && x1 <= std::max(point_a.x, point_b.x) &&
135 y1 >= std::min(point_a.y, point_b.y) && y1 <= std::max(point_a.y, point_b.y)) {
136 result_x = x1;
137 result_y = y1;
138 } else {
139 result_x = x2;
140 result_y = y2;
141 }
142 }
143
144 return std::make_tuple(Position(result_x, result_y),
145 (pathpoint_array[index_a].v + pathpoint_array[index_b].v) / 2.0, false);
146 }
147 RCLCPP_DEBUG(rclcpp::get_logger("control"), "No lookahead point found");
148 return std::make_tuple(Position(), 0.0, true);
149}
Position rear_axis_position(const Position &cg, double orientation, double dist_cg_2_rear_axis)
Calculate rear axis coordinates.
Definition utils.cpp:5
std::tuple< Position, int, double > get_closest_point(const std::vector< custom_interfaces::msg::PathPoint > &pathpoint_array, const Position &position)
Find the closest point on the path.
Definition utils.cpp:14
std::tuple< Position, double, bool > get_lookahead_point(const std::vector< custom_interfaces::msg::PathPoint > &pathpoint_array, int closest_point_id, double lookahead_distance, Position rear_axis_position, double last_to_first_max_dist)
Update Lookahead point.
Definition utils.cpp:35
double euclidean_distance(const Position &other) const
Definition position.cpp:10