Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (21.2 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 faceFront(void)
207
{
208
        int bomNum = -1;
209
        orb1_set_color(BLUE);
210
        while(bomNum != 4)
211
        {
212
                bom_refresh(BOM_ALL);
213
                bomNum = bom_get_max();
214
                if(bomNum == -1)
215
                {
216
                        //ignore
217
                }
218
                else if((bomNum < 4) || (bomNum >= 12))
219
                {
220
                        right(200);
221
                }
222
                else
223
                {
224
                        left(200);
225
                }
226
        }
227
        stop();
228
        return;
229
}
230

    
231
void aboutFace(int goal)
232
{
233
        int bomNum = -1;
234
        int speed = 170;        // speed with which to turn
235

    
236
        orb1_set_color(BLUE);                        // BLUE and PURPLE
237
        
238
        while(bomNum != goal)
239
        {
240
                // bomNum is the current maximum reading
241
                bom_refresh(BOM_ALL);
242
                bomNum = bom_get_max();
243
                right(speed);
244
        }
245
        stop();
246
        return;
247
}
248

    
249

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

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

    
280
void order(int action)
281
{
282
        currentPos++;
283
        send2(CIRCLE_EXECUTE, action);
284
        state = 20 + action;
285
}
286

    
287
void terminate(void)
288
{
289
        send2(CIRCLE_EXECUTE, 100);
290
        orb_set_color(GREEN);
291
        orb2_set_color(WHITE);
292
        while(1) ;
293
}
294

    
295

    
296

    
297

    
298
//*****************************************************************************************************************************************************************************************
299
//*****************************************************************************************************************************************************************************************
300
//*****************************************************************************************************************************************************************************************
301

    
302

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

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

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

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

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

    
356

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

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

    
369
                                        state = 1;
370
                                }
371

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

    
378
                        break;
379

    
380

    
381

    
382
//***********************************************************************************************************************************************************************************
383

    
384

    
385

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

    
391
                        case 1:
392
                                orb_set_color(CYAN);
393
                                orb1_set_color(YELLOW);
394

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

    
403
                                if(command != -1)
404
                                {
405
                                        edge_State = 0;
406
                                        switch(command)
407
                                        {
408
                                                case 0:
409
                                                        state = 10; break;
410

    
411
                                                case 1:
412
                                                        state = 11; break;
413

    
414
                                                case 2:
415
                                                        state = 12; break;
416

    
417
                                                case 3:
418
                                                        state = 13; break;
419

    
420
                                                case 100:
421
                                                        terminate(); break;
422
                                        }
423
                                }
424

    
425
                        break;
426

    
427

    
428

    
429
//***********************************************************************************************************************************************************************************
430

    
431

    
432

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

    
446
                                        case 1:
447
                                                order(CIRCLEUP); break;
448

    
449
                                        case 2:
450
                                                order(ORIENT); break;
451

    
452
                                        case 3:
453
                                                order(DRIVE); break;
454

    
455
                                        case 4:
456
                                                terminate(); break;
457
                                }
458
                                
459
                        break;
460

    
461

    
462

    
463
//***********************************************************************************************************************************************************************************
464

    
465

    
466
                        /* The following states are MACHINE states for the EDGE robot. */
467

    
468
                        /*
469
                                EDGE on COUNT
470
                        */
471
                        case 10:        
472

    
473

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

    
491
                                                        send2(CIRCLE_ACTION_ACK,robotid);
492

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

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

    
514
                                        case 2:        // wait for the second, general, done packet.
515

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

    
525
                        break;
526

    
527
                        /* The CIRCLEUP command for EDGE */
528

    
529
                        case 11:
530

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

    
565
                                                send2(CIRCLE_ACTION_ACK, robotid);
566

    
567
                                                stop();
568
                                                state = 1;
569
                                        break;
570

    
571
                                }
572

    
573

    
574
                        break;
575
                
576
                        /* An ORIENT series of steps for the EDGE robot. */
577

    
578
                        case 12:
579
                        
580

    
581
                                switch(edge_State)
582
                                {
583

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

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

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

    
621
                                        /* Turn until we reach the right direction (DIRECTION) */
622
                                        case 3:
623
                                                aboutFace(direction);
624
                                        break;
625

    
626
                                }
627

    
628

    
629
                        break;
630

    
631

    
632
                        /* The MOVE steps for the EDGE robot */
633

    
634
                        case 13:
635

    
636
                                switch(edge_State)
637
                                {
638
                                
639
                                        /* Wait for the command to move forward. */
640
                                        case 0:
641
                                                packet_data=wl_basic_do_default(&data_length);
642
                                                if(packet_data != 0 && data_length>=3 && packet_data[0]==CIRCLE_ACTION_FORWARD)
643
                                                {
644
                                                        orb_set_color(BLUE);
645
                                                        forward(packet_data[1]*10);
646
                                                        delay_ms(packet_data[2]*1000);
647
                                                        edge_State = 1;
648
                                                }
649
                                        break;
650

    
651
                                        /* Terminal. */
652
                                        case 1:
653
                                                stop();
654
                                                state = 1;
655
                                        break;
656

    
657

    
658
                                }        // end the EdgeState switch
659

    
660
                        break;                // break the Edge state in the main switch loop
661
                                
662
                        // END for EDGE robots
663
                        
664

    
665

    
666

    
667

    
668

    
669
//***********************************************************************************************************************************************************************************
670

    
671

    
672

    
673

    
674
                        /*
675
                           The MACHINE for the BEACON state
676
                        */
677

    
678
                        /* the COUNT code for the BEACON */
679
                        case 20:
680
                                switch(beacon_State) 
