Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (21.9 KB)

1

    
2
/*** PROGRAM INFORMATION ***
3

4
          This program assembles a group of robots into a circle and allows them movement
5
        within that formation.  Robots should be able to break formation and travel as a
6
        line, readjust in the face of obstacles, and reform if conditions are necessary.
7

8
          The program begins waiting for a button press.  When pressed, a robot assumes the
9
        BEACON position, which means that it is the robot in the center of the circle and
10
        therefore in charge.  It then gathers robots around it by sending them commands.
11
        This code is executed using two finite state machines, nested inside one another.
12
        One controls the overall state of the robot (whether it is a BEACON, an EDGE, or
13
        WAITING, for example).
14

15
          This code should be implemented so that most useful functions are built in to the
16
        machine.  For example, the BEACON robot should be able to call methods such as
17
        CircleUp() to gather robots around it, and Move(distance) to move the circle group
18
        all at once.
19

20
          This Code is the property of the Carnegie Mellon Robotics Club and is being used
21
        to test formation control in a low-cost robot colony.  Thanks to all members of
22
        RoboClub, especially Colony president John Sexton and the ever-present Chris Mar.
23
        
24
        AUTHORS: James Carroll, Steve DeVincentis, Hanzhang (Echo) Hu, Nico Paris, Joel Rey,
25
         Reva Street, Alex Zirbel                                                         */
26

    
27

    
28
#include <dragonfly_lib.h>
29
#include <wl_basic.h>
30
#include <encoders.h>
31
#include "circle.h"
32

    
33
/*** TODO: ***
34

35
        - Transform the code into a method-based state machine that uses the procedural state
36
                machines, which are hardcoded and hard to edit, as a backup.
37
        - Implement a drive straight method for use in keeping the robots more accurate as a
38
                group.
39
        - Fix the approach method: good robots usually work well, but bad robots often have
40
                errors which might be avoidable with the use of error checking.
41
        - Make robots more robust: packages are often lost, which throws the entire procedural
42
                nature of the program off.
43
        - Consider using the center bot to check distances
44
        - More testing is always good and necessary.                                        */
45

    
46
/*** BOT LOG ***
47

48
        4-1-2010: BOT 7 as BEACON and BOT 1 as EDGE worked extremely well.
49
        4-2-2010: BOT 7 and BOT 14 worked extremely well, no matter states.  BOT 1 started
50
                well, but malfunctioned later.                                                */
51

    
52
/*** TERMINOLOGY ***
53

54
        WAITINGSTATE:
55
                The robot waits to be given a signal to do something.  Wireless is on, in
56
                case the robot is called on to turn into an EDGE.  The color should be LIME
57
                or YELLOW-GREEN.
58

59
        BEACON_CONTROL:
60
                The code that executes commands when a robot is turned to BEACON mode.  This
61
                code may run predefined methods for simplicity.  One goal is to make these
62
                methods change the robot turn to to BEACON_MACHINE mode for a while, and then
63
                return to the CONTROL code where they left off.
64

65
        EDGE_CONTROL:
66
                Like BEACON_CONTROL, executes whatever orders are required of the robot as an
67
                EDGE.
68

69
        BEACON_MACHINE:
70
                A hardcoded list of functions which the robot is capable of running through.
71
                Consists of a finite state machine, where the robot executes a set of commands
72
                in a procedural manner and then returns to wherever it was in the control code.
73

74
        EDGE_MACHINE:
75
                Like the BEACON_MACHINE, but contains the same sort of procedural information
76
                for EDGE robots.
77

78
        END:
79
                A terminal state of the machine, where the robot just sits and waits.  The
80
                color should be GREEN and WHITE.
81

82

83
        TYPES OF WIRELESS PACKETS:
84
                CIRCLE_ACTION_EXIST 'E'
85
                CIRCLE_ACTION_POSITION 'P'
86
                CIRCLE_ACTION_ACK 'A'
87
                        A general acknowledgement package.
88
                CIRCLE_ACTION_DONE 'D'
89
                        Used by robots to tell when they have finished their action.
90
                CIRCLE_ACTION_GOTYOU 'G'
91
                        Used by the BEACON to tell a robot when it has been checked off.
92
                        At this point, the EDGE has been recognized.  Used for times when
93
                        all EDGE robots have to communicate to the center via the spam method.
94
                CIRCLE_ACTION_FORWARD 'F'
95
                        The BEACON tells the rest of the robots to move forward.
96
                CIRCLE_CLAIM_CENTER 'C'
97
                        Sent out by a robot when it takes over as BEACON.                */
