Project

General

Profile

Revision 0e6831f5

ID0e6831f5014ce2308936e6e635fafbb6a3d82684
Parent 9f547ef7
Child 3ac7a078

Added by unknown about 12 years ago

Initial ported traffic navigation code.

View differences:

scout/libscout/src/behaviors/trafficNavigation.cpp
1
/**
2
 * Copyright (c) 2011 Colony Project
3
 * 
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use,
8
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following
11
 * conditions:
12
 * 
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 * 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 */
25

  
26
#include "trafficNavigation.h"
27
#include "../linefollowing/lineDrive.h"
28

  
29
#define DEBUG_INTERSECTION
30
#ifdef MAIN_NEW
31

  
32
#ifdef DEBUG_INTERSECTION
33
  #define DBG_USBS(str) usb_puts(str)
34
  #define DBG_USBI(x) usb_puti(x)
35
#else
36
  #define DBG_USBS(str)
37
  #define DBG_USBI(x)
38
#endif
39

  
40
static int state, sign, turnDir;
41
static char sendBuffer[PACKET_LENGTH], queuePrevBot, queueNextBot, id, nextDir, nextPath, intersectionNum, resolvPrevBotID = -3;
42
unsigned char resolvSeed = 0xC9, resolvDraw = 0, resolvPrevBotDraw = 0;
43
bool done;
44

  
45

  
46
//TODO: classes for lineDrive::doDrive and other functions in line_drive.h, clock functions, sending/receiving packets, encoder data, initializations, get ids, etc.
47
void trafficNavigation::run()
48
{
49

  
50
	/* Initialize the dragonfly boards, the xbee, encoders, lineFollowing */
51
	
52
	id = get_robotid();
53
	sign = 0;
54
	delay_ms(500);
55
	
56
	//Test code
57
	state = SROAD;
58

  
59
	sendBuffer[1] = id;
60

  
61
	
62
	while (ok()) {
63
		/*DTN Finite State Machine*/
64
		switch(state){
65
		case SROAD:/*Following a normal road*/
66
			start();
67
			done = false;
68
			
69
			//finishes when reads a barcode: TODO: how do we detect intersections now?
70
			while(!done){
71
				sign = lineDrive::doDrive(180);
72
				switch(sign){
73
					case NORMAL:
74
					case FINISHED:
75
					case LOST:
76
					case ERROR:
77
						break;
78
					default:
79
						//we have a barcode!
80
						state = SINTERSECTION_ENTER;
81
						DBG_USBS("Read Barcode #:");
82
						DBG_USBI(sign);
83
						DBG_USBS("\n");
84
						done = true;
85
						break;
86

  
87
				}
88
			}
89
			break;
90
		case SINTERSECTION_ENTER:/*Entering, and in intersection*/
91
			stop();
92
			lineDrive::doDrive(0);
93

  
94
			DBG_USBS("STATE: SINTERSECTION_ENTER\n");
95

  
96
			/*Intersection queue:
97
			 *Each robot when entering the intersection will check for other robots
98
			 *in the intersection, and insert itself in a queue to go through.
99
			 */
100
			queuePrevBot = -1; //the bot that will drive before this bot
101
			queueNextBot = -1; //the bot that will drive after this bot
102
			resolvPrevBotID = -3; //in the case of a race, the bot that is
103
			                      //to enter the queue before this bot
104
			resolvPrevBotDraw = 0; //the random priority number that bot has
105
			resolvDraw = 0; //my random priority number
106
			
107
			intersectionNum = getIntersectNum(sign);
108
			if(intersectionNum == (char) -1){ //invalid
109
				state = SROAD;
110
				DBG_USBS("Barcode has invalid intersectionNum\n");
111
				break;
112
			}
113
			turnDir = validateTurn(sign, getTurnType(sign));
114
			if(turnDir == (char) -1){ //invalid
115
				state = SROAD;
116
				DBG_USBS("Barcode has invalid turn\n");
117
				break;
118
			}
119

  
120
			trafficNavigation::enterIntersection(); //sends wireless packet for entry
121
			state = SINTERSECTION_WAIT;
122

  
123
			rtc_reset(); //reset rtc for timeout wait for reply
124
			done = false;
125
			char retried = 0;
126
			while(rtc_get() < 8 && !done){//waits for a reply, otherwise assumes it is first in queue
127
				int ret = wirelessPacketHandle(SINTERSECTION_ENTER);
128
				if(rtc_get() > 6 && !retried){//by now all resolvs should be done from bots that arrived earlier...
129
					trafficNavigation::enterIntersection();
130
					retried = 1;
131
				}
132
				switch (ret) {
133
					case KPLACEDINQUEUE:
134
						done = true;
135
						break;
136
					case KFAILEDTOQUEUE:
137
						DBG_USBS("Failed to queue\n");
138
						trafficNavigation::enterIntersection();
139
						rtc_reset();
140
						break;
141
					case KRESOLVINGENTER:
142
						state = SINTERSECTION_ENTER_RESOLV;
143
						done = true;
144
						break;
145
				}
146
			}
147
			break;
148

  
149
		case SINTERSECTION_ENTER_RESOLV:
150
			DBG_USBS("STATE: SINTERSECTION_ENTER_RESOLV\n");
151

  
152
			rtc_reset();
153
			done = false;
154
			retried = 0;
155
			while(rtc_get() < 4 && !done){
156
				int ret = wirelessPacketHandle(SINTERSECTION_ENTER_RESOLV);
157
				switch (ret) {
158
					case KRESOLVINGENTER:
159
						break;
160
					case KPLACEDINQUEUE:
161
						done = true;
162
						break;
163
					case KFAILEDTOQUEUE:
164
						DBG_USBS("Failed to queue\n");
165
						trafficNavigation::enterIntersection();
166
						rtc_reset();
167
						break;
168
				}
169
				//if resolvPrevBotID == -1, this indicates that
170
				//there was a prevbot before, but it has entered
171
				//the queue so it's our turn.
172
				if(!done && resolvPrevBotID == (char) -1 && !retried){
173
					trafficNavigation::enterIntersection();
174
					rtc_reset();
175
					retried = 1;
176
				//if resolvPrevBotID == -2, we have been
177
				//resolving but never have seen a bot with lower
178
				//priority than us. after the 6/16ths sec
179
				//timeout, assume we are first.
180
				} else if(!done && resolvPrevBotID == (char) -2 && rtc_get() > 2){
181
					//send a intersection reply to myself to
182
					//trigger other bots to enter queue.
183
					sendBuffer[0] = WINTERSECTIONREPLY;
184
					sendBuffer[2] = intersectionNum;
185
					sendBuffer[3] = id;
186
					wl_basic_send_global_packet(42, sendBuffer, PACKET_LENGTH);
187

  
188
					done = true;
189
					break;
190
				}
191
			}
192
			state = SINTERSECTION_WAIT;
193
			break;
194
		case SINTERSECTION_WAIT:/*Waiting in intersection */
195

  
196

  
197
			DBG_USBS("STATE: SINTERSECTION_WAIT\n");
198

  
199
			done = false;
200
			while(queuePrevBot != (char) -1){
201
				done = true;
202
				int ret = wirelessPacketHandle(state);
203
				if (ret==KFIRSTINQUEUE) state = SINTERSECTION_DRIVE;
204
			}
205
			//hack to make sure bot that just left intersection is
206
			//really out of the intersection.
207
			rtc_reset();
208
			while(rtc_get() < 2 && done){//wait one second
209
				wirelessPacketHandle(state);
210
			}
211

  
212
			state = SINTERSECTION_DRIVE;
213
			break;
214
		case SINTERSECTION_DRIVE:
215
			DBG_USBS("STATE: SINTERSECTION_DRIVE\n");
216
			start();
217
			turn(getIntersectType(sign), turnDir);
218
			
219
			
220
			//Exits intersection
221
			sendBuffer[0] = WINTERSECTIONEXIT;
222
			sendBuffer[2] = intersectionNum;//Intersection #
223
			wl_basic_send_global_packet(42, sendBuffer, PACKET_LENGTH);
224

  
225
			state = SROAD;
226
			break;
227
		default:
228
			DBG_USBS("I got stuck in an unknown state (Likely highway) My state is ");
229
			DBG_USBI(state);
230
		}
231
	}
232
}
233

  
234
int trafficNavigation::wirelessPacketHandle(int state){
235
	int dataLength = 0;
236
	unsigned char *packet = NULL;
237
	packet = wl_basic_do_default(&dataLength);
238
	
239
	/* sanity check */
240
	if(dataLength == 0 || packet == NULL) //no packet
241
		return ENOPACKET;
242

  
243
	if(dataLength != PACKET_LENGTH)
244
		return EPACKETLEN;
245

  
246
	DBG_USBS("Recieved Wireless Packet: ");
247
	for(int i = 0; i < dataLength; i++){
248
		DBG_USBI(packet[i]);
249
		DBG_USBS(" ");
250
	}
251
	DBG_USBS("\n");
252

  
253
	switch (packet[0]){
254
		case WROADENTRY: //[type, bot, road]
255
			return ENOACTION;
256
			break;
257
		case WROADEXIT: //[type, bot, road]
258
			return ENOACTION;
259
			break;
260
		case WROADSTOP: //[type, bot, road]
261
			return ENOACTION;
262
			break;
263
		case WINTERSECTIONENTRY: //[type, bot, intersection, fromDir, toDir]
264
			if (packet[2] == intersectionNum){
265
				switch (state){
266
					case SINTERSECTION_ENTER:
267
						trafficNavigation::sendResolv(false);
268
						resolvPrevBotID = -2;
269
						return KRESOLVINGENTER;
270
						break;
271
					case SINTERSECTION_ENTER_RESOLV:
272
						return ENOACTION;
273
					case SINTERSECTION_WAIT:
274
					case SINTERSECTION_DRIVE:
275
						if(queueNextBot == (char) -1){
276
							sendBuffer[0] = WINTERSECTIONREPLY;
277
							sendBuffer[2] = intersectionNum;
278
							sendBuffer[3] = packet[1];
279
							wl_basic_send_global_packet(42, sendBuffer, PACKET_LENGTH);
280
							queueNextBot = packet[1];
281
							return KREPLIEDTOENTER;
282
						}
283
						break;
284

  
285
				}
286
			}
287
			break;
288
		case WINTERSECTIONREPLY: //[type, fromBot, intersection, toBot]
289
			if (packet[2] == intersectionNum){
290
				switch (state){
291
					case SINTERSECTION_ENTER:
292
					case SINTERSECTION_ENTER_RESOLV:
293
						if(packet[3] == id){ //Reply for me
294
							queuePrevBot = packet[1];
295
							return KPLACEDINQUEUE;
296
						} else {
297
							if(packet[3] == resolvPrevBotID)
298
								resolvPrevBotID = -1;
299
							return KFAILEDTOQUEUE;
300
						}
301
						break;
302
					default:
303
						return ENOACTION;
304
				}
305
			}
306
			break;
307
		case WINTERSECTIONEXIT: //[type, bot, intersection]
308
			if (packet[2] == intersectionNum){
309
				switch (state){
310
					case SINTERSECTION_WAIT:
311
						if(packet[1]==queuePrevBot){
312
							queuePrevBot=-1;
313
							return KFIRSTINQUEUE;
314
						}
315
				}
316
			}
317
			break;
318
		case WINTERSECTIONGO: //[type, bot, intersection]
319
			break;
320
		case WINTERSECTIONPOLICEENTRY: //[?]
321
			return ENOACTION;
322
			break;
323
		case WINTERSECTIONRESOLVERACE: //[type, bot, intersection, num]
324
			//in the case robots draw the same number these will be
325
			//arbitrated using the sending robot's id, prefering
326
			//lower ids
327
			DBG_USBS("Now in wireless WINTERSECTIONRESOLVERACE handler: resolvPrevBotID: ");
328
			DBG_USBI((int) resolvPrevBotID);
329
			DBG_USBS("\n");
330
			if (packet[2] == intersectionNum){
331
				switch (state){
332
					case SINTERSECTION_ENTER:
333
					case SINTERSECTION_ENTER_RESOLV:
334
						if(resolvPrevBotID == (char) -3){
335
							DBG_USBS("resolvPrevBotID == -3; sending a resolv packet and setting to -2\n");
336
							trafficNavigation::sendResolv(false);
337
							resolvPrevBotID = -2;
338
						}
339
						if((unsigned char) packet[3] == resolvDraw && id > packet[1]){
340
							//other bot drew same number as me,
341
							//and i have a higher id, so it goes first.
342
							DBG_USBS("bot ");
343
							DBG_USBI(packet[1]);
344
							DBG_USBS(" Drew the same number as me and I have a higher id, so it goes first\n");
345
							resolvPrevBotID = packet[1];
346
						} else if((unsigned char) packet[3] == resolvPrevBotDraw && resolvPrevBotID > packet[1]){
347
							//other bot drew same number as the bot before me,
348
							//so if it has a higher id than the bot before me,
349
							//it is going to go in between that one and me.
350
							DBG_USBS("bot ");
351
							DBG_USBI(packet[1]);
352
							DBG_USBS(" Drew the same number as the bot before me, and the bot before me has have a higher id, so this goes first\n");
353
							resolvPrevBotID = packet[1];
354
						} else if((unsigned char)packet[3] < resolvDraw && (unsigned char)packet[3] > resolvPrevBotDraw){
355
							//found a bot that goes in between the bot before me
356
							//and me, so now it is before me.
357
							DBG_USBS("bot ");
358
							DBG_USBI(packet[1]);
359
							DBG_USBS(" Drew a lower number bot before me, and the bot before me has have a higher id, so this goes first\n");
360
							resolvPrevBotDraw = packet[3];
361
							resolvPrevBotID = packet[1];
362
						}
363
						return KRESOLVINGENTER;
364
						break;
365
					case SINTERSECTION_WAIT:
366
					case SINTERSECTION_DRIVE:
367
						DBG_USBS("Trying to resolv in non resolv case...queueNextbot = "); DBG_USBI(queueNextBot); DBG_USBS("\n");
368
						if(queueNextBot == (char) -1){
369
							trafficNavigation::sendResolv(true);
370
						}
371
						return KRESOLVINGENTER;
372
						break;
373
				}
374
				
375
			}
376
			break;
377
		case WHIGHWAYENTRY: //[type, bot, highway]
378
			return ENOACTION;
379
			break;
380
		case WHIGHWAYREPLY: //[type, fromBot, highway, toBot]
381
			return ENOACTION;
382
			break;
383
		case WHIGHWAYEXIT: //[type, bot, highway]
384
			return ENOACTION;
385
			break;
386
		case WPINGGLOBAL: //[type, bot]
387
			return ENOACTION;
388
			break;
389
		case WPINGBOT: //[type, fromBot, toBot]
390
			return ENOACTION;
391
			break;
392
		case WPINGQUEUE: //[type, fromBot, toBot]
393
			return ENOACTION;
394
			break;
395
		case WPINGREPLY: //[type, fromBot, toBot]
396
			return ENOACTION;
397
			break;
398
		case WCOLLISIONAVOID: //[type, bot, intersection, collision-int] //Note: collision is an int and thus takes two spaces
399
			return ENOACTION;
400
			break;
401
		default:
402
			return ENOACTION;
403
			break;
404
	}
405
}
406

  
407
unsigned char trafficNavigation::resolvRandomNumberGen(){
408
	if ((resolvSeed *= (rtc_get() + encoder_read(LEFT))%9) == 0){
409
		return resolvSeed + 1; //0 is a reseved priority value for the last
410
		                 //bot that is already in the queue.
411
	}
412
	return resolvSeed;
413
}
414
void trafficNavigation::sendResolv(bool override){
415
	if(!override)
416
		resolvDraw = trafficNavigation::resolvRandomNumberGen();
417
	else
418
		resolvDraw = 0;
419
	sendBuffer[0] = WINTERSECTIONRESOLVERACE;
420
	sendBuffer[2] = intersectionNum;
421
	sendBuffer[3] = resolvDraw;
422
	wl_basic_send_global_packet(42, sendBuffer, PACKET_LENGTH);
423
}
424
void trafficNavigation::enterIntersection(void){
425
	//Sends packet announcing its entry to the intersection
426
	sendBuffer[0] = WINTERSECTIONENTRY;
427
	sendBuffer[2] = intersectionNum;//Intersection #
428
	sendBuffer[3] = 0; //getIntersectPos(sign);
429
	sendBuffer[4] = turnDir;
430
	wl_basic_send_global_packet(42, sendBuffer, PACKET_LENGTH);
431
}
scout/libscout/src/behaviors/trafficNavigation.h
1
/**
2
 * Copyright (c) 2011 Colony Project
3
 * 
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use,
8
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following
11
 * conditions:
12
 * 
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 * 
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 */
25

  
26
#ifndef _trafficNavigation_H_
27
#define _trafficNavigation_H_
28

  
29
#include "../Behavior.h"
30

  
31
//from old trafficNavigation.h
32
#ifndef trafficNavigation_H
33

  
34
/* Debug Options - These must go before includes */
35
#define MAIN_NEW
36
//#define SENDGRAPH
37

  
38
#include <dragonfly_lib.h>
39
#include <wl_basic.h>
40
#include "../linefollowing/lineDrive.h"
41
#include "highways.h"
42
#include "intersectData.h"
43
#include "validTurns.h"
44

  
45
/*States*/
46
#define SROAD 0
47
#define SINTERSECTION 9 /* for old version */
48
#define SINTERSECTION_ENTER 10
49
#define SINTERSECTION_ENTER_RESOLV 11
50
#define SINTERSECTION_WAIT 12
51
#define SINTERSECTION_DRIVE 13
52
#define SHIGHWAY 20
53
#define SCLEARPACKET 30
54

  
55
/*Sign Codes
56
 * bitwise OR labels to create a barcode or read one
57
 * There should be macros to extract these probably
58
 * The bits will be stored in some variable (char or short)
59
 * Bits if road: ? ? ? NAME NAME NAME TYPE CROAD
60
 * Bits if intersection: ? ? ? ? DIR DIR #WAYS CINTERSECTION
61
 */
