Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / traffic_navigation / main-new.c @ 1988

History | View | Annotate | Download (13 KB)

1
/*
2
 * main.c for Traffic Navigation
3
 * Runs the highest level behavior for the Dynamic Traffic Navigation (DTN) SURG
4
 *
5
 * Author: Colony Project, CMU Robotics Club
6
 */
7

    
8
#define MAIN_NEW
9

    
10
#include "traffic_navigation.h"
11
#include "../linefollowing/lineDrive.h"
12
#ifdef MAIN_NEW
13

    
14
#ifdef ORB_INTERSECTION
15
  #define ORB1_DBG_CLR(color) orb1_set_color(color)
16
  #define ORB2_DBG_CLR(color) orb2_set_color(color)
17
#else
18
  #define ORB1_DBG_CLR(color)
19
  #define ORB2_DBG_CLR(color)
20
#endif
21

    
22
#ifdef DEBUG_INTERSECTION
23
  #define DBG_USBS(str) usb_puts(str)
24
#else
25
  #define DBG_USBS(str)
26
#endif
27

    
28
        static int state, sign, turnDir;
29
        static char sendBuffer[PACKET_LENGTH], queuePrevBot, queueNextBot, id, nextDir, nextPath, intersectionNum, resolvPrevBotID = -3;
30
        unsigned char resolvSeed = 0xC9, resolvDraw = 0, resolvPrevBotDraw = 0;
31
        bool done;
32

    
33
        int wirelessPacketHandle(int state);
34
        void enterIntersection(void);
35
        void sendResolv(bool override);
36
        unsigned char resolvRandomNumberGen();