98

    
99

    
100

    
101
int END = 100;        
102
int WAITINGSTATE = 0;                /* Define some variables to keep track of the state machine.*/
103
int EDGE_CONTROL = 1;
104
int BEACON_CONTROL = 2;
105
int EDGE_MACHINE = 3;
106
int BEACON_MACHINE = 4;
107

    
108
int COUNT = 0;
109
int CIRCLEUP = 1;
110
int ORIENT = 2;
111
int DRIVE = 3;
112

    
113
int currentPos = 0;
114
int state = 0;
115

    
116

    
117
int timeout = 0;
118
int sending = 0;
119
int stop2 = 0;
120
struct vector slave_position;
121
int desired_max_bom;
122
int bom_max_counter;
123

    
124

    
125
void switch_sending(void)
126
{
127
        if(sending)
128
        {
129
                sending = 0;
130
                bom_off();
131
        }
132
        else
133
        {
134
                sending = 1;
135
                bom_on();
136
        }
137
}
138

    
139
void forward(int speed){                        // set the motors to this forward speed.
140
        motor_l_set(FORWARD,speed);
141
        motor_r_set(FORWARD,speed);
142
}
143
void left(int speed){                                // turn left at this speed.
144
        motor_l_set(FORWARD,speed);
145
        motor_r_set(BACKWARD,speed);
146
}
147
void right(int speed){
148
        motor_l_set(BACKWARD,speed);
149
        motor_r_set(FORWARD,speed);
150
}
151
void stop(void){                        // could be set to motors_off(), or just use this as an alternative.
152
        motor_l_set(BACKWARD,0);        // stop() is better - motors_off() creates a slight delay to turn them back on.
153
        motor_r_set(FORWARD,0);
154
}
155
void setforward(int spd1, int spd2){
156
        motor_l_set(FORWARD,spd1);
157
        motor_r_set(FORWARD,spd2);
158
}
159
void backward(int speed){
160
        motor_l_set(BACKWARD, speed);
161
        motor_r_set(BACKWARD, speed);
162
}
163
int get_distance(void){                                // takes an averaged reading of the front rangefinder
164
        int temp,distance,kk=5;                        // kk sets this to 5 readings.
165
        distance =0;
166
        for (int i=0; i<kk; i++){
167
                temp = range_read_distance(IR2);
168
                if (temp == -1)
169
                {
170
                        //temp=0;
171
                        i--;
172
                }
173
                else
174
                        distance+= temp;
175
                delay_ms(3);
176
        }
177
        if (kk>0)
178
                return (int)(distance/kk);
179
        else 
180
                return 0;
181
}
182

    
183
/* Sends a global packet with two arguments */
184
void send2(char arg0, char arg1)
185
{
186
        char send_buffer[2];
187
        send_buffer[0]=arg0;
188
        send_buffer[1]=arg1;
189
        wl_basic_send_global_packet(42,send_buffer,2);
190
}
191

    
192
/* Sends a global packet with three arguments */
193
void send3(char arg0, char arg1, char arg2)
194
{
195
        char send_buffer[3];
196
        send_buffer[0]=arg0;
197
        send_buffer[1]=arg1;
198
        send_buffer[2]=arg2;
199
        wl_basic_send_global_packet(42,send_buffer,3);
200
}
201

    
202
/*
203
        Orients the robot so that it is facing the beacon (or the broadcasting BOM).
204
        
205
*/
206
void correctTurn(void)
207
{
208
        orb1_set_color(BLUE);                        // BLUE and PURPLE
209
        left(220);
210
        while(1)
211
        {
212
                int bomNum = 0;                                // bomNum is the current maximum reading
213
                bom_refresh(BOM_ALL);
214
                bomNum = bom_get_max();
215
                usb_puti(bomNum);
216
                if(bomNum == 4)                                // when it's turned the right way, stop
217
                {
218
                        timeout = 0;
219
                        //motor_l_set(1, 200);
220
                        //motor_r_set(1, 200);
221
                        break;                                // exits the while() loop to stop the method
222
                }
223
                else                                        // facing the wrong way
224
                {
225
                        if(bomNum == -1)
226
                        {
227
                                timeout++;
228
                                
229
                                if(timeout > 5000)        // if it's been looking too long, move a little bit as it turns
230
                                {
231
                                        motor_r_set(FORWARD, 210);
232
                                        motor_l_set(BACKWARD, 190);
233
                                }
234
                        }
235
                        else if((bomNum >= 12) || (bomNum < 4))
236
                        {
237
                                motor_l_set(FORWARD, 200);
238
                                motor_r_set(BACKWARD, 200);
239
                                timeout = 0;
240
                        }
241
                        else
242
                        {
243
                                motor_l_set(BACKWARD, 200);
244
                                motor_r_set(FORWARD, 200);
245
                                timeout = 0;
246
                        }
247
                }
248
        }
249
        return;
250
}
251

    
252

    
253
/* 
254
    BLINK the given number times
255
*/
256
void blink(int num)
257
{
258
        for(int i = 0; i<num; i++)
259
        {
260
                orb_set_color(ORB_OFF);
261
                delay_ms(150);
262
                orb_set_color(RED);
263
                delay_ms(50);
264
        }
265
        orb_set_color(ORB_OFF);
266
}
267

    
268
/* 
269
    BLINK slowly the given number times
270
*/
271
void slowblink(int num)
272
{
273
        for(int i = 0; i<num; i++)
274
        {
275
                orb_set_color(ORB_OFF);
276
                delay_ms(300);
277
                orb_set_color(RED);
278
                delay_ms(200);
279
        }
280
        orb_set_color(ORB_OFF);
281
}
282

    
283
void order(int action)
284
{
285
        currentPos++;
286
        send2(CIRCLE_EXECUTE, action);
287
        state = 20 + action;
288
}
289

    
290
void terminate(void)
291
{
292
        send2(CIRCLE_EXECUTE, 100);
293
        orb_set_color(GREEN);
294
        orb2_set_color(WHITE);
295
        while(1) ;
296
}
297

    
298

    
299

    
300

    
301
//*****************************************************************************************************************************************************************************************
302
//*****************************************************************************************************************************************************************************************
303
//*****************************************************************************************************************************************************************************************
304

    
305

    
306
/*
307
        A state machine with five states.  The robot starts out in WAITINGSTATE mode, from which
308
        it recieves a signal of some sort and moves to a different state.
309
*/
310
int main(void)
311
{
312
        /* Initialize dragonfly board */
313
            dragonfly_init(ALL_ON);
314
            /* Initialize the basic wireless library */
315
            wl_basic_init_default();
316
            /* Set the XBee channel to 24 - must be standard among robots */
317
        wl_set_channel(24);
318

    
319
        int robotid = get_robotid();
320
        int centerid = 0;                // once the EDGE gets the first signal from a center, it stores who the center is.
321
        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.
322
        for (int i=0; i<17; i++) used[i] = 0;                // initially, no robots in the group.
323

    
324
        int data_length;                // keeps track of the length of wireless packets received.
325
        unsigned char *packet_data=wl_basic_do_default(&data_length);
326
        
327
        int beacon_State=0;                // these variables keep track of the inner state machines in the procedural MACHINE states.
328
        int edge_State=0;
329

    
330
        int waitingCounter=0;
331
        int robotsReceived=0;                // an important variable that stores the size of the group.
332
        int offset = 20;                // offset for the approaching: how far off the rangefinders can be
333
        int time=0;
334
        int direction = 4;                // keeps track of which way robots are facing relative to the center
335
        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
336
                                                // right distance away.
337
        int onefoot = 250;                // how far away to stop.
338
        
339
        while(1)
340
        {
341
                bom_refresh(BOM_ALL);
342

    
343
                                /*                
344
                                *******EXPECTED MOVES **********   (OUT OF DATE.  Will be updated once changes have been made.)
345
                                The designed movement:
346
                                 1. one center robot, several edge robots are on;
347
                                 2. center robots: button 1 is pressed;
348
                                 3. center robots: send global package telling edges that he exists;
349
                                 4. EDGE robots response with ACK. 
350
                                 5. EDGE robots wait for center robots to finish counting (DONE package)
351
                                 6. EDGE robtos approach the center robtot and stop at the "onefoot" distance, send message to the center
352
                                */
353
                
354
                
355
                /* This is the MAIN SWITCH LOOP, which governs the overall status of the robot. */
356
                switch(state)
357
                {
358

    
359

    
360
                        /*
361
                                The WAITINGSTATE.  This state constantly checks for wireless packets,
362
                                and updates its state as soon as it receives a signal.
363
                        */
364
                        case 0:
365

    
366
                                orb_set_color(YELLOW);
367
                                packet_data=wl_basic_do_default(&data_length);
368
                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_CLAIM_CENTER)
369
                                {
370
                                        centerid = packet_data[1];
371

    
372
                                        state = 1;
373
                                }
374

    
375
                                if(button1_read())
376
                                {
377
                                        send2(CIRCLE_CLAIM_CENTER, robotid);         // becomes the center if button1 is clicked.
378
                                        state = 2;
379
                                }
380

    
381
                        break;
382

    
383

    
384

    
385
//***********************************************************************************************************************************************************************************
386

    
387

    
388

    
389
                        /*
390
                                The CONTROL for the EDGE state.  This sets a certain procedure to follow, in the form of simple
391
                                commands, for a robot to follow if it is set to an EDGE.
392
                        */
393

    
394
                        case 1:
395
                                orb_set_color(CYAN);
396
                                orb1_set_color(YELLOW);
397

    
398
                                int command = -1;
399
                                
400
                                packet_data=wl_basic_do_default(&data_length);
401
                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_EXECUTE)
402
                                {
403
                                        command = packet_data[1];
404
                                }
405

    
406
                                if(command != -1)
407
                                {
408
                                        edge_State = 0;
409
                                        switch(command)
410
                                        {
411
                                                case 0:
412
                                                        state = 10; break;
413

    
414
                                                case 1:
415
                                                        state = 11; break;
416

    
417
                                                case 2:
418
                                                        state = 12; break;
419

    
420
                                                case 3:
421
                                                        state = 13; break;
422

    
423
                                                case 100:
424
                                                        terminate(); break;
425
                                        }
426
                                }
427

    
428
                        break;
429

    
430

    
431

    
432
//***********************************************************************************************************************************************************************************
433

    
434

    
435

    
436
                        /*
437
                                The CONTROL for the BEACON state.  This sets a certain procedure to follow, in the form of simple
438
                                commands, for a robot to follow if it is set to a BEACON.
439
                        */
440
                        case 2:
441
                                orb_set_color(PURPLE);
442
                                beacon_State = 0;
443
                                
444
                                switch(currentPos)
445
                                {
446
                                        case 0:
447
                                                order(COUNT);        break;
448

    
449
                                        case 1:
450
                                                order(CIRCLEUP); break;
451

    
452
                                        case 2:
453
                                                order(ORIENT); break;
454

    
455
                                        case 3:
456
                                                order(DRIVE); break;
457

    
458
                                        case 4:
459
                                                terminate(); break;
460
                                }
461
                                
462
                        break;
463

    
464

    
465

    
466
//***********************************************************************************************************************************************************************************
467

    
468

    
469
                        /* The following states are MACHINE states for the EDGE robot. */
470

    
471
                        /*
472
                                EDGE on COUNT
473
                        */
474
                        case 10:        
475

    
476

    
477
                                switch(edge_State)
478
                                {
479
                                        /*
480
                                                0. EDGE robots are on. 
481
                                                1. They are waiting for EXIST pacakage from the Center robots
482
                                                2. After they receive the package, they send ACK package to center.
483
                                                3. Done for now: display green.
484
                                        */
485
                                        case 0:
486
                                                bom_off();
487
                                                orb1_set_color(YELLOW);
488
                                                orb2_set_color(BLUE);
489
                                                packet_data=wl_basic_do_default(&data_length);
490
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_EXIST)
491
                                                {
492
                                                        centerid = packet_data[1];
493

    
494
                                                        send2(CIRCLE_ACTION_ACK,robotid);
495

    
496
                                                        edge_State=1;
497
                                                }
498
                                        break;
499
                                        /*
500
                                                1. Wait for DONE package 
501
                                                2. The counting process is DONE
502
                                        */
503
                                        case 1:                
504
                                        
505
                                                orb_set_color(YELLOW);
506
                                                orb2_set_color(PURPLE);
507

    
508
                                                send2(CIRCLE_ACTION_ACK,robotid);                // keep sending the packet until we get a response
509
                                                
510
                                                packet_data=wl_basic_do_default(&data_length);
511
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_GOTYOU && packet_data[1] == robotid)
512
                                                {
513
                                                        edge_State=2;
514
                                                }
