Project

General

Profile

Statistics
| Revision:

root / branches / autonomous_recharging / code / projects / autonomous_recharging / charging_station / wl_token_ring.c @ 198

History | View | Annotate | Download (18.6 KB)

1
#include <wl_token_ring.h>
2

    
3
#include <stdlib.h>
4
#include <stdio.h>
5

    
6
#include <wl_defs.h>
7
#include <wireless.h>
8
#include <sensor_matrix.h>
9

    
10
#ifdef ROBOT
11
#ifndef FIREFLY
12
#include <bom.h>
13
#endif
14
#include <time.h>
15
#endif
16

    
17
#define DEFAULT_SENSOR_MATRIX_SIZE 20
18

    
19
/*Ring States*/
20

    
21
#define NONMEMBER 0
22
#define MEMBER 1
23
#define JOINING 2
24
#define ACCEPTED 3
25
#define LEAVING 4
26

    
27
/*Frame Types*/
28
#define TOKEN_JOIN_ACCEPT_FRAME 1
29

    
30
/*Function Prototypes*/
31

    
32
/*Wireless Library Prototypes*/
33
void wl_token_ring_timeout_handler(void);
34
void wl_token_ring_response_handler(int frame, int received);
35
void wl_token_ring_receive_handler(char type, int source, unsigned char* packet,
36
                                                        int length);
37
void wl_token_ring_cleanup(void);
38

    
39
/*Helper Functions*/
40
void wl_token_pass_token(void);
41
int get_token_distance(int robot1, int robot2);
42
void wl_token_get_token(void);
43

    
44
/*Packet Handling Routines*/
45
void wl_token_pass_receive(int source, char nextRobot, unsigned char* sensorData, int sensorDataLength);
46
void wl_token_bom_on_receive(int source);
47
void wl_token_join_receive(int source);
48
void wl_token_join_accept_receive(int source);
49

    
50
/*Global Variables*/
51

    
52
//the sensor matrix
53
SensorMatrix* sensorMatrix;
54

    
55
//the robot we are waiting to say it has received the token. -1 if unspecified
56
int wl_token_next_robot = -1;
57

    
58
//true if the robot should be in the token ring, 0 otherwise
59
int ringState = NONMEMBER;
60
//the id of the robot who accepted us into the token ring, only used in ACCEPTED state
61
int acceptor = -1;
62
//id of the robot we are accepting
63
int accepted = -1;
64

    
65
//the counter for when we assume a robot is dead
66
int deathDelay = -1;
67
//the counter for joining, before we form our own token ring
68
int joinDelay = -1;
69

    
70
//current robot to check in the iterator
71
int iteratorCount = 0;
72

    
73
// the amount of time a robot has had its BOM on for
74
int bom_on_count = 0;
75

    
76
void do_nothing(void) {}
77
int get_nothing(void) {return -1;}
78

    
79
#ifdef ROBOT
80
#ifndef FIREFLY
81
void (*bom_on_function) (void) = bom_on;
82
void (*bom_off_function) (void) = bom_off;
83
int (*get_max_bom_function) (void) = get_max_bom;
84
#else
85
void (*bom_on_function) (void) = do_nothing;
86
void (*bom_off_function) (void) = do_nothing;
87
int (*get_max_bom_function) (void) = get_nothing;
88
#endif
89
#else
90
void (*bom_on_function) (void) = do_nothing;
91
void (*bom_off_function) (void) = do_nothing;
92
int (*get_max_bom_function) (void) = get_nothing;
93
#endif
94

    
95
PacketGroupHandler wl_token_ring_handler =
96
                {WL_TOKEN_RING_GROUP, wl_token_ring_timeout_handler,
97
                wl_token_ring_response_handler, wl_token_ring_receive_handler,
98
                wl_token_ring_cleanup};
99

    
100
/**
101
 * Initialize the token ring packet group and register it with the
102
 * wireless library. The robot will not join a token ring.
103
 **/
104
void wl_token_ring_register()
105
{
106
        if (wl_get_xbee_id() > 0xFF)
107
        {
108
                //Note: if this becomes an issue (unlikely), we could limit sensor information
109
                //to half a byte and use 12 bits for the id
110
                WL_DEBUG_PRINT("XBee ID must be single byte for token ring, is ");
111
                WL_DEBUG_PRINT_INT(wl_get_xbee_id());
112
                WL_DEBUG_PRINT(".\r\n");
113
                return;
114
        }
115
        
116
        sensorMatrix = sensor_matrix_create();
117
        //add ourselves to the sensor matrix
118
        sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 0);
