Project

General

Profile

Revision 340

We're ready to do a two robot autonomous recharging video with run around, aside from some docking problems. There seem to be wireless issues with three robots, however.

View differences:

wl_token_ring.c
1
/**
2
 * Copyright (c) 2007 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
/**
27
 * @file wl_token_ring.c
28
 * @brief Token Ring Implementation
29
 *
30
 * Implementation of the token ring packet group.
31
 *
32
 * @author Brian Coltin, Colony Project, CMU Robotics Club
33
 **/
34

  
1 35
#include <wl_token_ring.h>
2 36

  
3 37
#include <stdlib.h>
......
6 40
#include <wl_defs.h>
7 41
#include <wireless.h>
8 42
#include <sensor_matrix.h>
9
#include <queue.h>
10 43

  
11 44
#ifdef ROBOT
12 45
#ifndef FIREFLY
......
44 77

  
45 78
/*Packet Handling Routines*/
46 79
void wl_token_pass_receive(int source, char nextRobot, unsigned char* sensorData, int sensorDataLength);
47
void wl_token_interrupt_request_receive(int source, int robot);
48
void wl_token_interrupt_pass_receive(int source, int robot);
49 80
void wl_token_bom_on_receive(int source);
50 81
void wl_token_join_receive(int source);
51 82
void wl_token_join_accept_receive(int source);
......
69 100
int deathDelay = -1;
70 101
//the counter for joining, before we form our own token ring
71 102
int joinDelay = -1;
72
//queue containing ids of interruption requests
73
Queue* interrupting = NULL;
74 103

  
75 104
//current robot to check in the iterator
76 105
int iteratorCount = 0;
77 106

  
107
// the amount of time a robot has had its BOM on for
108
int bom_on_count = 0;
109

  
78 110
void do_nothing(void) {}
79 111
int get_nothing(void) {return -1;}
80 112

  
......
116 148
	}
117 149
	
118 150
	sensorMatrix = sensor_matrix_create();
119
	interrupting = queue_create();
120 151
	//add ourselves to the sensor matrix
121 152
	sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 0);
122 153

  
......
157 188
void wl_token_ring_cleanup()
158 189
{
159 190
	sensor_matrix_destroy(sensorMatrix);
160
	queue_destroy(interrupting);
161 191
}
162 192

  
163 193
/**
......
176 206
			WL_DEBUG_PRINT("Robot ");
177 207
			WL_DEBUG_PRINT_INT(wl_token_next_robot);
178 208
			WL_DEBUG_PRINT(" has died.\r\n");
209
			wl_token_next_robot = -1;
210
			deathDelay = DEATH_DELAY;
179 211
		}
180 212
		
181 213
		// we may have been dropped from the ring when this is received
......
209 241
		deathDelay--;
210 242
	if (joinDelay >= 0)
211 243
		joinDelay--;
244
	if (bom_on_count >= 0)
245
		bom_on_count++;
212 246
}
213 247

  
214 248
/**
......
249 283
			//add the robot to the sensor matrix if it is not already there
250 284
			wl_token_bom_on_receive(source);
251 285
			break;
252
		case WL_TOKEN_INTERRUPT_REQUEST:
253
			wl_token_interrupt_request_receive(source, packet[0]);
254
			break;
255
		case WL_TOKEN_INTERRUPT_PASS:
256
			wl_token_interrupt_pass_receive(source, packet[0]);
257
			break;
258 286
		case WL_TOKEN_JOIN:
259 287
			wl_token_join_receive(source);
260 288
			break;
......
276 304
{
277 305
	WL_DEBUG_PRINT("Joining the token ring.\r\n");
278 306
	ringState = JOINING;
279
	joinDelay = JOIN_DELAY;
307
	joinDelay = DEATH_DELAY * 2;
280 308
	wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_JOIN,
281 309
		NULL, 0, 0);
282 310
}
......
292 320
}
293 321

  
294 322
/**
295
 * Requests that the specified robot be given the token and
296
 * allowed to flash its BOM. After its BOM is flashed, the
297
 * token will return to the robot who sent it.
298
 *
299
 * @param robot the ID of the robot which should flash its BOM
300
 **/
301
void wl_token_request(int robot)
302
{
303
	char buf[1];
304
	buf[0] = robot;
305
	wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_INTERRUPT_REQUEST,
306
		buf, 1, 0);
