Statistics
| Revision:

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

History | View | Annotate | Download (23.2 KB)

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