Statistics
| Revision:

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

History | View | Annotate | Download (21.7 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 aboutFace(int goal)
207
{
208
        int goala = goal;
209
        int goalb = goal + 8;                        // the inverse of the goal direction, across the BOM.
210
        if(goalb >= 16) { goalb -= 16; }
211
212
        int inv = 0;
213
        if(goala > goalb)
214
        {
215
                goala = goalb;
216
                goalb = goal;
217
                inv = 1;
218
        }        
219
220
        orb1_set_color(BLUE);                        // BLUE and PURPLE
221
        left(220);
222
        while(1)
223
        {
224
                // bomNum is the current maximum reading
225
                bom_refresh(BOM_ALL);
226
                int bomNum = bom_get_max();
227
                if(bomNum == goal)                                // when it's turned the right way, stop
228
                {
229
                        timeout = 0;
230
                        stop();
231
                        break;                                // exits the while() loop to stop the method
232
                }
233
                else                                        // facing the wrong way
234
                {
235
236
                        if(bomNum == -1)
237
                        {
238
                                timeout++;
239
                                
240
                                if(timeout > 5000)        // if it's been looking too long, move a little bit as it turns
241
                                {
242
                                        motor_r_set(FORWARD, 210);
243
                                        motor_l_set(BACKWARD, 190);
244
                                }
245
                        }
246
                        else if((bomNum >= goalb) || (bomNum < goala))
247
                        {
248
                                if(inv)
249
                                        right(200);
250
                                else
251
                                        left(200);
252
                                timeout = 0;
253
                        }
254
                        else
255
                        {
256
                                if(inv)
257
                                        left(200);
258
                                else
259
                                        right(200);
260
                                timeout = 0;
261
                        }
262
                }
263
        }
264
        return;
265
}
266
267
268
/* 
269
    BLINK the given number times
270
*/
271
void blink(int num)
272
{
273
        for(int i = 0; i<num; i++)
274
        {
275
                orb_set_color(ORB_OFF);
276
                delay_ms(150);
277
                orb_set_color(RED);
278
                delay_ms(50);
279
        }
280
        orb_set_color(ORB_OFF);
281
}
282
283
/* 
284
    BLINK slowly the given number times
285
*/
286
void slowblink(int num)
287
{
288
        for(int i = 0; i<num; i++)
289
        {
290
                orb_set_color(ORB_OFF);
291
                delay_ms(300);
292
                orb_set_color(RED);
293
                delay_ms(200);
294
        }
295
        orb_set_color(ORB_OFF);
296
}
297
298
void order(int action)
299
{
300
        currentPos++;
301
        send2(CIRCLE_EXECUTE, action);
302
        state = 20 + action;
303
}
304
305
void terminate(void)
306
{
307
        send2(CIRCLE_EXECUTE, 100);
308
        orb_set_color(GREEN);
309
        orb2_set_color(WHITE);
310
        while(1) ;
311
}
312
313
314
315
316
//*****************************************************************************************************************************************************************************************
317
//*****************************************************************************************************************************************************************************************
318
//*****************************************************************************************************************************************************************************************
319
320
321
/*
322
        A state machine with five states.  The robot starts out in WAITINGSTATE mode, from which
323
        it recieves a signal of some sort and moves to a different state.
324
*/
325
int main(void)
326
{
327
        /* Initialize dragonfly board */
328
            dragonfly_init(ALL_ON);
329
            /* Initialize the basic wireless library */
330
            wl_basic_init_default();
331
            /* Set the XBee channel to 24 - must be standard among robots */
332
        wl_set_channel(24);
333
334
        int robotid = get_robotid();
335
        int centerid = 0;                // once the EDGE gets the first signal from a center, it stores who the center is.
336
        int used[17];                        // stores a list of bots which are in the group by storing a "1" in the array if the robot of that index is in the group.
337
        for (int i=0; i<17; i++) used[i] = 0;                // initially, no robots in the group.
338
339
        int data_length;                // keeps track of the length of wireless packets received.
340
        unsigned char *packet_data=wl_basic_do_default(&data_length);
341
        
342
        int beacon_State=0;                // these variables keep track of the inner state machines in the procedural MACHINE states.
343
        int edge_State=0;
344
345
        int waitingCounter=0;
346
        int robotsReceived=0;                // an important variable that stores the size of the group.
347
        int offset = 20;                // offset for the approaching: how far off the rangefinders can be
348
        int time=0;
349
        int direction = 4;                // keeps track of which way robots are facing relative to the center
350
        int distance=1000;                // how far away the robot is.  Initialized to a large value to ensure that the robot doesn't think it is already the
351
                                                // right distance away.
352
        int onefoot = 250;                // how far away to stop.
353
        
354
        while(1)
355
        {
356
                bom_refresh(BOM_ALL);
357
358
                                /*                
359
                                *******EXPECTED MOVES **********   (OUT OF DATE.  Will be updated once changes have been made.)
360
                                The designed movement:
361
                                 1. one center robot, several edge robots are on;
362
                                 2. center robots: button 1 is pressed;
363
                                 3. center robots: send global package telling edges that he exists;
364
                                 4. EDGE robots response with ACK. 
365
                                 5. EDGE robots wait for center robots to finish counting (DONE package)
366
                                 6. EDGE robtos approach the center robtot and stop at the "onefoot" distance, send message to the center
367
                                */
368
                
369
                
370
                /* This is the MAIN SWITCH LOOP, which governs the overall status of the robot. */
371
                switch(state)
372
                {
373
374
375
                        /*
376
                                The WAITINGSTATE.  This state constantly checks for wireless packets,
377
                                and updates its state as soon as it receives a signal.
378
                        */
379
                        case 0:
380
381
                                orb_set_color(YELLOW);
382
                                packet_data=wl_basic_do_default(&data_length);
383
                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_CLAIM_CENTER)
384
                                {
385
                                        centerid = packet_data[1];
386
387
                                        state = 1;
388
                                }
389
390
                                if(button1_read())
391
                                {
392
                                        send2(CIRCLE_CLAIM_CENTER, robotid);         // becomes the center if button1 is clicked.
393
                                        state = 2;
394
                                }
395
396
                        break;
397
398
399
400
//***********************************************************************************************************************************************************************************
401
402
403
404
                        /*
405
                                The CONTROL for the EDGE state.  This sets a certain procedure to follow, in the form of simple
406
                                commands, for a robot to follow if it is set to an EDGE.
407
                        */
408
409
                        case 1:
410
                                orb_set_color(CYAN);
411
                                orb1_set_color(YELLOW);
412
413
                                int command = -1;
414
                                
415
                                packet_data=wl_basic_do_default(&data_length);
416
                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_EXECUTE)
417
                                {
418
                                        command = packet_data[1];
419
                                }
420
421
                                if(command != -1)
422
                                {
423
                                        edge_State = 0;
424
                                        switch(command)
425
                                        {
426
                                                case 0:
427
                                                        state = 10; break;
428
429
                                                case 1:
430
                                                        state = 11; break;
431
432
                                                case 2:
433
                                                        state = 12; break;
434
435
                                                case 3:
436
                                                        state = 13; break;
437
438
                                                case 100:
439
                                                        terminate(); break;
440
                                        }
441
                                }
442
443
                        break;
444
445
446
447
//***********************************************************************************************************************************************************************************
448
449
450
451
                        /*
452
                                The CONTROL for the BEACON state.  This sets a certain procedure to follow, in the form of simple
453
                                commands, for a robot to follow if it is set to a BEACON.
454
                        */
455
                        case 2:
456
                                orb_set_color(PURPLE);
457
                                beacon_State = 0;
458
                                
459
                                switch(currentPos)
460
                                {
461
                                        case 0:
462
                                                order(COUNT);        break;
463
464
                                        case 1:
465
                                                order(CIRCLEUP); break;
466
467
                                        case 2:
468
                                                order(ORIENT); break;
469
470
                                        case 3:
471
                                                order(DRIVE); break;
472
473
                                        case 4:
474
                                                terminate(); break;
475
                                }
476
                                
477
                        break;
478
479
480
481
//***********************************************************************************************************************************************************************************
482
483
484
                        /* The following states are MACHINE states for the EDGE robot. */
485
486
                        /*
487
                                EDGE on COUNT
488
                        */
489
                        case 10:        
490
491
492
                                switch(edge_State)
493
                                {
494
                                        /*
495
                                                0. EDGE robots are on. 
496
                                                1. They are waiting for EXIST pacakage from the Center robots
497
                                                2. After they receive the package, they send ACK package to center.
498
                                                3. Done for now: display green.
499
                                        */
500
                                        case 0:
501
                                                bom_off();
502
                                                orb1_set_color(YELLOW);
503
                                                orb2_set_color(BLUE);
504
                                                packet_data=wl_basic_do_default(&data_length);
505
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_EXIST)
506
                                                {
507
                                                        centerid = packet_data[1];
508
509
                                                        send2(CIRCLE_ACTION_ACK,robotid);
510
511
                                                        edge_State=1;
512
                                                }
513
                                        break;
514
                                        /*
515
                                                1. Wait for DONE package 
516
                                                2. The counting process is DONE
517
                                        */
518
                                        case 1:                
519
                                        
520
                                                orb_set_color(YELLOW);
521
                                                orb2_set_color(PURPLE);
522
523
                                                send2(CIRCLE_ACTION_ACK,robotid);                // keep sending the packet until we get a response
524
                                                
525
                                                packet_data=wl_basic_do_default(&data_length);
526
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_GOTYOU && packet_data[1] == robotid)
527
                                                {
528
                                                        edge_State=2;
529
                                                }
530
                                        break;
531
532
                                        case 2:        // wait for the second, general, done packet.
533
534
                                                orb_set_color(YELLOW);
535
                                                packet_data=wl_basic_do_default(&data_length);
536
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_DONE && packet_data[1] == centerid)
537
                                                {
538
                                                        state = 1;
539
                                                }
