-
Notifications
You must be signed in to change notification settings - Fork 1
/
helpers.h
157 lines (123 loc) · 4.32 KB
/
helpers.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#ifndef HELPERS_H
#define HELPERS_H
#include <math.h>
#include <string>
#include <vector>
// for convenience
using std::string;
using std::vector;
// Checks if the SocketIO event has JSON data.
// If there is data the JSON object in string format will be returned,
// else the empty string "" will be returned.
string hasData(string s) {
auto found_null = s.find("null");
auto b1 = s.find_first_of("[");
auto b2 = s.find_first_of("}");
if (found_null != string::npos) {
return "";
} else if (b1 != string::npos && b2 != string::npos) {
return s.substr(b1, b2 - b1 + 2);
}
return "";
}
//
// Helper functions related to waypoints and converting from XY to Frenet
// or vice versa
//
// For converting back and forth between radians and degrees.
constexpr double pi() { return M_PI; }
double deg2rad(double x) { return x * pi() / 180; }
double rad2deg(double x) { return x * 180 / pi(); }
// Calculate distance between two points
double distance(double x1, double y1, double x2, double y2) {
return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
// Calculate closest waypoint to current x, y position
int ClosestWaypoint(double x, double y, const vector<double> &maps_x,
const vector<double> &maps_y) {
double closestLen = 100000; //large number
int closestWaypoint = 0;
for (int i = 0; i < maps_x.size(); ++i) {
double map_x = maps_x[i];
double map_y = maps_y[i];
double dist = distance(x,y,map_x,map_y);
if (dist < closestLen) {
closestLen = dist;
closestWaypoint = i;
}
}
return closestWaypoint;
}
// Returns next waypoint of the closest waypoint
int NextWaypoint(double x, double y, double theta, const vector<double> &maps_x,
const vector<double> &maps_y) {
int closestWaypoint = ClosestWaypoint(x,y,maps_x,maps_y);
double map_x = maps_x[closestWaypoint];
double map_y = maps_y[closestWaypoint];
double heading = atan2((map_y-y),(map_x-x));
double angle = fabs(theta-heading);
angle = std::min(2*pi() - angle, angle);
if (angle > pi()/2) {
++closestWaypoint;
if (closestWaypoint == maps_x.size()) {
closestWaypoint = 0;
}
}
return closestWaypoint;
}
// Transform from Cartesian x,y coordinates to Frenet s,d coordinates
vector<double> getFrenet(double x, double y, double theta,
const vector<double> &maps_x,
const vector<double> &maps_y) {
int next_wp = NextWaypoint(x,y, theta, maps_x,maps_y);
int prev_wp;
prev_wp = next_wp-1;
if (next_wp == 0) {
prev_wp = maps_x.size()-1;
}
double n_x = maps_x[next_wp]-maps_x[prev_wp];
double n_y = maps_y[next_wp]-maps_y[prev_wp];
double x_x = x - maps_x[prev_wp];
double x_y = y - maps_y[prev_wp];
// find the projection of x onto n
double proj_norm = (x_x*n_x+x_y*n_y)/(n_x*n_x+n_y*n_y);
double proj_x = proj_norm*n_x;
double proj_y = proj_norm*n_y;
double frenet_d = distance(x_x,x_y,proj_x,proj_y);
//see if d value is positive or negative by comparing it to a center point
double center_x = 1000-maps_x[prev_wp];
double center_y = 2000-maps_y[prev_wp];
double centerToPos = distance(center_x,center_y,x_x,x_y);
double centerToRef = distance(center_x,center_y,proj_x,proj_y);
if (centerToPos <= centerToRef) {
frenet_d *= -1;
}
// calculate s value
double frenet_s = 0;
for (int i = 0; i < prev_wp; ++i) {
frenet_s += distance(maps_x[i],maps_y[i],maps_x[i+1],maps_y[i+1]);
}
frenet_s += distance(0,0,proj_x,proj_y);
return {frenet_s,frenet_d};
}
// Transform from Frenet s,d coordinates to Cartesian x,y
vector<double> getXY(double s, double d, const vector<double> &maps_s,
const vector<double> &maps_x,
const vector<double> &maps_y) {
int prev_wp = -1;
while (s > maps_s[prev_wp+1] && (prev_wp < (int)(maps_s.size()-1))) {
++prev_wp;
}
int wp2 = (prev_wp+1)%maps_x.size();
double heading = atan2((maps_y[wp2]-maps_y[prev_wp]),
(maps_x[wp2]-maps_x[prev_wp]));
// the x,y,s along the segment
double seg_s = (s-maps_s[prev_wp]);
double seg_x = maps_x[prev_wp]+seg_s*cos(heading);
double seg_y = maps_y[prev_wp]+seg_s*sin(heading);
double perp_heading = heading-pi()/2;
double x = seg_x + d*cos(perp_heading);
double y = seg_y + d*sin(perp_heading);
return {x,y};
}
#endif // HELPERS_H