Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (21.8 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 inverse = (goal + 8) % 16;        // the inverse of the goal direction, across the BOM.
209
        int bomNum = -1;
210
        int speed;        // speed with which to turn
211

    
212
        orb1_set_color(BLUE);                        // BLUE and PURPLE
213
        left(180);
214
        while(bomNum != goal)
215
        {
216
                // bomNum is the current maximum reading
217
                bom_refresh(BOM_ALL);
218
                bomNum = bom_get_max();
219
                if(bomNum == -1)        // no other robots visible
220
                {
221
                        timeout++;
222
                        
223
                        if(timeout > 50)        // if it's been looking too long, move a little bit as it turns
224
                        {
225
                                motor_r_set(FORWARD, 210);
226
                                motor_l_set(BACKWARD, 190);
227
                        }
228
                }
229
                else if (goal > inverse)
230
                {
231
                        if (bomNum < goal && bomNum > inverse)        // goal clockwise of position
232
                        {
233
                                speed = 160 + 10 * (goal - bomNum);
234
                                right(180);
235
                        }
236
                        else        // goal counterclockwise of position
237
                        {
238
                                speed = 160 + 10 * ((bomNum > goal) ? bomNum - goal : goal - bomNum);
239
                                left(180);
240
                        }
241
                        timeout = 0;
242
                }
243
                else        // goal < inverse
244
                {
245
                        if (bomNum > goal && bomNum < inverse)        // goal counterclockwise of position
246
                        {
247
                                speed = 160 + 10 * (bomNum - goal);
248
                                left(180);
249
                        }
250
                        else
251
                        {
252
                                speed = 160 + 10 * ((bomNum < goal) ? goal - bomNum : bomNum - goal);
253
                                right(180);
254
                        }
255
                        timeout = 0;
256
                }
257
        }
258
        return;
259
}
260

    
261

    
262
/* 
263
    BLINK the given number times
264
*/
265
void blink(int num)
266
{
267
        for(int i = 0; i<num; i++)
268
        {
269
                orb_set_color(ORB_OFF);
270
                delay_ms(150);
271
                orb_set_color(RED);
272
                delay_ms(50);
273
        }
274
        orb_set_color(ORB_OFF);
275
}
276

    
277
/* 
278
    BLINK slowly the given number times
279
*/
280
void slowblink(int num)
281
{
282
        for(int i = 0; i<num; i++)
283
        {
284
                orb_set_color(ORB_OFF);
285
                delay_ms(300);
286
                orb_set_color(RED);
287
                delay_ms(200);
288
        }
289
        orb_set_color(ORB_OFF);
290
}
291

    
292
void order(int action)
293
{
294
        currentPos++;
295
        send2(CIRCLE_EXECUTE, action);
296
        state = 20 + action;
297
}
298

    
299
void terminate(void)
300
{
301
        send2(CIRCLE_EXECUTE, 100);
302
        orb_set_color(GREEN);
303
        orb2_set_color(WHITE);
304
        while(1) ;
305
}
306

    
307

    
308

    
309

    
310
//*****************************************************************************************************************************************************************************************
311
//*****************************************************************************************************************************************************************************************
312
//*****************************************************************************************************************************************************************************************
313

    
314

    
315
/*
316
        A state machine with five states.  The robot starts out in WAITINGSTATE mode, from which
317
        it recieves a signal of some sort and moves to a different state.
318
*/
319
int main(void)
320
{
321
        /* Initialize dragonfly board */
322
            dragonfly_init(ALL_ON);
323
            /* Initialize the basic wireless library */
324
            wl_basic_init_default();
325
            /* Set the XBee channel to 24 - must be standard among robots */
326
        wl_set_channel(24);
327

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

    
333
        int data_length;                // keeps track of the length of wireless packets received.
334
        unsigned char *packet_data=wl_basic_do_default(&data_length);
335
        
336
        int beacon_State=0;                // these variables keep track of the inner state machines in the procedural MACHINE states.
337
        int edge_State=0;
338

    
339
        int waitingCounter=0;
340
        int robotsReceived=0;                // an important variable that stores the size of the group.
341
        int offset = 20;                // offset for the approaching: how far off the rangefinders can be
342
        int time=0;
343
        int direction = 4;                // keeps track of which way robots are facing relative to the center
344
        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
345
                                                // right distance away.
346
        int onefoot = 250;                // how far away to stop.
347
        
348
        while(1)
349
        {
350
                bom_refresh(BOM_ALL);
351

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

    
368

    
369
                        /*
370
                                The WAITINGSTATE.  This state constantly checks for wireless packets,
371
                                and updates its state as soon as it receives a signal.
372
                        */
373
                        case 0:
374

    
375
                                orb_set_color(YELLOW);
376
                                packet_data=wl_basic_do_default(&data_length);
377
                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_CLAIM_CENTER)
378
                                {
379
                                        centerid = packet_data[1];
380

    
381
                                        state = 1;
382
                                }
383

    
384
                                if(button1_read())
385
                                {
386
                                        send2(CIRCLE_CLAIM_CENTER, robotid);         // becomes the center if button1 is clicked.
387
                                        state = 2;
388
                                }
389

    
390
                        break;
391

    
392

    
393

    
394
//***********************************************************************************************************************************************************************************
395

    
396

    
397

    
398
                        /*
399
                                The CONTROL for the EDGE state.  This sets a certain procedure to follow, in the form of simple
400
                                commands, for a robot to follow if it is set to an EDGE.
401
                        */
402

    
403
                        case 1:
404
                                orb_set_color(CYAN);
405
                                orb1_set_color(YELLOW);
406

    
407
                                int command = -1;
408
                                
409
                                packet_data=wl_basic_do_default(&data_length);
410
                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_EXECUTE)