62
#define CROAD 0x0 //0b
63
#define CINTERSECTION 0x1 //1b
64
#define CNORMALROAD 0x0 //00b
65
#define CHIGHWAYROAD 0x2 //10b
66
#define C4WAY 0x0 //00b
67
#define C3WAY 0x2 //10b
68
#define CNORTH 0x0 //0000b
69
#define CEAST 0x4 //0100b
70
#define CSOUTH 0x8 //1000b
71
#define CWEST 0x12 //1100b
72

  
73
/*Wireless Packet Types
74
 * The first byte of any wireless packet should be one of these types.
75
 * Each type will have its own structure
76
 * The second byte should be the id of the bot sending the packet
77
 * The third byte should be the number of the intersection or road that
78
 *   the packet pertains to
79
 */
80
#define PACKET_LENGTH 5
81
#define WROADENTRY 0 //[type, bot, road]
82
#define WROADREPLY 1 //[type, fromBot, road, toBot]
83
#define WROADEXIT 2 //[type, bot, road]
84
#define WROADSTOP 3 //[type, bot, road]
85
#define WINTERSECTIONENTRY 10   //[type, bot, intersection, fromDir, toDir]
86
#define WINTERSECTIONREPLY 11   //[type, fromBot, intersection, toBot]
87
#define WINTERSECTIONEXIT 12    //[type, bot, intersection]
88
#define WINTERSECTIONGO 13      //[type, bot, intersection]
89
#define WINTERSECTIONPOLICEENTRY 14
90
#define WINTERSECTIONRESOLVERACE 15   //[type, bot, intersection, num]
91
#define WHIGHWAYENTRY 20 //[type, bot, highway]
92
#define WHIGHWAYREPLY 21 //[type, fromBot, highway, toBot]
93
#define WHIGHWAYEXIT 22 //[type, bot, highway]
94
#define WPINGGLOBAL 30 //[type, bot]
95
#define WPINGBOT 31 //[type, fromBot, toBot]
96
#define WPINGQUEUE 32 //[type, fromBot, toBot]
97
#define WPINGREPLY 33 //[type, fromBot, toBot]
98
#define WCOLLISIONAVOID 41 //[type, bot, intersection, collision-int] //Note: collision is an int and thus takes two spaces
99
#define WGRAPHDATA 80
100

  
101
/*Wireless Parsing Status
102
 * For wireless parsing - status codes describing various errors/statuses with wireless
103
 * parsing. 
104
 * Errors begin with E - Note that all of these errors are actually returned as negative.
105
 *                     - values of >= 100 indicate a serious error
106
 * Non-Errors begin with K - returned as positive. (don't start with S because S
107
 *                           is for state)
108
 */