119

    
120
        wl_register_packet_group(&wl_token_ring_handler);
121
}
122

    
123
/**
124
 * Removes the packet group from the wireless library.
125
 **/
126
void wl_token_ring_unregister()
127
{
128
        wl_unregister_packet_group(&wl_token_ring_handler);
129
}
130

    
131
/**
132
 * Sets the functions that are called when the BOM ought to be
133
 * turned on or off. This could be used for things such as 
134
 * charging stations, which have multiple BOMs.
135
 *
136
 * @param on_function the function to be called when the BOM
137
 * should be turned on
138
 * @param off_function the function to be called when the BOM
139
 * should be turned off
140
 * @param max_bom_function the function to be called when a
141
 * measurement of the maximum BOM reading is needed.
142
 **/
143
void wl_token_ring_set_bom_functions(void (*on_function) (void),
144
        void (*off_function) (void), int (*max_bom_function) (void))
145
{
146
        bom_on_function = on_function;
147
        bom_off_function = off_function;
148
        get_max_bom_function = max_bom_function;
149
}
150

    
151
/**
152
 * Called to cleanup the token ring packet group.
153
 **/
154
void wl_token_ring_cleanup()
155
{
156
        sensor_matrix_destroy(sensorMatrix);
157
}
158

    
159
/**
160
 * Called approximately every quarter second by the wireless library.
161
 **/
162
void wl_token_ring_timeout_handler()
163
{
164
        //someone is not responding, assume they are dead
165
        if (deathDelay == 0)
166
        {
167
                //pass the token to the next robot if we think someone has died
168
                //also, declare that person dead, as long as it isn't us
169
                if (wl_token_next_robot != wl_get_xbee_id())
170
                {
171
                        sensor_matrix_set_in_ring(sensorMatrix, wl_token_next_robot, 0);
172
                        WL_DEBUG_PRINT("Robot ");
173
                        WL_DEBUG_PRINT_INT(wl_token_next_robot);
174
                        WL_DEBUG_PRINT(" has died.\r\n");
175
                        wl_token_next_robot = -1;
176
                        deathDelay = DEATH_DELAY;
177
                }
178
                
179
                // we may have been dropped from the ring when this is received
180
                if (ringState == MEMBER)
181
                        wl_token_pass_token();
182
        }
183

    
184
        //we must start our own token ring, no one is responding to us
185
        if (joinDelay == 0)
186
        {
187
                if (sensor_matrix_get_joined(sensorMatrix) == 0)
188
                {
189
                        WL_DEBUG_PRINT("Creating our own token ring, no robots seem to exist.\r\n");
190
                        sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 1);
191
                        ringState = MEMBER;
192
                        //this will make us pass the token to ourself
193
                        //repeatedly, and other robots when they join
194
                        deathDelay = DEATH_DELAY;
195
                        wl_token_next_robot = wl_get_xbee_id();
196
                }
197
                else
198
                {
199
                        WL_DEBUG_PRINT("Attempting to join the token ring again.\r\n");
200
                        //attempt to rejoin with a random delay
201
                        wl_token_ring_join();
202
                        joinDelay = rand() / (RAND_MAX / JOIN_DELAY) + 1;
203
                }
204
        }
205

    
206
        if (deathDelay >= 0)
207
                deathDelay--;
208
        if (joinDelay >= 0)
209
                joinDelay--;
210
        if (bom_on_count >= 0)
211
                bom_on_count++;
212
}
213

    
214
/**
215
 * Called when the XBee tells us if a packet we sent has been received.
216
 * 
217
 * @param frame the frame number assigned when the packet was sent
218
 * @param received 1 if the packet was received, 0 otherwise
219
 **/
220
void wl_token_ring_response_handler(int frame, int received)
221
{
222
        if (!received)
223
        {
224
                WL_DEBUG_PRINT("FAILED.\r\n");
225
        }
226
}
227

    
228
/**
229
 * Called when we recieve a token ring packet.
230
 * @param type the type of the packet
231
 * @param source the id of the robot who sent the packet
232
 * @param packet the data in the packet
233
 * @param length the length of the packet in bytes
234
 **/
235
void wl_token_ring_receive_handler(char type, int source, unsigned char* packet,
236
                                                        int length)