515
                                        break;
516

    
517
                                        case 2:        // wait for the second, general, done packet.
518

    
519
                                                orb_set_color(YELLOW);
520
                                                packet_data=wl_basic_do_default(&data_length);
521
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_DONE && packet_data[1] == centerid)
522
                                                {
523
                                                        state = 1;
524
                                                }
525
                                        break;
526
                                }
527

    
528
                        break;
529

    
530
                        /* The CIRCLEUP command for EDGE */
531

    
532
                        case 11:
533

    
534
                                switch(edge_State)
535
                                {
536
                                        
537
                                        case 0:
538
                                                // COLOR afer DONE ---> MAGENTA
539
                                                orb_set_color(MAGENTA);
540
                                                correctTurn();                        // turn to face the beacon
541
                                                forward(175);
542
                                                //range_init();
543
                                                
544
                                                
545
                                                distance = get_distance();
546
                                                time=0;
547
                                                while ((distance-offset)>=onefoot || distance==0 || (distance+offset)<onefoot)
548
                                                {
549
                                                        if(distance==0)
550
                                                                orb_set_color(WHITE);
551
                                                        else if(distance-offset>=onefoot)
552
                                                                forward(175);
553
                                                        else
554
                                                                backward(175);
555
                                                        //correctApproach();
556
                                                        distance = get_distance();
557
                                                        delay_ms(14);
558
                                                        time+=14;
559
                                                        if(time>50)
560
                                                        {
561
                                                                correctTurn();
562
                                                                time=0;
563
                                                        }
564
                                                }
565
                                                        
566
                                                stop();
567
                                                orb_set_color(GREEN);
568

    
569
                                                send2(CIRCLE_ACTION_ACK, robotid);
570

    
571
                                                stop();
572
                                                state = 1;
573
                                        break;
574

    
575
                                }
