Robot Agent  1.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
pheromone.c
Go to the documentation of this file.
1 
11  /* -- Includes -- */
12 /* system libraries */
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <math.h>
17 #include <time.h>
18 /* project libraries */
19 #include "pheromone.h"
20 #include "enviroment.h"
21 #include "general.h"
22 #include "def.h"
23 #include "debug.h"
24 
25 /* -- Defines -- */
26 
27 /* -- Functions -- */
28 
41  int width,
42  int lifetime,
43  int pheromone_radius,
44  int eval_radius,
45  int eval_dist,
46  int sector_max_size)
47 {
48  // Local variables
49  int i, j;
50 
51  // Allocate memory for robot structure
52  pheromone_t *ph = (pheromone_t *) malloc(sizeof(pheromone_t));
53 
54  // Save parameter values
55  ph->width = width;
56  ph->lifetime = lifetime;
57  ph->pheromone_radius = pheromone_radius;
58  ph->eval_radius = eval_radius;
59  ph->eval_dist = eval_dist;
60 
61  // Calculate how many grid cells fit in the room
62  ph->x_cells = ceil((float)env->room_max_width / (float)width);
63  ph->y_cells = ceil((float)env->room_max_height / (float)width);
64 
65  // Allocate memory
66  ph->map = (int **)malloc(ph->x_cells * sizeof(int *));
67  for(i = 0; i < ph->x_cells; i++)
68  {
69  ph->map[i] = (int *)malloc(ph->y_cells * sizeof(int));
70  for(j = 0; j < ph->y_cells; j++)
71  {
72  ph->map[i][j] = 0;
73  }
74  }
75 
76  // How many cells fit in the smell stencil
77  ph->eval_cells = ceil((float)(eval_radius * 2) / (float)width);
78  // Smell cells should be odd number (circle draw algorithm limitation)
79  if(ph->eval_cells % 2 == 0)
80  ph->eval_cells++;
81  // Make smell stencil
83 
84  // How many cells fit in the pheromone stencil
85  ph->pheromone_cells = ceil((float)(pheromone_radius * 2) / (float)width);
86  // Smell cells should be odd number (circle draw algorithm limitation)
87  if(ph->pheromone_cells % 2 == 0)
88  ph->pheromone_cells++;
89  // Make smell stencil
91 
92  // Calculate sectors
93  ph->sector_max_size = sector_max_size;
94  ph->sector_size = floor((float)sector_max_size / (float)ph->y_cells);
95  ph->sector_count = ceil((float)ph->x_cells / (float)ph->sector_size);
96  ph->sector_size_last = ph->x_cells % ph->sector_size;
97 
98  debug_printf("map: %d, %d\n",ph->x_cells, ph->y_cells);
99  debug_printf("sec: %d, %d, %d, %d\n", ph->y_cells, ph->sector_size, ph->sector_count, ph->sector_size_last);
100 
101  return ph;
102 }
103 
110 {
111  // Local variables
112  int i;
113 
114  // Free pheromone map
115  for(i = 0; i < ph->x_cells; i++)
116  {
117  free(ph->map[i]);
118  }
119  free(ph->map);
120 
121  // Free smell stencil
122  for(i = 0; i < ph->eval_cells; i++)
123  {
124  free(ph->eval_stencil[i]);
125  }
126  free(ph->eval_stencil);
127 
128  // Free pheromone stencil
129  for(i = 0; i < ph->pheromone_cells; i++)
130  {
131  free(ph->pheromone_stencil[i]);
132  }
133  free(ph->pheromone_stencil);
134 
135  // Free pheromone structure
136  free(ph);
137 
138 }
139 
146 void pheromone_make_stencil(int ***stencil, int size)
147 {
148  // Local variables
149  int i, j;
150 
151  // Allocate memory for smell area
152  (*stencil) = (int **)malloc(size * sizeof(int *));
153  for(i = 0; i < size; ++i)
154  {
155  (*stencil)[i] = (int *)malloc(size * sizeof(int));
156  for(j = 0; j < size; j++)
157  {
158  (*stencil)[i][j] = 0;
159  }
160  }
161 
162  // Draw circle
163  general_circle((*stencil), (size - 1)/2, (size - 1)/2, (size - 1)/2);
164 }
165 
174 void pheromone_put(pheromone_t *ph, int x, int y)
175 {
176  // Local variables
177  int i, j;
178  int cx, cy;
179 
180  // Calculate xy position to fit center (shift stencil so it fits in center)
181  cx = (x - ph->pheromone_radius);
182  cy = (y - ph->pheromone_radius);
183  if(cx >= 0 && cy >= 0)
184  {
185  cx = cx / ph->width;
186  cy = cy / ph->width;
187  }
188  else
189  {
190  return;
191  }
192 
193  // Apply pheromone stencil to pheromone map
194  for(i = 0; i < ph->pheromone_cells; i++)
195  {
196  for(j = 0; j < ph->pheromone_cells; j++)
197  {
198  // Check if stencil pixel is set
199  if(ph->pheromone_stencil[i][j] != 0)
200  {
201  // Check pheromone map borders
202  if((cx + i) >= 0 && (cy + j) >= 0 && (cx + i) < ph->x_cells && (cy + j) < ph->y_cells)
203  {
204  // Set pheromone with its timestamp
205  ph->map[cx + i][cy + j] = time(NULL) / ph->lifetime;
206  //printf("pheromone: %d, %d, %d\n", cx + i, cy + j, ph->map[cx + i][cy + j]);
207  }
208  }
209  }
210  }
211 }
212 
220 {
221  int i, j, k;
222  int x;
223  int y;
224  float a[5] = {-M_PI/2, -M_PI/4, 0, M_PI/4, M_PI/2};
225 
226  int t;
227  int s[5] = {0, 0, 0, 0, 0};
228  int s_t = 0;
229  float p[5] = {0, 0, 0, 0, 0};
230  float p_t = 0, p_r;
231 
232  // Test
233  float max = 0;
234  int max_i = 0;
235 
236  // Evaluate smell in 5 areas
237  for(k = 0; k < 5; k++)
238  {
239  // Calculate position of smell area
240  x = cos(robot->a + a[k]) * ((ph->pheromone_radius + ph->eval_radius) / ph->width) + (robot->x - ph->eval_radius) / ph->width;
241  y = sin(robot->a + a[k]) * ((ph->pheromone_radius + ph->eval_radius) / ph->width) + (robot->y - ph->eval_radius) / ph->width;
242 
243  // Applay smell stencil and evaluate smell in area
244  for(i = 0; i < ph->eval_cells; i++)
245  {
246  for(j = 0; j < ph->eval_cells; j++)
247  {
248  // Check if stencill element is full
249  if(ph->eval_stencil[i][j] != 0)
250  {
251  // Check if in range
252  if((x + i) >= 0 && (y + j) >= 0 && (x + i) < ph->x_cells && (y + j) < ph->y_cells)
253  {
254  t = ((time(NULL) / ph->lifetime) - ph->map[x + i][y + j]);
255  if(t > 255) {
256  t = 255;
257  }
258  else if(t < 0) {
259  t = 0;
260  }
261  s[k] += (256 - t) * 100; // !!!
262  }
263  else
264  {
265  s[k] += 999999;
266  }
267  }
268  }
269  }
270  s_t += s[k];
271  }
272 
273 
274  // Calculate probability
275  // It is calculated other way around, it should be normalized but it works well without it.
276  for(k = 0; k < 5; k++)
277  {
278  p[k] = ((float)s_t / (float)s[k]);
279  p_t += p[k];
280 
281  if(p[k] > max)
282  {
283  max = p[k];
284  max_i = k;
285  }
286  else if(p[k] == max)
287  {
288  if((rand() % 10) > 5)
289  {
290  max_i = k;
291  }
292  }
293  }
294 
295  debug_printf("%f, %f, %f, %f, %f\n", p[0], p[1], p[2], p[3], p[4]);
296 
297  if(p[0] == p[1] && p[0] == p[2] && p[0] == p[3] && p[0] == p[4])
298  {
299  return (rand() % 5);
300  }
301  else
302  {
303  return max_i;
304  }
305 
306  // Randomly choose direction based on probability
307  //p_r = fmod(rand(), p_t);
308 
309  // Check which direction was choosen and return it
310  if(p_r >= 0 && p_r < (p[0])) {
311  return s_PH_LEFT;
312  }
313  else if(p_r >= (p[0]) && p_r < (p[0] + p[1])) {
314  return s_PH_TOP_LEFT;
315  }
316  else if(p_r >= (p[0] + p[1]) && p_r < (p[0] + p[1] + p[2])){
317  return s_PH_TOP;
318  }
319  else if(p_r >= (p[0] + p[1] + p[2]) && p_r < (p[0] + p[1] + p[2] + p[3])) {
320  return s_PH_TOP_RIGHT;
321  }
322  else if(p_r >= (p[0] + p[1] + p[2] + p[3]) && p_r < (p[0] + p[1] + p[2] + p[3] + p[4])) {
323  return s_PH_RIGHT;
324  }
325 
326  // Return Error otherwise
327  return s_ERROR;
328 }
329 
337 {
338  // Local variables
339  int i,j, y = 0;
340 
341  // Output sector data starting at the right column
342  for(i = phms->num * ph->sector_size; i < ph->x_cells; i++)
343  {
344  for(j = 0; j < ph->y_cells; j++)
345  {
346  // Replace only if data is newer
347  if(ph->map[i][j] < (phms->timestamp - phms->data[y]))
348  {
349  ph->map[i][j] = phms->timestamp - phms->data[y];
350  }
351 
352  // Increase sector data counter
353  y++;
354  }
355 
356  // Finish if sector is done
357  if(y >= (ph->y_cells * ph->sector_size))
358  {
359  break;
360  }
361  }
362 
363  // If for cycle exits without "break", it was last sector, that was not full
364 }
365 
372 {
373  // Local variables
374  int i, j, x = 0, y = 0;
375  int t, t_curr;
376  unsigned char cell;
377 
378  // Allocate memory for pheromone map sector structures
380  for(i = 0; i < ph->sector_count; i++)
381  {
382  phms[i] = (pheromone_map_sector_t *)malloc(sizeof(pheromone_map_sector_t));
383  }
384 
385  // Get current timestamp
386  t_curr = time(NULL) / ph->lifetime;
387 
388  // Save data about first sector
389  phms[x]->num = x;
390  phms[x]->size = ph->y_cells * ph->sector_size;
391  phms[x]->timestamp = t_curr;
392  memset(phms[x]->data, 0xFF, ph->sector_max_size);
393 
394  // Loop through map data and fill in the sectors
395  for(i = 0; i < ph->x_cells; i++)
396  {
397  for(j = 0; j < ph->y_cells; j++)
398  {
399  // Calculate cell value
400  t = t_curr - ph->map[i][j];
401  if(t > 255) {
402  cell = 255;
403  }
404  else if(t < 1) {
405  cell = 1;
406  }
407  // THIS IS FOR TEST (SKIP COMMA CODE) !!!
408  else if(t == ',') {
409  cell = ',' + 1;
410  }
411  else {
412  cell = (unsigned char)t;
413  }
414 
415  // Save cell value in sector
416  phms[x]->data[y] = cell;
417 
418  // Increase sector data counter
419  y++;
420  // Check if sector is full. If yes then ...
421  if(y >= (ph->y_cells * ph->sector_size))
422  {
423  // Increase sector number
424  x++;
425  // Reset sector data counter
426  y = 0;
427 
428  // Save data about new sector
429  if(x < ph->sector_count)
430  {
431  phms[x]->num = x;
432  phms[x]->size = ph->y_cells * ph->sector_size;
433  phms[x]->timestamp = t_curr;
434  memset(phms[x]->data, 0xFF, ph->sector_max_size);
435  }
436  }
437  }
438  }
439 
440  return phms;
441 }
442 
450 {
451  // Local variables
452  int i;
453 
454  // Free Pheromone map sectors
455  for (i = 0; i < ph->sector_count; ++i)
456  {
457  free(phms[i]);
458  }
459 
460  // Free Pheromone map sector array
461  free(phms);
462 }
void debug_printf(const char *format,...)
Definition: debug.c:25
int ** eval_stencil
Definition: pheromone.h:30
int ** pheromone_stencil
Definition: pheromone.h:31
Pheromone structure.
Definition: pheromone.h:27
void pheromone_make_stencil(int ***stencil, int size)
Definition: pheromone.c:146
int pheromone_eval(pheromone_t *ph, robot_t *robot)
Definition: pheromone.c:219
float a
Definition: robot.h:29
pheromone_map_sector_t ** pheromone_map_extract(pheromone_t *ph)
Definition: pheromone.c:371
void pheromone_map_update(pheromone_t *ph, pheromone_map_sector_t *phms)
Definition: pheromone.c:336
void general_circle(int **arr, int cx, int cy, int radius)
Definition: general.c:180
Robot structure.
Definition: robot.h:25
unsigned char data[s_CONFIG_PHEROMONE_SECTOR_MAX_SIZE]
Definition: pheromone.h:63
#define s_ERROR
Definition: def.h:65
pheromone_t * pheromone_init(enviroment_t *env, int width, int lifetime, int pheromone_radius, int eval_radius, int eval_dist, int sector_max_size)
Definition: pheromone.c:40
void pheromone_put(pheromone_t *ph, int x, int y)
Definition: pheromone.c:174
void pheromone_destroy(pheromone_t *ph)
Definition: pheromone.c:109
void pheromone_map_destroy(pheromone_t *ph, pheromone_map_sector_t **phms)
Definition: pheromone.c:449
Pheromone Map Sector structure.
Definition: pheromone.h:58
Enviroment Structure - room points, tags, room point number, tag number.
Definition: enviroment.h:49