Statistics
| Revision:

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

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