540
                                        break;
541
                                }
542
543
                        break;
544
545
                        /* The CIRCLEUP command for EDGE */
546
547
                        case 11:
548
549
                                switch(edge_State)
550
                                {
551
                                        
552
                                        case 0:
553
                                                // COLOR afer DONE ---> MAGENTA
554
                                                orb_set_color(MAGENTA);
555
                                                aboutFace(4);                        // turn to face the beacon
556
                                                forward(175);
557
                                                //range_init();
558
                                                
559
                                                
560
                                                distance = get_distance();
561
                                                time=0;
562
                                                while ((distance-offset)>=onefoot || distance==0 || (distance+offset)<onefoot)
563
                                                {
564
                                                        if(distance==0)
565
                                                                orb_set_color(WHITE);
566
                                                        else if(distance-offset>=onefoot)
567
                                                                forward(175);
568
                                                        else
569
                                                                backward(175);
570
                                                        //correctApproach();
571
                                                        distance = get_distance();
572
                                                        delay_ms(14);
573
                                                        time+=14;
574
                                                        if(time>50)
575
                                                        {
576
                                                                aboutFace(4);
577
                                                                time=0;
578
                                                        }
579
                                                }
580
                                                        
581
                                                stop();
582
                                                orb_set_color(GREEN);
583
584
                                                send2(CIRCLE_ACTION_ACK, robotid);
585
586
                                                stop();
587
                                                state = 1;
588
                                        break;
589
590
                                }