411
                                {
412
                                        command = packet_data[1];
413
                                }
414

    
415
                                if(command != -1)
416
                                {
417
                                        edge_State = 0;
418
                                        switch(command)
419
                                        {
420
                                                case 0:
421
                                                        state = 10; break;
422

    
423
                                                case 1:
424
                                                        state = 11; break;
425

    
426
                                                case 2:
427
                                                        state = 12; break;
428

    
429
                                                case 3:
430
                                                        state = 13; break;
431

    
432
                                                case 100:
433
                                                        terminate(); break;
434
                                        }
435
                                }
436

    
437
                        break;
438

    
439

    
440

    
441
//***********************************************************************************************************************************************************************************
442

    
443

    
444

    
445
                        /*
446
                                The CONTROL for the BEACON state.  This sets a certain procedure to follow, in the form of simple
447
                                commands, for a robot to follow if it is set to a BEACON.
448
                        */
449
                        case 2:
450
                                orb_set_color(PURPLE);
451
                                beacon_State = 0;
452
                                
453
                                switch(currentPos)
454
                                {
455
                                        case 0:
456
                                                order(COUNT);        break;
457

    
458
                                        case 1:
459
                                                order(CIRCLEUP); break;
460

    
461
                                        case 2:
462
                                                order(ORIENT); break;
463

    
464
                                        case 3:
465
                                                order(DRIVE); break;
466

    
467
                                        case 4:
468
                                                terminate(); break;
469
                                }
470
                                
471
                        break;
472

    
473

    
474

    
475
//***********************************************************************************************************************************************************************************
476

    
477

    
478
                        /* The following states are MACHINE states for the EDGE robot. */
479

    
480
                        /*
481
                                EDGE on COUNT
482
                        */
483
                        case 10:        
484

    
485

    
486
                                switch(edge_State)
487
                                {
488
                                        /*
489
                                                0. EDGE robots are on. 
490
                                                1. They are waiting for EXIST pacakage from the Center robots
491
                                                2. After they receive the package, they send ACK package to center.
492
                                                3. Done for now: display green.
493
                                        */
494
                                        case 0:
495
                                                bom_off();
496
                                                orb1_set_color(YELLOW);
497
                                                orb2_set_color(BLUE);
498
                                                packet_data=wl_basic_do_default(&data_length);
499
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_EXIST)
500
                                                {
501
                                                        centerid = packet_data[1];
502

    
503
                                                        send2(CIRCLE_ACTION_ACK,robotid);
504

    
505
                                                        edge_State=1;
506
                                                }
507
                                        break;
508
                                        /*
509
                                                1. Wait for DONE package 
510
                                                2. The counting process is DONE
511
                                        */
512
                                        case 1:                
513
                                        
514
                                                orb_set_color(YELLOW);
515
                                                orb2_set_color(PURPLE);
516

    
517
                                                send2(CIRCLE_ACTION_ACK,robotid);                // keep sending the packet until we get a response
518
                                                
519
                                                packet_data=wl_basic_do_default(&data_length);
520
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_GOTYOU && packet_data[1] == robotid)
521
                                                {
522
                                                        edge_State=2;
523
                                                }
524
                                        break;
525

    
526
                                        case 2:        // wait for the second, general, done packet.
527

    
528
                                                orb_set_color(YELLOW);
529
                                                packet_data=wl_basic_do_default(&data_length);
530
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_DONE && packet_data[1] == centerid)
531
                                                {
532
                                                        state = 1;
533
                                                }
534
                                        break;
535
                                }
536

    
537
                        break;
538

    
539
                        /* The CIRCLEUP command for EDGE */
540

    
541
                        case 11:
542

    
543
                                switch(edge_State)