307
}
308

  
309
/**
310 323
 * Returns the BOM reading robot source has for robot dest.
311 324
 *
312 325
 * @param source the robot that made the BOM reading
......
317 330
 **/
318 331
int wl_token_get_sensor_reading(int source, int dest)
319 332
{
320
	return sensor_matrix_get_reading(sensorMatrix, source, dest);
333
	if (wl_token_is_robot_in_ring(dest) &&
334
			(source == wl_get_xbee_id() || wl_token_is_robot_in_ring(source)))
335
		return sensor_matrix_get_reading(sensorMatrix, source, dest);
336
	return -1;
321 337
}
322 338

  
323 339
/**
......
344 360
void wl_token_pass_receive(int source, char nextRobot, unsigned char* sensorData, int sensorDataLength)
345 361
{
346 362
	int i, j;
363

  
364
	// this prevents two tokens from being passed around at a time (second clause is in case we are joining)
365
	if (source != wl_token_next_robot && bom_on_count <= DEATH_DELAY / 2 &&
366
		ringState != ACCEPTED)
367
	{
368
		WL_DEBUG_PRINT("Received token pass when a robot should not have died yet.\n");
369
		WL_DEBUG_PRINT("There are probably two tokens going around, packet ignored.\n");
370
		return;
371
	}
372

  
373
	bom_on_count = -1;
347 374
	deathDelay = -1;
348

  
349
	WL_DEBUG_PRINT("Received the token, next robot is ");
375
	WL_DEBUG_PRINT("Received the token from robot");
376
	WL_DEBUG_PRINT_INT(source);
377
	WL_DEBUG_PRINT(", next robot is ");
350 378
	WL_DEBUG_PRINT_INT((int)nextRobot);
351 379
	WL_DEBUG_PRINT(" \r\n");
352 380
	sensor_matrix_set_in_ring(sensorMatrix, source, 1);
......
516 544
	WL_DEBUG_PRINT("Robot ");
517 545
	WL_DEBUG_PRINT_INT(source);
518 546
	WL_DEBUG_PRINT(" has flashed its bom.\r\n");
547
	
548
	bom_on_count = 0;
549

  
519 550
	sensor_matrix_set_reading(sensorMatrix, wl_get_xbee_id(), 
520 551
		source, get_max_bom_function());
521 552
}
......
536 567
			wl_get_xbee_id(), 1);
537 568
		WL_DEBUG_PRINT("Now a member of the token ring.\r\n");
538 569
		ringState = MEMBER;
570
		joinDelay = -1;
539 571
	}
540 572

  
541 573
	if (ringState == LEAVING || ringState == NONMEMBER)
......
548 580
		return;
549 581
	}
550 582
	
551
	//check for interruption requests
552
	if (queue_size(interrupting) > 0)
553
	{
554
		char buf[1];
555
		buf[0] = (char)(int)queue_remove(interrupting);
556
		
557
		//in case this robot has requested multiple times
558
		queue_remove_all(interrupting, (void*)(int)buf[0]);
559

  
560
		wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_INTERRUPT_PASS,
561
			buf, 1, 0);
562

  
563
		deathDelay = DEATH_DELAY;
564
		wl_token_next_robot = buf[0];
565
		return;
566
	}
567

  
568 583
	WL_DEBUG_PRINT("Our BOM has been flashed.\r\n");
569 584
	wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_BOM_ON,
570 585
		NULL, 0, 0);
......
578 593
	if (!sensor_matrix_get_in_ring(sensorMatrix, wl_get_xbee_id()))
579 594
	{
580 595
		WL_DEBUG_PRINT("Removed from sensor matrix while flashing BOM.\r\n");
596
		return;
581 597
	}
582 598
	
583 599
	wl_token_pass_token();
......
631 647
	WL_DEBUG_PRINT_INT(source);
632 648
	WL_DEBUG_PRINT(" into the token ring.\r\n");
633 649

  
634
	joinDelay = -1;
635
	
636 650
	// the token ring has not started yet
637 651
	if (sensor_matrix_get_joined(sensorMatrix) == 1)
638 652
		wl_token_pass_token();
......
650 664
	WL_DEBUG_PRINT("Accepted into the token ring by robot ");
651 665
	WL_DEBUG_PRINT_INT(source);
652 666
	WL_DEBUG_PRINT(".\r\n");
653
	joinDelay = -1;
667
	joinDelay = JOIN_DELAY;
654 668
	ringState = ACCEPTED;
655 669
	acceptor = source;
656 670

  
......
659 673
}
660 674

  
661 675
/**
662
 * Called when we receive a packet passing the token and interrupting
663
 * the token ring.
664
 * If the token has been passed to us, we flash our BOM
665
 * and pass it back.
666
 *
667
 * @param source the robot who sent the interrupt packet
668
 * @param robot the robot the token has been passed to
669
 **/