591
592
593
                        break;
594
                
595
                        /* An ORIENT series of steps for the EDGE robot. */
596
597
                        case 12:
598
                        
599
600
                                switch(edge_State)
601
                                {
602
603
                                        // waits for a packet to tell it to turn on the bom.
604
                                        case 0:
605
                                                packet_data=wl_basic_do_default(&data_length);
606
                                                if(packet_data != 0 && data_length==2 && packet_data[0]==CIRCLE_ACTION_GOTYOU && packet_data[1] == robotid)
607
                                                {
608
                                                        bom_on();
609
                                                        orb_set_color(ORANGE);
610
                                                        send2(CIRCLE_ACTION_ACK,centerid);
611
                                                        edge_State = 1;
612
                                                }
613
                                        break;
614
615
                                        // waits for a packet to tell it that it has been received.
616
                                        case 1:
617
                                                orb2_set_color(YELLOW);
618
                                                packet_data=wl_basic_do_default(&data_length);
619
                                                if(packet_data != 0 && data_length==3 && packet_data[0]==CIRCLE_ACTION_GOTYOU && packet_data[1] == robotid)
620
                                                {
621
                                                        bom_off();
622
                                                        direction = packet_data[2];
623
                                                        orb_set_color(YELLOW);
624
                                                        edge_State = 2;
625
                                                }
626
                                        break;
627
628
                                        /* Wait for the center bot to send a DONE packet; then turn to face the right direction. */
629
                                        case 2:
630
                                                orb_set_color(GREEN);
631
                                                packet_data=wl_basic_do_default(&data_length);
632
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_DONE)
633
                                                {
634
                                                        orb_set_color(WHITE);
635
                                                        orb2_set_color(CYAN);
636
                                                        edge_State = 3;
637
                                                }