237
{
238
        switch (type)
239
        {
240
                case WL_TOKEN_PASS:
241
                        if (length < 1)
242
                        {
243
                                WL_DEBUG_PRINT("Malformed Token Pass packet received.\r\n");
244
                                return;
245
                        }
246
                        wl_token_pass_receive(source, packet[0], packet + 1, length - 1);
247
                        break;
248
                case WL_TOKEN_BOM_ON:
249
                        //add the robot to the sensor matrix if it is not already there
250
                        wl_token_bom_on_receive(source);
251
                        break;
252
                case WL_TOKEN_JOIN:
253
                        wl_token_join_receive(source);
254
                        break;
255
                case WL_TOKEN_JOIN_ACCEPT:
256
                        wl_token_join_accept_receive(source);
257
                        break;
258
                default:
259
                        WL_DEBUG_PRINT("Unimplemented token ring packet received.\r\n");
260
                        break;
261
        }
262
}
263

    
264
/**
265
 * Causes the robot to join an existing token ring, or create one
266
 * if no token ring exists. The token ring uses global and robot to robot
267
 * packets, and does not rely on any PAN.
268
 **/
269
void wl_token_ring_join()
270
{
271
        WL_DEBUG_PRINT("Joining the token ring.\r\n");
272
        ringState = JOINING;
273
        joinDelay = DEATH_DELAY * 2;
274
        wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_JOIN,
275
                NULL, 0, 0);
276
}
277

    
278
/**
279
 * Causes the robot to leave the token ring. The robot stops
280
 * alerting others of its location, but continues storing the
281
 * locations of other robots.
282
 **/
283
void wl_token_ring_leave()
284
{
285
        ringState = LEAVING;
286
}
287

    
288
/**
289
 * Returns the BOM reading robot source has for robot dest.
290
 *
291
 * @param source the robot that made the BOM reading
292
 * @param dest the robot whose relative location is returned
293
 *
294
 * @return a BOM reading from robot source to robot dest,
295
 * in the range 0-15, or -1 if it is unknown
296
 **/
297
int wl_token_get_sensor_reading(int source, int dest)
298
{
299
        return sensor_matrix_get_reading(sensorMatrix, source, dest);
300
}
301

    
302
/**
303
 * Returns the BOM reading we have for robot dest.
304
 * 
305
 * @param dest the robot whose relative location is returned
306
 *
307
 * @return a BOM reading from us to robot dest, in the range
308
 * 0-15, or -1 if it is unkown
309
 **/
310
int wl_token_get_my_sensor_reading(int dest)
311
{
312
        return wl_token_get_sensor_reading(wl_get_xbee_id(), dest);
313
}
314

    
315
/**
316
 * This method is called when we receive a token pass packet.
317
 * @param source is the robot it came from
318
 * @param nextRobot is the robot the token was passed to
319
 * @param sensorData a char with an id followed by a char with the sensor
320
 *                reading for that robot, repeated for sensorDataLength bytes
321
 * @param sensorDataLength the length in bytes of sensorData
322
 */
