Statistics
| Revision:

root / trunk / code / behaviors / formation_control / circle / circle.c @ 1796

History | View | Annotate | Download (21.7 KB)

1 1749 azirbel
2 1749 azirbel
/*** PROGRAM INFORMATION ***
3 1749 azirbel
4 1749 azirbel
          This program assembles a group of robots into a circle and allows them movement
5 1749 azirbel
        within that formation.  Robots should be able to break formation and travel as a
6 1749 azirbel
        line, readjust in the face of obstacles, and reform if conditions are necessary.
7 1749 azirbel
8 1749 azirbel
          The program begins waiting for a button press.  When pressed, a robot assumes the
9 1749 azirbel
        BEACON position, which means that it is the robot in the center of the circle and
10 1749 azirbel
        therefore in charge.  It then gathers robots around it by sending them commands.
11 1749 azirbel
        This code is executed using two finite state machines, nested inside one another.
12 1749 azirbel
        One controls the overall state of the robot (whether it is a BEACON, an EDGE, or
13 1749 azirbel
        WAITING, for example).
14 1749 azirbel
15 1749 azirbel
          This code should be implemented so that most useful functions are built in to the
16 1749 azirbel
        machine.  For example, the BEACON robot should be able to call methods such as
17 1749 azirbel
        CircleUp() to gather robots around it, and Move(distance) to move the circle group
18 1749 azirbel
        all at once.
19 1749 azirbel
20 1749 azirbel
          This Code is the property of the Carnegie Mellon Robotics Club and is being used
21 1749 azirbel
        to test formation control in a low-cost robot colony.  Thanks to all members of
22 1749 azirbel
        RoboClub, especially Colony president John Sexton and the ever-present Chris Mar.
23 1749 azirbel
24 1749 azirbel
        AUTHORS: James Carroll, Steve DeVincentis, Hanzhang (Echo) Hu, Nico Paris, Joel Rey,
25 1749 azirbel
         Reva Street, Alex Zirbel                                                         */
26 1749 azirbel
27 1749 azirbel
28 1594 azirbel
#include <dragonfly_lib.h>
29 1594 azirbel
#include <wl_basic.h>
30 1594 azirbel
#include <encoders.h>
31 1594 azirbel
#include "circle.h"
32 1594 azirbel
33 1749 azirbel
/*** TODO: ***
34 1626 gnagaraj
35 1749 azirbel
        - Transform the code into a method-based state machine that uses the procedural state
36 1749 azirbel
                machines, which are hardcoded and hard to edit, as a backup.
37 1749 azirbel
        - Implement a drive straight method for use in keeping the robots more accurate as a
38 1749 azirbel
                group.
39 1749 azirbel
        - Fix the approach method: good robots usually work well, but bad robots often have
40 1749 azirbel
                errors which might be avoidable with the use of error checking.
41 1749 azirbel
        - Make robots more robust: packages are often lost, which throws the entire procedural
42 1749 azirbel
                nature of the program off.
43 1749 azirbel
        - Consider using the center bot to check distances
44 1749 azirbel
        - More testing is always good and necessary.                                        */
45 1691 azirbel
46 1749 azirbel
/*** BOT LOG ***
47 1691 azirbel
48 1749 azirbel
        4-1-2010: BOT 7 as BEACON and BOT 1 as EDGE worked extremely well.
49 1749 azirbel
        4-2-2010: BOT 7 and BOT 14 worked extremely well, no matter states.  BOT 1 started
50 1749 azirbel
                well, but malfunctioned later.                                                */
51 1691 azirbel
52 1749 azirbel
/*** TERMINOLOGY ***
53 1691 azirbel
54 1749 azirbel
        WAITINGSTATE:
55 1749 azirbel
                The robot waits to be given a signal to do something.  Wireless is on, in
56 1749 azirbel
                case the robot is called on to turn into an EDGE.  The color should be LIME
57 1749 azirbel
                or YELLOW-GREEN.
58 1594 azirbel
59 1749 azirbel
        BEACON_CONTROL:
60 1749 azirbel
                The code that executes commands when a robot is turned to BEACON mode.  This
61 1749 azirbel
                code may run predefined methods for simplicity.  One goal is to make these
62 1749 azirbel
                methods change the robot turn to to BEACON_MACHINE mode for a while, and then
63 1749 azirbel
                return to the CONTROL code where they left off.
64 1594 azirbel
65 1749 azirbel
        EDGE_CONTROL:
66 1749 azirbel
                Like BEACON_CONTROL, executes whatever orders are required of the robot as an
67 1749 azirbel
                EDGE.
68 1594 azirbel
69 1749 azirbel
        BEACON_MACHINE:
70 1749 azirbel
                A hardcoded list of functions which the robot is capable of running through.
71 1749 azirbel
                Consists of a finite state machine, where the robot executes a set of commands
72 1749 azirbel
                in a procedural manner and then returns to wherever it was in the control code.
73 1594 azirbel
74 1749 azirbel
        EDGE_MACHINE:
75 1749 azirbel
                Like the BEACON_MACHINE, but contains the same sort of procedural information
76 1749 azirbel
                for EDGE robots.
77 1749 azirbel
78 1749 azirbel
        END:
79 1749 azirbel
                A terminal state of the machine, where the robot just sits and waits.  The
80 1749 azirbel
                color should be GREEN and WHITE.
81 1749 azirbel
82 1749 azirbel
83 1749 azirbel
        TYPES OF WIRELESS PACKETS:
84 1749 azirbel
                CIRCLE_ACTION_EXIST 'E'
85 1749 azirbel
                CIRCLE_ACTION_POSITION 'P'
86 1749 azirbel
                CIRCLE_ACTION_ACK 'A'
87 1749 azirbel
                        A general acknowledgement package.
88 1749 azirbel
                CIRCLE_ACTION_DONE 'D'
89 1749 azirbel
                        Used by robots to tell when they have finished their action.
90 1749 azirbel
                CIRCLE_ACTION_GOTYOU 'G'
91 1749 azirbel
                        Used by the BEACON to tell a robot when it has been checked off.
92 1749 azirbel
                        At this point, the EDGE has been recognized.  Used for times when
93 1749 azirbel
                        all EDGE robots have to communicate to the center via the spam method.
94 1749 azirbel
                CIRCLE_ACTION_FORWARD 'F'
95 1749 azirbel
                        The BEACON tells the rest of the robots to move forward.
96 1749 azirbel
                CIRCLE_CLAIM_CENTER 'C'
97 1749 azirbel
                        Sent out by a robot when it takes over as BEACON.                */