576

    
577

    
578
                        break;
579
                
580
                        /* An ORIENT series of steps for the EDGE robot. */
581

    
582
                        case 12:
583
                        
584

    
585
                                switch(edge_State)
586
                                {
587

    
588
                                        // waits for a packet to tell it to turn on the bom.
589
                                        case 0:
590
                                                packet_data=wl_basic_do_default(&data_length);
591
                                                if(packet_data != 0 && data_length==2 && packet_data[0]==CIRCLE_ACTION_GOTYOU && packet_data[1] == robotid)
592
                                                {
593
                                                        bom_on();
594
                                                        orb_set_color(ORANGE);
595
                                                        send2(CIRCLE_ACTION_ACK,centerid);
596
                                                        edge_State = 1;
597
                                                }
598
                                        break;
599

    
600
                                        // waits for a packet to tell it that it has been received.
601
                                        case 1:
602
                                                orb2_set_color(YELLOW);
603
                                                packet_data=wl_basic_do_default(&data_length);
604
                                                if(packet_data != 0 && data_length==3 && packet_data[0]==CIRCLE_ACTION_GOTYOU && packet_data[1] == robotid)
605
                                                {
606
                                                        bom_off();
607
                                                        direction = packet_data[2];
608
                                                        blink(direction);
609
                                                        orb_set_color(YELLOW);
610
                                                        edge_State = 2;
611
                                                }
612
                                        break;
613

    
614
                                        /* Wait for the center bot to send a DONE packet; then turn to face the right direction. */
615
                                        case 2:
616
                                                orb_set_color(GREEN);
617
                                                packet_data=wl_basic_do_default(&data_length);
618
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_DONE)
619
                                                {
620
                                                        orb_set_color(WHITE);
621
                                                        orb2_set_color(CYAN);
622
                                                        edge_State = 3;
623
                                                }