323
void wl_token_pass_receive(int source, char nextRobot, unsigned char* sensorData, int sensorDataLength)
324
{
325
        int i, j;
326

    
327
        // this prevents two tokens from being passed around at a time (second clause is in case we are joining)
328
        if (source != wl_token_next_robot && bom_on_count <= DEATH_DELAY / 2 &&
329
                ringState != ACCEPTED)
330
        {
331
                WL_DEBUG_PRINT("Received token pass when a robot should not have died yet.\n");
332
                WL_DEBUG_PRINT("There are probably two tokens going around, packet ignored.\n");
333
                return;
334
        }
335

    
336
        bom_on_count = -1;
337
        deathDelay = -1;
338
        WL_DEBUG_PRINT("Received the token from robot");
339
        WL_DEBUG_PRINT_INT(source);
340
        WL_DEBUG_PRINT(", next robot is ");
341
        WL_DEBUG_PRINT_INT((int)nextRobot);
342
        WL_DEBUG_PRINT(" \r\n");
343
        sensor_matrix_set_in_ring(sensorMatrix, source, 1);
344

    
345
        //with this packet, we are passed the id of the next robot in the ring
346
        //and the sensor matrix, a list of id and sensor reading pairs (two bytes for both)
347
        j = 0;
348
        for (i = 0; i < sensor_matrix_get_size(sensorMatrix); i++)
349
        {
350
                if (i == source)
351
                        continue;
352
                
353
                //set the sensor information we receive
354
                if (j < sensorDataLength / 2 && sensorData[2 * j] == i)
355
                {
356
                        //the robot we were going to accept has already been accepted
357
                        if (accepted == i)
358
                        {
359
                                accepted = -1;
360
                                WL_DEBUG_PRINT("Someone accepted the robot we did.\r\n");
361
                        }
362
                        sensor_matrix_set_reading(sensorMatrix, source, i,
363
                                                sensorData[2 * j + 1]);
364
                        sensor_matrix_set_in_ring(sensorMatrix, i, 1);
365
                        j++;
366
                }
367
                else
368
                {
369
                        if (sensor_matrix_get_in_ring(sensorMatrix, i))
370
                        {
371
                                WL_DEBUG_PRINT("Robot ");
372
                                WL_DEBUG_PRINT_INT(i);
373
                                WL_DEBUG_PRINT(" has been removed from the sensor matrix of robot ");
374
                                WL_DEBUG_PRINT_INT(wl_get_xbee_id());
375
                                WL_DEBUG_PRINT(" due to a packet from robot ");
376
                                WL_DEBUG_PRINT_INT(source);
377
                                WL_DEBUG_PRINT(".\r\n");
378
                                sensor_matrix_set_in_ring(sensorMatrix, i, 0);
379
                        }
380

    
381
                        if (i == wl_get_xbee_id() && ringState == MEMBER)
382
                        {
383
                                ringState = NONMEMBER;
384
                                wl_token_ring_join();
385
                                
386
                                WL_DEBUG_PRINT("We have been removed from the ring ");
387
                                WL_DEBUG_PRINT("and are rejoining.\r\n");
388
                        }
389
                        
390
                        //the person who accepted us is dead... let's ask again
391
                        if (i == acceptor)
392
                        {
393
                                sensor_matrix_set_in_ring(sensorMatrix,
394
                                                wl_get_xbee_id(), 1);
395
                                ringState = NONMEMBER;
396
                                acceptor = -1;
397
                                wl_token_ring_join();
398
                        }
399
                }
400
        }
401

    
402
        wl_token_next_robot = nextRobot;
403
        
404
        deathDelay = get_token_distance(wl_get_xbee_id(), nextRobot) * DEATH_DELAY;
405
        
406
        //we have the token
407
        if (wl_token_next_robot == wl_get_xbee_id())
408
                wl_token_get_token();
409
}
410

    
411
/**
412
 * Gets the distance in the token ring between two robots.
413
 *
414
 * @param robot1 the first robot
415
 * @param robot2 the second robot
416
 *
417
 * @return the number of passes before the token is expected
418
 * to reach robot2 from robot1
419
 **/
420
int get_token_distance(int robot1, int robot2)
421
{
422
        int curr = robot1 + 1;
423
        int count = 1;
424
        while (1)
425
        {
426
                if (curr == sensor_matrix_get_size(sensorMatrix))
427
                        curr = 0;
428
                if (curr == robot2)
429
                        break;
430
                if (sensor_matrix_get_in_ring(sensorMatrix, curr))
431
                        count++;
432
                curr++;
433
        }
434
        return count;
435
}
436

    
437
/**
438
 * Passes the token to the next robot in the token ring.
439
 **/
440
void wl_token_pass_token()
441
{
442
        char nextRobot;
443
        int i = wl_get_xbee_id() + 1;
444
        if (accepted == -1)
445
        {
446
                while (1)
447
                {
448
                        if (i == sensor_matrix_get_size(sensorMatrix))
449
                                i = 0;
450
                        if (sensor_matrix_get_in_ring(sensorMatrix, i))
451
                        {
452
                                nextRobot = (char)i;
453
                                break;
454
                        }
455
                        i++;
456
                }
457
        }
458
        else
459
        {
460
                WL_DEBUG_PRINT("Accepting new robot, sending it the token.\r\n");
461
                //add a new robot to the token ring
462
                sensor_matrix_set_in_ring(sensorMatrix, accepted, 1);
463
                nextRobot = accepted;
464
                accepted = -1;
465
        }
466

    
467
        //we don't include ourself
468
        int packetSize = 1 + 2 * (sensor_matrix_get_joined(sensorMatrix) - 1);
469
        char* buf = (char*)malloc(packetSize * sizeof(char));
470
        if (!buf)
471
        {
472
                WL_DEBUG_PRINT_INT(packetSize);
473
                WL_DEBUG_PRINT("Out of memory - pass token.\r\n");
474
                return;
475
        }
476
        buf[0] = nextRobot;
477

    
478
        int j = 0;
479
        for (i = 0; i < sensor_matrix_get_size(sensorMatrix); i++)
480
                if (sensor_matrix_get_in_ring(sensorMatrix, i) && i != wl_get_xbee_id())
481
                {
482
                        buf[2*j + 1] = i;
483
                        buf[2*j + 2] = sensor_matrix_get_reading(sensorMatrix, wl_get_xbee_id(), i);
484
                        j++;
485
                }
486
        
487
        WL_DEBUG_PRINT("Passing the token to robot ");
488
        WL_DEBUG_PRINT_INT(buf[0]);
489
        WL_DEBUG_PRINT(".\r\n");
490
        wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_PASS,
491
                buf, packetSize, 3);