98 1749 azirbel
99 1749 azirbel
100 1749 azirbel
101 1749 azirbel
int END = 100;
102 1749 azirbel
int WAITINGSTATE = 0;                /* Define some variables to keep track of the state machine.*/
103 1749 azirbel
int EDGE_CONTROL = 1;
104 1749 azirbel
int BEACON_CONTROL = 2;
105 1749 azirbel
int EDGE_MACHINE = 3;
106 1749 azirbel
int BEACON_MACHINE = 4;
107 1749 azirbel
108 1774 azirbel
int COUNT = 0;
109 1774 azirbel
int CIRCLEUP = 1;
110 1774 azirbel
int ORIENT = 2;
111 1774 azirbel
int DRIVE = 3;
112 1749 azirbel
113 1774 azirbel
int currentPos = 0;
114 1774 azirbel
int state = 0;
115 1774 azirbel
116 1774 azirbel
117 1720 azirbel
int timeout = 0;
118 1720 azirbel
int sending = 0;
119 1720 azirbel
int stop2 = 0;
120 1720 azirbel
struct vector slave_position;
121 1720 azirbel
int desired_max_bom;
122 1720 azirbel
int bom_max_counter;
123 1618 jmcarrol
124 1618 jmcarrol
125 1720 azirbel
void switch_sending(void)
126 1720 azirbel
{
127 1720 azirbel
        if(sending)
128 1720 azirbel
        {
129 1720 azirbel
                sending = 0;
130 1720 azirbel
                bom_off();
131 1720 azirbel
        }
132 1720 azirbel
        else
133 1720 azirbel
        {
134 1720 azirbel
                sending = 1;
135 1720 azirbel
                bom_on();
136 1720 azirbel
        }
137 1720 azirbel
}
138 1720 azirbel
139 1594 azirbel
void forward(int speed){                        // set the motors to this forward speed.
140 1594 azirbel
        motor_l_set(FORWARD,speed);
141 1594 azirbel
        motor_r_set(FORWARD,speed);
142 1594 azirbel
}
143 1594 azirbel
void left(int speed){                                // turn left at this speed.
144 1594 azirbel
        motor_l_set(FORWARD,speed);
145 1594 azirbel
        motor_r_set(BACKWARD,speed);
146 1594 azirbel
}
147 1594 azirbel
void right(int speed){
148 1594 azirbel
        motor_l_set(BACKWARD,speed);
149 1594 azirbel
        motor_r_set(FORWARD,speed);
150 1594 azirbel
}
151 1749 azirbel
void stop(void){                        // could be set to motors_off(), or just use this as an alternative.
152 1749 azirbel
        motor_l_set(BACKWARD,0);        // stop() is better - motors_off() creates a slight delay to turn them back on.
153 1594 azirbel
        motor_r_set(FORWARD,0);
154 1594 azirbel
}
155 1594 azirbel
void setforward(int spd1, int spd2){
156 1594 azirbel
        motor_l_set(FORWARD,spd1);
157 1594 azirbel
        motor_r_set(FORWARD,spd2);
158 1594 azirbel
}
159 1594 azirbel
void backward(int speed){
160 1594 azirbel
        motor_l_set(BACKWARD, speed);
161 1594 azirbel
        motor_r_set(BACKWARD, speed);
162 1594 azirbel
}
163 1594 azirbel
int get_distance(void){                                // takes an averaged reading of the front rangefinder
164 1594 azirbel
        int temp,distance,kk=5;                        // kk sets this to 5 readings.
165 1594 azirbel
        distance =0;
166 1594 azirbel
        for (int i=0; i<kk; i++){
167 1594 azirbel
                temp = range_read_distance(IR2);
168 1594 azirbel
                if (temp == -1)
169 1594 azirbel
                {
170 1594 azirbel
                        //temp=0;
171 1594 azirbel
                        i--;
172 1594 azirbel
                }
173 1594 azirbel
                else
174 1594 azirbel
                        distance+= temp;
175 1594 azirbel
                delay_ms(3);
176 1594 azirbel
        }
177 1594 azirbel
        if (kk>0)
178 1594 azirbel
                return (int)(distance/kk);
179 1594 azirbel
        else
180 1594 azirbel
                return 0;
181 1594 azirbel
}
182 1618 jmcarrol
183 1724 azirbel
/* Sends a global packet with two arguments */
184 1724 azirbel
void send2(char arg0, char arg1)
185 1720 azirbel
{
186 1722 azirbel
        char send_buffer[2];
187 1724 azirbel
        send_buffer[0]=arg0;
188 1724 azirbel
        send_buffer[1]=arg1;
189 1720 azirbel
        wl_basic_send_global_packet(42,send_buffer,2);
190 1720 azirbel
}
191 1618 jmcarrol
192 1724 azirbel
/* Sends a global packet with three arguments */
193 1724 azirbel
void send3(char arg0, char arg1, char arg2)
194 1724 azirbel
{
195 1725 azirbel
        char send_buffer[3];
196 1724 azirbel
        send_buffer[0]=arg0;
197 1724 azirbel
        send_buffer[1]=arg1;
198 1724 azirbel
        send_buffer[2]=arg2;
199 1749 azirbel
        wl_basic_send_global_packet(42,send_buffer,3);
200 1724 azirbel
}
201 1724 azirbel
202 1639 azirbel
/*
203 1639 azirbel
        Orients the robot so that it is facing the beacon (or the broadcasting BOM).
204 1639 azirbel
205 1626 gnagaraj
*/
206 1776 azirbel
void aboutFace(int goal)
207 1618 jmcarrol
{
208 1796 azirbel
        int goala = goal;
209 1796 azirbel
        int goalb = goal + 8;                        // the inverse of the goal direction, across the BOM.
210 1796 azirbel
        if(goalb >= 16) { goalb -= 16; }
211 1776 azirbel
212 1796 azirbel
        int inv = 0;
213 1796 azirbel
        if(goala > goalb)
214 1796 azirbel
        {
215 1796 azirbel
                goala = goalb;
216 1796 azirbel
                goalb = goal;
217 1796 azirbel
                inv = 1;
218 1796 azirbel
        }
219 1796 azirbel
220 1627 gnagaraj
        orb1_set_color(BLUE);                        // BLUE and PURPLE
221 1627 gnagaraj
        left(220);
222 1627 gnagaraj
        while(1)
223 1618 jmcarrol
        {
224 1796 azirbel
                // bomNum is the current maximum reading
225 1627 gnagaraj
                bom_refresh(BOM_ALL);
226 1796 azirbel
                int bomNum = bom_get_max();
227 1776 azirbel
                if(bomNum == goal)                                // when it's turned the right way, stop
228 1618 jmcarrol
                {
229 1627 gnagaraj
                        timeout = 0;
230 1796 azirbel
                        stop();
231 1639 azirbel
                        break;                                // exits the while() loop to stop the method
232 1618 jmcarrol
                }
233 1639 azirbel
                else                                        // facing the wrong way
234 1618 jmcarrol
                {
235 1796 azirbel
236 1639 azirbel
                        if(bomNum == -1)
237 1639 azirbel
                        {
238 1627 gnagaraj
                                timeout++;
239 1627 gnagaraj
240 1639 azirbel
                                if(timeout > 5000)        // if it's been looking too long, move a little bit as it turns
241 1627 gnagaraj
                                {
242 1627 gnagaraj
                                        motor_r_set(FORWARD, 210);
243 1627 gnagaraj
                                        motor_l_set(BACKWARD, 190);
244 1627 gnagaraj
                                }
245 1627 gnagaraj
                        }
246 1796 azirbel
                        else if((bomNum >= goalb) || (bomNum < goala))
247 1627 gnagaraj
                        {
248 1796 azirbel
                                if(inv)
249 1796 azirbel
                                        right(200);
250 1796 azirbel
                                else
251 1796 azirbel
                                        left(200);
252 1627 gnagaraj
                                timeout = 0;
253 1627 gnagaraj
                        }
254 1627 gnagaraj
                        else
255 1627 gnagaraj
                        {
256 1796 azirbel
                                if(inv)
257 1796 azirbel
                                        left(200);
258 1796 azirbel
                                else
259 1796 azirbel
                                        right(200);
260 1627 gnagaraj
                                timeout = 0;
261 1627 gnagaraj
                        }
262 1618 jmcarrol
                }
263 1618 jmcarrol
        }
264 1627 gnagaraj
        return;
265 1618 jmcarrol
}
266 1618 jmcarrol
267 1626 gnagaraj
268 1639 azirbel
/*
269 1626 gnagaraj
    BLINK the given number times
270 1626 gnagaraj
*/
271 1717 azirbel
void blink(int num)
272 1717 azirbel
{
273 1594 azirbel
        for(int i = 0; i<num; i++)
274 1594 azirbel
        {
275 1594 azirbel
                orb_set_color(ORB_OFF);
276 1724 azirbel
                delay_ms(150);
277 1594 azirbel
                orb_set_color(RED);
278 1724 azirbel
                delay_ms(50);
279 1594 azirbel
        }
280 1594 azirbel
        orb_set_color(ORB_OFF);
281 1594 azirbel
}
282 1594 azirbel
283 1725 azirbel
/*
284 1725 azirbel
    BLINK slowly the given number times
285 1725 azirbel
*/
286 1725 azirbel
void slowblink(int num)
287 1725 azirbel
{
288 1725 azirbel
        for(int i = 0; i<num; i++)
289 1725 azirbel
        {
290 1725 azirbel
                orb_set_color(ORB_OFF);
291 1725 azirbel
                delay_ms(300);
292 1725 azirbel
                orb_set_color(RED);
293 1725 azirbel
                delay_ms(200);
294 1725 azirbel
        }
295 1725 azirbel
        orb_set_color(ORB_OFF);
296 1725 azirbel
}
297 1594 azirbel
298 1774 azirbel
void order(int action)
299 1774 azirbel
{
300 1774 azirbel
        currentPos++;
301 1774 azirbel
        send2(CIRCLE_EXECUTE, action);
302 1774 azirbel
        state = 20 + action;
303 1774 azirbel
}
304 1594 azirbel
305 1774 azirbel
void terminate(void)
306 1774 azirbel
{
307 1774 azirbel
        send2(CIRCLE_EXECUTE, 100);
308 1774 azirbel
        orb_set_color(GREEN);
309 1774 azirbel
        orb2_set_color(WHITE);
310 1774 azirbel
        while(1) ;
311 1774 azirbel
}
312 1626 gnagaraj
313 1626 gnagaraj
314 1639 azirbel
315 1774 azirbel
316 1639 azirbel
//*****************************************************************************************************************************************************************************************
317 1749 azirbel
//*****************************************************************************************************************************************************************************************
318 1749 azirbel
//*****************************************************************************************************************************************************************************************
319 1639 azirbel
320 1639 azirbel
321 1639 azirbel
/*
322 1749 azirbel
        A state machine with five states.  The robot starts out in WAITINGSTATE mode, from which
323 1749 azirbel
        it recieves a signal of some sort and moves to a different state.
324 1639 azirbel
*/
325 1594 azirbel
int main(void)
326 1594 azirbel
{
327 1594 azirbel
        /* Initialize dragonfly board */
328 1618 jmcarrol
            dragonfly_init(ALL_ON);
329 1618 jmcarrol
            /* Initialize the basic wireless library */
330 1618 jmcarrol
            wl_basic_init_default();
331 1749 azirbel
            /* Set the XBee channel to 24 - must be standard among robots */
332 1594 azirbel
        wl_set_channel(24);
333 1594 azirbel
334 1594 azirbel
        int robotid = get_robotid();
335 1749 azirbel
        int centerid = 0;                // once the EDGE gets the first signal from a center, it stores who the center is.
336 1749 azirbel
        int used[17];                        // stores a list of bots which are in the group by storing a "1" in the array if the robot of that index is in the group.
337 1749 azirbel
        for (int i=0; i<17; i++) used[i] = 0;                // initially, no robots in the group.
338 1749 azirbel
339 1749 azirbel
        int data_length;                // keeps track of the length of wireless packets received.
340 1594 azirbel
        unsigned char *packet_data=wl_basic_do_default(&data_length);
341 1594 azirbel
342 1749 azirbel
        int beacon_State=0;                // these variables keep track of the inner state machines in the procedural MACHINE states.
343 1635 sdevince
        int edge_State=0;
344 1749 azirbel
345 1610 azirbel
        int waitingCounter=0;
346 1749 azirbel
        int robotsReceived=0;                // an important variable that stores the size of the group.
347 1749 azirbel
        int offset = 20;                // offset for the approaching: how far off the rangefinders can be
348 1724 azirbel
        int time=0;
349 1749 azirbel
        int direction = 4;                // keeps track of which way robots are facing relative to the center
350 1749 azirbel
        int distance=1000;                // how far away the robot is.  Initialized to a large value to ensure that the robot doesn't think it is already the
351 1749 azirbel
                                                // right distance away.
352 1749 azirbel
        int onefoot = 250;                // how far away to stop.
353 1627 gnagaraj
354 1596 azirbel
        while(1)
355 1596 azirbel
        {
356 1626 gnagaraj
                bom_refresh(BOM_ALL);
357 1749 azirbel
358 1749 azirbel
                                /*
359 1749 azirbel
                                *******EXPECTED MOVES **********   (OUT OF DATE.  Will be updated once changes have been made.)
360 1749 azirbel
                                The designed movement:
361 1749 azirbel
                                 1. one center robot, several edge robots are on;
362 1749 azirbel
                                 2. center robots: button 1 is pressed;
363 1749 azirbel
                                 3. center robots: send global package telling edges that he exists;
364 1749 azirbel
                                 4. EDGE robots response with ACK.
365 1749 azirbel
                                 5. EDGE robots wait for center robots to finish counting (DONE package)
366 1749 azirbel
                                 6. EDGE robtos approach the center robtot and stop at the "onefoot" distance, send message to the center
367 1749 azirbel
                                */
368 1626 gnagaraj
369 1626 gnagaraj
370 1749 azirbel
                /* This is the MAIN SWITCH LOOP, which governs the overall status of the robot. */
371 1596 azirbel
                switch(state)
372 1596 azirbel
                {
373 1749 azirbel
374 1749 azirbel
375 1749 azirbel
                        /*
376 1749 azirbel
                                The WAITINGSTATE.  This state constantly checks for wireless packets,
377 1749 azirbel
                                and updates its state as soon as it receives a signal.
378 1626 gnagaraj
                        */
379 1749 azirbel
                        case 0:
380 1717 azirbel
381 1774 azirbel
                                orb_set_color(YELLOW);
382 1749 azirbel
                                packet_data=wl_basic_do_default(&data_length);
383 1749 azirbel
                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_CLAIM_CENTER)
384 1749 azirbel
                                {
385 1749 azirbel
                                        centerid = packet_data[1];
386 1749 azirbel
387 1775 azirbel
                                        state = 1;
388 1749 azirbel
                                }
389 1749 azirbel
390 1749 azirbel
                                if(button1_read())
391 1749 azirbel
                                {
392 1749 azirbel
                                        send2(CIRCLE_CLAIM_CENTER, robotid);         // becomes the center if button1 is clicked.
393 1775 azirbel
                                        state = 2;
394 1749 azirbel
                                }
395 1749 azirbel
396 1749 azirbel
                        break;
397 1749 azirbel
398 1749 azirbel
399 1749 azirbel
400 1749 azirbel
//***********************************************************************************************************************************************************************************
401 1749 azirbel
402 1749 azirbel
403 1749 azirbel
404 1749 azirbel
                        /*
405 1749 azirbel
                                The CONTROL for the EDGE state.  This sets a certain procedure to follow, in the form of simple
406 1749 azirbel
                                commands, for a robot to follow if it is set to an EDGE.
407 1749 azirbel
                        */
408 1749 azirbel
409 1749 azirbel
                        case 1:
410 1774 azirbel
                                orb_set_color(CYAN);
411 1774 azirbel
                                orb1_set_color(YELLOW);
412 1749 azirbel
413 1774 azirbel
                                int command = -1;
414 1774 azirbel
415 1774 azirbel
                                packet_data=wl_basic_do_default(&data_length);
416 1774 azirbel
                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_EXECUTE)
417 1774 azirbel
                                {
418 1774 azirbel
                                        command = packet_data[1];
419 1774 azirbel
                                }
420 1774 azirbel
421 1774 azirbel
                                if(command != -1)
422 1774 azirbel
                                {
423 1775 azirbel
                                        edge_State = 0;
424 1774 azirbel
                                        switch(command)
425 1774 azirbel
                                        {
426 1774 azirbel
                                                case 0:
427 1774 azirbel
                                                        state = 10; break;
428 1774 azirbel
429 1774 azirbel
                                                case 1:
430 1774 azirbel
                                                        state = 11; break;
431 1774 azirbel
432 1774 azirbel
                                                case 2:
433 1774 azirbel
                                                        state = 12; break;
434 1774 azirbel
435 1774 azirbel
                                                case 3:
436 1774 azirbel
                                                        state = 13; break;
437 1774 azirbel
438 1774 azirbel
                                                case 100:
439 1774 azirbel
                                                        terminate(); break;
440 1774 azirbel
                                        }
441 1774 azirbel
                                }
442 1774 azirbel
443 1749 azirbel
                        break;
444 1749 azirbel
445 1749 azirbel
446 1749 azirbel
447 1749 azirbel
//***********************************************************************************************************************************************************************************
448 1749 azirbel
449 1749 azirbel
450 1749 azirbel
451 1749 azirbel
                        /*
452 1749 azirbel
                                The CONTROL for the BEACON state.  This sets a certain procedure to follow, in the form of simple
453 1749 azirbel
                                commands, for a robot to follow if it is set to a BEACON.
454 1749 azirbel
                        */
455 1749 azirbel
                        case 2:
456 1774 azirbel
                                orb_set_color(PURPLE);
457 1775 azirbel
                                beacon_State = 0;
458 1774 azirbel
459 1774 azirbel
                                switch(currentPos)
460 1774 azirbel
                                {
461 1774 azirbel
                                        case 0:
462 1774 azirbel
                                                order(COUNT);        break;
463 1774 azirbel
464 1774 azirbel
                                        case 1:
465 1774 azirbel
                                                order(CIRCLEUP); break;
466 1774 azirbel
467 1774 azirbel
                                        case 2:
468 1774 azirbel
                                                order(ORIENT); break;
469 1774 azirbel
470 1774 azirbel
                                        case 3:
471 1774 azirbel
                                                order(DRIVE); break;
472 1774 azirbel
473 1774 azirbel
                                        case 4:
474 1774 azirbel
                                                terminate(); break;
475 1774 azirbel
                                }
476 1774 azirbel
477 1749 azirbel
                        break;
478 1749 azirbel
479 1749 azirbel
480 1749 azirbel
481 1749 azirbel
//***********************************************************************************************************************************************************************************
482 1749 azirbel
483 1749 azirbel
484 1774 azirbel
                        /* The following states are MACHINE states for the EDGE robot. */
485 1774 azirbel
486 1749 azirbel
                        /*
487 1774 azirbel
                                EDGE on COUNT
488 1749 azirbel
                        */
489 1774 azirbel
                        case 10:
490 1749 azirbel
491 1774 azirbel
492 1635 sdevince
                                switch(edge_State)
493 1594 azirbel
                                {
494 1635 sdevince
                                        /*
495 1635 sdevince
                                                0. EDGE robots are on.
496 1720 azirbel
                                                1. They are waiting for EXIST pacakage from the Center robots
497 1635 sdevince
                                                2. After they receive the package, they send ACK package to center.
498 1717 azirbel
                                                3. Done for now: display green.
499 1635 sdevince
                                        */
500 1774 azirbel
                                        case 0:
501 1635 sdevince
                                                bom_off();
502 1721 azirbel
                                                orb1_set_color(YELLOW);
503 1775 azirbel
                                                orb2_set_color(BLUE);
504 1635 sdevince
                                                packet_data=wl_basic_do_default(&data_length);
505 1635 sdevince
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_EXIST)
506 1635 sdevince
                                                {
507 1721 azirbel
                                                        centerid = packet_data[1];
508 1723 azirbel
509 1724 azirbel
                                                        send2(CIRCLE_ACTION_ACK,robotid);
510 1723 azirbel
511 1635 sdevince
                                                        edge_State=1;
512 1635 sdevince
                                                }
513 1635 sdevince
                                        break;
514 1635 sdevince
                                        /*
515 1635 sdevince
                                                1. Wait for DONE package
516 1635 sdevince
                                                2. The counting process is DONE
517 1635 sdevince
                                        */
518 1635 sdevince
                                        case 1:
519 1635 sdevince
520 1721 azirbel
                                                orb_set_color(YELLOW);
521 1721 azirbel
                                                orb2_set_color(PURPLE);
522 1723 azirbel
523 1724 azirbel
                                                send2(CIRCLE_ACTION_ACK,robotid);                // keep sending the packet until we get a response
524 1723 azirbel
525 1635 sdevince
                                                packet_data=wl_basic_do_default(&data_length);
526 1723 azirbel
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_GOTYOU && packet_data[1] == robotid)
527 1635 sdevince
                                                {
528 1635 sdevince
                                                        edge_State=2;
529 1635 sdevince
                                                }