109
#define ENOPACKET -10 //The received packet doesn't exist.
110
#define ENOACTION -15 //The received packet has no defined action, and this is OK
111
#define ENOIMPLEMENT -20 //The received packet has no defined action and needs to be implemented.
112
#define EPACKETLEN -100 //The received packet was the wrong length
113
#define KOK 1
114
#define KPLACEDINQUEUE 20
115
#define KFAILEDTOQUEUE 21
116
#define KFIRSTINQUEUE 22
117
#define KREPLIEDTOENTER 23
118
#define KRESOLVINGENTER 24 //resolving a race between bots trying to enter intersection at the same time.
119

  
120
/*Macros
121
 */
122
#define ISPING(p) ((p)[0]==WPINGGLOBAL || (p)[0]==WPINGBOT || (p)[0]==WPINGQUEUE)
123

  
124
#endif
125
//
126

  
127
#ifdef DEBUG_INTERSECTION
128
  #define DBG_USBS(str) usb_puts(str)
129
  #define DBG_USBI(x) usb_puti(x)
130
#else
131
  #define DBG_USBS(str)
132
  #define DBG_USBI(x)
133
#endif
134

  
135

  
136
class trafficNavigation : Behavior
137
{
138
    public:
139
        trafficNavigation(std::string scoutname) : Behavior(scoutname) {};
140

  
141
        void run();
142
		int wirelessPacketHandle(int state);
143
		void enterIntersection(void);
144
		void sendResolv(bool override);
145
		unsigned char resolvRandomNumberGen();
146
};
147

  
148
#endif

Also available in: Unified diff