492

    
493
        wl_token_next_robot = nextRobot;
494
        deathDelay = DEATH_DELAY;
495
        free(buf);
496
}
497

    
498
/**
499
 * Called when a packet is received stating that another robot has turned
500
 * its BOM on. Our BOM is then read, and the data is added to the sensor
501
 * matrix.
502
 *
503
 * @param source the robot whose BOM is on
504
 **/
505
void wl_token_bom_on_receive(int source)
506
{
507
        WL_DEBUG_PRINT("Robot ");
508
        WL_DEBUG_PRINT_INT(source);
509
        WL_DEBUG_PRINT(" has flashed its bom.\r\n");
510
        
511
        bom_on_count = 0;
512

    
513
        sensor_matrix_set_reading(sensorMatrix, wl_get_xbee_id(), 
514
                source, get_max_bom_function());
515
}
516

    
517
/**
518
 * This method is called when we receive the token. Upon receiving
519
 * the token, we must send a BOM_ON packet, flash the BOM, and send
520
 * the token to the next robot.
521
 * 
522
 * If there is a pending request for the token, this is processed first.
523
 **/
524
void wl_token_get_token()
525
{
526
        WL_DEBUG_PRINT("We have the token.\r\n");
527
        if (ringState == ACCEPTED)
528
        {
529
                sensor_matrix_set_in_ring(sensorMatrix,
530
                        wl_get_xbee_id(), 1);
531
                WL_DEBUG_PRINT("Now a member of the token ring.\r\n");
532
                ringState = MEMBER;
533
                joinDelay = -1;
534
        }
535

    
536
        if (ringState == LEAVING || ringState == NONMEMBER)
537
        {
538
                sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 0);
539
                if (ringState == NONMEMBER)
540
                {
541
                        WL_DEBUG_PRINT("We should have left the token ring, but didn't.\r\n");
542
                }
543
                return;
544
        }
545
        
546
        WL_DEBUG_PRINT("Our BOM has been flashed.\r\n");
547
        wl_send_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_BOM_ON,
548
                NULL, 0, 0);
549

    
550
        bom_on_function();
551
        #ifdef ROBOT
552
        delay_ms(BOM_DELAY);
553
        #endif
554
        bom_off_function();
555
        
556
        if (!sensor_matrix_get_in_ring(sensorMatrix, wl_get_xbee_id()))
557
        {
558
                WL_DEBUG_PRINT("Removed from sensor matrix while flashing BOM.\r\n");
559
                return;
560
        }
561
        
562
        wl_token_pass_token();
563
}
564

    
565
/**
566
 * Called when a request to join the token ring is received.
567
 * If we are the robot preceding the requester in the ring,
568
 * we respond with a JOIN_ACCEPT packet and pass the token to
569
 * this robot when we receive the token.
570
 *
571
 * @param source the robot who requested to join
572
 **/
573
void wl_token_join_receive(int source)
574
{
575
        WL_DEBUG_PRINT("Received joining request from robot ");
576
        WL_DEBUG_PRINT_INT(source);
577
        WL_DEBUG_PRINT(".\r\n");
578

    
579
        //we cannot accept the request if we are not a member
580
        if (ringState != MEMBER)
581
                return;
582
        //if they didn't get our response, see if we should respond again
583
        if (accepted == source)
584
                accepted = -1;
585
        //we can only accept one request at a time
586
        if (accepted != -1)
587
                return;
588
        
589
        //check if we are the preceding robot in the token ring
590
        int i = source - 1;
591
        while (1)
592
        {
593
                if (i < 0)
594
                        i = sensor_matrix_get_size(sensorMatrix) - 1;
595
                //we must send a join acceptance
596
                if (i == wl_get_xbee_id())
597
                        break;
598

    
599
                //another robot will handle it
600
                if (sensor_matrix_get_in_ring(sensorMatrix, i))
601
                        return;
602
                i--;
603
        }
604

    
605
        accepted = source;
606
        wl_send_robot_to_robot_global_packet(WL_TOKEN_RING_GROUP, WL_TOKEN_JOIN_ACCEPT,
607
                NULL, 0, source, TOKEN_JOIN_ACCEPT_FRAME);
608
        
609
        WL_DEBUG_PRINT("Accepting robot ");
610
        WL_DEBUG_PRINT_INT(source);
611
        WL_DEBUG_PRINT(" into the token ring.\r\n");
612

    
613
        // the token ring has not started yet
614
        if (sensor_matrix_get_joined(sensorMatrix) == 1)
615
                wl_token_pass_token();
616
}
617

    
618
/**
619
 * Called when we receive a JOIN_ACCEPT packet in attempting to join
620
 * the token ring.
621
 * Our attempt to join the ring is stopped, and we wait for the token.
622
 *
623
 * @param source the robot who accepted us
624
 **/