530 1635 sdevince
                                        break;
531 1721 azirbel
532 1721 azirbel
                                        case 2:        // wait for the second, general, done packet.
533 1721 azirbel
534 1721 azirbel
                                                orb_set_color(YELLOW);
535 1721 azirbel
                                                packet_data=wl_basic_do_default(&data_length);
536 1722 azirbel
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_DONE && packet_data[1] == centerid)
537 1721 azirbel
                                                {
538 1774 azirbel
                                                        state = 1;
539 1721 azirbel
                                                }
540 1723 azirbel
                                        break;
541 1774 azirbel
                                }
542 1774 azirbel
543 1774 azirbel
                        break;
544 1774 azirbel
545 1774 azirbel
                        /* The CIRCLEUP command for EDGE */
546 1774 azirbel
547 1774 azirbel
                        case 11:
548 1774 azirbel
549 1774 azirbel
                                switch(edge_State)
550 1774 azirbel
                                {
551 1596 azirbel
552 1774 azirbel
                                        case 0:
553 1635 sdevince
                                                // COLOR afer DONE ---> MAGENTA
554 1635 sdevince
                                                orb_set_color(MAGENTA);
555 1776 azirbel
                                                aboutFace(4);                        // turn to face the beacon
556 1635 sdevince
                                                forward(175);
557 1635 sdevince
                                                //range_init();
558 1635 sdevince
559 1635 sdevince
560 1635 sdevince
                                                distance = get_distance();
561 1635 sdevince
                                                time=0;
562 1635 sdevince
                                                while ((distance-offset)>=onefoot || distance==0 || (distance+offset)<onefoot)
563 1635 sdevince
                                                {
564 1635 sdevince
                                                        if(distance==0)
565 1635 sdevince
                                                                orb_set_color(WHITE);
566 1635 sdevince
                                                        else if(distance-offset>=onefoot)
567 1635 sdevince
                                                                forward(175);
568 1635 sdevince
                                                        else
569 1635 sdevince
                                                                backward(175);
570 1635 sdevince
                                                        //correctApproach();
571 1635 sdevince
                                                        distance = get_distance();
572 1635 sdevince
                                                        delay_ms(14);
573 1635 sdevince
                                                        time+=14;
574 1749 azirbel
                                                        if(time>50)
575 1717 azirbel
                                                        {
576 1776 azirbel
                                                                aboutFace(4);
577 1635 sdevince
                                                                time=0;
578 1635 sdevince
                                                        }
579 1635 sdevince
                                                }
580 1635 sdevince
581 1635 sdevince
                                                stop();
582 1724 azirbel
                                                orb_set_color(GREEN);
583 1639 azirbel
584 1724 azirbel
                                                send2(CIRCLE_ACTION_ACK, robotid);
585 1639 azirbel
586 1724 azirbel
                                                stop();
587 1774 azirbel
                                                state = 1;
588 1635 sdevince
                                        break;
589 1717 azirbel
590 1774 azirbel
                                }