544
                                {
545
                                        
546
                                        case 0:
547
                                                // COLOR afer DONE ---> MAGENTA
548
                                                orb_set_color(MAGENTA);
549
                                                aboutFace(4);                        // turn to face the beacon
550
                                                forward(175);
551
                                                //range_init();
552
                                                
553
                                                
554
                                                distance = get_distance();
555
                                                time=0;
556
                                                while ((distance-offset)>=onefoot || distance==0 || (distance+offset)<onefoot)
557
                                                {
558
                                                        if(distance==0)
559
                                                                orb_set_color(WHITE);
560
                                                        else if(distance-offset>=onefoot)
561
                                                                forward(175);
562
                                                        else
563
                                                                backward(175);
564
                                                        //correctApproach();
565
                                                        distance = get_distance();
566
                                                        delay_ms(14);
567
                                                        time+=14;
568
                                                        if(time>50)
569
                                                        {
570
                                                                aboutFace(4);
571
                                                                time=0;
572
                                                        }
573
                                                }
574
                                                        
575
                                                stop();
576
                                                orb_set_color(GREEN);
577

    
578
                                                send2(CIRCLE_ACTION_ACK, robotid);
579

    
580
                                                stop();
581
                                                state = 1;
582
                                        break;
583

    
584
                                }
585

    
586

    
587
                        break;
588
                
589
                        /* An ORIENT series of steps for the EDGE robot. */
590

    
591
                        case 12:
592
                        
593

    
594
                                switch(edge_State)
595
                                {
596

    
597
                                        // waits for a packet to tell it to turn on the bom.
598
                                        case 0:
599
                                                packet_data=wl_basic_do_default(&data_length);
600
                                                if(packet_data != 0 && data_length==2 && packet_data[0]==CIRCLE_ACTION_GOTYOU && packet_data[1] == robotid)
601
                                                {
602
                                                        bom_on();
603
                                                        orb_set_color(ORANGE);
604
                                                        send2(CIRCLE_ACTION_ACK,centerid);
605
                                                        edge_State = 1;
606
                                                }
607
                                        break;
608

    
609
                                        // waits for a packet to tell it that it has been received.
610
                                        case 1:
611
                                                orb2_set_color(YELLOW);
612
                                                packet_data=wl_basic_do_default(&data_length);
613
                                                if(packet_data != 0 && data_length==3 && packet_data[0]==CIRCLE_ACTION_GOTYOU && packet_data[1] == robotid)
614
                                                {
615
                                                        bom_off();
616
                                                        direction = packet_data[2];
617
                                                        orb_set_color(YELLOW);
618
                                                        edge_State = 2;
619
                                                }
620
                                        break;
621

    
622
                                        /* Wait for the center bot to send a DONE packet; then turn to face the right direction. */
623
                                        case 2:
624
                                                orb_set_color(GREEN);
625
                                                packet_data=wl_basic_do_default(&data_length);
626
                                                if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_DONE)
627
                                                {
628
                                                        orb_set_color(WHITE);
629
                                                        orb2_set_color(CYAN);
630
                                                        edge_State = 3;
631
                                                }
632
                                        break;
633

    
634
                                        /* Turn until we reach the right direction (DIRECTION) */
635
                                        case 3:
636
                                                aboutFace(direction);
637
                                        break;
638

    
639
                                }
640

    
641

    
642
                        break;
643

    
644

    
645
                        /* The MOVE steps for the EDGE robot */
646

    
647
                        case 13:
648

    
649
                                switch(edge_State)
650
                                {
651
                                
652
                                        /* Wait for the command to move forward. */
653
                                        case 0:
654
                                                packet_data=wl_basic_do_default(&data_length);
655
                                                if(packet_data != 0 && data_length>=3 && packet_data[0]==CIRCLE_ACTION_FORWARD)
656
                                                {
657
                                                        orb_set_color(BLUE);
658
                                                        forward(packet_data[1]*10);
659
                                                        delay_ms(packet_data[2]*1000);
660
                                                        edge_State = 1;
661
                                                }
662
                                        break;
663

    
664
                                        /* Terminal. */
665
                                        case 1:
666
                                                stop();
667
                                                state = 1;
668
                                        break;
669

    
670

    
671
                                }        // end the EdgeState switch
672

    
673
                        break;                // break the Edge state in the main switch loop
674
                                
675
                        // END for EDGE robots
676
                        
677

    
678

    
679

    
680

    
681

    
682
//***********************************************************************************************************************************************************************************
683

    
684

    
685

    
686

    
687
                        /*
688
                           The MACHINE for the BEACON state
689
                        */
690

    
691
                        /* the COUNT code for the BEACON */
692
                        case 20:
693
                                switch(beacon_State) 