638
                                        break;
639
640
                                        /* Turn until we reach the right direction (DIRECTION) */
641
                                        case 3:
642
                                                aboutFace(direction);
643
                                        break;
644
645
                                }
646
647
648
                        break;
649
650
651
                        /* The MOVE steps for the EDGE robot */
652
653
                        case 13:
654
655
                                switch(edge_State)
656
                                {
657
                                
658
                                        /* Wait for the command to move forward. */
659
                                        case 0:
660
                                                packet_data=wl_basic_do_default(&data_length);
661
                                                if(packet_data != 0 && data_length>=3 && packet_data[0]==CIRCLE_ACTION_FORWARD)
662
                                                {
663
                                                        orb_set_color(BLUE);
664
                                                        forward(packet_data[1]*10);
665
                                                        delay_ms(packet_data[2]*1000);
666
                                                        edge_State = 1;
667
                                                }
668
                                        break;
669
670
                                        /* Terminal. */
671
                                        case 1:
672
                                                stop();
673
                                                state = 1;
674
                                        break;
675
676
677
                                }        // end the EdgeState switch
678
679
                        break;                // break the Edge state in the main switch loop
680
                                
681
                        // END for EDGE robots
682
                        
683
684
685
686
687
688
//***********************************************************************************************************************************************************************************
689
690
691
692
693
                        /*
694
                           The MACHINE for the BEACON state
695
                        */
696
697
                        /* the COUNT code for the BEACON */
698
                        case 20:
699
                                switch(beacon_State) 
700
                                {
701
702
                                        /* 0. center  robots on wait for pressing button 1 */
703
                                        case 0:
704
                                                bom_on();
705
                                                orb_set_color(BLUE);
706
                                                robotsReceived = 0;
707
                                                beacon_State=1;
708
                                        break;        
709
710
                                        /* 1. Send EXIST package to EDGE robots */
711
                                        case 1:
712
                                                orb_set_color(RED);
713
                                                send2(CIRCLE_ACTION_EXIST,robotid);
714
                                                beacon_State=2;
715
                                        break;
716
717
                                        /* 2. Count the number of the EDGE robots *******NOTE: at most  1000  times of loop ******  */
718
                                        case 2:
719
                                                waitingCounter++;
720
                                                orb1_set_color(YELLOW);
721
                                                orb2_set_color(BLUE);
722
                                                packet_data=wl_basic_do_default(&data_length);
723
                                        
724
                                                if(packet_data!=0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_ACK)
725
                                                {
726
                                                        orb_set_color(RED);
727
                                                        orb2_set_color(BLUE);
728
                                                        //only add to robots seen if you haven't gotten an ACK from this robot
729
                                                        if(used[packet_data[1]]==0)
730
                                                        {
731
                                                                robotsReceived++;
732
                                                                used[packet_data[1]] = 1;
733
734
                                                                usb_puts("Added: ");
735
                                                                usb_puti(packet_data[1]);
736
                                                                usb_puts("\r\n");
737
                                                        }
738
739
                                                        // NEW: sends a packet to each robot it receives telling them to be done.
740
                                                        send2(CIRCLE_ACTION_GOTYOU,packet_data[1]);
741
                                                }
742
                                                if(waitingCounter >= 300){
743
                                                        beacon_State=3;
744
                                                }
745
                                        break;
746
747
                                        /* COUNTing is DONE.  Sending DONE package. */        
748
                                        case 3:
749
                                                blink(robotsReceived);
750
                                                orb_set_color(GREEN);
751
                                                send2(CIRCLE_ACTION_DONE, robotid);
752
                                                state = 2;
753
                                        break;
754
                                }
