Statistics
| Revision:

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

History | View | Annotate | Download (21.9 KB)

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