591 1774 azirbel
592 1774 azirbel
593 1774 azirbel
                        break;
594 1774 azirbel
595 1774 azirbel
                        /* An ORIENT series of steps for the EDGE robot. */
596 1774 azirbel
597 1774 azirbel
                        case 12:
598 1774 azirbel
599 1774 azirbel
600 1774 azirbel
                                switch(edge_State)
601 1774 azirbel
                                {
602 1774 azirbel
603 1724 azirbel
                                        // waits for a packet to tell it to turn on the bom.
604 1774 azirbel
                                        case 0:
605 1724 azirbel
                                                packet_data=wl_basic_do_default(&data_length);
606 1724 azirbel
                                                if(packet_data != 0 && data_length==2 && packet_data[0]==CIRCLE_ACTION_GOTYOU && packet_data[1] == robotid)
607 1724 azirbel
                                                {
608 1724 azirbel
                                                        bom_on();
609 1724 azirbel
                                                        orb_set_color(ORANGE);
610 1724 azirbel
                                                        send2(CIRCLE_ACTION_ACK,centerid);
611 1774 azirbel
                                                        edge_State = 1;
612 1724 azirbel
                                                }
613 1724 azirbel
                                        break;
614 1724 azirbel
615 1724 azirbel
                                        // waits for a packet to tell it that it has been received.
616 1774 azirbel
                                        case 1:
617 1724 azirbel
                                                orb2_set_color(YELLOW);
618 1724 azirbel
                                                packet_data=wl_basic_do_default(&data_length);
619 1749 azirbel
                                                if(packet_data != 0 && data_length==3 && packet_data[0]==CIRCLE_ACTION_GOTYOU && packet_data[1] == robotid)
620 1724 azirbel
                                                {
621 1724 azirbel
                                                        bom_off();
622 1724 azirbel
                                                        direction = packet_data[2];
623 1724 azirbel
                                                        orb_set_color(YELLOW);
624 1774 azirbel
                                                        edge_State = 2;
625 1724 azirbel
                                                }
626 1724 azirbel
                                        break;
627 1724 azirbel
628 1749 azirbel
                                        /* Wait for the center bot to send a DONE packet; then turn to face the right direction. */
629 1774 azirbel
                                        case 2:
630 1749 azirbel
                                                orb_set_color(GREEN);
631 1749 azirbel
                                                packet_data=wl_basic_do_default(&data_length);
632 1749 azirbel
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_DONE)
633 1749 azirbel
                                                {
634 1749 azirbel
                                                        orb_set_color(WHITE);
635 1749 azirbel
                                                        orb2_set_color(CYAN);
636 1774 azirbel
                                                        edge_State = 3;
637 1749 azirbel
                                                }