755
756
                        break;
757
758
                        /* The CIRCLEUP method for BEACON */
759
                        case 21:
760
761
                                switch(beacon_State)
762
                                {
763
764
                                        /* Wait for all the robots to get to right distance/position */
765
                                        case 0: 
766
                                                left(170);
767
                                                orb1_set_color(YELLOW);
768
                                                orb2_set_color(WHITE);
769
                                        
770
                                                int numOk = 0;
771
                                        
772
                                                while(numOk<robotsReceived)
773
                                                {
774
                                                        packet_data=wl_basic_do_default(&data_length);
775
                                                        if(packet_data!=0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_ACK)
776
                                                        {
777
                                                                numOk++;
778
                                                        }
779
                                                }
780
                                        
781
                                                state = 2;
782
                                        break;
783
                                }
784
785
                        break;
786
787
788
                        /* The ORIENT code for the beacon */
789
                        case 22:
790
791
                                switch(beacon_State)
792
                                {
793
                                        /* Turns all the robots in the same direction */
794
                                        case 0:
795
                                                stop();
796
                                                bom_off();
797
                                                orb_set_color(ORANGE);
798
                                                
799
                                                // for each robot, tells them to turn their bom on, then tells them which way they should face.
800
                                                for(int i=0; i < 17; i++)
801
                                                {
802
                                                        if(used[i] == 1)
803
                                                        {
804
                                                                send2(CIRCLE_ACTION_GOTYOU, i);
805
                                                                while(1)        // waits for a response so it knows the BOM is on.
806
                                                                {
807
                                                                        orb_set_color(RED);
808
                                                                        orb2_set_color(WHITE);
809
                                                                        packet_data=wl_basic_do_default(&data_length);
810
                                                                        if(packet_data!=0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_ACK)
811
                                                                        {
812
                                                                                orb_set_color(ORANGE);
813
                                                                                break;
814
                                                                        }
815
                                                                }
816
817
                                                                bom_refresh(BOM_ALL);
818
                                                                direction = bom_get_max();
819
                                                                direction += 8;
820
                                                                if(direction > 15) direction -= 16;
821
                                                                send3(CIRCLE_ACTION_GOTYOU, i, direction);
822
                                                                delay_ms(20);
823
                                                        }
824
                                                }
825
                                                beacon_State = 1;
826
                                        break;
827
                        
828
                                        /* Sends a DONE packet to signify that it has read in all the robots' directions and sent packets.
829
                                                Edge robots should now turn to face the right direction. */
830
                                        case 1:
831
                                                send2(CIRCLE_ACTION_DONE,robotid);
832
                                                bom_on();
833
                                                state = 2;
834
                                        break;
835
                                }
836
837
                        break;
838
839
840
                        /* The DRIVE code for the beacon */
841
                        case 23:
842
843
                                switch(beacon_State)
844
                                {
845
846
                                        /* Tells the robots to move forward and moves itself. */
847
                                        case 0:
848
                                                orb_set_color(YELLOW);
849
                                                delay_ms(5000);
850
851
                                                // format: type of ack, speed divided by 10, time in seconds.
852
                                                send3(CIRCLE_ACTION_FORWARD,20,2);
853
                                                orb_set_color(BLUE);
854
                                                forward(200);
855
                                                delay_ms(2000);
856
                                                stop();
857
                                                beacon_State = 1;
858
                                        break;
859
860
                                        /* Terminal. */
861
                                        case 1:
862
                                                stop();
863
                                                state = 2;
864
                                        break;
865
                                }
866
                        break;
867
868
//***********************************************************************************************************************************************************************************
869
                        
870
                }        // ends the main switch
871
        }                // ends the main while loop
872
873
        orb_set_color(RED);        // error, we should never break from the while loop!
874
875
        while(1); /* END HERE, just in case something happened.  This way we can see the red orb. */
876
}
877
878