-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrobot.c
370 lines (292 loc) · 16 KB
/
robot.c
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
#include "robot.h"
void setup_robot(struct Robot *robot) {
robot->x = 270;
robot->y = 460;
robot->true_x = 270;
robot->true_y = 460;
robot->width = ROBOT_WIDTH;
robot->height = ROBOT_HEIGHT;
robot->direction = 0;
robot->angle = 0;
robot->currentSpeed = 0;
robot->crashed = 0;
robot->auto_mode = 0;
printf("Press arrow keys to move manually, or enter to move automatically\n\n");
}
int robot_off_screen(struct Robot * robot) {
if (robot->x < 0 || robot->y < 0)
return 0;
if (robot->x > OVERALL_WINDOW_WIDTH || robot->y > OVERALL_WINDOW_HEIGHT)
return 0;
return 1;
}
int checkRobotHitWall(struct Robot * robot, struct Wall * wall) {
int overlap = checkOverlap(robot->x,robot->width,robot->y,robot->height, robot->angle,
wall->x,wall->width,wall->y, wall->height);
return overlap;
}
int checkRobotHitWalls(struct Robot * robot, struct Wall_collection * head) {
struct Wall_collection *ptr = head;
while(ptr != NULL) {
if (checkRobotHitWall(robot, &ptr->wall))
return 1;
ptr = ptr->next;
}
return 0;
}
int checkRobotReachedEnd(struct Robot * robot, int x, int y, int width, int height){
int overlap = checkOverlap(robot->x,robot->width,robot->y,robot->height, robot->angle,
x,width,y,height);
return overlap;
}
void robotCrash(struct Robot * robot) {
robot->currentSpeed = 0;
if (!robot->crashed)
printf("Ouchies!!!!!\n\nPress space to start again\n");
robot->crashed = 1;
}
void robotSuccess(struct Robot * robot, int msec) {
robot->currentSpeed = 0;
if (!robot->crashed){
printf("Success!!!!!\n\n");
printf("Time taken %d seconds %d milliseconds \n", msec/1000, msec%1000);
printf("Press space to start again\n");
}
robot->crashed = 1;
}
int checkRobotSensor(int x, int y, int sensorSensitivityLength, int angle, struct Wall * wall) {
//viewing_region of sensor is a square of 2 pixels * chosen length of sensitivity
int overlap = checkOverlap(x,2,y,sensorSensitivityLength, angle,
wall->x,wall->width,wall->y, wall->height);
return overlap;
}
// main calls all of the check robot sensor functions
// instead of having 3 really big, half redundant methods, we have combined them, sort of
// with this sensorAngle variable, we know which sensor we are checking and do the correct math in one method
int sensorAngle;
// for right sensor
int checkRobotSensorFrontRightAllWalls(struct Robot * robot, struct Wall_collection * head) {
sensorAngle = 30;
return checkRobotSensorAllWalls(robot, head);
}
// left sensor
int checkRobotSensorFrontLeftAllWalls(struct Robot * robot, struct Wall_collection * head) {
sensorAngle = -30;
return checkRobotSensorAllWalls(robot, head);
}
// front sensor
int checkRobotSensorFrontAllWalls(struct Robot * robot, struct Wall_collection * head) {
sensorAngle = 0;
return checkRobotSensorAllWalls(robot, head);
}
// general sensor check
int checkRobotSensorAllWalls(struct Robot * robot, struct Wall_collection * head) {
struct Wall_collection *ptr, *head_store;
head_store = head;
int sensorSensitivityLength = floor(SENSOR_VISION/10);
int robotCentreX = robot->x+ROBOT_WIDTH/2;
int robotCentreY = robot->y+ROBOT_HEIGHT/2;
int xTL, yTL;
// loops backwards because closer wall is way more important than further wall
// this also prevents the sensors from seeing through walls
for (int i = 9; i >= 0; i--)
{
ptr = head_store;
// right sensor
if (sensorAngle == 30) {
xTL = (int) round(robotCentreX+(ROBOT_WIDTH/2-2)*cos(((robot->angle)+30)*PI/180)-(-ROBOT_HEIGHT/2-SENSOR_VISION+sensorSensitivityLength*i)*sin(((robot->angle)+30)*PI/180));
yTL = (int) round(robotCentreY-(-ROBOT_WIDTH/2-2)*sin(((robot->angle)+30)*PI/180)+(-ROBOT_HEIGHT/2-SENSOR_VISION+sensorSensitivityLength*i)*cos(((robot->angle)+30)*PI/180));
}
// left sensor
else if (sensorAngle == -30) {
xTL = (int) round(robotCentreX+(-ROBOT_WIDTH/2)*cos(((robot->angle)-30)*PI/180)-(-ROBOT_HEIGHT/2-SENSOR_VISION+sensorSensitivityLength*i)*sin(((robot->angle)-30)*PI/180));
yTL = (int) round(robotCentreY-(ROBOT_WIDTH/2)*sin(((robot->angle)-30)*PI/180)+(-ROBOT_HEIGHT/2-SENSOR_VISION+sensorSensitivityLength*i)*cos(((robot->angle)-30)*PI/180));
}
// front sensor
else {
xTL = (int) round(robotCentreX+(ROBOT_WIDTH/2000)*cos((robot->angle)*PI/180)-(-ROBOT_HEIGHT/1-SENSOR_VISION*3+sensorSensitivityLength*i*3)*sin((robot->angle)*PI/180));
yTL = (int) round(robotCentreY+(ROBOT_WIDTH/2000)*sin((robot->angle)*PI/180)+(-ROBOT_HEIGHT/1-SENSOR_VISION*3+sensorSensitivityLength*i*3)*cos((robot->angle)*PI/180));
}
// check all the walls against the sensor
while(ptr != NULL) {
if (checkRobotSensor(xTL, yTL, sensorSensitivityLength, robot->angle, &ptr->wall))
return i;
ptr = ptr->next;
}
}
return 0;
}
// draw robot and sensor
void robotUpdate(struct SDL_Renderer * renderer, struct Robot * robot) {
int robotCentreX, robotCentreY, xTR, yTR, xTL, yTL, xBR, yBR, xBL, yBL;
SDL_SetRenderDrawColor(renderer, 100, 100, 100, 255);
//Rotating Square
//Vector rotation to work out corners x2 = x1cos(angle)-y1sin(angle), y2 = x1sin(angle)+y1cos(angle)
robotCentreX = robot->x+ROBOT_WIDTH/2;
robotCentreY = robot->y+ROBOT_HEIGHT/2;
xTR = (int) round(robotCentreX+(ROBOT_WIDTH/2)*cos((robot->angle)*PI/180)-(-ROBOT_HEIGHT/2)*sin((robot->angle)*PI/180));
yTR = (int) round(robotCentreY+(ROBOT_WIDTH/2)*sin((robot->angle)*PI/180)+(-ROBOT_HEIGHT/2)*cos((robot->angle)*PI/180));
xBR = (int) round(robotCentreX+(ROBOT_WIDTH/2)*cos((robot->angle)*PI/180)-(ROBOT_HEIGHT/2)*sin((robot->angle)*PI/180));
yBR = (int) round(robotCentreY+(ROBOT_WIDTH/2)*sin((robot->angle)*PI/180)+(ROBOT_HEIGHT/2)*cos((robot->angle)*PI/180));
xBL = (int) round(robotCentreX+(-ROBOT_WIDTH/2)*cos((robot->angle)*PI/180)-(ROBOT_HEIGHT/2)*sin((robot->angle)*PI/180));
yBL = (int) round(robotCentreY+(-ROBOT_WIDTH/2)*sin((robot->angle)*PI/180)+(ROBOT_HEIGHT/2)*cos((robot->angle)*PI/180));
xTL = (int) round(robotCentreX+(-ROBOT_WIDTH/2)*cos((robot->angle)*PI/180)-(-ROBOT_HEIGHT/2)*sin((robot->angle)*PI/180));
yTL = (int) round(robotCentreY+(-ROBOT_WIDTH/2)*sin((robot->angle)*PI/180)+(-ROBOT_HEIGHT/2)*cos((robot->angle)*PI/180));
SDL_RenderDrawLine(renderer,xTR, yTR, xBR, yBR);
SDL_RenderDrawLine(renderer,xBR, yBR, xBL, yBL);
SDL_RenderDrawLine(renderer,xBL, yBL, xTL, yTL);
SDL_RenderDrawLine(renderer,xTL, yTL, xTR, yTR);
// Front Right Sensor
int sensor_sensitivity = floor(SENSOR_VISION/10);
int i;
for (i = 0; i < 10; i++)
{
xTL = (int) round(robotCentreX+(ROBOT_WIDTH/2-2)*cos(((robot->angle)+30)*PI/180)-(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*i)*sin(((robot->angle)+30)*PI/180));
yTL = (int) round(robotCentreY-(-ROBOT_WIDTH/2-2)*sin(((robot->angle)+30)*PI/180)+(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*i)*cos(((robot->angle)+30)*PI/180));
xTR = (int) round(robotCentreX+(ROBOT_WIDTH/2)*cos(((robot->angle)+30)*PI/180)-(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*i)*sin(((robot->angle)+30)*PI/180));
yTR = (int) round(robotCentreY-(-ROBOT_WIDTH/2)*sin(((robot->angle)+30)*PI/180)+(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*i)*cos(((robot->angle)+30)*PI/180));
xBL = (int) round(robotCentreX+(ROBOT_WIDTH/2-2)*cos(((robot->angle)+30)*PI/180)-(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*(i-1))*sin(((robot->angle)+30)*PI/180));
yBL = (int) round(robotCentreY-(-ROBOT_WIDTH/2-2)*sin(((robot->angle)+30)*PI/180)+(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*(i-1))*cos(((robot->angle)+30)*PI/180));
xBR = (int) round(robotCentreX+(ROBOT_WIDTH/2)*cos(((robot->angle)+30)*PI/180)-(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*(i-1))*sin(((robot->angle)+30)*PI/180));
yBR = (int) round(robotCentreY-(-ROBOT_WIDTH/2)*sin(((robot->angle)+30)*PI/180)+(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*(i-1))*cos(((robot->angle)+30)*PI/180));
SDL_SetRenderDrawColor(renderer, 80+(20*(5-i)), 80+(20*(5-i)), 80+(20*(5-i)), 255);
SDL_RenderDrawLine(renderer,xTR, yTR, xBR, yBR);
SDL_RenderDrawLine(renderer,xBR, yBR, xBL, yBL);
SDL_RenderDrawLine(renderer,xBL, yBL, xTL, yTL);
SDL_RenderDrawLine(renderer,xTL, yTL, xTR, yTR);
}
// Front Left Sensor
for (i = 0; i < 10; i++)
{
xTL = (int) round(robotCentreX+(-ROBOT_WIDTH/2)*cos(((robot->angle)-30)*PI/180)-(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*i)*sin(((robot->angle)-30)*PI/180));
yTL = (int) round(robotCentreY-(ROBOT_WIDTH/2)*sin(((robot->angle)-30)*PI/180)+(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*i)*cos(((robot->angle)-30)*PI/180));
xTR = (int) round(robotCentreX+(-ROBOT_WIDTH/2+2)*cos(((robot->angle)-30)*PI/180)-(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*i)*sin(((robot->angle)-30)*PI/180));
yTR = (int) round(robotCentreY-(ROBOT_WIDTH/2+2)*sin(((robot->angle)-30)*PI/180)+(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*i)*cos(((robot->angle)-30)*PI/180));
xBL = (int) round(robotCentreX+(-ROBOT_WIDTH/2)*cos(((robot->angle)-30)*PI/180)-(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*(i-1))*sin(((robot->angle)-30)*PI/180));
yBL = (int) round(robotCentreY-(ROBOT_WIDTH/2)*sin(((robot->angle)-30)*PI/180)+(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*(i-1))*cos(((robot->angle)-30)*PI/180));
xBR = (int) round(robotCentreX+(-ROBOT_WIDTH/2+2)*cos(((robot->angle)-30)*PI/180)-(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*(i-1))*sin(((robot->angle)-30)*PI/180));
yBR = (int) round(robotCentreY-(ROBOT_WIDTH/2+2)*sin(((robot->angle)-30)*PI/180)+(-ROBOT_HEIGHT/2-SENSOR_VISION+sensor_sensitivity*(i-1))*cos(((robot->angle)-30)*PI/180));
SDL_SetRenderDrawColor(renderer, 80+(20*(5-i)), 80+(20*(5-i)), 80+(20*(5-i)), 255);
SDL_RenderDrawLine(renderer,xTR, yTR, xBR, yBR);
SDL_RenderDrawLine(renderer,xBR, yBR, xBL, yBL);
SDL_RenderDrawLine(renderer,xBL, yBL, xTL, yTL);
SDL_RenderDrawLine(renderer,xTL, yTL, xTR, yTR);
}
// Front Sensor
for (i = 0; i < 10; i++)
{
xTL = (int) round(robotCentreX+(-ROBOT_WIDTH/2000)*cos(((robot->angle))*PI/180)-(-ROBOT_HEIGHT/2000-SENSOR_VISION*4.16+sensor_sensitivity*i*4.16)*sin(((robot->angle))*PI/180));
yTL = (int) round(robotCentreY+(-ROBOT_WIDTH/2000)*sin(((robot->angle))*PI/180)+(-ROBOT_HEIGHT/2000-SENSOR_VISION*4.16+sensor_sensitivity*i*4.16)*cos(((robot->angle))*PI/180));
xTR = (int) round(robotCentreX+(-ROBOT_WIDTH/2000-2)*cos(((robot->angle))*PI/180)-(-ROBOT_HEIGHT/2000-SENSOR_VISION*4.16+sensor_sensitivity*i*4.16)*sin(((robot->angle))*PI/180));
yTR = (int) round(robotCentreY+(-ROBOT_WIDTH/2000-2)*sin(((robot->angle))*PI/180)+(-ROBOT_HEIGHT/2000-SENSOR_VISION*4.16+sensor_sensitivity*i*4.16)*cos(((robot->angle))*PI/180));
xBL = (int) round(robotCentreX+(-ROBOT_WIDTH/2000)*cos(((robot->angle))*PI/180)-(-ROBOT_HEIGHT/2000-SENSOR_VISION*4.16+sensor_sensitivity*(i-1)*4.16)*sin(((robot->angle))*PI/180));
yBL = (int) round(robotCentreY+(-ROBOT_WIDTH/2000)*sin(((robot->angle))*PI/180)+(-ROBOT_HEIGHT/2000-SENSOR_VISION*4.16+sensor_sensitivity*(i-1)*4.16)*cos(((robot->angle))*PI/180));
xBR = (int) round(robotCentreX+(-ROBOT_WIDTH/2000-2)*cos(((robot->angle))*PI/180)-(-ROBOT_HEIGHT/2000-SENSOR_VISION*4.16+sensor_sensitivity*(i-1)*4.16)*sin(((robot->angle))*PI/180));
yBR = (int) round(robotCentreY+(-ROBOT_WIDTH/2000-2)*sin(((robot->angle))*PI/180)+(-ROBOT_HEIGHT/2000-SENSOR_VISION*4.16+sensor_sensitivity*(i-1)*4.16)*cos(((robot->angle))*PI/180));
SDL_SetRenderDrawColor(renderer, 80+(20*(5-i)), 80+(20*(5-i)), 80+(20*(5-i)), 255);
SDL_RenderDrawLine(renderer,xTR, yTR, xBR, yBR);
SDL_RenderDrawLine(renderer,xBR, yBR, xBL, yBL);
SDL_RenderDrawLine(renderer,xBL, yBL, xTL, yTL);
SDL_RenderDrawLine(renderer,xTL, yTL, xTR, yTR);
}
}
// manual movement with arrow keys
void robotMotorMove(struct Robot * robot) {
// handle turning robot
switch (robot->direction) {
case LEFT :
robot->angle = (robot->angle-DEFAULT_ANGLE_CHANGE)%360;
break;
case RIGHT :
robot->angle = (robot->angle+DEFAULT_ANGLE_CHANGE)%360;
break;
}
// handle speed of robot
switch (robot->changeSpeed) {
case 1:
robot->currentSpeed += DEFAULT_SPEED_CHANGE;
if (robot->currentSpeed > MAX_ROBOT_SPEED)
robot->currentSpeed = MAX_ROBOT_SPEED;
break;
case -1:
robot->currentSpeed -= DEFAULT_SPEED_CHANGE;
if (robot->currentSpeed < -MAX_ROBOT_SPEED)
robot->currentSpeed = -MAX_ROBOT_SPEED;
break;
}
robot->direction = 0;
robot->true_x += (-robot->currentSpeed * sin(-robot->angle*PI/180));
robot->true_y += (-robot->currentSpeed * cos(-robot->angle*PI/180));
robot->x = (int) round(robot->true_x);
robot->y = (int) round(robot->true_y);
}
int wallfound = 0;
int wallfollowing = 0;
int panicSpot = 0;
// auto movement and navigation of the robot
void robotAutoMotorMove(struct Robot * robot, int front_left_sensor, int front_right_sensor, int front_sensor) {
// PANIC SPOT
// dead ends
if (panicSpot > 0) {
robot->direction = RIGHT;
panicSpot--;
if (front_right_sensor <= 2 && front_sensor <= 5) {
panicSpot = 0;
robot->direction = STRAIGHT;
}
return;
}
if ((front_sensor > 7 && front_left_sensor > 7 && front_right_sensor > 7) ) {
panicSpot = 12;
robot->currentSpeed = 0;
robot->changeSpeed = 0;
robot->direction = STRAIGHT;
wallfound = 0;
wallfollowing = 0;
return;
}
// we need to be moving!
if (robot->currentSpeed == 0) {
robot->changeSpeed = 1;
}
// speed up/down if wall is far/close
if (front_sensor == 0)
robot->changeSpeed = 1;
else if (front_sensor > 0 && robot->currentSpeed > 4 && robot->currentSpeed != 0)
robot->changeSpeed = -1;
// found a wall to follow
if (wallfound == 0 && front_sensor > 6) {
wallfound = 1;
} else {
// main navigation with sensors
// too close to a wall on left or too close infront but right is clear
if (front_left_sensor > 6 ||
(front_sensor > 6 && front_right_sensor < 3))
robot->direction = RIGHT;
// too far from left wall to follow, stay closer
else if (front_left_sensor < 5 && wallfollowing == 1)
robot->direction = LEFT;
// otherwise, we are where we want to be in relation to the left wall
else
robot->direction = STRAIGHT;
// this will override the direction set to left or right on lines 321, and 325
// if ahead is relatively clear and we aren't too close to the right wall
// it doesn't really matter how far away we are from the left wall
// we can just go straight
if (front_sensor <= 1 && front_right_sensor <= 5)
robot->direction = STRAIGHT;
// this handles left turns that aren't just getting closer to the wall
// on both left side of the "track" and right side
if ((front_left_sensor <= 2 && wallfollowing == 1) || // left side
(front_sensor > 6 && front_right_sensor > 4)) // right side
robot->direction = LEFT;
// TOO CLOSE TO WALL!!
// failsafes to not hit wall
if (front_left_sensor > 7)
robot->direction = RIGHT;
else if (front_right_sensor > 7)
robot->direction = LEFT;
}
if (wallfollowing == 0 && front_left_sensor > 2 && front_right_sensor < front_left_sensor-1)
wallfollowing = 1;
}