638 1725 azirbel
                                        break;
639 1725 azirbel
640 1749 azirbel
                                        /* Turn until we reach the right direction (DIRECTION) */
641 1774 azirbel
                                        case 3:
642 1776 azirbel
                                                aboutFace(direction);
643 1749 azirbel
                                        break;
644 1749 azirbel
645 1774 azirbel
                                }
646 1774 azirbel
647 1774 azirbel
648 1774 azirbel
                        break;
649 1774 azirbel
650 1774 azirbel
651 1774 azirbel
                        /* The MOVE steps for the EDGE robot */
652 1774 azirbel
653 1774 azirbel
                        case 13:
654 1774 azirbel
655 1774 azirbel
                                switch(edge_State)
656 1774 azirbel
                                {
657 1774 azirbel
658 1749 azirbel
                                        /* Wait for the command to move forward. */
659 1774 azirbel
                                        case 0:
660 1749 azirbel
                                                packet_data=wl_basic_do_default(&data_length);
661 1749 azirbel
                                                if(packet_data != 0 && data_length>=3 && packet_data[0]==CIRCLE_ACTION_FORWARD)
662 1749 azirbel
                                                {
663 1749 azirbel
                                                        orb_set_color(BLUE);
664 1775 azirbel
                                                        forward(packet_data[1]*10);
665 1775 azirbel
                                                        delay_ms(packet_data[2]*1000);
666 1774 azirbel
                                                        edge_State = 1;
667 1749 azirbel
                                                }
668 1749 azirbel
                                        break;
669 1749 azirbel
670 1749 azirbel
                                        /* Terminal. */
671 1774 azirbel
                                        case 1:
672 1749 azirbel
                                                stop();
673 1774 azirbel
                                                state = 1;
674 1717 azirbel
                                        break;
675 1639 azirbel
676 1717 azirbel
677 1717 azirbel
                                }        // end the EdgeState switch
