Robot Agent  1.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
pf.c
Go to the documentation of this file.
1 
11  /* -- Includes -- */
12 /* system libraries */
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <math.h>
16 #include <string.h>
17 /* project libraries */
18 #include "pf.h"
19 #include "robot.h"
20 #include "enviroment.h"
21 #include "debug.h"
22 
23  /* -- Defines -- */
24 
25 /* -- Functions -- */
26 
38 pf_t *pf_init( int num,
39  enviroment_t *envs,
40  int move_noise,
41  float turn_noise,
42  int sense_tag_noise,
43  int sense_wall_noise,
44  int radius)
45 {
46  int i;
47 
48  // Allocate Particle filter structure
49  pf_t *pfs = (pf_t *) malloc(sizeof(pf_t));
50 
51  // Set number of particles
52  pfs->num = num;
53 
54  // Allocate memory
55  pfs->particles = malloc(pfs->num * sizeof(robot_t));
56 
57  for(i = 0; i < pfs->num ; i++)
58  {
59  // Set random initial pose for particles (robots)
60  robot_set_pose(&pfs->particles[i], rand() % envs->room_max_width,
61  rand() % envs->room_max_height,
62  fmod(rand(), M_PI * 2));
63  // Set noise
64  robot_set_noise(&pfs->particles[i], move_noise,
65  turn_noise,
66  sense_tag_noise,
67  sense_wall_noise);
68 
69  // Set initial weight
70  pfs->particles[i].radius = radius;
71 
72  // Set initial weight
73  pfs->particles[i].weight = (float)1 / (float)pfs->num;
74  }
75 
76  return pfs;
77 }
78 
84 void pf_destroy(pf_t *pfs)
85 {
86  // Free memory (Robot struct - particles)
87  free(pfs->particles);
88  // Free memory (Particle filter struct)
89  free(pfs);
90 }
91 
99 void pf_drive(pf_t *pfs, int distance, int angle, int uncertain)
100 {
101  int i;
102 
103  // Move all particles
104  for(i = 0; i < pfs->num; i++)
105  {
106  robot_drive(&pfs->particles[i], distance, angle, uncertain);
107  }
108 }
109 
117 void pf_weight_tag(pf_t *pfs, enviroment_t *envs, int tag_num)
118 {
119  int i;
120 
121  // Evaluate each particle
122  for(i = 0; i < pfs->num; i++)
123  {
124  pfs->particles[i].tag_num = tag_num;
125  robot_eval_tag(&pfs->particles[i], envs);
126  }
127 }
128 
137 {
138  int i;
139 
140  // Evaluate each particle
141  for(i = 0; i < pfs->num; i++)
142  {
143  robot_eval_wall(&pfs->particles[i], envs);
144  }
145 }
146 
152 void pf_resample(pf_t *pfs)
153 {
154  // Local variables
155  robot_t **resampled;
156  int i, index = (rand() % pfs->num);
157  float beta = 0;
158  float mw = 0, w_sum = 0;
159 
160  // Allocate memory
161  resampled = (robot_t **)malloc(pfs->num * sizeof(robot_t *));
162  for(i = 0; i < pfs->num; i++)
163  {
164  resampled[i] = (robot_t *)malloc(sizeof(robot_t));
165  }
166 
167  // Find max weight
168  for(i = 0; i < pfs->num; i++)
169  {
170  if(mw < pfs->particles[i].weight)
171  mw = pfs->particles[i].weight;
172  }
173 
174  // TEST !!!
175  debug_printf("MAX WEIGHT: %f\n", mw);
176 
177  // Resample
178  for(i = 0; i < pfs->num; i++)
179  {
180  beta += (float)rand() / ((float)RAND_MAX / (mw * 2));
181  while(beta > pfs->particles[index].weight)
182  {
183  beta -= pfs->particles[index].weight;
184  index = (index + 1) % pfs->num;
185  }
186 
187  memcpy(resampled[i], &pfs->particles[index], sizeof(robot_t));
188 
189  // Calculate sum for normalization (so that sum of all weights is one)
190  w_sum += pfs->particles[index].weight;
191 
192  }
193 
194  // Restore to particles array
195  for(i = 0; i < pfs->num; i++)
196  {
197  memcpy(&pfs->particles[i], resampled[i], sizeof(robot_t));
198  pfs->particles[i].weight = resampled[i]->weight / w_sum;
199  }
200 
201  // Free memory
202  for(i = 0; i < pfs->num; i++)
203  {
204  free(resampled[i]);
205  }
206  free(resampled);
207 }
208 
215 void pf_estimate(pf_t *pfs, robot_t *robot)
216 {
217  int i;
218  float ex = 0, ey = 0;
219  float vx = 0, vy = 0, va = 0;
220 
221  // Loop through all particles
222  for(i = 0; i < pfs->num; i++)
223  {
224  // Calculate position taking into account weights
225  ex += (float)pfs->particles[i].x * pfs->particles[i].weight;
226  ey += (float)pfs->particles[i].y * pfs->particles[i].weight;
227 
228  // Calculate vector for heading direction
229  vx += pfs->particles[i].weight * cos(pfs->particles[i].a);
230  vy += pfs->particles[i].weight * sin(pfs->particles[i].a);
231  }
232 
233  // Calculate angle from the vector
234  if(vy >= 0 && vx > 0)
235  va = atan(vy / vx);
236  else if(vy <= 0 && vx > 0)
237  va = 2 * M_PI + atan(vy / vx);
238  else if(vx != 0)
239  va = M_PI + atan(vy / vx);
240  else if(vy > 0)
241  va = M_PI / 2;
242  else if(vy < 0)
243  va = (3 * M_PI) / 2;
244  else
245  va = 0;
246 
247  // Save estimated values
248  robot->x = (int)ex;
249  robot->y = (int)ey;
250  robot->a = va;
251 }
252 
253 
261 void pf_random(pf_t *pfs, enviroment_t *envs, int tag_num)
262 {
263  int i;
264  int num = rand() % 100; // Number of randomly drawn particles
265  int particle_id;
266 
267  // Draw random particles and place them close to the read RFID tag
268  for(i = 0; i < num; i++)
269  {
270  // Randomly draw id of particle
271  particle_id = rand() % pfs->num;
272 
273  // Set random position near the read tag
274  pfs->particles[particle_id].x = envs->tags[tag_num].x + (300 - (rand() % 600));
275  pfs->particles[particle_id].y = envs->tags[tag_num].y + (300 - (rand() % 600));
276 
277  // Randomize angle only once a while
278  /*if((rand() % 10) > 5)
279  {
280  pfs->particles[particle_id].a = fmod(rand(), M_PI * 2);
281  }*/
282 
283  // Give a low probability
284  pfs->particles[particle_id].weight = 0.00001;
285  }
286 }
287 
294 int pf_accuracy(pf_t *pfs, enviroment_t *envs)
295 {
296  int i;
297  int xmin = 99999, xmax = 0, ymin = 99999, ymax = 0;
298  int width, height, area, field_area;
299  float accuracy;
300  int percent;
301 
302  //
303  for(i = 0; i < pfs->num; i++)
304  {
305  // Look only at good particles
306  if(pfs->particles[i].weight > 0.00001)
307  {
308  // Find MIN
309  if(xmin > pfs->particles[i].x)
310  xmin = pfs->particles[i].x;
311 
312  if(ymin > pfs->particles[i].y)
313  ymin = pfs->particles[i].y;
314 
315  // Find MAX
316  if(xmax < pfs->particles[i].x)
317  xmax = pfs->particles[i].x;
318 
319  if(ymax < pfs->particles[i].y)
320  ymax = pfs->particles[i].y;
321  }
322  }
323 
324  width = xmax - xmin;
325  height = ymax - ymin;
326  area = width * height;
327  field_area = envs->room_max_width * envs->room_max_height;
328 
329  accuracy = 1 - ((float)area / (float)field_area);
330  if(accuracy < 0)
331  {
332  percent = 0;
333  }
334  else
335  {
336  percent = (int)(accuracy * 100);
337  }
338 
339 
340  debug_printf("accuracy: %d [%f] - %d [%d x %d], %d\n", percent, accuracy, area, width, height, field_area);
341 
342  return percent;
343 }
void debug_printf(const char *format,...)
Definition: debug.c:25
float robot_eval_wall(robot_t *robot, enviroment_t *envs)
Definition: robot.c:250
void pf_random(pf_t *pfs, enviroment_t *envs, int tag_num)
Definition: pf.c:261
int tag_num
Definition: robot.h:40
float robot_eval_tag(robot_t *robot, enviroment_t *envs)
Definition: robot.c:214
float a
Definition: robot.h:29
int num
Definition: pf.h:28
robot_t * particles
Definition: pf.h:26
Particle filter structure.
Definition: pf.h:24
void robot_set_noise(robot_t *robot, int move_noise, float turn_noise, int sense_tag_noise, int sense_wall_noise)
Definition: robot.c:100
void robot_drive(robot_t *robot, int distance, int angle, int uncertain)
Definition: robot.c:115
void pf_drive(pf_t *pfs, int distance, int angle, int uncertain)
Definition: pf.c:99
void pf_destroy(pf_t *pfs)
Definition: pf.c:84
int radius
Definition: robot.h:38
enviroment_tag_t * tags
Definition: enviroment.h:52
float weight
Definition: robot.h:31
void pf_estimate(pf_t *pfs, robot_t *robot)
Definition: pf.c:215
void robot_set_pose(robot_t *robot, int x, int y, int a)
Definition: robot.c:84
void pf_weight_tag(pf_t *pfs, enviroment_t *envs, int tag_num)
Definition: pf.c:117
Robot structure.
Definition: robot.h:25
int pf_accuracy(pf_t *pfs, enviroment_t *envs)
Definition: pf.c:294
void pf_weight_wall(pf_t *pfs, enviroment_t *envs)
Definition: pf.c:136
pf_t * pf_init(int num, enviroment_t *envs, int move_noise, float turn_noise, int sense_tag_noise, int sense_wall_noise, int radius)
Definition: pf.c:38
void pf_resample(pf_t *pfs)
Definition: pf.c:152
Enviroment Structure - room points, tags, room point number, tag number.
Definition: enviroment.h:49