670
void wl_token_interrupt_pass_receive(int source, int robot)
671
{
672
	if (wl_get_xbee_id() != robot)
673
	{
674
		queue_remove_all(interrupting, (void*)robot);
675
		wl_token_next_robot = robot;
676
		deathDelay = DEATH_DELAY + rand() / (RAND_MAX / (2 * DEATH_DELAY));
677
		return;
678
	}
679
	wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_BOM_ON,
680
		NULL, 0, 0);
681
	
682
	bom_on_function();
683
	#ifdef ROBOT
684
	delay_ms(BOM_DELAY);
685
	#endif
686
	bom_off_function();
687

  
688
	//we don't include ourself, only if we are in the ring
689
	int packetSize = 1 + 2 * (sensor_matrix_get_joined(sensorMatrix) - 1);
690
	if (!sensor_matrix_get_in_ring(sensorMatrix, wl_get_xbee_id()))
691
		packetSize += 2;
692
	char* buf = (char*)malloc(packetSize * sizeof(char));
693
	if (!buf)
694
	{
695
		WL_DEBUG_PRINT("Out of memory - pass_receive.\r\n");
696
		return;
697
	}
698
	
699
	//return the token to where we got it from
700
	buf[0] = source;
701

  
702
	int i = 0, j = 0;
703
	for (i = 0; i < sensor_matrix_get_size(sensorMatrix); i++)
704
		if (sensor_matrix_get_in_ring(sensorMatrix, i) && i != wl_get_xbee_id())
705
		{
706
			buf[2*j + 1] = i;
707
			buf[2*j + 2] = sensor_matrix_get_reading(sensorMatrix, wl_get_xbee_id(), i);
708
			j++;
709
		}
710
	
711
	wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_PASS,
712
		buf, packetSize, 0);
713

  
714
	wl_token_next_robot = source;
715
	deathDelay = DEATH_DELAY;
716
	free(buf);
717
}
718

  
719
/**
720 676
 * Returns the number of robots in the token ring.
721 677
 *
722 678
 * @return the number of robots in the token ring
......
752 708
		i++;
753 709
	if (i == sensor_matrix_get_size(sensorMatrix))
754 710
		i = -1;
711
	iteratorCount = i;
755 712
}
756 713

  
757 714
/**
......
765 722
 **/
766 723
int wl_token_iterator_has_next(void)
767 724
{
768
	return iteratorCount == -1;
725
	return iteratorCount != -1;
769 726
}
770 727

  
771 728
/**
......
791 748
}
792 749

  
793 750
/**
794
 * Called when we receive a request to interrupt the token ring.
795
 * We add the robot to our list of interrupt requests,
796
 * and will send the token to this robot when we next receive the
797
 * token, unless someone else does so first.
751
 * Returns the number of robots currently in the token ring.
798 752
 *
799
 * @param source the robot requesting interruption
800
 * @param robt the robot requested to interrupt the token ring
753
 * @return the number of robots in the token ring
801 754
 **/
802
void wl_token_interrupt_request_receive(int source, int robot)
755
int wl_token_get_num_robots(void)
803 756
{
804
	queue_add(interrupting, (void*)robot);
757
	return sensor_matrix_get_joined(sensorMatrix);
805 758
}
806 759

  
807
int wl_token_get_num_robots(void){
808
  return sensor_matrix_get_joined(sensorMatrix);
760
/**
761
 * Returns the number of robots in the sensor matrix.
762
 *
763
 * @return the number of robots in the sensor matrix
764
 **/
765
int wl_token_get_matrix_size(void)
766
{
767
	return sensor_matrix_get_size(sensorMatrix);
809 768
}
810 769

  
811
int wl_token_get_matrix_size(void){
812
  return sensor_matrix_get_size(sensorMatrix);
813
}

Also available in: Unified diff