678 1717 azirbel
679 1717 azirbel
                        break;                // break the Edge state in the main switch loop
680 1626 gnagaraj
681 1717 azirbel
                        // END for EDGE robots
682 1626 gnagaraj
683 1626 gnagaraj
684 1626 gnagaraj
685 1626 gnagaraj
686 1626 gnagaraj
687 1639 azirbel
688 1749 azirbel
//***********************************************************************************************************************************************************************************
689 1639 azirbel
690 1639 azirbel
691 1639 azirbel
692 1639 azirbel
693 1639 azirbel
                        /*
694 1749 azirbel
                           The MACHINE for the BEACON state
695 1774 azirbel
                        */
696 1774 azirbel
697 1774 azirbel
                        /* the COUNT code for the BEACON */
698 1774 azirbel
                        case 20:
699 1717 azirbel
                                switch(beacon_State)
700 1717 azirbel
                                {
701 1717 azirbel
702 1717 azirbel
                                        /* 0. center  robots on wait for pressing button 1 */
703 1720 azirbel
                                        case 0:
704 1717 azirbel
                                                bom_on();
705 1775 azirbel
                                                orb_set_color(BLUE);
706 1774 azirbel
                                                robotsReceived = 0;
707 1775 azirbel
                                                beacon_State=1;
708 1626 gnagaraj
                                        break;
709 1717 azirbel
710 1717 azirbel
                                        /* 1. Send EXIST package to EDGE robots */
711 1717 azirbel
                                        case 1:
712 1717 azirbel
                                                orb_set_color(RED);
713 1724 azirbel
                                                send2(CIRCLE_ACTION_EXIST,robotid);
714 1717 azirbel
                                                beacon_State=2;
715 1626 gnagaraj
                                        break;
716 1721 azirbel
717 1717 azirbel
                                        /* 2. Count the number of the EDGE robots *******NOTE: at most  1000  times of loop ******  */
718 1720 azirbel
                                        case 2:
719 1717 azirbel
                                                waitingCounter++;
720 1717 azirbel
                                                orb1_set_color(YELLOW);
721 1717 azirbel
                                                orb2_set_color(BLUE);
722 1717 azirbel
                                                packet_data=wl_basic_do_default(&data_length);
723 1639 azirbel
724 1717 azirbel
                                                if(packet_data!=0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_ACK)
725 1717 azirbel
                                                {
726 1717 azirbel
                                                        orb_set_color(RED);
727 1717 azirbel
                                                        orb2_set_color(BLUE);
728 1717 azirbel
                                                        //only add to robots seen if you haven't gotten an ACK from this robot
729 1723 azirbel
                                                        if(used[packet_data[1]]==0)
730 1723 azirbel
                                                        {
731 1717 azirbel
                                                                robotsReceived++;
732 1724 azirbel
                                                                used[packet_data[1]] = 1;
733 1639 azirbel
734 1717 azirbel
                                                                usb_puts("Added: ");
735 1717 azirbel
                                                                usb_puti(packet_data[1]);
736 1717 azirbel
                                                                usb_puts("\r\n");
737 1717 azirbel
                                                        }
738 1721 azirbel
739 1723 azirbel
                                                        // NEW: sends a packet to each robot it receives telling them to be done.
740 1724 azirbel
                                                        send2(CIRCLE_ACTION_GOTYOU,packet_data[1]);
741 1626 gnagaraj
                                                }
742 1724 azirbel
                                                if(waitingCounter >= 300){
743 1717 azirbel
                                                        beacon_State=3;
744 1717 azirbel
                                                }
745 1626 gnagaraj
                                        break;
746 1717 azirbel
747 1717 azirbel
                                        /* COUNTing is DONE.  Sending DONE package. */
748 1717 azirbel
                                        case 3:
749 1717 azirbel
                                                blink(robotsReceived);
750 1717 azirbel
                                                orb_set_color(GREEN);
751 1724 azirbel
                                                send2(CIRCLE_ACTION_DONE, robotid);
752 1774 azirbel
                                                state = 2;
753 1626 gnagaraj
                                        break;
754 1774 azirbel
                                }