681
                                {
682

    
683
                                        /* 0. center  robots on wait for pressing button 1 */
684
                                        case 0:
685
                                                bom_on();
686
                                                orb_set_color(BLUE);
687
                                                robotsReceived = 0;
688
                                                beacon_State=1;
689
                                        break;        
690

    
691
                                        /* 1. Send EXIST package to EDGE robots */
692
                                        case 1:
693
                                                orb_set_color(RED);
694
                                                send2(CIRCLE_ACTION_EXIST,robotid);
695
                                                beacon_State=2;
696
                                        break;
697

    
698
                                        /* 2. Count the number of the EDGE robots *******NOTE: at most  1000  times of loop ******  */
699
                                        case 2:
700
                                                waitingCounter++;
701
                                                orb1_set_color(YELLOW);
702
                                                orb2_set_color(BLUE);
703
                                                packet_data=wl_basic_do_default(&data_length);
704
                                        
705
                                                if(packet_data!=0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_ACK)
706
                                                {
707
                                                        orb_set_color(RED);
708
                                                        orb2_set_color(BLUE);
709
                                                        //only add to robots seen if you haven't gotten an ACK from this robot
710
                                                        if(used[packet_data[1]]==0)
711
                                                        {
712
                                                                robotsReceived++;
713
                                                                used[packet_data[1]] = 1;
714

    
715
                                                                usb_puts("Added: ");
716
                                                                usb_puti(packet_data[1]);
717
                                                                usb_puts("\r\n");
718
                                                        }
719

    
720
                                                        // NEW: sends a packet to each robot it receives telling them to be done.
721
                                                        send2(CIRCLE_ACTION_GOTYOU,packet_data[1]);
722
                                                }
723
                                                if(waitingCounter >= 300){
724
                                                        beacon_State=3;
725
                                                }
726
                                        break;
727

    
728
                                        /* COUNTing is DONE.  Sending DONE package. */        
729
                                        case 3:
730
                                                blink(robotsReceived);
731
                                                orb_set_color(GREEN);
732
                                                send2(CIRCLE_ACTION_DONE, robotid);
733
                                                state = 2;
734
                                        break;
735
                                }
736

    
737
                        break;
738

    
739
                        /* The CIRCLEUP method for BEACON */
740
                        case 21:
741

    
742
                                switch(beacon_State)
743
                                {
744

    
745
                                        /* Wait for all the robots to get to right distance/position */
746
                                        case 0: 
747
                                                left(170);
748
                                                orb1_set_color(YELLOW);
749
                                                orb2_set_color(WHITE);
750
                                        
751
                                                int numOk = 0;
752
                                        
753
                                                while(numOk<robotsReceived)
754
                                                {
755
                                                        packet_data=wl_basic_do_default(&data_length);
756
                                                        if(packet_data!=0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_ACK)
757
                                                        {
758
                                                                numOk++;
759
                                                        }
760
                                                }
761
                                        
762
                                                state = 2;
763
                                        break;
764
                                }
765

    
766
                        break;
767

    
768

    
769
                        /* The ORIENT code for the beacon */
770
                        case 22:
771

    
772
                                switch(beacon_State)
773
                                {
774
                                        /* Turns all the robots in the same direction */
775
                                        case 0:
776
                                                stop();
777
                                                bom_off();
778
                                                orb_set_color(ORANGE);
779
                                                
780
                                                // for each robot, tells them to turn their bom on, then tells them which way they should face.
781
                                                for(int i=0; i < 17; i++)
782
                                                {
783
                                                        if(used[i] == 1)
784
                                                        {
785
                                                                send2(CIRCLE_ACTION_GOTYOU, i);
786
                                                                while(1)        // waits for a response so it knows the BOM is on.
787
                                                                {
788
                                                                        orb_set_color(RED);
789
                                                                        orb2_set_color(WHITE);
790
                                                                        packet_data=wl_basic_do_default(&data_length);
791
                                                                        if(packet_data!=0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_ACK)
792
                                                                        {
793
                                                                                orb_set_color(ORANGE);
794
                                                                                break;
795
                                                                        }
796
                                                                }
797

    
798
                                                                bom_refresh(BOM_ALL);
799
                                                                direction = bom_get_max();
800
                                                                direction += 8;
801
                                                                if(direction > 15) direction -= 16;
802
                                                                send3(CIRCLE_ACTION_GOTYOU, i, direction);
803
                                                                delay_ms(20);
804
                                                        }
805
                                                }
806
                                                beacon_State = 1;
807
                                        break;
808
                        
809
                                        /* Sends a DONE packet to signify that it has read in all the robots' directions and sent packets.
810
                                                Edge robots should now turn to face the right direction. */
811
                                        case 1:
812
                                                send2(CIRCLE_ACTION_DONE,robotid);
813
                                                bom_on();
814
                                                state = 2;
815
                                        break;
816
                                }
817

    
818
                        break;
819

    
820

    
821
                        /* The DRIVE code for the beacon */
822
                        case 23:
823

    
824
                                switch(beacon_State)
825
                                {
826

    
827
                                        /* Tells the robots to move forward and moves itself. */
828
                                        case 0:
829
                                                orb_set_color(YELLOW);
830
                                                delay_ms(5000);
831

    
832
                                                // format: type of ack, speed divided by 10, time in seconds.
833
                                                send3(CIRCLE_ACTION_FORWARD,20,2);
834
                                                orb_set_color(BLUE);
835
                                                forward(200);
836
                                                delay_ms(2000);
837
                                                stop();
838
                                                beacon_State = 1;
839
                                        break;
840

    
841
                                        /* Terminal. */
842
                                        case 1:
843
                                                stop();
844
                                                state = 2;
845
                                        break;
846
                                }
847
                        break;
848

    
849
//***********************************************************************************************************************************************************************************
850
                        
851
                }        // ends the main switch
852
        }                // ends the main while loop
853

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

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

    
859