694
                                {
695

    
696
                                        /* 0. center  robots on wait for pressing button 1 */
697
                                        case 0:
698
                                                bom_on();
699
                                                orb_set_color(BLUE);
700
                                                robotsReceived = 0;
701
                                                beacon_State=1;
702
                                        break;        
703

    
704
                                        /* 1. Send EXIST package to EDGE robots */
705
                                        case 1:
706
                                                orb_set_color(RED);
707
                                                send2(CIRCLE_ACTION_EXIST,robotid);
708
                                                beacon_State=2;
709
                                        break;
710

    
711
                                        /* 2. Count the number of the EDGE robots *******NOTE: at most  1000  times of loop ******  */
712
                                        case 2:
713
                                                waitingCounter++;
714
                                                orb1_set_color(YELLOW);
715
                                                orb2_set_color(BLUE);
716
                                                packet_data=wl_basic_do_default(&data_length);
717
                                        
718
                                                if(packet_data!=0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_ACK)
719
                                                {
720
                                                        orb_set_color(RED);
721
                                                        orb2_set_color(BLUE);
722
                                                        //only add to robots seen if you haven't gotten an ACK from this robot
723
                                                        if(used[packet_data[1]]==0)
724
                                                        {
725
                                                                robotsReceived++;
726
                                                                used[packet_data[1]] = 1;
727

    
728
                                                                usb_puts("Added: ");
729
                                                                usb_puti(packet_data[1]);
730
                                                                usb_puts("\r\n");
731
                                                        }
732

    
733
                                                        // NEW: sends a packet to each robot it receives telling them to be done.
734
                                                        send2(CIRCLE_ACTION_GOTYOU,packet_data[1]);
735
                                                }
736
                                                if(waitingCounter >= 300){
737
                                                        beacon_State=3;
738
                                                }
739
                                        break;
740

    
741
                                        /* COUNTing is DONE.  Sending DONE package. */        
742
                                        case 3:
743
                                                blink(robotsReceived);
744
                                                orb_set_color(GREEN);
745
                                                send2(CIRCLE_ACTION_DONE, robotid);
746
                                                state = 2;
747
                                        break;
748
                                }
749

    
750
                        break;
751

    
752
                        /* The CIRCLEUP method for BEACON */
753
                        case 21:
754

    
755
                                switch(beacon_State)
756
                                {
757

    
758
                                        /* Wait for all the robots to get to right distance/position */
759
                                        case 0: 
760
                                                left(170);
761
                                                orb1_set_color(YELLOW);
762
                                                orb2_set_color(WHITE);
763
                                        
764
                                                int numOk = 0;
765
                                        
766
                                                while(numOk<robotsReceived)
767
                                                {
768
                                                        packet_data=wl_basic_do_default(&data_length);
769
                                                        if(packet_data!=0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_ACK)
770
                                                        {
771
                                                                numOk++;
772
                                                        }
773
                                                }
774
                                        
775
                                                state = 2;
776
                                        break;
777
                                }
778

    
779
                        break;
780

    
781

    
782
                        /* The ORIENT code for the beacon */
783
                        case 22:
784

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

    
811
                                                                bom_refresh(BOM_ALL);
812
                                                                direction = bom_get_max();
813
                                                                direction += 8;
814
                                                                if(direction > 15) direction -= 16;
815
                                                                send3(CIRCLE_ACTION_GOTYOU, i, direction);
816
                                                                delay_ms(20);
817
                                                        }
818
                                                }
819
                                                beacon_State = 1;
820
                                        break;
821
                        
822
                                        /* Sends a DONE packet to signify that it has read in all the robots' directions and sent packets.
823
                                                Edge robots should now turn to face the right direction. */
824
                                        case 1:
825
                                                send2(CIRCLE_ACTION_DONE,robotid);
826
                                                bom_on();
827
                                                state = 2;
828
                                        break;
829
                                }
830

    
831
                        break;
832

    
833

    
834
                        /* The DRIVE code for the beacon */
835
                        case 23:
836

    
837
                                switch(beacon_State)
838
                                {
839

    
840
                                        /* Tells the robots to move forward and moves itself. */
841
                                        case 0:
842
                                                orb_set_color(YELLOW);
843
                                                delay_ms(5000);
844

    
845
                                                // format: type of ack, speed divided by 10, time in seconds.
846
                                                send3(CIRCLE_ACTION_FORWARD,20,2);
847
                                                orb_set_color(BLUE);
848
                                                forward(200);
849
                                                delay_ms(2000);
850
                                                stop();
851
                                                beacon_State = 1;
852
                                        break;
853

    
854
                                        /* Terminal. */
855
                                        case 1:
856
                                                stop();
857
                                                state = 2;
858
                                        break;
859
                                }
860
                        break;
861

    
862
//***********************************************************************************************************************************************************************************
863
                        
864
                }        // ends the main switch
865
        }                // ends the main while loop
866

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

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

    
872