755 1717 azirbel
756 1774 azirbel
                        break;
757 1774 azirbel
758 1774 azirbel
                        /* The CIRCLEUP method for BEACON */
759 1774 azirbel
                        case 21:
760 1774 azirbel
761 1774 azirbel
                                switch(beacon_State)
762 1774 azirbel
                                {
763 1774 azirbel
764 1717 azirbel
                                        /* Wait for all the robots to get to right distance/position */
765 1774 azirbel
                                        case 0:
766 1720 azirbel
                                                left(170);
767 1717 azirbel
                                                orb1_set_color(YELLOW);
768 1717 azirbel
                                                orb2_set_color(WHITE);
769 1626 gnagaraj
770 1717 azirbel
                                                int numOk = 0;
771 1626 gnagaraj
772 1717 azirbel
                                                while(numOk<robotsReceived)
773 1626 gnagaraj
                                                {
774 1717 azirbel
                                                        packet_data=wl_basic_do_default(&data_length);
775 1717 azirbel
                                                        if(packet_data!=0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_ACK)
776 1717 azirbel
                                                        {
777 1717 azirbel
                                                                numOk++;
778 1717 azirbel
                                                        }
779 1626 gnagaraj
                                                }
780 1626 gnagaraj
781 1774 azirbel
                                                state = 2;
782 1774 azirbel
                                        break;
783 1774 azirbel
                                }
