Project

General

Profile

Statistics
| Revision:

root / branches / orbit / code / behaviors / bfs_fsm / bfs_fsm.c @ 582

History | View | Annotate | Download (7.16 KB)

1
#include <dragonfly_lib.h>
2
#include <wireless.h>
3
#include <wl_token_ring.h>
4
#include <queue.h>
5
#include <string.h>
6
#include "bfs_fsm.h"
7
#include "smart_run_around_fsm.h"
8
//#include "orbit_fsm.h"
9

    
10
/* Used to find a robot (or other object)
11

12
  Uses bom and token ring
13
  
14
  Assumes:
15
    robots are already in a token ring
16
*/
17

    
18

    
19
/* private function prototypes */
20
void evaluate_state(void);
21
int bfs_follow(void);
22

    
23

    
24
/* init */
25
void bfs_init(int robot) {
26
  range_init();
27
  analog_init(1);
28
  motors_init();
29
  orb_init();
30
  orb_enable();
31
  //usb_init();
32
  run_around_init();
33
 
34
  /*Start in the start state, BFS_SEEK */ 
35
  bfs_state = BFS_SEEK;
36
  
37
  bfs_otherRobot = robot; // set which robot to seek
38
  bfs_my_id = wl_get_xbee_id();
39
  bfs_follow_id = -1;
40
  
41
  bfs_pControl=0;
42
  bfs_bom = 0;
43

    
44
  
45
  /*Initialize distances to zero.*/ 
46
  bfs_d1=1000; bfs_d2=1000; bfs_d3=1000; bfs_d4=1000; bfs_d5=1000;
47
  
48
}
49

    
50
/*The main function, call this to update states as frequently as possible.*/
51
void bfs_fsm(void) {
52
  
53
  /*The following lines ensure that undefined (-1) values
54
  will not update the distances.*/ 
55
  int temp;  
56
    
57
  wl_do(); // update wireless
58
  
59
    
60
  if (bfs_state == BFS_SEEK || bfs_state == BFS_FOLLOW) {
61
    bfs_follow_id = bfs_follow();
62
    if (bfs_follow_id == BFS_NO_VAL)
63
      bfs_state = BFS_SEEK; // move to seek state
64
    else {
65
      // found robot to follow to goal
66
      bfs_state = BFS_FOLLOW;
67
      
68
      // get bom reading
69
      temp = wl_token_get_my_sensor_reading(bfs_follow_id);
70
      bfs_bom = (temp == -1) ? bfs_bom : temp;
71
      
72
      // modify bom reading so right is negative, left is positive
73
      if (bfs_bom <= 12)
74
        bfs_bom -= 4;
75
      else
76
        bfs_bom -= 20;
77
      
78
      bfs_pControl = bfs_bom*4;
79
      
80
      
81
      // get range reading for front
82
      temp=range_read_distance(IR2);
83
      bfs_d2=(temp == -1) ? bfs_d2 : temp;
84
      
85
      if (bfs_d2 < BFS_ORBIT_DISTANCE) {
86
        bfs_state = BFS_ORBIT; // move to orbit state
87
        //orbit_init(bfs_follow_id);
88
      }
89
    }  
90
  }
91
  else if (bfs_state == BFS_ORBIT) {
92
    
93
      // get range reading for front
94
      temp=range_read_distance(IR2);
95
      bfs_d2=(temp == -1) ? bfs_d2 : temp;
96
      
97
      if (bfs_d2 < BFS_ORBIT_DISTANCE)
98
        bfs_state = BFS_STOP; // move to stop state  
99
  }
100
  
101
  // evaluate state
102
  evaluate_state();
103
}
104

    
105

    
106
//Acts on state change.
107
void evaluate_state(){
108
    switch(bfs_state){
109
    case(BFS_SEEK): orb_set_color(RED);
110
      // move around
111
      run_around_FSM(); // note: better to just incorporate into this file later one
112
      break;
113
    
114
    case(BFS_FOLLOW): orb_set_color(GREEN);
115
      // follow another robot
116
      move(BFS_STRAIGHT_SPEED,bfs_pControl);
117
      break;
118
      
119
    case(BFS_ORBIT): orb_set_color(BLUE);
120
      // orbit a robot
121
      //orbit_fsm();
122
      move(0,0);
123
      break;
124
      
125
    case(BFS_STOP): orb_set_color(YELLOW);
126
      // stop
127
      move(0,0);
128
      break;
129
      
130
    default: orb_set_color(YELLOW);
131
      /*Should never get here, so stop.*/
132
      move(0,0);
133
      break;
134
  }
135
}
136

    
137
/* find a robot to follow using BFS 
138
  ported from colonybfs by Felix
139
*/
140
int bfs_follow()
141
{
142
  
143
/* pseudocode for BFS
144

145
procedure bfs(v)
146
    q := make_queue()
147
    enqueue(q,v)
148
    mark v as visited
149
    while q is not empty
150
        v = dequeue(q)
151
        process v
152
        for all unvisited vertices v' adjacent to v
153
            mark v' as visited
154
            enqueue(q,v')
155
*/
156

    
157
  Queue* q = queue_create();
158

    
159
  //int num_current_robots = wl_token_get_robots_in_ring();
160

    
161
  // keep track of which nodes you have visited.  Indexed by robot #
162
  // 1 if visited, 0 if not
163
  unsigned char visited_nodes[BFS_MAX_ROBOTS];
164
  // keep track of the distance from the start robot to other robots
165
  // also indexed by robot#
166
  unsigned char node_distances[BFS_MAX_ROBOTS];
167
  // this is the path you take
168
  unsigned char path[BFS_MAX_ROBOTS];
169
    
170
  //variables you will need
171
  unsigned char current_node;                 //current node
172
  unsigned char current_neighbour_node;       //neighbor to the current node
173
  unsigned char current_neighbour_val;        //value of that neighbour's sensors
174
  unsigned char current_distance;              //keep track of current distance to the start
175
    
176
  unsigned char large_number = 255;
177
  
178
  unsigned char* add_value;
179
  
180
  
181

    
182
  //set visited nodes to all 0
183
  memset(visited_nodes, 0, BFS_MAX_ROBOTS);
184
  
185
  //set all the distances to a very large number
186
  //this isn't technically necessary, but it's probably a good thing -- just in case
187
  memset(node_distances, large_number, BFS_MAX_ROBOTS);
188
  
189
  //set the path to all LARGE_NUMBER as well
190
  memset(path, large_number, BFS_MAX_ROBOTS);
191

    
192
  //queue_remove_all(q);
193

    
194
  //add the start node
195
  add_value = (unsigned char*)malloc(sizeof(char));
196
  (*add_value) = bfs_my_id;
197
  queue_add(q, add_value);
198
  visited_nodes[bfs_my_id] = 1;
199
  node_distances[bfs_my_id] = 0;
200
  
201
  while(!queue_is_empty(q)){
202
    add_value = queue_remove(q);
203
    current_node = (*add_value);
204
    
205
    //get the current distance from you to the start
206
    current_distance = node_distances[current_node];
207
    
208
    //this node is on your 'path'
209
    path[current_distance] = current_node;
210
    //note: it's OK if this path leads nowhere -- the path will be
211
    //overwritten by a node that does lead to the goal
212
    //(if there is no path, we set path to null anyways)
213
    
214
    //from now on, all further nodes will be one further away -- increment
215
    current_distance++;
216
    
217
    
218
    //process node -- basically check if it's the goal
219
    if(current_node == bfs_otherRobot) {
220
      //you reach the goal
221
      //return the first robot in the path, which is the one
222
      //to follow
223
      /*
224
      lcd_putchar('.');
225
      lcd_putchar('.');
226
      for(i = 0; i < MAX_ROBOTS; i++)
227
          lcd_putchar(path[i] +48);           //print out the path for fun -- remove this later
228
      lcd_putchar('.');
229
      lcd_putchar('.');
230
      */
231
      return path[1];         //path[0] is you.  path[1] is who you want to follow
232
    }
233
    
234
    // go through all nodes adjacent to current
235
    // in effect, this means going through the current node's row in the matrix
236
    
237
    wl_token_iterator_begin();
238
    while(wl_token_iterator_has_next()) {
239
      //the robot # is actually just the index
240
      current_neighbour_node = wl_token_iterator_next();
241
      //the value is what is stored in the matrix (this is important)
242
      current_neighbour_val = wl_token_get_sensor_reading(current_node,current_neighbour_node);
243
      
244
      //check for connected-ness and that it was not visited
245
      //            unconnected                           visited
246
      if( (current_neighbour_val == BFS_NO_VAL) || (visited_nodes[current_neighbour_node]) ) {
247
        //if it is either unconnected or previously visited, exit
248
        continue;   //go to the next node
249
      }
250
      
251
      //update the distance from the start node to this node
252
      node_distances[current_neighbour_node] = current_distance;
253
      //also mark it as visited
254
      visited_nodes[current_neighbour_node] = 1;
255
      
256
      //also enqueue each neighbour
257
      add_value = (unsigned char*)malloc(sizeof(char));
258
      (*add_value) = current_neighbour_node;
259
      queue_add(q, add_value);
260
    
261
    }
262
  }
263
  
264
  //if we get to here, there is no path
265
  memset(path, 0, BFS_MAX_ROBOTS);
266
  return BFS_NO_VAL;
267

    
268
}
269

    
270