00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 #include <assert.h>
00029 #include <math.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 
00033 
00034 #include "nav2d_localizer/pf_vector.h"
00035 #include "nav2d_localizer/pf_kdtree.h"
00036 
00037 
00038 
00039 static int pf_kdtree_equal(pf_kdtree_t *self, int key_a[], int key_b[]);
00040 
00041 
00042 static pf_kdtree_node_t *pf_kdtree_insert_node(pf_kdtree_t *self, pf_kdtree_node_t *parent,
00043                                                pf_kdtree_node_t *node, int key[], double value);
00044 
00045 
00046 static pf_kdtree_node_t *pf_kdtree_find_node(pf_kdtree_t *self, pf_kdtree_node_t *node, int key[]);
00047 
00048 
00049 static void pf_kdtree_cluster_node(pf_kdtree_t *self, pf_kdtree_node_t *node, int depth);
00050 
00051 
00052 
00053 
00054 
00055 #ifdef INCLUDE_RTKGUI
00056 
00057 
00058 static void pf_kdtree_draw_node(pf_kdtree_t *self, pf_kdtree_node_t *node, rtk_fig_t *fig);
00059 
00060 #endif
00061 
00062 
00063 
00065 
00066 pf_kdtree_t *pf_kdtree_alloc(int max_size)
00067 {
00068   pf_kdtree_t *self;
00069 
00070   self = calloc(1, sizeof(pf_kdtree_t));
00071 
00072   self->size[0] = 0.50;
00073   self->size[1] = 0.50;
00074   self->size[2] = (10 * M_PI / 180);
00075 
00076   self->root = NULL;
00077 
00078   self->node_count = 0;
00079   self->node_max_count = max_size;
00080   self->nodes = calloc(self->node_max_count, sizeof(pf_kdtree_node_t));
00081 
00082   self->leaf_count = 0;
00083 
00084   return self;
00085 }
00086 
00087 
00089 
00090 void pf_kdtree_free(pf_kdtree_t *self)
00091 {
00092   free(self->nodes);
00093   free(self);
00094   return;
00095 }
00096 
00097 
00099 
00100 void pf_kdtree_clear(pf_kdtree_t *self)
00101 {
00102   self->root = NULL;
00103   self->leaf_count = 0;
00104   self->node_count = 0;
00105 
00106   return;
00107 }
00108 
00109 
00111 
00112 void pf_kdtree_insert(pf_kdtree_t *self, pf_vector_t pose, double value)
00113 {
00114   int key[3];
00115 
00116   key[0] = floor(pose.v[0] / self->size[0]);
00117   key[1] = floor(pose.v[1] / self->size[1]);
00118   key[2] = floor(pose.v[2] / self->size[2]);
00119 
00120   self->root = pf_kdtree_insert_node(self, NULL, self->root, key, value);
00121 
00122   
00123   
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 
00140 
00141 
00142 
00143   return;
00144 }
00145 
00146 
00148 
00149 
00150 double pf_kdtree_get_prob(pf_kdtree_t *self, pf_vector_t pose)
00151 {
00152   int key[3];
00153   pf_kdtree_node_t *node;
00154 
00155   key[0] = floor(pose.v[0] / self->size[0]);
00156   key[1] = floor(pose.v[1] / self->size[1]);
00157   key[2] = floor(pose.v[2] / self->size[2]);
00158 
00159   node = pf_kdtree_find_node(self, self->root, key);
00160   if (node == NULL)
00161     return 0.0;
00162   return node->value;
00163 }
00164 
00165 
00167 
00168 int pf_kdtree_get_cluster(pf_kdtree_t *self, pf_vector_t pose)
00169 {
00170   int key[3];
00171   pf_kdtree_node_t *node;
00172 
00173   key[0] = floor(pose.v[0] / self->size[0]);
00174   key[1] = floor(pose.v[1] / self->size[1]);
00175   key[2] = floor(pose.v[2] / self->size[2]);
00176 
00177   node = pf_kdtree_find_node(self, self->root, key);
00178   if (node == NULL)
00179     return -1;
00180   return node->cluster;
00181 }
00182 
00183 
00185 
00186 int pf_kdtree_equal(pf_kdtree_t *self, int key_a[], int key_b[])
00187 {
00188   
00189 
00190   if (key_a[0] != key_b[0])
00191     return 0;
00192   if (key_a[1] != key_b[1])
00193     return 0;
00194 
00195   if (key_a[2] != key_b[2])
00196     return 0;
00197 
00198   
00199 
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00209   return 1;
00210 }
00211 
00212 
00214 
00215 pf_kdtree_node_t *pf_kdtree_insert_node(pf_kdtree_t *self, pf_kdtree_node_t *parent,
00216                                         pf_kdtree_node_t *node, int key[], double value)
00217 {
00218   int i;
00219   int split, max_split;
00220 
00221   
00222   if (node == NULL)
00223   {
00224     assert(self->node_count < self->node_max_count);
00225     node = self->nodes + self->node_count++;
00226     memset(node, 0, sizeof(pf_kdtree_node_t));
00227 
00228     node->leaf = 1;
00229 
00230     if (parent == NULL)
00231       node->depth = 0;
00232     else
00233       node->depth = parent->depth + 1;
00234 
00235     for (i = 0; i < 3; i++)
00236       node->key[i] = key[i];
00237 
00238     node->value = value;
00239     self->leaf_count += 1;
00240   }
00241 
00242   
00243   else if (node->leaf)
00244   {
00245     
00246     if (pf_kdtree_equal(self, key, node->key))
00247     {
00248       node->value += value;
00249     }
00250 
00251     
00252     else
00253     {
00254       
00255       
00256       max_split = 0;
00257       node->pivot_dim = -1;
00258       for (i = 0; i < 3; i++)
00259       {
00260         split = abs(key[i] - node->key[i]);
00261         if (split > max_split)
00262         {
00263           max_split = split;
00264           node->pivot_dim = i;
00265         }
00266       }
00267       assert(node->pivot_dim >= 0);
00268 
00269       node->pivot_value = (key[node->pivot_dim] + node->key[node->pivot_dim]) / 2.0;
00270 
00271       if (key[node->pivot_dim] < node->pivot_value)
00272       {
00273         node->children[0] = pf_kdtree_insert_node(self, node, NULL, key, value);
00274         node->children[1] = pf_kdtree_insert_node(self, node, NULL, node->key, node->value);
00275       }
00276       else
00277       {
00278         node->children[0] = pf_kdtree_insert_node(self, node, NULL, node->key, node->value);
00279         node->children[1] = pf_kdtree_insert_node(self, node, NULL, key, value);
00280       }
00281 
00282       node->leaf = 0;
00283       self->leaf_count -= 1;
00284     }
00285   }
00286 
00287   
00288   else
00289   {
00290     assert(node->children[0] != NULL);
00291     assert(node->children[1] != NULL);
00292 
00293     if (key[node->pivot_dim] < node->pivot_value)
00294       pf_kdtree_insert_node(self, node, node->children[0], key, value);
00295     else
00296       pf_kdtree_insert_node(self, node, node->children[1], key, value);
00297   }
00298 
00299   return node;
00300 }
00301 
00302 
00304 
00305 pf_kdtree_node_t *pf_kdtree_find_node(pf_kdtree_t *self, pf_kdtree_node_t *node, int key[])
00306 {
00307   if (node->leaf)
00308   {
00309     
00310 
00311     
00312     if (pf_kdtree_equal(self, key, node->key))
00313       return node;
00314     else
00315       return NULL;
00316   }
00317   else
00318   {
00319     
00320 
00321     assert(node->children[0] != NULL);
00322     assert(node->children[1] != NULL);
00323 
00324     
00325     if (key[node->pivot_dim] < node->pivot_value)
00326       return pf_kdtree_find_node(self, node->children[0], key);
00327     else
00328       return pf_kdtree_find_node(self, node->children[1], key);
00329   }
00330 
00331   return NULL;
00332 }
00333 
00334 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00357 
00358 void pf_kdtree_cluster(pf_kdtree_t *self)
00359 {
00360   int i;
00361   int queue_count, cluster_count;
00362   pf_kdtree_node_t **queue, *node;
00363 
00364   queue_count = 0;
00365   queue = calloc(self->node_count, sizeof(queue[0]));
00366 
00367   
00368   for (i = 0; i < self->node_count; i++)
00369   {
00370     node = self->nodes + i;
00371     if (node->leaf)
00372     {
00373       node->cluster = -1;
00374       assert(queue_count < self->node_count);
00375       queue[queue_count++] = node;
00376 
00377       
00378       assert(node == pf_kdtree_find_node(self, self->root, node->key));
00379     }
00380   }
00381 
00382   cluster_count = 0;
00383 
00384   
00385   while (queue_count > 0)
00386   {
00387     node = queue[--queue_count];
00388 
00389     
00390     if (node->cluster >= 0)
00391       continue;
00392 
00393     
00394     node->cluster = cluster_count++;
00395 
00396     
00397     pf_kdtree_cluster_node(self, node, 0);
00398   }
00399 
00400   free(queue);
00401   return;
00402 }
00403 
00404 
00406 
00407 void pf_kdtree_cluster_node(pf_kdtree_t *self, pf_kdtree_node_t *node, int depth)
00408 {
00409   int i;
00410   int nkey[3];
00411   pf_kdtree_node_t *nnode;
00412 
00413   for (i = 0; i < 3 * 3 * 3; i++)
00414   {
00415     nkey[0] = node->key[0] + (i / 9) - 1;
00416     nkey[1] = node->key[1] + ((i % 9) / 3) - 1;
00417     nkey[2] = node->key[2] + ((i % 9) % 3) - 1;
00418 
00419     nnode = pf_kdtree_find_node(self, self->root, nkey);
00420     if (nnode == NULL)
00421       continue;
00422 
00423     assert(nnode->leaf);
00424 
00425     
00426     
00427     if (nnode->cluster >= 0)
00428     {
00429       assert(nnode->cluster == node->cluster);
00430       continue;
00431     }
00432 
00433     
00434     nnode->cluster = node->cluster;
00435 
00436     pf_kdtree_cluster_node(self, nnode, depth + 1);
00437   }
00438   return;
00439 }
00440 
00441 
00442 
00443 #ifdef INCLUDE_RTKGUI
00444 
00446 
00447 void pf_kdtree_draw(pf_kdtree_t *self, rtk_fig_t *fig)
00448 {
00449   if (self->root != NULL)
00450     pf_kdtree_draw_node(self, self->root, fig);
00451   return;
00452 }
00453 
00454 
00456 
00457 void pf_kdtree_draw_node(pf_kdtree_t *self, pf_kdtree_node_t *node, rtk_fig_t *fig)
00458 {
00459   double ox, oy;
00460   char text[64];
00461 
00462   if (node->leaf)
00463   {
00464     ox = (node->key[0] + 0.5) * self->size[0];
00465     oy = (node->key[1] + 0.5) * self->size[1];
00466 
00467     rtk_fig_rectangle(fig, ox, oy, 0.0, self->size[0], self->size[1], 0);
00468 
00469     
00470     
00471 
00472     snprintf(text, sizeof(text), "%d", node->cluster);
00473     rtk_fig_text(fig, ox, oy, 0.0, text);
00474   }
00475   else
00476   {
00477     assert(node->children[0] != NULL);
00478     assert(node->children[1] != NULL);
00479     pf_kdtree_draw_node(self, node->children[0], fig);
00480     pf_kdtree_draw_node(self, node->children[1], fig);
00481   }
00482 
00483   return;
00484 }
00485 
00486 #endif