784 1774 azirbel
785 1774 azirbel
                        break;
786 1774 azirbel
787 1774 azirbel
788 1774 azirbel
                        /* The ORIENT code for the beacon */
789 1774 azirbel
                        case 22:
790 1774 azirbel
791 1774 azirbel
                                switch(beacon_State)
792 1774 azirbel
                                {
793 1724 azirbel
                                        /* Turns all the robots in the same direction */
794 1774 azirbel
                                        case 0:
795 1717 azirbel
                                                stop();
796 1724 azirbel
                                                bom_off();
797 1724 azirbel
                                                orb_set_color(ORANGE);
798 1724 azirbel
799 1724 azirbel
                                                // for each robot, tells them to turn their bom on, then tells them which way they should face.
800 1724 azirbel
                                                for(int i=0; i < 17; i++)
801 1724 azirbel
                                                {
802 1724 azirbel
                                                        if(used[i] == 1)
803 1724 azirbel
                                                        {
804 1724 azirbel
                                                                send2(CIRCLE_ACTION_GOTYOU, i);
805 1724 azirbel
                                                                while(1)        // waits for a response so it knows the BOM is on.
806 1724 azirbel
                                                                {
807 1724 azirbel
                                                                        orb_set_color(RED);
808 1724 azirbel
                                                                        orb2_set_color(WHITE);
809 1724 azirbel
                                                                        packet_data=wl_basic_do_default(&data_length);
810 1724 azirbel
                                                                        if(packet_data!=0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_ACK)
811 1724 azirbel
                                                                        {
812 1724 azirbel
                                                                                orb_set_color(ORANGE);
813 1724 azirbel
                                                                                break;
814 1724 azirbel
                                                                        }
815 1724 azirbel
                                                                }
816 1724 azirbel
817 1749 azirbel
                                                                bom_refresh(BOM_ALL);
818 1724 azirbel
                                                                direction = bom_get_max();
819 1749 azirbel
                                                                direction += 8;
820 1749 azirbel
                                                                if(direction > 15) direction -= 16;
821 1724 azirbel
                                                                send3(CIRCLE_ACTION_GOTYOU, i, direction);
822 1749 azirbel
                                                                delay_ms(20);
823 1724 azirbel
                                                        }
824 1724 azirbel
                                                }
825 1774 azirbel
                                                beacon_State = 1;
826 1724 azirbel
                                        break;
827 1724 azirbel
828 1749 azirbel
                                        /* Sends a DONE packet to signify that it has read in all the robots' directions and sent packets.
829 1749 azirbel
                                                Edge robots should now turn to face the right direction. */
830 1774 azirbel
                                        case 1:
831 1749 azirbel
                                                send2(CIRCLE_ACTION_DONE,robotid);
832 1749 azirbel
                                                bom_on();
833 1774 azirbel
                                                state = 2;
834 1749 azirbel
                                        break;
835 1774 azirbel
                                }
836 1749 azirbel
837 1774 azirbel
                        break;
838 1774 azirbel
839 1774 azirbel
840 1774 azirbel
                        /* The DRIVE code for the beacon */
841 1774 azirbel
                        case 23:
842 1774 azirbel
843 1774 azirbel
                                switch(beacon_State)
844 1774 azirbel
                                {
845 1774 azirbel
846 1749 azirbel
                                        /* Tells the robots to move forward and moves itself. */
847 1775 azirbel
                                        case 0:
848 1749 azirbel
                                                orb_set_color(YELLOW);
849 1749 azirbel
                                                delay_ms(5000);
850 1749 azirbel
851 1775 azirbel
                                                // format: type of ack, speed divided by 10, time in seconds.
852 1775 azirbel
                                                send3(CIRCLE_ACTION_FORWARD,20,2);
853 1749 azirbel
                                                orb_set_color(BLUE);
854 1749 azirbel
                                                forward(200);
855 1749 azirbel
                                                delay_ms(2000);
856 1749 azirbel
                                                stop();
857 1775 azirbel
                                                beacon_State = 1;
858 1749 azirbel
                                        break;
859 1749 azirbel
860 1724 azirbel
                                        /* Terminal. */
861 1775 azirbel
                                        case 1:
862 1749 azirbel
                                                stop();
863 1774 azirbel
                                                state = 2;
864 1717 azirbel
                                        break;
865 1717 azirbel
                                }
866 1717 azirbel
                        break;
867 1749 azirbel
868 1749 azirbel
//***********************************************************************************************************************************************************************************
869 1717 azirbel
870 1749 azirbel
                }        // ends the main switch
871 1749 azirbel
        }                // ends the main while loop
872 1594 azirbel
873 1749 azirbel
        orb_set_color(RED);        // error, we should never break from the while loop!
874 1594 azirbel
875 1749 azirbel
        while(1); /* END HERE, just in case something happened.  This way we can see the red orb. */
876 1594 azirbel
}
877 1749 azirbel