37

    
38
int main (void) {
39
        
40
        /* Initialize the dragonfly boards, the xbee, encoders, lineFollowing */
41
        dragonfly_init(ALL_ON);
42
        xbee_init();
43
        encoders_init();
44
        lineDrive_init();
45
        rtc_init(SIXTEENTH_SECOND, NULL);        
46
        wl_basic_init_default();
47
        wl_set_channel(13);
48
        initializeData();
49
        
50
        id = get_robotid();
51
        sign = 0;
52
        ORB1_DBG_CLR(GREEN);
53
        delay_ms(1000);
54
        ORB1_DBG_CLR(ORB_OFF);
55
        
56
        //Test code
57
        state = SROAD;
58

    
59
        sendBuffer[1] = id;
60

    
61
        /*
62
        doDrive(180);
63
        turn(DOUBLE, ILEFT);
64
        */
65
        /*
66
        while(1)
67
                doDrive(255);
68
        */
69
        
70
        while (1) {
71
                /*DTN Finite State Machine*/
72
                switch(state){
73
                case SROAD:/*Following a normal road*/
74
                        /* implement other road behaviors?
75
                         *    -tailgating
76
                         */
77
      ORB1_DBG_CLR(WHITE);
78
      ORB2_DBG_CLR(ORB_OFF);
79
                        start();
80
                        done = false;
81
                        while(!done){
82
                                sign = doDrive(180);
83
                                switch(sign){
84
                                        case NORMAL:
85
                                        case FINISHED:
86
                                        case LOST:
87
                                        case ERROR:
88
                                                break;
89
                                        default:
90
                                                //we have a barcode!
91
                                                state = SINTERSECTION_ENTER;
92
                                                done = true;
93
                                                break;
94

    
95
                                }
96
                        }
97
                        break;
98
                case SINTERSECTION_ENTER:/*Entering, and in intersection*/
99
                        stop();
100
                        doDrive(0);
101
      ORB1_DBG_CLR(RED);
102
      ORB2_DBG_CLR(ORB_OFF);
103

    
104
                        DBG_USBS("STATE: SINTERSECTION_ENTER\n");
105

    
106
                        /*Intersection queue:
107
                         *Each robot when entering the intersection will check for other robots
108
                         *in the intersection, and insert itself in a queue to go through.
109
                         */
110
                        queuePrevBot = -1; //the bot that will drive before this bot
111
                        queueNextBot = -1; //the bot that will drive after this bot
112
                        resolvPrevBotID = -3; //in the case of a race, the bot that is
113
                                              //to enter the queue before this bot
114
                        resolvPrevBotDraw = 0; //the random priority number that bot has
115
                        resolvDraw = 0; //my random priority number
116
                        
117
                        intersectionNum = getIntersectNum(sign);
118
                        if(intersectionNum == (char) -1){ //invalid
119
                                state = SROAD;
120
                                break;
121
                        }
122
                        turnDir = validateTurn(sign, getTurnType(sign));
123
                        if(turnDir == (char) -1){ //invalid
124
                                state = SROAD;
125
                                break;
126
                        }
127

    
128
                        enterIntersection(); //sends wireless packet for entry
129
                        state = SINTERSECTION_WAIT;
130

    
131
                        rtc_reset(); //reset rtc for timeout wait for reply
132
                        done = false;
133
                        char retried = 0;
134
                        while(rtc_get() < 16 && !done){//waits for a reply, otherwise assumes it is first in queue
135
                                int ret = wirelessPacketHandle(SINTERSECTION_ENTER);
136
                                if(rtc_get() > 12 && !retried){//by now all resolvs should be done from bots that arrived earlier...
137
                                        ORB2_DBG_CLR(PURPLE);
138
                                        enterIntersection();
139
                                        retried = 1;
140
                                }
141
                                switch (ret) {
142
                                        case KPLACEDINQUEUE:
143
                                                ORB2_DBG_CLR(GREEN);
144
                                                done = true;
145
                                                break;
146
                                        case KFAILEDTOQUEUE:
147
                                                DBG_USBS("Failed to queue\n");
148
                                                ORB2_DBG_CLR(RED);
149
                                                enterIntersection();
150
                                                rtc_reset();
151
                                                break;
152
                                        case KRESOLVINGENTER:
153

    
154
                                                ORB2_DBG_CLR(ORANGE);
155
                                                state = SINTERSECTION_ENTER_RESOLV;
156
                                                done = true;
157
                                                break;
158
                                }
159
                        }
160
                        break;
161

    
162
                case SINTERSECTION_ENTER_RESOLV:
163
                        ORB1_DBG_CLR(PURPLE);
164
                        ORB2_DBG_CLR(ORB_OFF);
165
                        DBG_USBS("STATE: SINTERSECTION_ENTER_RESOLV\n");
166

    
167
                        rtc_reset();
168
                        done = false;
169
                        retried = 0;
170
                        while(rtc_get() < 9 && !done){
171
                                int ret = wirelessPacketHandle(SINTERSECTION_ENTER_RESOLV);
172
                                switch (ret) {
173
                                        case KRESOLVINGENTER:
174

    
175
                                                ORB2_DBG_CLR(YELLOW);
176

    
177
                                                break;
178
                                        case KPLACEDINQUEUE:
179

    
180
                                                ORB2_DBG_CLR(GREEN);
181

    
182
                                                done = true;
183
                                                break;
184
                                        case KFAILEDTOQUEUE:
185
                                                usb_puts("Failed to queue\n");
186
                                                orb2_set_color(RED);
187
                                                enterIntersection();
188
                                                rtc_reset();
189
                                                break;
190
                                }
191
                                //if resolvPrevBotID == -1, this indicates that
192
                                //there was a prevbot before, but it has entered
193
                                //the queue so it's our turn.
194
                                if(!done && resolvPrevBotID == (char) -1 && !retried){
195
                                        enterIntersection();
196
                                        rtc_reset();
197
                                        retried = 1;
198
                                //if resolvPrevBotID == -2, we have been
199
                                //resolving but never have seen a bot with lower
200
                                //priority than us. after the 6/16ths sec
201
                                //timeout, assume we are first.
202
                                } else if(!done && resolvPrevBotID == (char) -2 && rtc_get() > 6){
203
                                        //send a intersection reply to myself to
204
                                        //trigger other bots to enter queue.
205
                                        sendBuffer[0] = WINTERSECTIONREPLY;
206
                                        sendBuffer[2] = intersectionNum;
207
                                        sendBuffer[3] = id;
208
                                        wl_basic_send_global_packet(42, sendBuffer, PACKET_LENGTH);
209

    
210
                                        done = true;
211
                                        break;
212
                                }
213
                        }
214
                        state = SINTERSECTION_WAIT;
215
                        break;
216
                case SINTERSECTION_WAIT:/*Waiting in intersection */
217

    
218
                        ORB1_DBG_CLR(YELLOW);
219
                        ORB2_DBG_CLR(ORB_OFF);
220

    
221
                        DBG_USBS("STATE: SINTERSECTION_WAIT\n");
222

    
223

    
224
                        while(queuePrevBot != (char) -1){
225
                                int ret = wirelessPacketHandle(state);
226
                                switch (ret){
227
                                        case KFIRSTINQUEUE:
228

    
229
                                                ORB2_DBG_CLR(GREEN);
230

    
231
                                                state = SINTERSECTION_DRIVE;
232
                                                break;
233
                                        case KREPLIEDTOENTER:
234

    
235
                                                ORB2_DBG_CLR(BLUE);
236

    
237
                                                break;
238
                                        case KRESOLVINGENTER:
239

    
240
                                                ORB2_DBG_CLR(ORANGE);
241

    
242
                                                break;
243
                                }
244
                        }
245
                        state = SINTERSECTION_DRIVE;
246
                        break;
247
                        
248
                case SINTERSECTION_DRIVE:
249
                        DBG_USBS("STATE: SINTERSECTION_DRIVE\n");
250

    
251

    
252
                        ORB1_DBG_CLR(GREEN);
253
                        ORB2_DBG_CLR(ORB_OFF);
254

    
255
                        start();
256
                        turn(getIntersectType(sign), turnDir);
257
                        while(doDrive(180) != FINISHED){
258
                        //while(!button2_click()){
259
                                 int ret = wirelessPacketHandle(state);
260
                                 switch (ret){
261
                                         case KREPLIEDTOENTER:
262

    
263
                                                ORB2_DBG_CLR(BLUE);
264

    
265
                                                break;
266
                                         case KRESOLVINGENTER:
267

    
268
                                                 ORB2_DBG_CLR(ORANGE);
269

    
270
                                                break;
271
                                 }
272
                         }
273
                        
274
                        //Exits intersection
275

    
276
                        ORB1_DBG_CLR(WHITE);
277

    
278

    
279
                        sendBuffer[0] = WINTERSECTIONEXIT;
280
                        sendBuffer[2] = intersectionNum;//Intersection #
281
                        wl_basic_send_global_packet(42, sendBuffer, PACKET_LENGTH);
282

    
283
                        //Exits intersection
284
                        /*
285
                        while(1){
286
                                if(button1_click()){
287
                                        start();
288
                                        state = SHIGHWAY;
289
                                        break;
290
                                }
291
                                if(button2_click()){
292
                                        start();
293
                                        state = SROAD;
294
                                        break;
295
                                }
296
                        }*/
297
                        state = SROAD;
298
                        break;
299
                case SHIGHWAY:/*On highway*/
300

    
301
                        ORB1_DBG_CLR(CYAN);
302

    
303
                        while(!button1_click()){
304
                                highwayFSM();
305
                        }
306
                        state = SINTERSECTION_ENTER;
307
                        break;
308
                default:
309
                        usb_puts("I got stuck in an unknown state! My state is ");
310
                        usb_puti(state);
311
                }
312
        }
313

    
314
}
315

    
316
int wirelessPacketHandle(int state){
317
        int dataLength = 0;
318
        unsigned char *packet = NULL;
319
        packet = wl_basic_do_default(&dataLength);
320
        
321
        /* sanity check */
322
        if(dataLength == 0 || packet == NULL) //no packet
323
                return ENOPACKET;
324

    
325
        if(dataLength != PACKET_LENGTH)
326
                return EPACKETLEN;
327

    
328
        usb_puts("Recieved Wireless Packet: ");
329
        for(int i = 0; i < dataLength; i++){
330
                usb_puti(packet[i]);
331
                usb_putc(' ');
332
        }
333
        usb_putc('\n');
334

    
335
        switch (packet[0]){
336
                case WROADENTRY: //[type, bot, road]
337
                        return ENOACTION;
338
                        break;
339
                case WROADEXIT: //[type, bot, road]
340
                        return ENOACTION;
341
                        break;
342
                case WROADSTOP: //[type, bot, road]
343
                        return ENOACTION;
344
                        break;
345
                case WINTERSECTIONENTRY: //[type, bot, intersection, fromDir, toDir]
346
                        if (packet[2] == intersectionNum){
347
                                switch (state){
348
                                        case SINTERSECTION_ENTER:
349
                                                sendResolv(false);
350
                                                resolvPrevBotID = -2;
351
                                                return KRESOLVINGENTER;
352
                                                break;
353
                                        case SINTERSECTION_ENTER_RESOLV:
354
                                                return ENOACTION;
355
                                        case SINTERSECTION_WAIT:
356
                                        case SINTERSECTION_DRIVE:
357
                                                if(queueNextBot == (char) -1){
358
                                                        sendBuffer[0] = WINTERSECTIONREPLY;
359
                                                        sendBuffer[2] = intersectionNum;
360
                                                        sendBuffer[3] = packet[1];
361
                                                        wl_basic_send_global_packet(42, sendBuffer, PACKET_LENGTH);
362
                                                        queueNextBot = packet[1];
363
                                                        return KREPLIEDTOENTER;
364
                                                }
365
                                                break;
366

    
367
                                }
368
                        }
369
                        break;
370
                case WINTERSECTIONREPLY: //[type, fromBot, intersection, toBot]
371
                        if (packet[2] == intersectionNum){
372
                                switch (state){
373
                                        case SINTERSECTION_ENTER:
374
                                        case SINTERSECTION_ENTER_RESOLV:
375
                                                if(packet[3] == id){ //Reply for me
376
                                                        queuePrevBot = packet[1];
377
                                                        return KPLACEDINQUEUE;
378
                                                } else {
379
                                                        if(packet[3] == resolvPrevBotID)
380
                                                                resolvPrevBotID = -1;
381
                                                        return KFAILEDTOQUEUE;
382
                                                }
383
                                                break;
384
                                        default:
385
                                                return ENOACTION;
386
                                }
387
                        }
388
                        break;
389
                case WINTERSECTIONEXIT: //[type, bot, intersection]
390
                        if (packet[2] == intersectionNum){
391
                                switch (state){
392
                                        case SINTERSECTION_WAIT:
393
                                                if(packet[1]==queuePrevBot){
394
                                                        queuePrevBot=-1;
395
                                                        return KFIRSTINQUEUE;
396
                                                }
397
                                }
398
                        }
399
                        break;
400
                case WINTERSECTIONGO: //[type, bot, intersection]
401
                        break;
402
                case WINTERSECTIONPOLICEENTRY: //[?]
403
                        return ENOACTION;
404
                        break;
405
                case WINTERSECTIONRESOLVERACE: //[type, bot, intersection, num]
406
                        //in the case robots draw the same number these will be
407
                        //arbitrated using the sending robot's id, prefering
408
                        //lower ids
409
                        usb_puts("Now in wireless WINTERSECTIONRESOLVERACE handler: resolvPrevBotID: ");
410
                        usb_puti((int) resolvPrevBotID);
411
                        usb_putc('\n');
412
                        if (packet[2] == intersectionNum){
413
                                switch (state){
414
                                        case SINTERSECTION_ENTER:
415
                                        case SINTERSECTION_ENTER_RESOLV:
416
                                                if(resolvPrevBotID == (char) -3){
417
                                                        usb_puts("resolvPrevBotID == -3; sending a resolv packet and setting to -2\n");
418
                                                        sendResolv(false);
419
                                                        resolvPrevBotID = -2;
420
                                                }
421
                                                if((unsigned char) packet[3] == resolvDraw && id > packet[1]){
422
                                                        //other bot drew same number as me,
423
                                                        //and i have a higher id, so it goes first.
424
                                                        usb_puts("bot ");
425
                                                        usb_puti(packet[1]);
426
                                                        usb_puts(" Drew the same number as me and I have a higher id, so it goes first\n");
427
                                                        resolvPrevBotID = packet[1];
428
                                                } else if((unsigned char) packet[3] == resolvPrevBotDraw && resolvPrevBotID > packet[1]){
429
                                                        //other bot drew same number as the bot before me,
430
                                                        //so if it has a higher id than the bot before me,
431
                                                        //it is going to go in between that one and me.
432
                                                        usb_puts("bot ");
433
                                                        usb_puti(packet[1]);
434
                                                        usb_puts(" Drew the same number as the bot before me, and the bot before me has have a higher id, so this goes first\n");
435
                                                        resolvPrevBotID = packet[1];
436
                                                } else if((unsigned char)packet[3] < resolvDraw && (unsigned char)packet[3] > resolvPrevBotDraw){
437
                                                        //found a bot that goes in between the bot before me
438
                                                        //and me, so now it is before me.
439
                                                        usb_puts("bot ");
440
                                                        usb_puti(packet[1]);
441
                                                        usb_puts(" Drew a lower number bot before me, and the bot before me has have a higher id, so this goes first\n");
442
                                                        resolvPrevBotDraw = packet[3];
443
                                                        resolvPrevBotID = packet[1];
444
                                                }
445
                                                return KRESOLVINGENTER;
446
                                                break;
447
                                        case SINTERSECTION_WAIT:
448
                                        case SINTERSECTION_DRIVE:
449
                                                usb_puts("Trying to resolv in non resolv case...queueNextbot = "); usb_puti(queueNextBot); usb_puts("\n");
450
                                                if(queueNextBot == (char) -1){
451
                                                        sendResolv(true);
452
                                                }
453
                                                return KRESOLVINGENTER;
454
                                                break;
455
                                }
456
                                
457
                        }
458
                        break;
459
                case WHIGHWAYENTRY: //[type, bot, highway]
460
                        return ENOACTION;
461
                        break;
462
                case WHIGHWAYREPLY: //[type, fromBot, highway, toBot]
463
                        return ENOACTION;
464
                        break;
465
                case WHIGHWAYEXIT: //[type, bot, highway]
466
                        return ENOACTION;
467
                        break;
468
                case WPINGGLOBAL: //[type, bot]
469
                        return ENOACTION;
470
                        break;
471
                case WPINGBOT: //[type, fromBot, toBot]
472
                        return ENOACTION;
473
                        break;
474
                case WPINGQUEUE: //[type, fromBot, toBot]
475
                        return ENOACTION;
476
                        break;
477
                case WPINGREPLY: //[type, fromBot, toBot]
478
                        return ENOACTION;
479
                        break;
480
                case WCOLLISIONAVOID: //[type, bot, intersection, collision-int] //Note: collision is an int and thus takes two spaces
481
                        return ENOACTION;
482
                        break;
483
                default:
484
                        return ENOACTION;
485
                        break;
486
        }
487
}
488

    
489
unsigned char resolvRandomNumberGen(){
490
        if ((resolvSeed *= (rtc_get())%9) == 0){
491
                return resolvSeed + 1; //0 is a reseved priority value for the last
492
                                 //bot that is already in the queue.
493
        }
494
        return resolvSeed;
495
}
496
void sendResolv(bool override){
497
        if(!override)
498
                resolvDraw = resolvRandomNumberGen();
499
        else
500
                resolvDraw = 0;
501
        sendBuffer[0] = WINTERSECTIONRESOLVERACE;
502
        sendBuffer[2] = intersectionNum;
503
        sendBuffer[3] = resolvDraw;
504
        wl_basic_send_global_packet(42, sendBuffer, PACKET_LENGTH);
505
}
506
void enterIntersection(void){
507
        //Sends packet announcing its entry to the intersection
508
        sendBuffer[0] = WINTERSECTIONENTRY;
509
        sendBuffer[2] = intersectionNum;//Intersection #
510
        sendBuffer[3] = 0; //getIntersectPos(sign);
511
        sendBuffer[4] = turnDir;
512
        wl_basic_send_global_packet(42, sendBuffer, PACKET_LENGTH);
513
}
514

    
515
#endif