This repository has been archived by the owner on Jan 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ZumoAI.c
138 lines (123 loc) · 3.29 KB
/
ZumoAI.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
#include "osObjects.h"
#include "sonar.h"
#include "servo.h"
#include "motors.h"
osThreadId tid_zumoAI; // ZumoAI thread id
uint16_t EnemyDistance;
int32_t EnemyAngle;
typedef enum {
FIND_ENEMY,
TURN_TOWARD_ENEMY,
RAM
} Phase_t;
/**
@brief Thread ZumoAI initialization
*/
int Init_ZumoAI(void) {
tid_zumoAI = osThreadCreate(osThread(zumoAI), NULL);
if(!tid_zumoAI) return(-1);
SendMessage("ZumoAI: ZumoAI online.\n");
return(0);
}
/**
@brief Thread ZumoAI termination function
*/
void Kill_ZumoAI(void){
osThreadTerminate(tid_zumoAI); // terminate thread
tid_zumoAI = 0; // thread id
driveStop();
ServoChangeMode(MANUAL);
ServoMoveByDegree(0);
SendMessage("ZumoAI: Process terminated.\n");
}
/**
@brief Finding enemy phase
This function checks if the servo is locked onto something.
If sonar is not locked, make full sweep and rotate.
Wait for sonar lock.
If there is lock, break the loop and save enemy position.
*/
Phase_t FindEnemy(void){
osEvent Evt;
SendMessage("ZumoAI: Searching for enemy.\n");
while(ServoState != LOCKED){
/* Wait for sonar lock */
osSignalClear(tid_zumoAI,SIG_ENEMY_LOCK_ON);
osSignalClear(tid_zumoAI,SIG_SWEEP_COMPLETE);
Evt = osSignalWait(0,osWaitForever);
if(Evt.value.signals & SIG_ENEMY_LOCK_ON){
break;
}
if(Evt.value.signals & SIG_SWEEP_COMPLETE){
osDelay(20);
rotate(120);
SendMessage("ZumoAI: Enemy not found. Rotating.\n");
}
}
EnemyDistance = lastDistance;
EnemyAngle = ServoPosition;
return TURN_TOWARD_ENEMY;
}
/**
@brief Turning toward the enemy
If the enemy is found, rotate towards it.
*/
Phase_t TurnTowardEnemy(void){
SendMessage("ZumoAI: Enemy found!\n");
if(EnemyAngle > 15 || EnemyAngle < -15){
SendMessage("ZumoAI: Enemy at %d. Rotating...\n",EnemyAngle);
osDelay(20);
rotate(EnemyAngle);
ServoSweepDir = (EnemyAngle>0) ? SWEEP_LEFT : SWEEP_RIGHT;
osSignalClear(tid_zumoAI,SIG_MOVE_COMPLETE);
osSignalWait(SIG_MOVE_COMPLETE,osWaitForever);
if (ServoState != LOCKED){
SendMessage("ZumoAI: Enemy lost after rotation.\n");
return FIND_ENEMY;
}
}
return RAM;
}
/**
@brief Ram the enemy.
Ram enemy by driving forward for given distace.
Update distance toward enemy every 2 seconds if lock is not lost.
*/
Phase_t Ram(void){
osEvent Evt;
while(1){
osDelay(20);
drive(40,FORWARD,lastDistance);
//drive(100,FORWARD,0); // uncomment this line to ram instead of stoping in front of the enemy. Comment out the line above.
SendMessage("ZumoAI: Rammming!\n");
osSignalClear(tid_zumoAI,SIG_ENEMY_LOCK_LOST);
Evt = osSignalWait(SIG_ENEMY_LOCK_LOST,2000);
if (Evt.status != osEventTimeout){
return FIND_ENEMY;
}
EnemyDistance = lastDistance;
}
}
/**
@brief ZumoAI thread main loop
*/
void zumoAI(void const *argument){
Phase_t ZumoNextPhase = FIND_ENEMY;
ServoChangeSweepMode(SCAN_AND_LOCK);
ServoChangeMode(SWEEP);
//osDelay(5000);
/* Main Loop */
while(1){
switch(ZumoNextPhase){
case FIND_ENEMY:
ZumoNextPhase = FindEnemy();
break;
case TURN_TOWARD_ENEMY:
ZumoNextPhase = TurnTowardEnemy();
break;
case RAM:
ZumoNextPhase = Ram();
break;
}
}
}