Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (21.5 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

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

    
248

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

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

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

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

    
294

    
295

    
296

    
297
//*****************************************************************************************************************************************************************************************
298
//*****************************************************************************************************************************************************************************************
299
//*****************************************************************************************************************************************************************************************
300

    
301

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

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

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

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

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

    
355

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

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

    
368
                                        state = 1;
369
                                }
370

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

    
377
                        break;
378

    
379

    
380

    
381
//***********************************************************************************************************************************************************************************
382

    
383

    
384

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

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

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

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

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

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

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

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

    
424
                        break;
425

    
426

    
427

    
428
//***********************************************************************************************************************************************************************************
429

    
430

    
431

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

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

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

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

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

    
460

    
461

    
462
//***********************************************************************************************************************************************************************************
463

    
464

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

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

    
472

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

    
490
                                                        send2(CIRCLE_ACTION_ACK,robotid);
491

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

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

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

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

    
524
                        break;
525

    
526
                        /* The CIRCLEUP command for EDGE */
527

    
528
                        case 11:
529

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

    
565
                                                send2(CIRCLE_ACTION_ACK, robotid);
566

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

    
571
                                }
572

    
573

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

    
578
                        case 12:
579
                        
580

    
581
                                switch(edge_State)
582
                                {
583

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

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

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

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

    
626
                                }
627

    
628

    
629
                        break;
630

    
631

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

    
634
                        case 13:
635

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

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

    
657

    
658
                                }        // end the EdgeState switch
659

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

    
665

    
666

    
667

    
668

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

    
671

    
672

    
673

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

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

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

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

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

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

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

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

    
737
                        break;
738

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

    
742
                                switch(beacon_State)
743
                                {
744

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

    
766
                        break;
767

    
768

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

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

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

    
818
                        break;
819

    
820

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

    
824
                                switch(beacon_State)
825
                                {
826

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

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

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

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

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

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

    
859