Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (5.94 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
  *turn_speed = error * 20; // set turn speed
169
  *speed = -SPEED * error * error / 25 + SPEED; // set speed
170
}
171

    
172
// create connected components and pick a leader for each chain
173
// CURRENTLY JUST LOOKS FOR CLOSEST ROBOT TO FOLLOW
174
static int get_local_leader(void) {
175
  int nodeB;
176
  int cur_weight;
177
  int best_weight = 1000; // set to infinity initially
178
  int best_node = -1;
179

    
180
  wl_token_iterator_begin();
181

    
182
  // iterator through robots in token ring
183
  while (wl_token_iterator_has_next()) {
184
    nodeB = wl_token_iterator_next();
185
    if (nodeB == local_id) {
186
      continue; // can't follow self
187
    }
188

    
189
    // get an edge weight based on the robot position
190
    cur_weight = get_edge_weight(local_id, nodeB);
191

    
192
    if (nodeB == global_leader && cur_weight != -1) {
193
      // always follow the global leader if you have the option to
194
      best_node = nodeB;
195
      break;
196
    }
197

    
198
    if (cur_weight >= 0 && cur_weight < best_weight) {
199
      // this is new best node, so save values.
200
      best_weight = cur_weight;
201
      best_node = nodeB;
202
    }
203
  }
204

    
205
  return best_node;
206
}
207

    
208
// get edge weight of sensor matrix
209
// add in BOM range data when BOM 1.5 comes out
210
static int get_edge_weight(int robot1, int robot2) {
211
  int bom = wl_token_get_sensor_reading(robot1,robot2);
212

    
213
  // Robots closer to directly in front of us have lower weight.
214
  switch(bom) {
215
  case 12:
216
    return 10;
217

    
218
  case 13:
219
  case 11:
220
    return 9;
221

    
222
  case 14:
223
  case 10:
224
    return 8;
225

    
226
  case 15:
227
  case 9:
228
    return 7;
229

    
230
  case 0:
231
  case 8:
232
    return 6;
233

    
234
  case 1:
235
  case 7:
236
    return 5;
237

    
238
  case 2:
239
  case 6:
240
    return 4;
241

    
242
  case 3:
243
  case 5:
244
    return 3;
245

    
246
  case 4:
247
    return 2;
248
  }
249

    
250
  return -1;
251
}