624
                                        break;
625

    
626
                                        /* Turn until we reach the right direction (DIRECTION) */
627
                                        case 3:
628
                                                bom_refresh(BOM_ALL);
629
                                                int currentdir = bom_get_max();
630
                                                int direction2 = direction+8;
631
                                                
632
                                                if(currentdir == direction)
633
                                                {
634
                                                        stop();
635
                                                        state = 1;
636
                                                }
637
                                                else if(
638

    
639
                                                /*left(170);
640
                                                bom_refresh(BOM_ALL);
641
                                                if(bom_get_max() == direction)
642
                                                {
643
                                                        stop();
644
                                                        orb_set_color(YELLOW);
645
                                                        state = 1;
646
                                                }*/
647
                                        break;
648

    
649
                                }
650

    
651

    
652
                        break;
653

    
654

    
655
                        /* The MOVE steps for the EDGE robot */
656

    
657
                        case 13:
658

    
659
                                switch(edge_State)
660
                                {
661
                                
662
                                        /* Wait for the command to move forward. */
663
                                        case 0:
664
                                                packet_data=wl_basic_do_default(&data_length);
665
                                                if(packet_data != 0 && data_length>=3 && packet_data[0]==CIRCLE_ACTION_FORWARD)
666
                                                {
667
                                                        orb_set_color(BLUE);
668
                                                        forward(packet_data[1]*10);
669
                                                        delay_ms(packet_data[2]*1000);
670
                                                        edge_State = 1;
671
                                                }
672
                                        break;
673

    
674
                                        /* Terminal. */
675
                                        case 1:
676
                                                stop();
677
                                                state = 1;
678
                                        break;
679

    
680

    
681
                                }        // end the EdgeState switch
