-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSimpleDriver.cpp
317 lines (269 loc) · 9.55 KB
/
SimpleDriver.cpp
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "SimpleDriver.h"
using namespace std;
/* Track info */
const int trackWidth = 20;
const float sin75 = 0.96592582628;
/* Gear Changing Constants*/
const int SimpleDriver::gearUp[6] =
{
5000, 6000, 6000, 6500, 7000, 0
};
const int SimpleDriver::gearDown[6] =
{
0, 2500, 3000, 3000, 3500, 3500
};
/* Stuck constants*/
const int SimpleDriver::stuckTime = 25;
const float SimpleDriver::stuckAngle = .523598775; // PI/6
/* Accel and Brake Constants*/
const float SimpleDriver::maxSpeedDist = 70;
// const float SimpleDriver::maxSpeed = 150;
const float SimpleDriver::maxSpeed = 300;
const float SimpleDriver::sin5 = 0.08716;
const float SimpleDriver::cos5 = 0.99619;
/* Steering constants*/
const float SimpleDriver::steerLock = 0.785398; // the maximum angle of rotation applied through the steering wheel to get the maximum angle out of the car's steering
const float SimpleDriver::steerSensitivityOffset = 80.0;
const float SimpleDriver::wheelSensitivityCoeff = 1;
/* ABS Filter Constants */
const float SimpleDriver::wheelRadius[4] = {0.3179, 0.3179, 0.3276, 0.3276};
const float SimpleDriver::absSlip = 2.0;
const float SimpleDriver::absRange = 3.0;
const float SimpleDriver::absMinSpeed = 3.0;
/* Clutch constants */
const float SimpleDriver::clutchMax = 0.5;
const float SimpleDriver::clutchDelta = 0.05;
const float SimpleDriver::clutchRange = 0.82;
const float SimpleDriver::clutchDeltaTime = 0.02;
const float SimpleDriver::clutchDeltaRaced = 10;
const float SimpleDriver::clutchDec = 0.01;
const float SimpleDriver::clutchMaxModifier = 1.3;
const float SimpleDriver::clutchMaxTime = 1.5;
/* PID constants */
// PID controller for the speed
double dt = 0.1;
double setpoint = 0;
double kp = 4, ki = 1.5, kd = 0.01;
auto controller = new PID(kp, ki, kd, setpoint, dt);
int SimpleDriver::getGear(CarState &cs)
{
int gear = cs.getGear();
int rpm = cs.getRpm();
// if gear is 0 (N) or -1 (R) just return 1
if (gear < 1)
return 1;
// check if the RPM value of car is greater than the one suggested
// to shift up the gear from the current one
if (gear < 6 && rpm >= gearUp[gear - 1])
return gear + 1;
else
// check if the RPM value of car is lower than the one suggested
// to shift down the gear from the current one
if (gear > 1 && rpm <= gearDown[gear - 1])
return gear - 1;
else // otherwhise keep current gear
return gear;
}
float SimpleDriver::getSteer(CarState &cs)
{
double measured_value = (cs.getAngle() / (PI))
+ (cs.getTrack(6) - cs.getTrack(12)) / 180
+ (cs.getTrack(7) - cs.getTrack(11)) / 250
// + (cs.getTrack(0) - cs.getTrack(18)) / 20;
+ (-cs.getTrackPos()) / 7
;
double output = controller->compute(measured_value);
cout << output << '\n';
return - (output / 4);
}
float SimpleDriver::getAccel(CarState &cs)
{
// checks if car is out of track
if (abs(cs.getTrackPos()) < 1)
{
// reading of sensor at +5 degree w.r.t. car axis
float rxSensor = cs.getTrack(10);
// reading of sensor parallel to car axis
float cSensor = cs.getTrack(9);
// reading of sensor at -5 degree w.r.t. car axis
float sxSensor = cs.getTrack(8);
float targetSpeed;
// track is straight and enough far from a turn so goes to max speed
if (cSensor > maxSpeedDist || (cSensor >= rxSensor && cSensor >= sxSensor))
targetSpeed = maxSpeed;
else
{
// approaching a turn on right
if (rxSensor > sxSensor)
{
// computing approximately the "angle" of turn
float h = cSensor * sin5;
float b = rxSensor - cSensor * cos5;
float sinAngle = b * b / (h * h + b * b);
// estimate the target speed depending on turn and on how close it is
targetSpeed = maxSpeed * (cSensor * sinAngle / maxSpeedDist);
}
// approaching a turn on left
else
{
// computing approximately the "angle" of turn
float h = cSensor * sin5;
float b = sxSensor - cSensor * cos5;
float sinAngle = b * b / (h * h + b * b);
// estimate the target speed depending on turn and on how close it is
targetSpeed = maxSpeed * (cSensor * sinAngle / maxSpeedDist);
}
}
// accel/brake command is expontially scaled w.r.t. the difference between target speed and current one
return 2 / (1 + exp(cs.getSpeedX() - targetSpeed)) - 1;
}
else
return 0.3; // when out of track returns a moderate acceleration command
}
CarControl
SimpleDriver::wDrive(CarState cs)
{
/* PID variables */
// check if car is currently stuck
if (fabs(cs.getAngle()) > stuckAngle)
{
// update stuck counter
stuck++;
}
else
{
// if not stuck reset stuck counter
stuck = 0;
}
// after car is stuck for a while apply recovering policy
if (stuck > stuckTime)
{
/* set gear and sterring command assuming car is
* pointing in a direction out of track */
// to bring car parallel to track axis
float steer = -cs.getAngle() / steerLock; // normalizing as steering acctuation accepts [-1, 1] range values
int gear = -1; // gear R
// if car is pointing in the correct direction revert gear and steer
if (cs.getAngle() * cs.getTrackPos() > 0) // when the car is on the left side of the track and turned to the left (or on the right side and turned to the right), both values will have the same sign, so their product will be positive.
{
gear = 1;
steer = -steer;
}
// Calculate clutching
clutching(cs, clutch);
// build a CarControl variable and return it
CarControl cc(1.0, 0.0, gear, steer, clutch);
return cc;
}
else // car is not stuck
{
// compute accel/brake command
const float accel_and_brake = getAccel(cs);
// compute gear
const int gear = getGear(cs);
// compute steering
float steer = getSteer(cs);
// normalize steering
if (steer < -1) {steer = -1;}
if (steer > 1) {steer = 1;}
// set accel and brake from the joint accel/brake command
float accel, brake;
if (accel_and_brake > 0)
{
accel = accel_and_brake;
brake = 0;
}
else
{
accel = 0;
// apply ABS to brake
brake = filterABS(cs, -accel_and_brake);
}
// Calculate clutching
clutching(cs, clutch);
// build a CarControl variable and return it
CarControl cc(accel, brake, gear, steer, clutch);
return cc;
}
}
float SimpleDriver::filterABS(CarState &cs, float brake)
{
// convert speed to m/s
float speed = cs.getSpeedX() / 3.6;
// when spedd lower than min speed for abs do nothing
if (speed < absMinSpeed)
return brake;
// compute the speed of wheels in m/s
float slip = 0.0f;
for (int i = 0; i < 4; i++)
{
slip += cs.getWheelSpinVel(i) * wheelRadius[i];
}
// slip is the difference between actual speed of car and average speed of wheels
slip = speed - slip / 4.0f;
// when slip too high applu ABS
if (slip > absSlip)
{
brake = brake - (slip - absSlip) / absRange;
}
// check brake is not negative, otherwise set it to zero
if (brake < 0)
return 0;
else
return brake;
}
void SimpleDriver::onShutdown()
{
cout << "Bye bye!" << endl;
}
void SimpleDriver::onRestart()
{
cout << "Restarting the race!" << endl;
}
void SimpleDriver::clutching(CarState &cs, float &clutch)
{
double maxClutch = clutchMax;
double delta = clutchDelta;
if (cs.getGear() < 2)
{
// // Apply a stronger clutch output when the gear is one and the race is just started
delta *= 50;
// maxClutch *= clutchMaxModifier;
if (cs.getCurLapTime() < clutchMaxTime)
clutch = maxClutch;
}
// check clutch is not bigger than maximum values
clutch = min(maxClutch, double(clutch));
// if clutch is not at max value decrease it quite quickly
if (clutch != maxClutch)
{
clutch -= delta;
clutch = max(0.0, double(clutch));
}
// if clutch is at max value decrease it very slowly
else
clutch -= clutchDec;
}
void SimpleDriver::init(float *angles)
{
// set angles as {-90,-75,-60,-45,-30,20,15,10,5,0,5,10,15,20,30,45,60,75,90}
for (int i = 0; i < 5; i++)
{
angles[i] = -90 + i * 15;
angles[18 - i] = 90 - i * 15;
}
for (int i = 5; i < 9; i++)
{
angles[i] = -20 + (i - 5) * 5;
angles[18 - i] = 20 - (i - 5) * 5;
}
angles[9] = 0;
}