-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinento.cpp
417 lines (373 loc) · 9.51 KB
/
inento.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
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
//Begin page main
//Begin page main
//Begin page Picture Stuff
#define MIN_PIC_ENERGY 1.1f
#define MAX_UPLOAD_VEL 0.05f
#define MAX_UPLOAD_ANGLE 0.25f
#define MIN_UPLOAD_ENERGY 1.25f
#define UPLOAD_ANGLE_PID_TARGET 0.20f
bool inFacingEPID;
float earthFacingDirectional[3];
float angleToEarth;
void faceEarth()
{
if (uploadConditionsMet) {
inFacingEPID = false;
}
else {
api.setAttitudeTarget(earthFacingDirectional);
}
if (!inFacingEPID && angleToEarth > MAX_UPLOAD_ANGLE) {
for (int i = 0; i <= 2; i++) {
earthFacingDirectional[i] = zr_att(my_state)[i];
}
dropInclinationToTargetAngle(zr_att(my_state), earthFacingDirectional);
inFacingEPID = true;
}
}
void face()
{
if (!facingOther) {
float facing_vec[3];
mathVecSubtract(facing_vec, zr_pos(other_state), zr_pos(my_state), 3);
mathVecNormalize(facing_vec, 3);
api.setAttitudeTarget(facing_vec);
}
}
void attemptPic()
{
if (facingOther && memoryFilled < 2 && energy >= MIN_PIC_ENERGY && game.isCameraOn() && game.getMirrorTimeRemaining() == 0 && !game.posInDark(zr_pos(other_state))
&& picCondition()) {
game.takePic();
}
}
bool picCondition()
{
if (mirrorsHeld == 2 && game.getPicPoints() < 0.11) {
return false;
}
return true;
}
void attemptUpload()
{
faceEarth();
if (uploadConditionsMet) {
game.uploadPics();
}
}
void tryPic()
{
if (memoryFilled == 2 || ((phase == 4 || state == PHASE2_ENERGY) && memoryFilled > 0)) {
angleToEarth = acosf((zr_att(my_state))[2]);
attemptUpload();
}
else {
face();
attemptPic();
}
}
//End page Picture Stuff
//Begin page main
enum State {
PHASE1_MIRROR, // starting game phase, the robot will head towards the closest mirror then transition to phase1_item
PHASE12_ITEM, // moves towards the top scoring item while in phase1 or phase2. will transition to phase2_wait
PHASE2_WAIT, // moves towards the target dark zone during phase 2
PHASE2_ENERGY, // 24 seconds before the zone switch, activates a mirror and moves to the target dark zone in phase 2
PHASE3_TRACKING, // sits in the target dark zone in phase3 and takes pictures
PHASE4_ENDGAME // uses all remaining energy for pictures and uploads
} state;
int phase;
char color;
int game_time;
bool end_pos_reached;
float energy;
void init()
{
setItems();
inFacingEPID = false;
end_pos_reached;
setEarth();
setSphereData();
game_time = 0;
phase = 1;
state = PHASE1_MIRROR;
setColor();
setMirrorValues();
setSwitchTimes();
DEBUG(("Greetings from Paly Robotics, FRC Team #8"));
DEBUG(("After the match visit us at palyrobotics.com"));
}
void loop()
{
updateValues();
game_time++;
setSphereData();
setGamePhase();
switch (state) {
case PHASE1_MIRROR:
phase1_mirrorLoop();
break;
case PHASE12_ITEM:
phase12_itemLoop();
break;
case PHASE2_WAIT:
phase2_waitLoop();
break;
case PHASE2_ENERGY:
phase2_energyLoop();
break;
case PHASE3_TRACKING:
phase3_trackingLoop();
break;
case PHASE4_ENDGAME:
phase4_endgameLoop();
break;
}
tryPic();
}
//End page main
//Begin page mathHelper
void dropInclinationToTargetAngle(float currentAtt[3], float upload[3])
{
float c = sinf(UPLOAD_ANGLE_PID_TARGET) / sqrtf(mathSquare(currentAtt[0]) + mathSquare(currentAtt[1]));
upload[0] = c * currentAtt[0];
upload[1] = c * currentAtt[1];
upload[2] = cosf(UPLOAD_ANGLE_PID_TARGET);
}
//End page mathHelper
//Begin page moveHelper
void endpointMove(float stopped_edge, float lower_edge, float upper_edge, float destination[])
{
api.setPositionTarget(destination);
if (stopped(stopped_edge) && zr_pos(my_state)[1] < upper_edge && zr_pos(my_state)[1] > lower_edge) {
end_pos_reached = true;
}
}
void moveToItem(int ID, float v_pid_edge, float p_pid_edge)
{
float vector_between[3];
mathVecSubtract(vector_between, items[ID], zr_pos(my_state), 3);
float distance = mathVecMagnitude(vector_between, 3);
if (distance > v_pid_edge) {
api.setVelocityTarget(vector_between);
}
if (distance < p_pid_edge) {
api.setPositionTarget(items[ID]);
}
}
//End page moveHelper
//Begin page phase12_item
// picks up the top scoring object regardless of current position while in phase 1 or 2
#define TOP_SCORING_ID 6
#define P12_VELOCITY_PID_EDGE 0.3f
#define P12_POSITION_PID_EDGE 0.3f
void phase12_itemLoop()
{
moveToItem(TOP_SCORING_ID, P12_VELOCITY_PID_EDGE, P12_POSITION_PID_EDGE);
if (game.hasItem(TOP_SCORING_ID) != -1 || phase == 3) {
state = PHASE2_WAIT;
phase2_waitInit();
}
}
//End page phase12_item
//Begin page phase1_mirror
// phase 1 mirror currently only goes for the closest mirror as the tracking remains bugged
#define P1_VELOCITY_PID_EDGE 0.53f
#define P1_POSITION_PID_EDGE 0.4f
#define BLUE_MIRROR 8
#define RED_MIRROR 7
int close_mirror;
void phase1_mirrorLoop()
{
moveToItem(close_mirror, P1_VELOCITY_PID_EDGE, P1_POSITION_PID_EDGE);
if (game.getNumMirrorsHeld() > 0) {
state = PHASE12_ITEM;
}
}
void setMirrorValues()
{
close_mirror = RED_MIRROR;
if (color == 'B') {
close_mirror = BLUE_MIRROR;
}
}
//End page phase1_mirror
//Begin page phase2_energy
void phase2_energyInit()
{
end_pos_reached = false;
destination_pos[1] = -0.2f;
game.useMirror();
}
void phase2_energyLoop()
{
if (!end_pos_reached) {
endpointMove(0.04f, -0.25f, -0.15f, destination_pos);
}
else {
state = PHASE3_TRACKING;
}
if (phase == 3) {
state = PHASE3_TRACKING;
}
}
//End page phase2_energy
//Begin page phase2_wait
void phase2_waitInit()
{
end_pos_reached = false;
destination_pos[0] = 0.0f;
destination_pos[1] = 0.15f;
destination_pos[2] = -0.5f;
}
void phase2_waitLoop()
{
if (!end_pos_reached) {
endpointMove(0.001f, 0.14f, 0.16f, destination_pos);
}
if (game_time > switch_times[1] - 24) {
state = PHASE2_ENERGY;
end_pos_reached = true;
phase2_energyInit();
}
}
//End page phase2_wait
//Begin page phase3_tracking
#define PHASE_3_TRACKING_Y -0.2f
#define PHASE_3_TRACKING_Z -0.5f
#define ENERGY_FOLLOW_LIMIT 1.0f
void phase3_trackingLoop()
{
if (energy > ENERGY_FOLLOW_LIMIT) {
follow(PHASE_3_TRACKING_Y);
}
if (phase == 4) {
state = PHASE4_ENDGAME;
}
}
void follow(float y)
{
float target_pos[3];
target_pos[0] = 0.0f;
target_pos[1] = PHASE_3_TRACKING_Y;
target_pos[2] = PHASE_3_TRACKING_Z;
api.setPositionTarget(target_pos);
}
//End page phase3_tracking
//Begin page phase4_endgame
#define ZPOSITION -0.5f
void phase4_endgameLoop()
{
float pos[3];
pos[0] = 0.0f;
pos[1] = 0.25f;
pos[2] = -0.5f;
api.setPositionTarget(pos);
}
//End page phase4_endgame
//Begin page stateHelper
float my_state[12];
float other_state[12];
float switch_times[4];
float earth[3];
float items[9][3];
float destination_pos[3];
bool facingOther;
int memoryFilled;
int mirrorsHeld;
float rotVel;
bool uploadConditionsMet;
int counter;
void updateValues()
{
energy = game.getEnergy();
facingOther = game.isFacingOther();
memoryFilled = game.getMemoryFilled();
mirrorsHeld = game.getNumMirrorsHeld();
rotVel = getRotVel(my_state);
uploadConditionsMet = getUploadConditionsMet();
}
void setSphereData()
{
api.getMyZRState(my_state);
api.getOtherZRState(other_state);
}
void setEarth()
{
earth[0] = 0;
earth[1] = 0;
earth[2] = 1;
}
void setColor()
{
color = 'R';
if (zr_pos(my_state)[0] > 0) {
color = 'B';
}
}
void setSwitchTimes()
{
switch_times[0] = game.getLightSwitchTime();
switch_times[1] = switch_times[0] + 60;
switch_times[2] = switch_times[1] + 60;
switch_times[3] = 32000;
}
void setGamePhase()
{
if (game_time > switch_times[phase - 1]) {
phase++;
}
}
bool getUploadConditionsMet()
{
return (angleToEarth < MAX_UPLOAD_ANGLE && rotVel < MAX_UPLOAD_VEL);
}
/*
* Provides easy access to different parts of the zr state
* Example Use:
* zr_velocity(mystate)[3]; //gets the 3rd element of the velocity vector of the
* //of 'mystate', where mystate is the zr state of, presumably, our robot
*/
//velocity vector
float* zr_velocity(float state[12])
{
return &state[3];
}
//position vector
float* zr_pos(float state[12])
{
return &state[0];
}
//attitude vector
float* zr_att(float state[12])
{
return &state[6];
}
//rotation vector
float* zr_rot(float state[12])
{
return &state[9];
}
float getRotVel(float state[12])
{
float rot[3];
for (int i = 0; i < 3; i++) {
rot[i] = zr_rot(my_state)[i];
}
return mathVecMagnitude(rot, 3);
}
void setItems()
{
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 3; j++) {
items[i][j] = ITEM_LOC[i][j];
}
}
}
bool stopped(float limit)
{
return mathVecMagnitude(zr_velocity(my_state), 3) > limit;
}
//End page stateHelper
//End page main
//End page main