682

    
683
                        break;                // break the Edge state in the main switch loop
684
                                
685
                        // END for EDGE robots
686
                        
687

    
688

    
689

    
690

    
691

    
692
//***********************************************************************************************************************************************************************************
693

    
694

    
695

    
696

    
697
                        /*
698
                           The MACHINE for the BEACON state
699
                        */
700

    
701
                        /* the COUNT code for the BEACON */
702
                        case 20:
703
                                switch(beacon_State) 
704
                                {
705

    
706
                                        /* 0. center  robots on wait for pressing button 1 */
707
                                        case 0:
708
                                                bom_on();
709
                                                orb_set_color(BLUE);
710
                                                robotsReceived = 0;
711
                                                beacon_State=1;
712
                                        break;        
713

    
714
                                        /* 1. Send EXIST package to EDGE robots */
715
                                        case 1:
716
                                                orb_set_color(RED);
717
                                                send2(CIRCLE_ACTION_EXIST,robotid);
718
                                                beacon_State=2;
719
                                        break;
720

    
721
                                        /* 2. Count the number of the EDGE robots *******NOTE: at most  1000  times of loop ******  */
722
                                        case 2:
723
                                                waitingCounter++;
724
                                                orb1_set_color(YELLOW);
725
                                                orb2_set_color(BLUE);
726
                                                packet_data=wl_basic_do_default(&data_length);
727
                                        
728
                                                if(packet_data!=0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_ACK)
729
                                                {
730
                                                        orb_set_color(RED);
731
                                                        orb2_set_color(BLUE);
732
                                                        //only add to robots seen if you haven't gotten an ACK from this robot
733
                                                        if(used[packet_data[1]]==0)
734
                                                        {
735
                                                                robotsReceived++;
736
                                                                used[packet_data[1]] = 1;
737

    
738
                                                                usb_puts("Added: ");
739
                                                                usb_puti(packet_data[1]);
740
                                                                usb_puts("\r\n");
741
                                                        }
742

    
743
                                                        // NEW: sends a packet to each robot it receives telling them to be done.
744
                                                        send2(CIRCLE_ACTION_GOTYOU,packet_data[1]);
745
                                                }
746
                                                if(waitingCounter >= 300){
747
                                                        beacon_State=3;
748
                                                }
749
                                        break;
750

    
751
                                        /* COUNTing is DONE.  Sending DONE package. */        
752
                                        case 3:
753
                                                blink(robotsReceived);
754
                                                orb_set_color(GREEN);
755
                                                send2(CIRCLE_ACTION_DONE, robotid);
756
                                                state = 2;
757
                                        break;
758
                                }
