Revision 1569
Cleaning up ir_branch to Make correctly.
branches/ir_branch/behaviors/library_test/main.c | ||
---|---|---|
1 |
#include <dragonfly_lib.h> |
|
2 |
//#include "smart_run_around_fsm.h" |
|
3 |
|
|
4 |
// Martin "deffi" Herrmann Test |
|
5 |
|
|
6 |
static void oset(uint8_t r,uint8_t g,uint8_t b) |
|
7 |
{ |
|
8 |
orbs_set(r,g,b,255-r,255-g,255-b); |
|
9 |
} |
|
10 |
|
|
11 |
static void color_circle (void) |
|
12 |
{ |
|
13 |
while(1) |
|
14 |
{ |
|
15 |
for (uint8_t part=0; part<6; ++part) |
|
16 |
{ |
|
17 |
for (uint8_t up=0; up<255; ++up) |
|
18 |
{ |
|
19 |
uint8_t dn=255-up; |
|
20 |
uint8_t on=255; |
|
21 |
uint8_t of=0; |
|
22 |
|
|
23 |
if (1) |
|
24 |
{ |
|
25 |
// Maximum brightness mode |
|
26 |
switch (part) |
|
27 |
{ |
|
28 |
case 0: oset (on, up, of); break; |
|
29 |
case 1: oset (dn, on, of); break; |
|
30 |
case 2: oset (of, on, up); break; |
|
31 |
case 3: oset (of, dn, on); break; |
|
32 |
case 4: oset (up, of, on); break; |
|
33 |
case 5: oset (on, of, dn); break; |
|
34 |
} |
|
35 |
} |
|
36 |
else |
|
37 |
{ |
|
38 |
// Constant brightness mode (not very constant though) |
|
39 |
switch (part%3) |
|
40 |
{ |
|
41 |
case 0: oset (dn, up, of); break; |
|
42 |
case 1: oset (of, dn, up); break; |
|
43 |
case 2: oset (up, of, dn); break; |
|
44 |
} |
|
45 |
} |
|
46 |
|
|
47 |
delay_ms (2); |
|
48 |
} |
|
49 |
} |
|
50 |
} |
|
51 |
} |
|
52 |
|
|
53 |
static void acl(void) |
|
54 |
{ |
|
55 |
#define redval 255 |
|
56 |
#define greenval 150 |
|
57 |
#define interval 1300 |
|
58 |
#define flash 20 |
|
59 |
#define pause 200 |
|
60 |
|
|
61 |
#define def do { orb1_set(redval,0,0); orb2_set(0,greenval,0); } while (0) |
|
62 |
#define wht do { orb_set(255,255,255); } while (0) |
|
63 |
|
|
64 |
while (1) |
|
65 |
{ |
|
66 |
wht; delay_ms (flash); |
|
67 |
def; delay_ms (pause-flash); |
|
68 |
wht; delay_ms (flash); |
|
69 |
def; delay_ms (pause-flash); |
|
70 |
def; delay_ms (interval-2*pause-2*flash); |
|
71 |
} |
|
72 |
} |
|
73 |
|
|
74 |
int main(void) { |
|
75 |
// dragonfly_init(ALL_ON); |
|
76 |
dragonfly_init(0); |
|
77 |
|
|
78 |
usb_init (); |
|
79 |
usb_puts ("Startup\r\n"); |
|
80 |
|
|
81 |
|
|
82 |
//encoders_init (); |
|
83 |
|
|
84 |
//analog_init(ADC_START); |
|
85 |
//analog_init(0); |
|
86 |
|
|
87 |
//range_init(); |
|
88 |
|
|
89 |
//DDRF=2; |
|
90 |
|
|
91 |
//motors_init (); |
|
92 |
//motor2_set (FORWARD, 64); |
|
93 |
|
|
94 |
//orb_init_binary (); |
|
95 |
orb_init_pwm (); |
|
96 |
|
|
97 |
if (false) |
|
98 |
{ |
|
99 |
orbs_set (255, 0, 0, 0, 0, 0); delay_ms (500); |
|
100 |
orbs_set (0, 255, 0, 0, 0, 0); delay_ms (500); |
|
101 |
orbs_set (0, 0, 255, 0, 0, 0); delay_ms (500); |
|
102 |
orbs_set (0, 0, 0, 255, 0, 0); delay_ms (500); |
|
103 |
orbs_set (0, 0, 0, 0, 255, 0); delay_ms (500); |
|
104 |
orbs_set (0, 0, 0, 0, 0, 255); delay_ms (500); |
|
105 |
} |
|
106 |
|
|
107 |
if (false) |
|
108 |
{ |
|
109 |
orb_set (1,1,1); |
|
110 |
while (1) |
|
111 |
{ |
|
112 |
SYNC |
|
113 |
{ |
|
114 |
for (uint8_t m=0; m<100; ++m) |
|
115 |
{ |
|
116 |
_delay_us(10); |
|
117 |
} |
|
118 |
} |
|
119 |
} |
|
120 |
} |
|
121 |
|
|
122 |
if (false) |
|
123 |
{ |
|
124 |
while (1) |
|
125 |
{ |
|
126 |
for (uint8_t x=0; x<255; ++x) |
|
127 |
{ |
|
128 |
orbs_set (x, 1, 2, 3, 4, 5); |
|
129 |
|
|
130 |
for (uint8_t n=0; n<80; ++n) |
|
131 |
{ |
|
132 |
SYNC |
|
133 |
{ for (uint8_t m=0; m<1; ++m) _delay_us(50); } |
|
134 |
} |
|
135 |
} |
|
136 |
|
|
137 |
for (uint8_t x=255; x>0; --x) |
|
138 |
{ |
|
139 |
orbs_set (x, 1, 1, 1, 1, 1); |
|
140 |
delay_ms (4); |
|
141 |
} |
|
142 |
} |
|
143 |
} |
|
144 |
|
|
145 |
if (false) |
|
146 |
{ |
|
147 |
//orbs_set (2,4,6,8,10,12); |
|
148 |
//orbs_set (32, 64, 96, 128, 160, 192); |
|
149 |
orbs_set (128,128,128,128,128,128); |
|
150 |
while (1); |
|
151 |
} |
|
152 |
|
|
153 |
if (false) |
|
154 |
{ |
|
155 |
if (!button2_read ()) |
|
156 |
{ |
|
157 |
orb_set_mode (orb_mode_pwm); |
|
158 |
orb_disable_timer (); |
|
159 |
|
|
160 |
while (1) |
|
161 |
{ |
|
162 |
// Continuously call the sorting routine for timing test |
|
163 |
for (uint8_t i=0; i<200; ++i) |
|
164 |
{ |
|
165 |
orbs_set (10,20,30,40,50,60); |
|
166 |
delay_ms (10); |
|
167 |
} |
|
168 |
|
|
169 |
for (uint8_t i=0; i<200; ++i) |
|
170 |
{ |
|
171 |
orbs_set (60,50,40,30,20,10); |
|
172 |
delay_ms (10); |
|
173 |
} |
|
174 |
} |
|
175 |
} |
|
176 |
else |
|
177 |
{ |
|
178 |
while (button2_read ()); |
|
179 |
if (button1_read ()) |
|
180 |
{ |
|
181 |
color_circle (); |
|
182 |
} |
|
183 |
else |
|
184 |
{ |
|
185 |
acl (); |
|
186 |
} |
|
187 |
} |
|
188 |
} |
|
189 |
|
|
190 |
|
|
191 |
|
|
192 |
// Do some lighting |
|
193 |
if (!button2_read ()) |
|
194 |
color_circle (); |
|
195 |
else |
|
196 |
acl (); |
|
197 |
|
|
198 |
} |
|
199 |
|
branches/ir_branch/behaviors/library_test/Makefile | ||
---|---|---|
1 |
# this is a local makefile |
|
2 |
|
|
3 |
# Relative path to the root directory (containing lib directory) |
|
4 |
ifndef COLONYROOT |
|
5 |
COLONYROOT := .. |
|
6 |
|
|
7 |
# Target file name (without extension). |
|
8 |
TARGET = main |
|
9 |
|
|
10 |
# Uncomment this to use the wireless library |
|
11 |
USE_WIRELESS = 1 |
|
12 |
|
|
13 |
# com1 = serial port. Use lpt1 to connect to parallel port. |
|
14 |
AVRDUDE_PORT = $(shell if uname -s |grep -i w32 >/dev/null; then echo 'COM4:'; else echo '/dev/ttyUSB0'; fi) |
|
15 |
|
|
16 |
else |
|
17 |
COLONYROOT := ../$(COLONYROOT) |
|
18 |
endif |
|
19 |
|
|
20 |
include $(COLONYROOT)/Makefile |
branches/ir_branch/behaviors/hunter_prey/ref/Makefile | ||
---|---|---|
1 |
CC = gcc |
|
2 |
CFLAGS = -Wall -g |
|
3 |
|
|
4 |
all: ref |
|
5 |
|
|
6 |
ref: *.c ../../libwireless/lib/*.c |
|
7 |
$(CC) $(CFLAGS) *.c -L../../libwireless/lib -o ref -DWL_DEBUG -lwireless -lpthread -ggdb |
|
8 |
|
|
9 |
clean: |
|
10 |
rm -f *.o ref ../lib/*.o |
|
11 |
|
branches/ir_branch/behaviors/hunter_prey/ref/main.c | ||
---|---|---|
1 |
#include <stdlib.h> |
|
2 |
#include <stdio.h> |
|
3 |
#include <time.h> |
|
4 |
#include <unistd.h> |
|
5 |
#include "../../libwireless/lib/wl_basic.h" |
|
6 |
#include "../../libwireless/lib/wireless.h" |
|
7 |
#include "../hunter_prey.h" |
|
8 |
|
|
9 |
#define TYPE 42 // packet type for wireless communication |
|
10 |
|
|
11 |
#define NUM_BOTS 17 |
|
12 |
#define TOTAL_GAME_TIME 600*5 //in 100 ms intervals |
|
13 |
|
|
14 |
void packet_receive(char type, int source, unsigned char* packet, int length); |
|
15 |
|
|
16 |
volatile unsigned int preyTime[20]; |
|
17 |
volatile int preyBot=-1; |
|
18 |
|
|
19 |
void waitKey(void) { |
|
20 |
unsigned char buf[10]; |
|
21 |
|
|
22 |
//read from stdin |
|
23 |
while(read(0, buf, 10)==10) { |
|
24 |
printf("!"); |
|
25 |
fflush(stdout); |
|
26 |
} |
|
27 |
|
|
28 |
while(getchar()==-1); |
|
29 |
} |
|
30 |
|
|
31 |
void print_stats(void) { |
|
32 |
|
|
33 |
int i=0; |
|
34 |
|
|
35 |
for(i=0;i<NUM_BOTS;i++) { |
|
36 |
printf("%5d ", preyTime[i]); |
|
37 |
} |
|
38 |
|
|
39 |
printf("\n"); |
|
40 |
|
|
41 |
} |
|
42 |
|
|
43 |
int main(int argc, char *argv[]) |
|
44 |
{ |
|
45 |
char send_buffer[2]; // holds data to send |
|
46 |
int data_length; // length of data received |
|
47 |
unsigned char *packet_data; // data received |
|
48 |
int ret; |
|
49 |
int i; |
|
50 |
int winner, maxTime=0; |
|
51 |
|
|
52 |
unsigned int channel = 0xF; |
|
53 |
|
|
54 |
struct timespec delay, rem; |
|
55 |
|
|
56 |
delay.tv_sec = 0; |
|
57 |
delay.tv_nsec = 100000000; |
|
58 |
|
|
59 |
|
|
60 |
if(argc > 1) { |
|
61 |
channel = atoi(argv[1]); |
|
62 |
} |
|
63 |
|
|
64 |
printf("using wireless channel %d\n", channel); |
|
65 |
|
|
66 |
wl_set_com_port("/dev/ttyUSB0"); |
|
67 |
// set up wireless |
|
68 |
ret = wl_basic_init(&packet_receive); |
|
69 |
|
|
70 |
if(ret) { |
|
71 |
printf("ERROR: wl_basic_init failed. %d\n", ret); |
|
72 |
return ret; |
|
73 |
} |
|
74 |
//wl_set_channel(channel); |
|
75 |
|
|
76 |
for(i=0;i<NUM_BOTS;i++) { |
|
77 |
preyTime[i]=0; |
|
78 |
} |
|
79 |
|
|
80 |
ret = 0; |
|
81 |
i=0; |
|
82 |
|
|
83 |
printf("ready\n"); |
|
84 |
|
|
85 |
//TODO: use rtc to make this more accurate |
|
86 |
while(i < TOTAL_GAME_TIME) { |
|
87 |
wl_do(); |
|
88 |
|
|
89 |
if(ret==0) { |
|
90 |
ret = nanosleep(&delay, &rem); |
|
91 |
} |
|
92 |
else { |
|
93 |
ret = nanosleep(&rem, &rem); |
|
94 |
} |
|
95 |
|
|
96 |
//update counts when we have waited at least enough time |
|
97 |
if(ret == 0 && preyBot >= 0) { |
|
98 |
preyTime[preyBot]++; |
|
99 |
|
|
100 |
if(i==0) { //time starts on the first real tag |
|
101 |
printf("\nThe race is on!\n"); |
|
102 |
} |
|
103 |
i++; |
|
104 |
} |
|
105 |
|
|
106 |
if((TOTAL_GAME_TIME - i)%600 == 0) { |
|
107 |
printf("%d minutes remaining!\n", (TOTAL_GAME_TIME - i)/600); |
|
108 |
} |
|
109 |
|
|
110 |
if(i%10==0) { |
|
111 |
print_stats(); |
|
112 |
if( TOTAL_GAME_TIME - i <= 100) |
|
113 |
printf("%d...\n", (TOTAL_GAME_TIME - i)/10); |
|
114 |
} |
|
115 |
} |
|
116 |
|
|
117 |
|
|
118 |
for(i=1;i<NUM_BOTS;i++) { |
|
119 |
if(preyTime[i] > maxTime) { |
|
120 |
maxTime = preyTime[i]; |
|
121 |
winner = i; |
|
122 |
} |
|
123 |
} |
|
124 |
|
|
125 |
printf("\n\GAME OVER!n\nAAAAAAAAAAND the winner is\nBOT %d!!!!\n", winner); |
|
126 |
|
|
127 |
return 0; |
|
128 |
} |
|
129 |
|
|
130 |
void packet_receive(char type, int source, unsigned char* packet, int length) |
|
131 |
{ |
|
132 |
|
|
133 |
if(type==42 && length>=2){ |
|
134 |
if(packet[0] == HUNTER_PREY_ACTION_TAG) { |
|
135 |
//TODO: check tag |
|
136 |
|
|
137 |
} |
|
138 |
else if(packet[0] == HUNTER_PREY_ACTION_ACK) { |
|
139 |
|
|
140 |
preyBot = packet[1]; |
|
141 |
printf("bot %d is prey!\n", preyBot); |
|
142 |
|
|
143 |
} |
|
144 |
else { |
|
145 |
printf("got invalid packet! %c%d\n", packet[0], packet[1]); |
|
146 |
} |
|
147 |
} |
|
148 |
else { |
|
149 |
printf("got unknown packet! type=%d, length=%d\n", type, length); |
|
150 |
} |
|
151 |
} |
|
152 |
|
branches/ir_branch/behaviors/hunter_prey/Makefile | ||
---|---|---|
1 |
# this is a local makefile |
|
2 |
|
|
3 |
# Relative path to the root directory (containing lib directory) |
|
4 |
ifndef COLONYROOT |
|
5 |
COLONYROOT := .. |
|
6 |
|
|
7 |
# Target file name (without extension). |
|
8 |
TARGET = main |
|
9 |
|
|
10 |
# Uncomment this to use the wireless library |
|
11 |
USE_WIRELESS = 1 |
|
12 |
|
|
13 |
# com1 = serial port. Use lpt1 to connect to parallel port. |
|
14 |
AVRDUDE_PORT = $(shell if uname -s |grep -i w32 >/dev/null; then echo 'COM4:'; else echo '/dev/ttyUSB0'; fi) |
|
15 |
|
|
16 |
else |
|
17 |
COLONYROOT := ../$(COLONYROOT) |
|
18 |
endif |
|
19 |
|
|
20 |
include $(COLONYROOT)/Makefile |
branches/ir_branch/behaviors/hunter_prey/john/Makefile | ||
---|---|---|
1 |
# this is a local makefile |
|
2 |
|
|
3 |
# Relative path to the root directory (containing lib directory) |
|
4 |
ifndef COLONYROOT |
|
5 |
COLONYROOT := .. |
|
6 |
|
|
7 |
# Target file name (without extension). |
|
8 |
TARGET = main |
|
9 |
|
|
10 |
# Uncomment this to use the wireless library |
|
11 |
USE_WIRELESS = 1 |
|
12 |
|
|
13 |
# com1 = serial port. Use lpt1 to connect to parallel port. |
|
14 |
AVRDUDE_PORT = $(shell if uname -s |grep -i w32 >/dev/null; then echo 'COM4:'; else echo '/dev/ttyUSB0'; fi) |
|
15 |
|
|
16 |
else |
|
17 |
COLONYROOT := ../$(COLONYROOT) |
|
18 |
endif |
|
19 |
|
|
20 |
include $(COLONYROOT)/Makefile |
branches/ir_branch/behaviors/hunter_prey/john/main.c | ||
---|---|---|
1 |
/* |
|
2 |
* Hunter-Prey main.c File - Implementation of Hunter-Prey behavior which |
|
3 |
* uses finite state machines to manage the behavior. A top level |
|
4 |
* state machine controls the high level behavior switches between |
|
5 |
* "hunter" and "prey" and manages the wireless communication. Two |
|
6 |
* additional state machines control the behavior of the robot when |
|
7 |
* it is in "prey" mode and when it is in "hunter" mode. |
|
8 |
* |
|
9 |
* Author: John Sexton, Colony Project, CMU Robotics Club |
|
10 |
*/ |
|
11 |
|
|
12 |
#include <dragonfly_lib.h> |
|
13 |
#include <wl_basic.h> |
|
14 |
#include "hunter_prey.h" |
|
15 |
#include "encoders.h" |
|
16 |
|
|
17 |
#define WL_CHANNEL 15 |
|
18 |
|
|
19 |
#define BACK_THRESHOLD -5000 |
|
20 |
#define TURN_DIST 1024 |
|
21 |
#define IR_DIST_THRESHOLD 200 |
|
22 |
|
|
23 |
/* State Macros */ |
|
24 |
|
|
25 |
/* Top Level FSM States */ |
|
26 |
#define TOP_INIT 0 |
|
27 |
#define TOP_HUNTER_HUNT 1 |
|
28 |
#define TOP_HUNTER_TAG 2 |
|
29 |
#define TOP_HUNTER_PURSUE 3 |
|
30 |
#define TOP_PREY_AVOID 4 |
|
31 |
#define TOP_HUNTER_WAIT 5 |
|
32 |
#define TOP_ERROR 6 |
|
33 |
|
|
34 |
/* Hunter FSM States */ |
|
35 |
#define HUNTER_SPIRAL 0 |
|
36 |
#define HUNTER_CHASE 1 |
|
37 |
|
|
38 |
/* Prey FSM States */ |
|
39 |
#define PREY_START_BACK 0 |
|
40 |
#define PREY_BACKING 1 |
|
41 |
#define PREY_TURN 2 |
|
42 |
#define PREY_AVOID 3 |
|
43 |
|
|
44 |
|
|
45 |
/* Function prototype declarations */ |
|
46 |
int hunter_FSM(int, int, int); |
|
47 |
int prey_FSM(int); |
|
48 |
|
|
49 |
/* Variables used to receive packets */ |
|
50 |
unsigned char* packet_data; |
|
51 |
int data_length; |
|
52 |
|
|
53 |
/* Data buffer used to send packets */ |
|
54 |
char send_buffer[1]; |
|
55 |
|
|
56 |
int main(void) |
|
57 |
{ |
|
58 |
|
|
59 |
/* Initialize dragonfly board */ |
|
60 |
dragonfly_init(ALL_ON); |
|
61 |
xbee_init(); |
|
62 |
encoders_init(); |
|
63 |
|
|
64 |
/* Initialize the basic wireless library */ |
|
65 |
wl_basic_init_default(); |
|
66 |
|
|
67 |
/* Set the XBee channel to assigned channel */ |
|
68 |
wl_set_channel(WL_CHANNEL); |
|
69 |
|
|
70 |
|
|
71 |
/* ****** CODE HERE ******* */ |
|
72 |
|
|
73 |
/* Initialize state machines */ |
|
74 |
int state = TOP_INIT; |
|
75 |
int hunter_state = HUNTER_SPIRAL; |
|
76 |
int prey_state = PREY_AVOID; |
|
77 |
|
|
78 |
int frontIR = 0; |
|
79 |
int maxBOM = 0; |
|
80 |
int robotID = get_robotid(); |
|
81 |
int oldTime = 0, curTime = 0; |
|
82 |
|
|
83 |
while (1) { |
|
84 |
|
|
85 |
/* Check if we've received a wireless packet */ |
|
86 |
packet_data = wl_basic_do_default(&data_length); |
|
87 |
|
|
88 |
/* Top level state machines */ |
|
89 |
switch(state) { |
|
90 |
|
|
91 |
case TOP_INIT: |
|
92 |
orbs_set_color(RED, GREEN); |
|
93 |
delay_ms(500); |
|
94 |
orbs_set_color(GREEN, RED); |
|
95 |
delay_ms(500); |
|
96 |
|
|
97 |
/* Allow user to pick the starting behavior */ |
|
98 |
if (button1_read()) { |
|
99 |
state = TOP_PREY_AVOID; |
|
100 |
prey_state = PREY_AVOID; |
|
101 |
} else { |
|
102 |
state = TOP_HUNTER_HUNT; |
|
103 |
hunter_state = HUNTER_SPIRAL; |
|
104 |
} |
|
105 |
break; |
|
106 |
case TOP_HUNTER_HUNT: |
|
107 |
orbs_set_color(RED, RED); |
|
108 |
|
|
109 |
if (packet_data && data_length == 2 |
|
110 |
&& packet_data[0] == HUNTER_PREY_ACTION_ACK) { |
|
111 |
/* If we've received an ACK, we need to wait */ |
|
112 |
state = TOP_HUNTER_WAIT; |
|
113 |
} else { |
|
114 |
/* Record some sensor readings and check if we can TAG */ |
|
115 |
bom_refresh(BOM_ALL); |
|
116 |
frontIR = range_read_distance(IR2); |
|
117 |
maxBOM = get_max_bom(); |
|
118 |
if (hunter_prey_tagged(maxBOM, frontIR) || button1_read()) { |
|
119 |
state = TOP_HUNTER_TAG; |
|
120 |
} else { |
|
121 |
/* If we haven't tagged, then enter hunter FSM */ |
|
122 |
hunter_state = hunter_FSM(hunter_state, maxBOM, frontIR); |
|
123 |
} |
|
124 |
} |
|
125 |
break; |
|
126 |
case TOP_HUNTER_TAG: |
|
127 |
orbs_set_color(RED, PURPLE); |
|
128 |
delay_ms(500); |
|
129 |
|
|
130 |
if (packet_data && data_length == 2 |
|
131 |
&& packet_data[0] == HUNTER_PREY_ACTION_ACK) { |
|
132 |
/* If we've received an ACK, then someone beat us to the TAG and |
|
133 |
* we need to wait. */ |
|
134 |
state = TOP_HUNTER_WAIT; |
|
135 |
} else { |
|
136 |
/* Prepare and send the TAG packet */ |
|
137 |
send_buffer[0] = HUNTER_PREY_ACTION_TAG; |
|
138 |
send_buffer[1] = robotID; |
|
139 |
wl_basic_send_global_packet(42, send_buffer, 2); |
|
140 |
|
|
141 |
/* Record the time so we don't spam a TAG message on the network */ |
|
142 |
oldTime = rtc_get(); |
|
143 |
state = TOP_HUNTER_PURSUE; |
|
144 |
} |
|
145 |
break; |
|
146 |
case TOP_HUNTER_PURSUE: |
|
147 |
orbs_set_color(RED, BLUE); |
|
148 |
curTime = rtc_get(); |
|
149 |
|
|
150 |
if (packet_data && data_length == 2 |
|
151 |
&& packet_data[0] == HUNTER_PREY_ACTION_ACK) { |
|
152 |
/* Check if we've received a new wireless packet */ |
|
153 |
|
|
154 |
if (packet_data[1] == robotID) { |
|
155 |
/* We've been ACKed, so we can now become the prey */ |
|
156 |
state = TOP_PREY_AVOID; |
|
157 |
prey_state = PREY_START_BACK; |
|
158 |
} else { |
|
159 |
/* If we get an ACK with a different robotID, then someone beat us |
|
160 |
* to the TAG, so we must wait */ |
|
161 |
state = TOP_HUNTER_WAIT; |
|
162 |
} |
|
163 |
|
|
164 |
} else if (curTime - oldTime > 1) { |
|
165 |
/* If 1 second has ellapsed, return to normal hunting state (we can |
|
166 |
* TAG again now) */ |
|
167 |
state = TOP_HUNTER_HUNT; |
|
168 |
} else if (oldTime > curTime) { |
|
169 |
/* If for some reason the timer overflows, or the wireless library |
|
170 |
* (which is also using the same timer) resets the timer, |
|
171 |
* reinitialize the timer so that we don't wait too long for the |
|
172 |
* timer to catch back up. */ |
|
173 |
oldTime = curTime; |
|
174 |
} else { |
|
175 |
/* If no other behavioral changes need to be made, then continue |
|
176 |
* with the hunter FSM where we left off */ |
|
177 |
bom_refresh(BOM_ALL); |
|
178 |
frontIR = range_read_distance(IR2); |
|
179 |
maxBOM = get_max_bom(); |
|
180 |
hunter_state = hunter_FSM(hunter_state, maxBOM, frontIR); |
|
181 |
} |
|
182 |
break; |
|
183 |
case TOP_PREY_AVOID: |
|
184 |
orbs_set_color(GREEN, GREEN); |
|
185 |
if (packet_data && data_length == 2 |
|
186 |
&& packet_data[0] == HUNTER_PREY_ACTION_TAG) { |
|
187 |
/* Check if we've received a TAG yet. If so then send an ACK back */ |
|
188 |
|
|
189 |
send_buffer[0] = HUNTER_PREY_ACTION_ACK; |
|
190 |
send_buffer[1] = packet_data[1]; |
|
191 |
wl_basic_send_global_packet(42, send_buffer, 2); |
|
192 |
|
|
193 |
state = TOP_HUNTER_WAIT; |
|
194 |
} else { |
|
195 |
/* If we haven't received a TAG yet, continue with prey FSM */ |
|
196 |
bom_on(); |
|
197 |
prey_state = prey_FSM(prey_state); |
|
198 |
} |
|
199 |
break; |
|
200 |
case TOP_HUNTER_WAIT: |
|
201 |
/* Set orb colors and wait to give the prey the 5 second head start */ |
|
202 |
orbs_set_color(BLUE, BLUE); |
|
203 |
bom_off(); |
|
204 |
motors_off(); |
|
205 |
delay_ms(5000); |
|
206 |
state = TOP_HUNTER_HUNT; |
|
207 |
hunter_state = HUNTER_SPIRAL; |
|
208 |
break; |
|
209 |
case TOP_ERROR: |
|
210 |
default: |
|
211 |
orbs_set_color(PURPLE, PURPLE); |
|
212 |
state = TOP_ERROR; |
|
213 |
while(1); |
|
214 |
break; |
|
215 |
} |
|
216 |
|
|
217 |
} |
|
218 |
|
|
219 |
/* ****** END HERE ******* */ |
|
220 |
|
|
221 |
while(1); |
|
222 |
|
|
223 |
return 0; |
|
224 |
|
|
225 |
} |
|
226 |
|
|
227 |
|
|
228 |
/* |
|
229 |
* prey_FSM - Prey finite state machine which starts by backing away, turning, |
|
230 |
* and then running and avoiding obstacles. |
|
231 |
* |
|
232 |
* Arguments: |
|
233 |
* prey_state - Current prey state. |
|
234 |
* |
|
235 |
* returns - The new state of the prey state machine. |
|
236 |
*/ |
|
237 |
|
|
238 |
int prey_FSM(int prey_state) { |
|
239 |
|
|
240 |
/* Variable to store the front rangefinder readings */ |
|
241 |
int rangeVals[3] = {0, 0, 0}; |
|
242 |
|
|
243 |
switch (prey_state) { |
|
244 |
|
|
245 |
case PREY_START_BACK: |
|
246 |
motor_l_set(BACKWARD, 255); |
|
247 |
motor_r_set(BACKWARD, 255); |
|
248 |
encoder_rst_dx(LEFT); |
|
249 |
return PREY_BACKING; |
|
250 |
break; |
|
251 |
case PREY_BACKING: |
|
252 |
if (encoder_get_x(LEFT) < BACK_THRESHOLD) { |
|
253 |
motor_l_set(BACKWARD, 255); |
|
254 |
motor_r_set(FORWARD, 255); |
|
255 |
encoder_rst_dx(RIGHT); |
|
256 |
return PREY_TURN; |
|
257 |
} else { |
|
258 |
return PREY_BACKING; |
|
259 |
} |
|
260 |
break; |
|
261 |
case PREY_TURN: |
|
262 |
if (encoder_get_x(RIGHT) > TURN_DIST) { |
|
263 |
return PREY_AVOID; |
|
264 |
} else { |
|
265 |
return PREY_TURN; |
|
266 |
} |
|
267 |
break; |
|
268 |
case PREY_AVOID: |
|
269 |
rangeVals[0] = range_read_distance(IR1); |
|
270 |
rangeVals[1] = range_read_distance(IR2); |
|
271 |
rangeVals[2] = range_read_distance(IR3); |
|
272 |
|
|
273 |
/* Drive away if we detect obstacles using the rangefinders */ |
|
274 |
if (rangeVals[1] > 0 && rangeVals[1] < IR_DIST_THRESHOLD) { |
|
275 |
motor_l_set(FORWARD, 255); |
|
276 |
motor_r_set(BACKWARD, 255); |
|
277 |
return PREY_AVOID; |
|
278 |
} else if (rangeVals[0] > 0 && rangeVals[0] < IR_DIST_THRESHOLD) { |
|
279 |
motor_l_set(FORWARD, 255); |
|
280 |
motor_r_set(FORWARD, 170); |
|
281 |
return PREY_AVOID; |
|
282 |
} else if (rangeVals[2] > 0 && rangeVals[2] < IR_DIST_THRESHOLD) { |
|
283 |
motor_l_set(FORWARD, 170); |
|
284 |
motor_r_set(FORWARD, 255); |
|
285 |
return PREY_AVOID; |
|
286 |
} else { |
|
287 |
motor_l_set(FORWARD, 255); |
|
288 |
motor_r_set(FORWARD, 255); |
|
289 |
return PREY_AVOID; |
|
290 |
} |
|
291 |
break; |
|
292 |
default: |
|
293 |
return PREY_AVOID; |
|
294 |
break; |
|
295 |
|
|
296 |
} |
|
297 |
|
|
298 |
return prey_state; |
|
299 |
|
|
300 |
} |
|
301 |
|
|
302 |
|
|
303 |
/* |
|
304 |
* hunter_FSM - Hunter finite state machine which defaults to spiraling |
|
305 |
* outwards until the BOM can locate the prey. Once the BOM locates |
|
306 |
* the prey, chase the prey as fast as possible. |
|
307 |
* |
|
308 |
* Arguments: |
|
309 |
* hunter_state - Current hunter state. |
|
310 |
* maxBOM - Current maximum BOM value. |
|
311 |
* frontIR - Current front IR rangefinder reading value. |
|
312 |
* |
|
313 |
* returns - The new state of the hunter state machine. |
|
314 |
*/ |
|
315 |
|
|
316 |
int hunter_FSM(int hunter_state, int maxBOM, int frontIR) { |
|
317 |
|
|
318 |
switch(hunter_state) { |
|
319 |
|
|
320 |
case HUNTER_SPIRAL: |
|
321 |
if (maxBOM != -1) { |
|
322 |
return HUNTER_CHASE; |
|
323 |
} else { |
|
324 |
motor_l_set(FORWARD, 170); |
|
325 |
motor_r_set(FORWARD, 190); |
|
326 |
return HUNTER_SPIRAL; |
|
327 |
} |
|
328 |
break; |
|
329 |
case HUNTER_CHASE: |
|
330 |
|
|
331 |
/* A large look-up table to set the speed of the motors based on |
|
332 |
* where the prey robot is. */ |
|
333 |
if (maxBOM == -1) { |
|
334 |
return HUNTER_CHASE; |
|
335 |
} else if (maxBOM == 4) { |
|
336 |
motor_l_set(FORWARD, 255); |
|
337 |
motor_r_set(FORWARD, 255); |
|
338 |
return HUNTER_CHASE; |
|
339 |
} else if (maxBOM == 3) { |
|
340 |
motor_l_set(FORWARD, 255); |
|
341 |
motor_r_set(FORWARD, 240); |
|
342 |
return HUNTER_CHASE; |
|
343 |
} else if (maxBOM == 5) { |
|
344 |
motor_l_set(FORWARD, 240); |
|
345 |
motor_r_set(FORWARD, 255); |
|
346 |
return HUNTER_CHASE; |
|
347 |
} else if (maxBOM < 3) { |
|
348 |
motor_l_set(FORWARD, 255); |
|
349 |
motor_r_set(FORWARD, 170); |
|
350 |
return HUNTER_CHASE; |
|
351 |
} else if (maxBOM > 5 && maxBOM <= 8) { |
|
352 |
motor_l_set(FORWARD, 170); |
|
353 |
motor_r_set(FORWARD, 255); |
|
354 |
return HUNTER_CHASE; |
|
355 |
} else if (maxBOM > 8 && maxBOM < 12) { |
|
356 |
motor_l_set(BACKWARD, 255); |
|
357 |
motor_r_set(FORWARD, 255); |
|
358 |
return HUNTER_CHASE; |
|
359 |
} else { |
|
360 |
motor_l_set(FORWARD, 255); |
|
361 |
motor_r_set(BACKWARD, 255); |
|
362 |
return HUNTER_CHASE; |
|
363 |
} |
|
364 |
break; |
|
365 |
default: |
|
366 |
return HUNTER_SPIRAL; |
|
367 |
break; |
|
368 |
|
|
369 |
} |
|
370 |
|
|
371 |
return hunter_state; |
|
372 |
|
|
373 |
} |
branches/ir_branch/behaviors/hunter_prey/john/hunter_prey.c | ||
---|---|---|
1 |
#include "hunter_prey.h" |
|
2 |
#include <dragonfly_lib.h> |
|
3 |
|
|
4 |
#define TAG_TIME 3 |
|
5 |
#define TAG_RANGE 200 |
|
6 |
|
|
7 |
/**** This file should not be edited! ****/ |
|
8 |
|
|
9 |
|
|
10 |
/* |
|
11 |
* The criteria for tagging are the following: |
|
12 |
* * The max bom is betweed 1 and 7 |
|
13 |
* * The front rangefinder reads less than TAG_RANGE |
|
14 |
* * -1 values from the rangefinder are ignored |
|
15 |
* * These conditions are met across TAG_TIME calls to this function |
|
16 |
*/ |
|
17 |
|
|
18 |
unsigned char hunter_prey_tagged(int max_bom, int frontRange) { |
|
19 |
|
|
20 |
static int onTarget = 0; |
|
21 |
|
|
22 |
if(max_bom < 7 && max_bom > 1 && frontRange > 0 && frontRange < TAG_RANGE) { |
|
23 |
if(onTarget == 0) { |
|
24 |
onTarget = TAG_TIME; |
|
25 |
usb_puts("On target!\n"); |
|
26 |
} |
|
27 |
else { |
|
28 |
if(--onTarget <= 0) { |
|
29 |
onTarget = 0; |
|
30 |
usb_puts("TAG!\n"); |
|
31 |
return 1; |
|
32 |
} |
|
33 |
} |
|
34 |
} |
|
35 |
else{ |
|
36 |
//don't reset onTarget because the robot got too close |
|
37 |
if(frontRange > 0) |
|
38 |
onTarget = 0; |
|
39 |
} |
|
40 |
|
|
41 |
return 0; |
|
42 |
|
|
43 |
} |
branches/ir_branch/behaviors/hunter_prey/john/hunter_prey.h | ||
---|---|---|
1 |
#ifndef _HUNTER_PREY_H |
|
2 |
#define _HUNTER_PREY_H |
|
3 |
|
|
4 |
#include <inttypes.h> |
|
5 |
|
|
6 |
/**** This file should not be edited! ****/ |
|
7 |
|
|
8 |
/* |
|
9 |
* The packet structure is 2 bytes |
|
10 |
* byte 0 is the action, which is one of the values below |
|
11 |
* byte 1 is the robot id |
|
12 |
*/ |
|
13 |
|
|
14 |
#define HUNTER_PREY_ACTION_TAG 'T' |
|
15 |
#define HUNTER_PREY_ACTION_ACK 'A' |
|
16 |
|
|
17 |
unsigned char hunter_prey_tagged(int max_bom, int front_rangefinder); |
|
18 |
|
|
19 |
#endif |
branches/ir_branch/behaviors/hunter_prey/testbench/main.c | ||
---|---|---|
1 |
/* testbench for Lab 2 first checkpoint |
|
2 |
* determine whether robot under test complies with communication standard |
|
3 |
* to be conducted using XBee USB dongle |
|
4 |
*/ |
|
5 |
|
|
6 |
/* The tests shall be as follows |
|
7 |
* 1. Receive a TAG, send an ACK |
|
8 |
* - Robot passes if it sends a tag and changes to prey state |
|
9 |
* 2. Send a TAG, receive an ACK |
|
10 |
* - Pass if sends ACK, changes to wait state, then hunter state |
|
11 |
* 3. Receive TAG, send slightly delayed (< 1s) ACK |
|
12 |
* - Pass if sends one and only one TAG packet (and changes state appropriately) |
|
13 |
* 4. Receive TAG, do not send ACK |
|
14 |
* - Pass if sends one and only one TAG packet (and does not change state) |
|
15 |
* 5. Receive TAG, send ACK to incorrect robot |
|
16 |
* - Pass if goes to wait state, then back to hunter state |
|
17 |
* 6. Simulate TAG from robot A to B, ACK from B to A |
|
18 |
* - Pass if ignores TAG, goes to wait then hunter in response to ACK |
|
19 |
*/ |
|
20 |
|
|
21 |
#include <stdlib.h> |
|
22 |
#include <stdio.h> |
|
23 |
#include <unistd.h> |
|
24 |
#include "../../libwireless/lib/wl_basic.h" |
|
25 |
#include "../../libwireless/lib/wireless.h" |
|
26 |
#include "hunter_prey.h" |
|
27 |
#include <time.h> |
|
28 |
|
|
29 |
#define TYPE 42 // packet type for wireless communication |
|
30 |
#define ROBOTID 255 // make up a robot id because the PC doesn't have one |
|
31 |
|
|
32 |
|
|
33 |
void waitKey() { |
|
34 |
unsigned char buf[10]; |
|
35 |
|
|
36 |
//read from stdin |
|
37 |
while(read(0, buf, 10)==10) { |
|
38 |
printf("!"); |
|
39 |
fflush(stdout); |
|
40 |
} |
|
41 |
|
|
42 |
while(getchar()==-1); |
|
43 |
} |
|
44 |
|
|
45 |
int main(int argc, char *argv[]) |
|
46 |
{ |
|
47 |
char send_buffer[2]; // holds data to send |
|
48 |
int data_length; // length of data received |
|
49 |
unsigned char *packet_data; // data received |
|
50 |
int ret; |
|
51 |
|
|
52 |
unsigned int channel = 0xF; |
|
53 |
|
|
54 |
struct timespec delay8, rem; |
|
55 |
|
|
56 |
if(argc > 1) { |
|
57 |
channel = atoi(argv[1]); |
|
58 |
} |
|
59 |
|
|
60 |
printf("using wireless channel %d\n", channel); |
|
61 |
|
|
62 |
delay8.tv_sec = 2; |
|
63 |
delay8.tv_nsec = 800000000; |
|
64 |
|
|
65 |
wl_set_com_port("/dev/ttyUSB0"); |
|
66 |
// set up wireless |
|
67 |
ret = wl_basic_init_default(); |
|
68 |
|
|
69 |
if(ret) { |
|
70 |
printf("ERROR: wl_basic_init_default returned %d\n", ret); |
|
71 |
return ret; |
|
72 |
} |
|
73 |
|
|
74 |
ret = wl_set_channel(channel); |
|
75 |
|
|
76 |
if(ret) { |
|
77 |
printf("ERROR: set channel failed! %d\n", ret); |
|
78 |
return ret; |
|
79 |
} |
|
80 |
|
|
81 |
printf("Testing communications\n\n"); |
|
82 |
|
|
83 |
// Receive TAG, send ACK |
|
84 |
printf("Receive TAG, send ACK... "); |
|
85 |
fflush(stdout); |
|
86 |
// Wait until we receive a packet |
|
87 |
while (!(packet_data = wl_basic_do_default(&data_length))); |
|
88 |
|
|
89 |
printf("got packet, validating and sending ack..."); |
|
90 |
fflush(stdout); |
|
91 |
|
|
92 |
if (data_length > 2) |
|
93 |
{ |
|
94 |
printf("Excessive TAG packet length... "); |
|
95 |
fflush(stdout); |
|
96 |
} |
|
97 |
|
|
98 |
if (data_length >= 2 && packet_data[0] == HUNTER_PREY_ACTION_TAG) |
|
99 |
{ |
|
100 |
// send back an ACK |
|
101 |
send_buffer[0] = HUNTER_PREY_ACTION_ACK; |
|
102 |
send_buffer[1] = packet_data[1]; |
|
103 |
printf("sending ack intended for robot %d\n", packet_data[1]); |
|
104 |
fflush(stdout); |
|
105 |
wl_basic_send_global_packet(TYPE, send_buffer, 2); |
|
106 |
|
|
107 |
printf("PASSED\n"); |
|
108 |
} |
|
109 |
else |
|
110 |
printf("FAILED\n"); |
|
111 |
|
|
112 |
printf("robot should be prey\nPress enter to continue...\n"); |
|
113 |
waitKey(); |
|
114 |
|
|
115 |
// Send a TAG, receive an ACK |
|
116 |
printf("Send TAG, wait for ACK... "); |
|
117 |
fflush(stdout); |
|
118 |
|
|
119 |
send_buffer[0] = HUNTER_PREY_ACTION_TAG; |
|
120 |
send_buffer[1] = ROBOTID; |
|
121 |
// robot number stays the same |
|
122 |
wl_basic_send_global_packet(TYPE, send_buffer, 2); |
|
123 |
|
|
124 |
// Wait for an ACK |
|
125 |
ret = nanosleep(&delay8, &rem); // wait for 800 ms before sending ACK |
|
126 |
|
|
127 |
while(ret) { |
|
128 |
// printf("nanosleep not done, needs to wait %ld more\n", rem.tv_nsec); |
|
129 |
ret = nanosleep(&rem, &rem); |
|
130 |
} |
|
131 |
|
|
132 |
data_length = -1; |
|
133 |
packet_data = wl_basic_do_default(&data_length); |
|
134 |
|
|
135 |
// Check ACK for presence and correctness |
|
136 |
if (!packet_data || data_length < 2 || |
|
137 |
packet_data[0] != HUNTER_PREY_ACTION_ACK || |
|
138 |
packet_data[1] != ROBOTID) { |
|
139 |
printf("FAILED, packet=%p, len=%d\n", packet_data, data_length); |
|
140 |
if(data_length >= 2) { |
|
141 |
printf("\tpacket = [%c, %d]\n",packet_data[0], packet_data[1]); |
|
142 |
} |
|
143 |
} |
|
144 |
else |
|
145 |
printf("PASSED\n"); |
|
146 |
|
|
147 |
printf("Robot should be Hunter\nPress enter to continue...\n"); |
|
148 |
|
|
149 |
waitKey(); |
|
150 |
|
|
151 |
// Receive a TAG, send a delayed ACK |
|
152 |
printf("Receive a TAG, send a delayed ACK... "); |
|
153 |
fflush(stdout); |
|
154 |
|
|
155 |
while (!(packet_data = wl_basic_do_default(&data_length))); |
|
156 |
|
|
157 |
if (data_length >= 2 && packet_data[0] == HUNTER_PREY_ACTION_TAG) |
|
158 |
{ |
|
159 |
printf("got TAG, waiting..."); |
|
160 |
fflush(stdout); |
|
161 |
// wait before sending ACK back |
|
162 |
//usleep(900000); |
|
163 |
delay8.tv_sec = 0; |
|
164 |
ret = nanosleep(&delay8, &rem); // wait for 800 ms before sending ACK |
|
165 |
|
|
166 |
while(ret) { |
|
167 |
printf("."); |
|
168 |
fflush(stdout);// printf("nanosleep not done, needs to wait %ld more\n", rem.tv_nsec); |
|
169 |
ret = nanosleep(&rem, &rem); |
|
170 |
} |
|
171 |
|
|
172 |
|
|
173 |
if (wl_basic_do_default(&data_length)) |
|
174 |
printf("FAILED, got another TAG too soon\n"); |
|
175 |
else |
|
176 |
{ |
|
177 |
// send packet |
|
178 |
send_buffer[0] = HUNTER_PREY_ACTION_ACK; |
|
179 |
send_buffer[1] = packet_data[1]; |
|
180 |
wl_basic_send_global_packet(TYPE, send_buffer, 2); |
|
181 |
|
|
182 |
printf("PASSED\n"); |
|
183 |
} |
|
184 |
} |
|
185 |
|
|
186 |
else |
|
187 |
printf("FAILED\n"); |
|
188 |
|
|
189 |
|
|
190 |
printf("robot should be prey.\n Press Enter...\n"); |
|
191 |
waitKey(); |
|
192 |
|
|
193 |
printf("sending courtesy tag..."); |
|
194 |
fflush(stdout); |
|
195 |
send_buffer[0] = HUNTER_PREY_ACTION_TAG; |
|
196 |
send_buffer[1] = ROBOTID; |
|
197 |
// robot number stays the same |
|
198 |
wl_basic_send_global_packet(TYPE, send_buffer, 2); |
|
199 |
printf("done.\nwaiting for ack..."); |
|
200 |
fflush(stdout); |
|
201 |
|
|
202 |
while (!(packet_data = wl_basic_do_default(&data_length))); |
|
203 |
|
|
204 |
if (!packet_data || data_length < 2 || |
|
205 |
packet_data[0] != HUNTER_PREY_ACTION_ACK || |
|
206 |
packet_data[1] != ROBOTID) |
|
207 |
printf("FAILED, packet=%p, len=%d\n", packet_data, data_length); |
|
208 |
else |
|
209 |
printf("done\n"); |
|
210 |
|
|
211 |
|
|
212 |
// Receive a TAG, never send an ACK |
|
213 |
printf("Receive TAG, never send ACK... "); |
|
214 |
fflush(stdout); |
|
215 |
|
|
216 |
while (!(packet_data = wl_basic_do_default(&data_length))); |
|
217 |
|
|
218 |
if (data_length >= 2 && packet_data[0] == HUNTER_PREY_ACTION_TAG) |
|
219 |
{ |
|
220 |
|
|
221 |
printf("got TAG, monitoring for 5 seconds\n"); |
|
222 |
fflush(stdout); |
|
223 |
delay8.tv_sec = 5; |
|
224 |
delay8.tv_nsec = 0; |
|
225 |
|
|
226 |
ret = nanosleep(&delay8, &rem); // wait for 5 secs |
|
227 |
while(ret) { |
|
228 |
// printf("nanosleep not done, needs to wait %ld more\n", rem.tv_nsec); |
|
229 |
ret = nanosleep(&rem, &rem); |
|
230 |
} |
|
231 |
|
|
232 |
if (wl_basic_do_default(&data_length)) |
|
233 |
printf("FAILED, robot is spamming\n"); |
|
234 |
else |
|
235 |
printf("PASSED\n"); |
|
236 |
} |
|
237 |
|
|
238 |
else |
|
239 |
printf("FAILED\n"); |
|
240 |
|
|
241 |
printf("robot should be hunter.\nPress enter...\n"); |
|
242 |
|
|
243 |
waitKey(); |
|
244 |
|
|
245 |
// Receive TAG, send ACK to incorrect robot |
|
246 |
printf("Receive TAG, send ACK to incorrect robot... "); |
|
247 |
fflush(stdout); |
|
248 |
|
|
249 |
// Wait until we receive a packet |
|
250 |
while (!(packet_data = wl_basic_do_default(&data_length))); |
|
251 |
|
|
252 |
if (data_length >= 2 && packet_data[0] == HUNTER_PREY_ACTION_TAG) |
|
253 |
{ |
|
254 |
// send back an ACK |
|
255 |
send_buffer[0] = HUNTER_PREY_ACTION_ACK; |
|
256 |
send_buffer[1] = packet_data[1] + 1; |
|
257 |
wl_basic_send_global_packet(TYPE, send_buffer, 2); |
|
258 |
|
|
259 |
printf("PASSED\n"); |
|
260 |
} |
|
261 |
else |
|
262 |
printf("FAILED\n"); |
|
263 |
|
|
264 |
|
|
265 |
printf("robot should wait and then still be hunter.\nPress Enter...\n"); |
|
266 |
waitKey(); |
|
267 |
|
|
268 |
// Simulate TAG from robot A to B, ACK from robot B to A |
|
269 |
printf("Send TAG from robot A to B, ACK from B to A... "); |
|
270 |
fflush(stdout); |
|
271 |
|
|
272 |
// TAG |
|
273 |
send_buffer[0] = HUNTER_PREY_ACTION_TAG; |
|
274 |
send_buffer[1] = packet_data[1] - 1; // robot other than testee |
|
275 |
wl_basic_send_global_packet(TYPE, send_buffer, 2); |
|
276 |
|
|
277 |
// ACK |
|
278 |
send_buffer[0] = HUNTER_PREY_ACTION_ACK; |
|
279 |
// send_buffer[1] stays the same |
|
280 |
wl_basic_send_global_packet(TYPE, send_buffer, 2); |
|
281 |
|
|
282 |
if (wl_basic_do_default(&data_length)) |
|
283 |
printf("FAILED\n"); |
|
284 |
else |
|
285 |
printf("PASSED\n"); |
|
286 |
|
|
287 |
printf("robot should be waiting\n"); |
|
288 |
|
|
289 |
return 0; |
|
290 |
} |
|
291 |
|
branches/ir_branch/behaviors/hunter_prey/testbench/hunter_prey.h | ||
---|---|---|
1 |
#ifndef _HUNTER_PREY_H |
|
2 |
#define _HUNTER_PREY_H |
|
3 |
|
|
4 |
#include <inttypes.h> |
|
5 |
|
|
6 |
/* |
|
7 |
* The packet structure is 2 bytes |
|
8 |
* byte 0 is the action, which is one of the values below |
|
9 |
* byte 1 is the robot id |
|
10 |
*/ |
|
11 |
|
|
12 |
#define HUNTER_PREY_ACTION_TAG 'T' |
|
13 |
#define HUNTER_PREY_ACTION_ACK 'A' |
|
14 |
|
|
15 |
uint8_t hunter_prey_tagged(int max_bom, int front_rangefinder); |
|
16 |
|
|
17 |
#endif |
branches/ir_branch/behaviors/hunter_prey/testbench/Makefile | ||
---|---|---|
1 |
CC = gcc |
|
2 |
CFLAGS = -Wall -g |
|
3 |
|
|
4 |
all: testbench |
|
5 |
|
|
6 |
testbench: *.c ../../libwireless/lib/*.c |
|
7 |
$(CC) $(CFLAGS) *.c -L../../libwireless/lib -o testbench -DWL_DEBUG -lwireless -lpthread -ggdb |
|
8 |
|
|
9 |
clean: |
|
10 |
rm -f *.o testbench ../lib/*.o |
|
11 |
|
branches/ir_branch/behaviors/hunter_prey/abenico/smart_run_around_fsm.c | ||
---|---|---|
1 |
#include <dragonfly_lib.h> |
|
2 |
#include "smart_run_around_fsm.h" |
|
3 |
|
|
4 |
void run_around_init(void) |
|
5 |
{ |
|
6 |
//range_init(); |
|
7 |
//orb_init(); |
|
8 |
|
|
9 |
state = SRA_FORWARD; // start out moving forward |
|
10 |
// initialize rangefinder values to 0 |
|
11 |
d1 = 0, d2 = 0, d3 = 0, d4 = 0, d5 = 0; |
|
12 |
} |
|
13 |
|
|
14 |
/* evaluate rangefinder input and update state |
|
15 |
* call this function as often as possible to avoid collisions |
|
16 |
*/ |
|
17 |
void run_around_FSM(void) |
|
18 |
{ |
|
19 |
/* TODO: find a better way to handle rangefinder input |
|
20 |
* robot should deal with -1s (obstacles too close or too far to detect) |
|
21 |
* in a way that keeps it from crashing or driving in circles |
|
22 |
*/ |
|
23 |
// do not update distances when rangefinders return -1 |
|
24 |
// otherwise update distances with new rangefinder values |
|
25 |
int16_t temp; |
|
26 |
|
|
27 |
temp = range_read_distance(IR1); |
|
28 |
d1 = (temp == -1) ? d1 : temp; |
|
29 |
|
|
30 |
temp = range_read_distance(IR2); |
|
31 |
d2 = (temp == -1) ? d2 : temp; |
|
32 |
|
|
33 |
temp = range_read_distance(IR3); |
|
34 |
d3 = (temp == -1) ? d3 : temp; |
|
35 |
|
|
36 |
temp = range_read_distance(IR4); |
|
37 |
d4 = (temp == -1) ? d4 : temp; |
|
38 |
|
|
39 |
temp = range_read_distance(IR5); |
|
40 |
d5 = (temp == -1) ? d5 : temp; |
|
41 |
|
|
42 |
// update state based on rangefinder input |
|
43 |
if (d2 < IR2_DANGER) // avoid frontal collision by turning in place |
|
44 |
state = SRA_SPIN; |
|
45 |
/* nowhere to turn, so don't |
|
46 |
* will probably need to turn around soon, but not yet |
|
47 |
*/ |
|
48 |
else if (d1 < IR13_DANGER && d3 < IR13_DANGER) |
|
49 |
state = SRA_FORWARD; |
|
50 |
// avoid left-side collision by turning right |
|
51 |
else if (d1 < IR13_DANGER || d5 < IR45_DANGER) |
|
52 |
state = SRA_RIGHT; |
|
53 |
// avoid right-side collision by turning left |
|
54 |
else if (d3 < IR13_DANGER || d4 < IR45_DANGER) |
|
55 |
state = SRA_LEFT; |
|
56 |
else if (d2 < IR2_INTEREST) // should turn to avoid obstacle up ahead |
|
57 |
{ |
|
58 |
if (d3 >= d1) // more room on right |
|
59 |
state = SRA_RIGHT; |
|
60 |
else // more room on left |
|
61 |
state = SRA_LEFT; |
|
62 |
} |
|
63 |
else // no obstacles close by, so keep going straight |
|
64 |
state = SRA_FORWARD; |
|
65 |
|
|
66 |
/* Debugging via USB output */ |
|
67 |
/* usb_puts("IR1: "); */ |
|
68 |
/* usb_puti(d1); */ |
|
69 |
/* usb_puts(" IR2: "); */ |
|
70 |
/* usb_puti(d2); */ |
|
71 |
/* usb_puts(" IR3: "); */ |
|
72 |
/* usb_puti(d3); */ |
|
73 |
/* usb_puts(" IR4: "); */ |
|
74 |
/* usb_puti(d4); */ |
|
75 |
/* usb_puts(" IR5: "); */ |
|
76 |
/* usb_puti(d5); */ |
|
77 |
/* usb_puts("\n\r"); */ |
|
78 |
|
|
79 |
evaluate_state(); // take action on updated state |
|
80 |
} |
|
81 |
|
|
82 |
// behave according to current state |
|
83 |
// TODO: adjust speeds after testing |
|
84 |
void evaluate_state(void) |
|
85 |
{ |
|
86 |
switch (state) |
|
87 |
{ |
|
88 |
case SRA_FORWARD: |
|
89 |
//orb_set_color(GREEN); |
|
90 |
move(220, 0); // drive straight forward |
|
91 |
break; |
|
92 |
case SRA_LEFT: |
|
93 |
//orbs_set_color(GREEN, YELLOW); // green on left side |
|
94 |
move(HALF_SPD, NRML_TURN); // drive forward and to the left |
|
95 |
break; |
|
96 |
case SRA_RIGHT: |
|
97 |
//orbs_set_color(YELLOW, GREEN); // green on right side |
|
98 |
move(HALF_SPD, -NRML_TURN); // drive forward and to the right |
|
99 |
break; |
|
100 |
case SRA_SPIN: |
|
101 |
//orb_set_color(RED); |
|
102 |
move(0, NRML_TURN); // spin CCW without traveling |
|
103 |
break; |
|
104 |
default: // should never reach this |
|
105 |
//orb_set_color(PURPLE); |
|
106 |
move(0, 0); // stop completely |
|
107 |
} |
|
108 |
} |
|
109 |
|
branches/ir_branch/behaviors/hunter_prey/abenico/hunter_prey.h | ||
---|---|---|
1 |
#ifndef _HUNTER_PREY_H |
|
2 |
#define _HUNTER_PREY_H |
|
3 |
|
|
4 |
#include <inttypes.h> |
|
5 |
|
|
6 |
/* |
|
7 |
* The packet structure is 2 bytes |
|
8 |
* byte 0 is the action, which is one of the values below |
|
9 |
* byte 1 is the robot id |
|
10 |
*/ |
|
11 |
|
|
12 |
#define HUNTER_PREY_ACTION_TAG 'T' |
|
13 |
#define HUNTER_PREY_ACTION_ACK 'A' |
|
14 |
|
|
15 |
uint8_t hunter_prey_tagged(int max_bom, int front_rangefinder); |
|
16 |
|
|
17 |
#endif |
branches/ir_branch/behaviors/hunter_prey/abenico/smart_run_around_fsm.h | ||
---|---|---|
1 |
// smart_run_around_fsm.h |
|
2 |
// required to run Smart Run Around functions |
|
3 |
// declare functions and global variables |
|
4 |
|
|
5 |
#ifndef _RUN_AROUND_FSM_H_ |
|
6 |
#define _RUN_AROUND_FSM_H_ |
|
7 |
|
|
8 |
// states (robot shall never move in reverse) |
|
9 |
// these constants may be changed (but can't overlap) without effect |
|
10 |
#define SRA_FORWARD 0 // drive straight forward |
|
11 |
#define SRA_LEFT 1 // drive forward and to the left |
|
12 |
#define SRA_RIGHT 2 // drive forward and to the right |
|
13 |
#define SRA_SPIN 3 // turn without traveling (last resort if otherwise stuck) |
|
14 |
|
|
15 |
/* conditions on rangefinders (in mm) informing state changes |
|
16 |
* distances are 50 greater than in real life, cannot be smaller than 100 |
|
17 |
* naming format: SENSOR_URGENCY |
|
18 |
* changing these constants affects robot operation |
|
19 |
*/ |
|
20 |
#define IR2_DANGER 150 // 10 cm: dangerously close to front |
|
21 |
#define IR13_DANGER 200 // 15 cm: dangerously close to sides (looking ahead) |
|
22 |
#define IR2_INTEREST 300 // 25 cm: notably close to front |
|
23 |
#define IR45_DANGER 150 // dangerously close to side (looking sideways) |
|
24 |
|
|
25 |
uint8_t state; // current state of FSM: SRA_FORWARD, SRA_LEFT, SRA_RIGHT, SRA_SPIN |
|
26 |
int16_t d1, d2, d3, d4, d5; // values returned by rangefinders |
|
27 |
|
|
28 |
// initialize rangefinders and global variables |
|
29 |
void run_around_init(void); |
|
30 |
|
|
31 |
/* evaluate rangefinder input and update state |
|
32 |
* call this function as often as possible to avoid collisions |
|
33 |
*/ |
|
34 |
void run_around_FSM(void); |
|
35 |
|
|
36 |
// behave according to current state |
|
37 |
void evaluate_state(void); |
|
38 |
|
|
39 |
#endif |
|
40 |
|
branches/ir_branch/behaviors/hunter_prey/abenico/Makefile | ||
---|---|---|
1 |
# this is a local makefile |
|
2 |
|
|
3 |
# Relative path to the root directory (containing lib directory) |
|
4 |
ifndef COLONYROOT |
|
5 |
COLONYROOT := .. |
|
6 |
|
|
7 |
# Target file name (without extension). |
|
8 |
TARGET = main |
|
9 |
|
|
10 |
# Uncomment this to use the wireless library |
|
11 |
USE_WIRELESS = 1 |
|
12 |
|
|
13 |
# com1 = serial port. Use lpt1 to connect to parallel port. |
|
14 |
AVRDUDE_PORT = $(shell if uname -s |grep -i w32 >/dev/null; then echo 'COM4:'; else echo '/dev/ttyUSB0'; fi) |
|
15 |
|
|
16 |
else |
|
17 |
COLONYROOT := ../$(COLONYROOT) |
|
18 |
endif |
|
19 |
|
|
20 |
include $(COLONYROOT)/Makefile |
branches/ir_branch/behaviors/hunter_prey/abenico/main.c | ||
---|---|---|
1 |
#include <dragonfly_lib.h> |
|
2 |
#include <wireless.h> |
|
3 |
#include <wl_basic.h> |
|
4 |
#include "smart_run_around_fsm.h" |
|
5 |
#include "hunter_prey.h" |
|
6 |
|
|
7 |
#define CHAN 0xC |
|
8 |
#define ACK_PAUSE 5000 |
|
9 |
|
|
10 |
#define ROBOT_HUNTER 0 |
|
11 |
#define ROBOT_PREY 1 |
|
12 |
#define ROBOT_TAGGED 2 |
|
13 |
#define ROBOT_IDLE 3 |
|
14 |
|
|
15 |
void packet_receive(unsigned char* packet, int length); |
|
16 |
|
|
17 |
volatile uint8_t robotState; // current state |
|
18 |
volatile uint8_t tagger; // id of tagging robot |
|
19 |
uint8_t id; // my robot's id |
|
20 |
|
|
21 |
void test_bom(void) { |
|
22 |
int i; |
|
23 |
int val; |
|
24 |
|
|
25 |
while(1) { |
|
26 |
bom_refresh(BOM_ALL); |
|
27 |
|
|
28 |
for(i=0; i<16; i++) { |
|
29 |
val = bom_get(i); |
|
30 |
usb_puti(val); |
|
31 |
usb_putc(' '); |
|
32 |
} |
|
33 |
|
|
34 |
usb_puts("| "); |
|
35 |
|
|
36 |
usb_puti(range_read_distance (IR1)); |
|
37 |
usb_putc(' '); |
|
38 |
usb_puti(range_read_distance (IR2)); |
|
39 |
usb_putc(' '); |
|
40 |
usb_puti(range_read_distance (IR3)); |
|
41 |
usb_putc(' '); |
|
42 |
usb_puti(range_read_distance (IR4)); |
Also available in: Unified diff