Project

General

Profile

Statistics
| Revision:

root / branches / lemmings / code / behaviors / lemmings / lemmings.c @ 271

History | View | Annotate | Download (6.53 KB)

1
#include <dragonfly_lib.h>
2
#include <wl_defs.h>
3
#include <wireless.h>
4
#include <wl_token_ring.h>
5
//#include <colonet_dragonfly.h>
6
//#include "smart_run_around_fsm.h"
7
#include "lemmings.h"
8

    
9
/*A simple behavior for following the leader
10
  SINGLE_FILE pattern not implemented yet
11
*/
12

    
13
// FSM states
14
#define LEAD 0    // be a leader
15
#define FOLLOW 1        // follow another robot
16

    
17
#define FOLLOW_MULTI_DEFAULT 1 // set default multi-following pattern
18
#define SPEED 200 // set default speed
19

    
20
/* Globals */
21
static int cur_state;                 // current state
22
static int local_leader;  // follow this bot (-1 if leader)
23
static int global_leader; // this is the global leader
24
static int follow_multi;        // set to 0 for single-file following, 1 for tree following
25
static int local_id;      // this is the local robot id
26

    
27
/* Internal prototypes */
28
static int get_local_leader(void);
29
static int get_edge_weight(int robot1, int robot2);
30
static void get_bom_velocity(int bom_id, int* turn_speed, int* speed);
31

    
32
void lemmings_init() {
33
  // usb_puts("lemmings_init\n");
34

    
35
  //  colonet_init();
36
  //run_around_init(); // prepare for moving
37

    
38
  // set to defaults
39
  cur_state = FOLLOW;
40
  local_leader = -1;
41
  global_leader = -1;
42
  local_id = wl_get_xbee_id();
43

    
44
  follow_multi = FOLLOW_MULTI_DEFAULT;
45
}
46

    
47
/* The main function, call this to update states as frequently as possible. */
48
void lemmings_FSM(void) {
49
  int leader_bom = 0, turn_speed = 0, speed = 0;
50
  static int leader_check_count = 0;
51

    
52

    
53
  if (wl_token_get_num_robots() <= 1) {
54
    /* if there is only one robot in the token ring, there is nothing to
55
       follow, so don't do anything */
56
    motors_off();
57
    return;
58
  }
59

    
60
  //usb_puts("state: ");
61
  //usb_puti(cur_state);
62
  //usb_puts("\n");
63

    
64
  // only check for new global leader once every 5 iterations
65
  leader_check_count++;
66
  if (leader_check_count % 5 == 0) {
67
    wl_token_iterator_begin();
68

    
69
    // find robot with max id and assign as leader
70
    int max = -1;
71
    while (wl_token_iterator_has_next()) {
72
      int n = wl_token_iterator_next();
73
      if (n > max) {
74
        max = n;
75
      }
76
/*       usb_puti(n); */
77
/*       usb_puts("\n"); */
78
    }
79
    
80
/*     usb_puti(local_id); */
81
/*     usb_puts(" is the local robot\n"); */
82

    
83
    if (max == local_id) {
84
      // become the global leader
85
      orb_set_color(BLUE);
86
      cur_state = LEAD;
87
      local_leader = -1;
88
//      usb_puts(" becoming leader \n");
89
    } else {
90
      // become a follower
91
      orb_set_color(RED);
92
      cur_state = FOLLOW;
93
//      usb_puts(" becoming follower\n");
94
    }
95

    
96
    global_leader = max; // set the global leader
97
  }
98

    
99
  switch (cur_state) {
100
  case LEAD:
101
    // do lead action - move straight ahead
102
    orb_set_color(BLUE);
103
    move(SPEED, 0);
104
    break;
105

    
106
  case FOLLOW:
107
    orb_set_color(RED);
108

    
109
    // Make sure we can see our local leader
110
    leader_bom = (local_leader>=0)?wl_token_get_sensor_reading(local_id, local_leader):-1;
111

    
112
    if (leader_bom < 0) {
113
      //usb_puts("no connection to leader\n");
114

    
115
      // Can't see our old leader -- get new bot to follow.
116
      local_leader = get_local_leader();
117
      
118
      if (local_leader == -1) {
119
        // nothing to follow, so become a local_leader and start leading
120
        //usb_puts("can't see anyone - becoming a leader\n");
121
        cur_state = LEAD;
122
        local_leader = -1;
123
        orb_set_color(BLUE);
124
        move(SPEED, 0);
125
        return;
126
      } else {
127
        //usb_puts("new leader is");
128
        //usb_puti(local_leader);
129
        //usb_puts("\n");
130
        // get data in order to follow leader
131
        leader_bom = wl_token_get_sensor_reading(local_id, local_leader);
132
        get_bom_velocity(leader_bom, &turn_speed, &speed);
133
      }
134
    } else {
135
      // Leader is still in sight, so follow it
136
      get_bom_velocity(leader_bom, &turn_speed, &speed);
137
    }
138
    
139
  //usb_puts("following robot# ");
140
  //usb_puti(local_leader);
141
  //usb_puts(" bom of leader: ");
142
  //usb_puti(leader_bom);
143
  //usb_puts("\n");
144

    
145
    move(speed, turn_speed); // move in direction of leader
146
    break;
147
  }
148
}
149

    
150
// translate bom reading into direction and speed
151
static void get_bom_velocity(int bom_id, int* turn_speed, int* speed) {
152
  int error = 0;
153

    
154
  if (bom_id < 0 || bom_id > 15) {
155
    //   usb_puts("ERROR - invalid bom_id\n");
156
    *turn_speed = 0;
157
    *speed = 0;
158
    return;
159
  }
160

    
161
  // set so right is negative, left is positive
162
  if (bom_id <= 12) {
163
    error = bom_id - 4;
164
  } else {
165
    error = bom_id - 20;
166
  }
167

    
168
  // set turn speed and main speed
169
  // if error is small, turn slowly and travel at normal speed
170
  // if error is large, turn faster and travel at reduced speed
171
  switch(error)
172
  {
173
  case 0:
174
    *turn_speed = 0;
175
    *speed = SPEED;
176
    return;
177
  case 1:
178
  case -1:
179
    *turn_speed = error * 5;
180
    *speed = SPEED;
181
    return;
182
  case 2:
183
  case -2:
184
    *turn_speed = error * 8;
185
    *speed = SPEED;
186
    return;
187
  case 3:
188
  case -3:
189
    *turn_speed = error * 12;
190
    *speed = SPEED;
191
    return;
192
  case 4:
193
  case -4:
194
    *turn_speed = error * 16;
195
    *speed = SPEED - SPEED * error * error / 36;
196
    return;
197
  }
198
  // if not in a case
199
  *turn_speed = error * 20;
200
  *speed = SPEED - SPEED * error * error / 36;
201
}
202

    
203
// create connected components and pick a leader for each chain
204
// CURRENTLY JUST LOOKS FOR CLOSEST ROBOT TO FOLLOW
205
static int get_local_leader(void) {
206
  int nodeB;
207
  int cur_weight;
208
  int best_weight = 1000; // set to infinity initially
209
  int best_node = -1;
210

    
211
  wl_token_iterator_begin();
212

    
213
  // iterator through robots in token ring
214
  while (wl_token_iterator_has_next()) {
215
    nodeB = wl_token_iterator_next();
216
    if (nodeB == local_id) {
217
      continue; // can't follow self
218
    }
219

    
220
    // get an edge weight based on the robot position
221
    cur_weight = get_edge_weight(local_id, nodeB);
222

    
223
    if (nodeB == global_leader && cur_weight != -1) {
224
      // always follow the global leader if you have the option to
225
      best_node = nodeB;
226
      break;
227
    }
228

    
229
    if (cur_weight >= 0 && cur_weight < best_weight) {
230
      // this is new best node, so save values.
231
      best_weight = cur_weight;
232
      best_node = nodeB;
233
    }
234
  }
235

    
236
  return best_node;
237
}
238

    
239
// get edge weight of sensor matrix
240
// add in BOM range data when BOM 1.5 comes out
241
static int get_edge_weight(int robot1, int robot2) {
242
  int bom = wl_token_get_sensor_reading(robot1,robot2);
243

    
244
  // Robots closer to directly in front of us have lower weight.
245
  switch(bom) {
246
  case 12:
247
    return 10;
248

    
249
  case 13:
250
  case 11:
251
    return 9;
252

    
253
  case 14:
254
  case 10:
255
    return 8;
256

    
257
  case 15:
258
  case 9:
259
    return 7;
260

    
261
  case 0:
262
  case 8:
263
    return 6;
264

    
265
  case 1:
266
  case 7:
267
    return 5;
268

    
269
  case 2:
270
  case 6:
271
    return 4;
272

    
273
  case 3:
274
  case 5:
275
    return 3;
276

    
277
  case 4:
278
    return 2;
279
  }
280

    
281
  return -1;
282
}