759

    
760
                        break;
761

    
762
                        /* The CIRCLEUP method for BEACON */
763
                        case 21:
764

    
765
                                switch(beacon_State)
766
                                {
767

    
768
                                        /* Wait for all the robots to get to right distance/position */
769
                                        case 0: 
770
                                                left(170);
771
                                                orb1_set_color(YELLOW);
772
                                                orb2_set_color(WHITE);
773
                                        
774
                                                int numOk = 0;
775
                                        
776
                                                while(numOk<robotsReceived)
777
                                                {
778
                                                        packet_data=wl_basic_do_default(&data_length);
779
                                                        if(packet_data!=0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_ACK)
780
                                                        {
781
                                                                numOk++;
782
                                                        }
783
                                                }
784
                                        
785
                                                state = 2;
786
                                        break;
787
                                }
788

    
789
                        break;
790

    
791

    
792
                        /* The ORIENT code for the beacon */
793
                        case 22:
794

    
795
                                switch(beacon_State)
796
                                {
797
                                        /* Turns all the robots in the same direction */
798
                                        case 0:
799
                                                stop();
800
                                                bom_off();
801
                                                orb_set_color(ORANGE);
802
                                                
803
                                                // for each robot, tells them to turn their bom on, then tells them which way they should face.
804
                                                for(int i=0; i < 17; i++)
805
                                                {
806
                                                        if(used[i] == 1)
807
                                                        {
808
                                                                send2(CIRCLE_ACTION_GOTYOU, i);
809
                                                                while(1)        // waits for a response so it knows the BOM is on.
810
                                                                {
811
                                                                        orb_set_color(RED);
812
                                                                        orb2_set_color(WHITE);
813
                                                                        packet_data=wl_basic_do_default(&data_length);
814
                                                                        if(packet_data!=0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_ACK)
815
                                                                        {
816
                                                                                orb_set_color(ORANGE);
817
                                                                                break;
818
                                                                        }
819
                                                                }
820

    
821
                                                                bom_refresh(BOM_ALL);
822
                                                                direction = bom_get_max();
823
                                                                direction += 8;
824
                                                                if(direction > 15) direction -= 16;
825
                                                                blink(direction);
826
                                                                send3(CIRCLE_ACTION_GOTYOU, i, direction);
827
                                                                delay_ms(20);
828
                                                        }
829
                                                }
830
                                                beacon_State = 1;
831
                                        break;
832
                        
833
                                        /* Sends a DONE packet to signify that it has read in all the robots' directions and sent packets.
834
                                                Edge robots should now turn to face the right direction. */
835
                                        case 1:
836
                                                send2(CIRCLE_ACTION_DONE,robotid);
837
                                                bom_on();
838
                                                state = 2;
839
                                        break;
840
                                }
841

    
842
                        break;
843

    
844

    
845
                        /* The DRIVE code for the beacon */
846
                        case 23:
847

    
848
                                switch(beacon_State)
849
                                {
850

    
851
                                        /* Tells the robots to move forward and moves itself. */
852
                                        case 0:
853
                                                orb_set_color(YELLOW);
854
                                                delay_ms(5000);
855

    
856
                                                // format: type of ack, speed divided by 10, time in seconds.
857
                                                send3(CIRCLE_ACTION_FORWARD,20,2);
858
                                                orb_set_color(BLUE);
859
                                                forward(200);
860
                                                delay_ms(2000);
861
                                                stop();
862
                                                beacon_State = 1;
863
                                        break;
864

    
865
                                        /* Terminal. */
866
                                        case 1:
867
                                                stop();
868
                                                state = 2;
869
                                        break;
870
                                }
871
                        break;
872

    
873
//***********************************************************************************************************************************************************************************
874
                        
875
                }        // ends the main switch
876
        }                // ends the main while loop
877

    
878
        orb_set_color(RED);        // error, we should never break from the while loop!
879

    
880
        while(1); /* END HERE, just in case something happened.  This way we can see the red orb. */
881
}
882

    
883