Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (7.01 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
static int speed;         // robot's forward speed
27
static int turn_speed;    // robot's turning speed
28

    
29
/* Internal prototypes */
30
static int get_local_leader(void);
31
static int get_edge_weight(int robot1, int robot2);
32
static void get_bom_velocity(int bom_id);
33

    
34
void lemmings_init() {
35
  // usb_puts("lemmings_init\n");
36

    
37
  //  colonet_init();
38
  //run_around_init(); // prepare for moving
39
  //range_init();
40
  //analog_init();
41
  /* range finder code interferes with token ring */
42
  orb_init();
43
  orb_enable();
44

    
45
  // set to defaults
46
  cur_state = FOLLOW;
47
  local_leader = -1;
48
  global_leader = -1;
49
  local_id = wl_get_xbee_id();
50
  speed = SPEED;
51
  turn_speed = 0;
52

    
53
  follow_multi = FOLLOW_MULTI_DEFAULT;
54
}
55

    
56
/* The main function, call this to update states as frequently as possible. */
57
void lemmings_FSM(void) {
58
  int leader_bom = 0;
59
  static int leader_check_count = 0;
60

    
61

    
62
  if (wl_token_get_num_robots() <= 1) {
63
    /* if there is only one robot in the token ring, there is nothing to
64
       follow, so don't do anything */
65
    motors_off();
66
    speed = 0;
67
    orb_set_color(GREEN);
68
    return;
69
  }
70

    
71
  //usb_puts("state: ");
72
  //usb_puti(cur_state);
73
  //usb_puts("\n");
74

    
75
  // only check for new global leader once every 5 iterations
76
  leader_check_count++;
77
  if (leader_check_count % 3 == 0) {
78

    
79
    if (cur_state == LEAD && leader_check_count % 12 == 0) {
80
      // find robot with max id and assign as leader
81
      int max = -1;
82
      wl_token_iterator_begin();
83
      while (wl_token_iterator_has_next()) {
84
        int n = wl_token_iterator_next();
85
        if (n > max) {
86
          max = n;
87
        }
88
  /*       usb_puti(n); */
89
  /*       usb_puts("\n"); */
90
      }
91

    
92
      if (max == local_id) {
93
        // become the global leader
94
        orb_set_color(BLUE);
95
        cur_state = LEAD;
96
        local_leader = -1;
97
        speed = SPEED;
98
        turn_speed = 0;
99
  //      usb_puts(" becoming leader \n");
100
      } 
101
      else {
102
        // become a follower
103
        orb_set_color(RED);
104
        cur_state = FOLLOW;
105
//      usb_puts(" becoming follower\n");
106
      }
107

    
108
      global_leader = max; // set the global leader
109
    }
110
    
111
    if (cur_state == FOLLOW) {
112
      // Make sure we can see our local leader
113
      leader_bom = (local_leader>=0)?wl_token_get_sensor_reading(local_id, local_leader):-1;
114

    
115
      if (leader_bom < 0) {
116
        //usb_puts("no connection to leader\n");
117

    
118
        // Can't see our old leader -- get new bot to follow.
119
        local_leader = get_local_leader();
120
        
121
        if (local_leader == -1) {
122
          /* if there is only one robot in the token ring, there is nothing to
123
            follow, so don't do anything */
124
          /*motors_off();
125
          speed = 0;
126
          return;*/
127
          // nothing to follow, so become a local_leader and start leading
128
          //usb_puts("can't see anyone - becoming a leader\n");
129
          cur_state = LEAD;
130
          local_leader = -1;
131
          orb_set_color(BLUE);
132
          speed = SPEED;
133
          turn_speed = 0;
134
        } else {
135
          //usb_puts("new leader is");
136
          //usb_puti(local_leader);
137
          //usb_puts("\n");
138
          // get data in order to follow leader
139
          leader_bom = wl_token_get_sensor_reading(local_id, local_leader);
140
          get_bom_velocity(leader_bom);
141
        }
142
      } else {
143
        // Leader is still in sight, so follow it
144
        get_bom_velocity(leader_bom);
145
      }
146
    }
147
  }
148
  else {
149
    // prevent spinning in circles
150
    turn_speed /= 5;
151
  }
152
  
153
  // check if running into something
154
  /*int range = range_read_distance(IR2);
155
  if (range > 0 && range < 150) {
156
    if (cur_state == LEAD) {
157
      turn_speed = 100; // turn to avoid
158
    }
159
    else {
160
      speed = 0; // stop to avoid
161
    }
162
  }*/
163
  
164
  // do movement
165
  move(speed, turn_speed);
166
}
167

    
168
// translate bom reading into direction and speed
169
static void get_bom_velocity(int bom_id) {
170
  int error = 0;
171

    
172
  if (bom_id < 0 || bom_id > 15) {
173
    //   usb_puts("ERROR - invalid bom_id\n");
174
    turn_speed = 0;
175
    speed = 0;
176
    return;
177
  }
178

    
179
  // set so right is negative, left is positive
180
  if (bom_id <= 12) {
181
    error = bom_id - 4;
182
  } else {
183
    error = bom_id - 20;
184
  }
185

    
186
  // set turn speed and main speed
187
  // if error is small, turn slowly and travel at normal speed
188
  // if error is large, turn faster and travel at reduced speed
189
  switch(error)
190
  {
191
  case 0:
192
    turn_speed = 0;
193
    speed = SPEED;
194
    return;
195
  case 1:
196
  case -1:
197
    turn_speed = error * 5;
198
    speed = SPEED;
199
    return;
200
  case 2:
201
  case -2:
202
    turn_speed = error * 8;
203
    speed = SPEED;
204
    return;
205
  case 3:
206
  case -3:
207
    turn_speed = error * 12;
208
    speed = SPEED;
209
    return;
210
  case 4:
211
  case -4:
212
    turn_speed = error * 16;
213
    speed = SPEED - SPEED * error * error / 36;
214
    return;
215
  }
216
  // if not in a case
217
  turn_speed = error * 20;
218
  speed = SPEED - SPEED * error * error / 36;
219
}
220

    
221
// create connected components and pick a leader for each chain
222
// CURRENTLY JUST LOOKS FOR CLOSEST ROBOT TO FOLLOW
223
static int get_local_leader(void) {
224
  int nodeB;
225
  int cur_weight;
226
  int best_weight = 1000; // set to infinity initially
227
  int best_node = -1;
228

    
229
  wl_token_iterator_begin();
230

    
231
  // iterator through robots in token ring
232
  while (wl_token_iterator_has_next()) {
233
    nodeB = wl_token_iterator_next();
234
    if (nodeB == local_id) {
235
      continue; // can't follow self
236
    }
237

    
238
    // get an edge weight based on the robot position
239
    cur_weight = get_edge_weight(local_id, nodeB);
240

    
241
    if (nodeB == global_leader && cur_weight != -1) {
242
      // always follow the global leader if you have the option to
243
      best_node = nodeB;
244
      break;
245
    }
246

    
247
    if (cur_weight >= 0 && cur_weight < best_weight) {
248
      // this is new best node, so save values.
249
      best_weight = cur_weight;
250
      best_node = nodeB;
251
    }
252
  }
253

    
254
  return best_node;
255
}
256

    
257
// get edge weight of sensor matrix
258
// add in BOM range data when BOM 1.5 comes out
259
static int get_edge_weight(int robot1, int robot2) {
260
  int bom = wl_token_get_sensor_reading(robot1,robot2);
261

    
262
  // Robots closer to directly in front of us have lower weight.
263
  switch(bom) {
264
  case 12:
265
    return 10;
266

    
267
  case 13:
268
  case 11:
269
    return 9;
270

    
271
  case 14:
272
  case 10:
273
    return 8;
274

    
275
  case 15:
276
  case 9:
277
    return 7;
278

    
279
  case 0:
280
  case 8:
281
    return 6;
282

    
283
  case 1:
284
  case 7:
285
    return 5;
286

    
287
  case 2:
288
  case 6:
289
    return 4;
290

    
291
  case 3:
292
  case 5:
293
    return 3;
294

    
295
  case 4:
296
    return 2;
297
  }
298

    
299
  return -1;
300
}