625
void wl_token_join_accept_receive(int source)
626
{
627
        WL_DEBUG_PRINT("Accepted into the token ring by robot ");
628
        WL_DEBUG_PRINT_INT(source);
629
        WL_DEBUG_PRINT(".\r\n");
630
        joinDelay = JOIN_DELAY;
631
        ringState = ACCEPTED;
632
        acceptor = source;
633

    
634
        //add ourselves to the token ring
635
        sensor_matrix_set_in_ring(sensorMatrix, wl_get_xbee_id(), 1);
636
}
637

    
638
/**
639
 * Returns the number of robots in the token ring.
640
 *
641
 * @return the number of robots in the token ring
642
 **/
643
int wl_token_get_robots_in_ring(void)
644
{
645
        return sensor_matrix_get_joined(sensorMatrix);
646
}
647

    
648
/**
649
 * Returns true if the specified robot is in the token ring, false
650
 * otherwise.
651
 *
652
 * @param robot the robot to check for whether it is in the token ring
653
 * @return nonzero if the robot is in the token ring, zero otherwise
654
 **/
655
int wl_token_is_robot_in_ring(int robot)
656
{
657
        return sensor_matrix_get_in_ring(sensorMatrix, robot);
658
}
659

    
660
/**
661
 * Begins iterating through the robots in the token ring.
662
 *
663
 * @see wl_token_iterator_has_next, wl_token_iterator_next
664
 **/
665
void wl_token_iterator_begin(void)
666
{
667
        int i = 0;
668
        iteratorCount = 0;
669
        while (!sensor_matrix_get_in_ring(sensorMatrix, i) &&
670
                        i < sensor_matrix_get_size(sensorMatrix))
671
                i++;
672
        if (i == sensor_matrix_get_size(sensorMatrix))
673
                i = -1;
674
        iteratorCount = i;
675
}
676

    
677
/**
678
 * Returns true if there are more robots in the token ring
679
 * to iterate through, and false otherwise.
680
 *
681
 * @return nonzero if there are more robots to iterate through,
682
 * zero otherwise
683
 *
684
 * @see wl_token_iterator_begin, wl_token_iterator_next
685
 **/
686
int wl_token_iterator_has_next(void)
687
{
688
        return iteratorCount != -1;
689
}
690

    
691
/**
692
 * Returns the next robot ID in the token ring.
693
 *
694
 * @return the next robot ID in the token ring, or -1 if none exists
695
 *
696
 * @see wl_token_iterator_begin, wl_token_iterator_has_next
697
 **/
698
int wl_token_iterator_next(void)
699
{
700
        int result = iteratorCount;
701
        if (result < 0)
702
                return result;
703

    
704
        iteratorCount++;
705
        while (!sensor_matrix_get_in_ring(sensorMatrix, iteratorCount) &&
706
                iteratorCount < sensor_matrix_get_size(sensorMatrix))
707
                iteratorCount++;
708
        if (iteratorCount == sensor_matrix_get_size(sensorMatrix))
709
                iteratorCount = -1;
710
        return result;
711
}
712

    
713
/**
714
 * Returns the number of robots currently in the token ring.
715
 *
716
 * @return the number of robots in the token ring
717
 **/
718
int wl_token_get_num_robots(void)
719
{
720
        return sensor_matrix_get_joined(sensorMatrix);
721
}
722

    
723
/**
724
 * Returns the number of robots in the sensor matrix.
725
 *
726
 * @return the number of robots in the sensor matrix
727
 **/
728
int wl_token_get_matrix_size(void)
729
{
730
        return sensor_matrix_get_size(sensorMatrix);
731
}
732