pf_kdtree.c
Go to the documentation of this file.
1 //this package is based on amcl and has been modified to fit gmcl
2 /*
3  * Author: Mhd Ali Alshikh Khalil
4  * Date: 20 June 2021
5  *
6 */
7 
8 //amcl author clarification
9 /*
10  * Player - One Hell of a Robot Server
11  * Copyright (C) 2000 Brian Gerkey & Kasper Stoy
12  * gerkey@usc.edu kaspers@robotics.usc.edu
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Lesser General Public
16  * License as published by the Free Software Foundation; either
17  * version 2.1 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27  *
28  */
29 /**************************************************************************
30  * Desc: kd-tree functions
31  * Author: Andrew Howard
32  * Date: 18 Dec 2002
33  * CVS: $Id: pf_kdtree.c 7057 2008-10-02 00:44:06Z gbiggs $
34  *************************************************************************/
35 
36 #include <assert.h>
37 #include <math.h>
38 #include <stdlib.h>
39 #include <string.h>
40 
41 
42 #include "gmcl/pf/pf_vector.h"
43 #include "gmcl/pf/pf_kdtree.h"
44 
45 
46 // Compare keys to see if they are equal
47 static int pf_kdtree_equal(pf_kdtree_t *self, int key_a[], int key_b[]);
48 
49 // Insert a node into the tree
51  pf_kdtree_node_t *node, int key[], double value);
52 
53 // Recursive node search
54 static pf_kdtree_node_t *pf_kdtree_find_node(pf_kdtree_t *self, pf_kdtree_node_t *node, int key[]);
55 
56 // Recursively label nodes in this cluster
57 static void pf_kdtree_cluster_node(pf_kdtree_t *self, pf_kdtree_node_t *node, int depth);
58 
59 // Recursive node printing
60 //static void pf_kdtree_print_node(pf_kdtree_t *self, pf_kdtree_node_t *node);
61 
62 
63 #ifdef INCLUDE_RTKGUI
64 
65 // Recursively draw nodes
66 static void pf_kdtree_draw_node(pf_kdtree_t *self, pf_kdtree_node_t *node, rtk_fig_t *fig);
67 
68 #endif
69 
70 
71 
73 // Create a tree
75 {
76  pf_kdtree_t *self;
77 
78  self = calloc(1, sizeof(pf_kdtree_t));
79 
80  self->size[0] = 0.50;
81  self->size[1] = 0.50;
82  self->size[2] = (10 * M_PI / 180);
83 
84  self->root = NULL;
85 
86  self->node_count = 0;
87  self->node_max_count = max_size;
88  self->nodes = calloc(self->node_max_count, sizeof(pf_kdtree_node_t));
89 
90  self->leaf_count = 0;
91 
92  return self;
93 }
94 
95 
97 // Destroy a tree
99 {
100  free(self->nodes);
101  free(self);
102  return;
103 }
104 
105 
107 // Clear all entries from the tree
109 {
110  self->root = NULL;
111  self->leaf_count = 0;
112  self->node_count = 0;
113 
114  return;
115 }
116 
117 
119 // Insert a pose into the tree.
120 void pf_kdtree_insert(pf_kdtree_t *self, pf_vector_t pose, double value)
121 {
122  int key[3];
123 
124  key[0] = floor(pose.v[0] / self->size[0]);
125  key[1] = floor(pose.v[1] / self->size[1]);
126  key[2] = floor(pose.v[2] / self->size[2]);
127 
128  self->root = pf_kdtree_insert_node(self, NULL, self->root, key, value);
129 
130  // Test code
131  /*
132  printf("find %d %d %d\n", key[0], key[1], key[2]);
133  assert(pf_kdtree_find_node(self, self->root, key) != NULL);
134 
135  pf_kdtree_print_node(self, self->root);
136 
137  printf("\n");
138 
139  for (i = 0; i < self->node_count; i++)
140  {
141  node = self->nodes + i;
142  if (node->leaf)
143  {
144  printf("find %d %d %d\n", node->key[0], node->key[1], node->key[2]);
145  assert(pf_kdtree_find_node(self, self->root, node->key) == node);
146  }
147  }
148  printf("\n\n");
149  */
150 
151  return;
152 }
153 
154 
156 // Determine the probability estimate for the given pose. TODO: this
157 // should do a kernel density estimate rather than a simple histogram.
159 {
160  int key[3];
161  pf_kdtree_node_t *node;
162 
163  key[0] = floor(pose.v[0] / self->size[0]);
164  key[1] = floor(pose.v[1] / self->size[1]);
165  key[2] = floor(pose.v[2] / self->size[2]);
166 
167  node = pf_kdtree_find_node(self, self->root, key);
168  if (node == NULL)
169  return 0.0;
170  return node->value;
171 }
172 
173 
175 // Determine the cluster label for the given pose
177 {
178  int key[3];
179  pf_kdtree_node_t *node;
180 
181  key[0] = floor(pose.v[0] / self->size[0]);
182  key[1] = floor(pose.v[1] / self->size[1]);
183  key[2] = floor(pose.v[2] / self->size[2]);
184 
185  node = pf_kdtree_find_node(self, self->root, key);
186  if (node == NULL)
187  return -1;
188  return node->cluster;
189 }
190 
191 
193 // Compare keys to see if they are equal
194 int pf_kdtree_equal(pf_kdtree_t *self, int key_a[], int key_b[])
195 {
196  //double a, b;
197 
198  if (key_a[0] != key_b[0])
199  return 0;
200  if (key_a[1] != key_b[1])
201  return 0;
202 
203  if (key_a[2] != key_b[2])
204  return 0;
205 
206  /* TODO: make this work (pivot selection needs fixing, too)
207  // Normalize angles
208  a = key_a[2] * self->size[2];
209  a = atan2(sin(a), cos(a)) / self->size[2];
210  b = key_b[2] * self->size[2];
211  b = atan2(sin(b), cos(b)) / self->size[2];
212 
213  if ((int) a != (int) b)
214  return 0;
215  */
216 
217  return 1;
218 }
219 
220 
222 // Insert a node into the tree
224  pf_kdtree_node_t *node, int key[], double value)
225 {
226  int i;
227  int split, max_split;
228 
229  // If the node doesnt exist yet...
230  if (node == NULL)
231  {
232  assert(self->node_count < self->node_max_count);
233  node = self->nodes + self->node_count++;
234  memset(node, 0, sizeof(pf_kdtree_node_t));
235 
236  node->leaf = 1;
237 
238  if (parent == NULL)
239  node->depth = 0;
240  else
241  node->depth = parent->depth + 1;
242 
243  for (i = 0; i < 3; i++)
244  node->key[i] = key[i];
245 
246  node->value = value;
247  self->leaf_count += 1;
248  }
249 
250  // If the node exists, and it is a leaf node...
251  else if (node->leaf)
252  {
253  // If the keys are equal, increment the value
254  if (pf_kdtree_equal(self, key, node->key))
255  {
256  node->value += value;
257  }
258 
259  // The keys are not equal, so split this node
260  else
261  {
262  // Find the dimension with the largest variance and do a mean
263  // split
264  max_split = 0;
265  node->pivot_dim = -1;
266  for (i = 0; i < 3; i++)
267  {
268  split = abs(key[i] - node->key[i]);
269  if (split > max_split)
270  {
271  max_split = split;
272  node->pivot_dim = i;
273  }
274  }
275  assert(node->pivot_dim >= 0);
276 
277  node->pivot_value = (key[node->pivot_dim] + node->key[node->pivot_dim]) / 2.0;
278 
279  if (key[node->pivot_dim] < node->pivot_value)
280  {
281  node->children[0] = pf_kdtree_insert_node(self, node, NULL, key, value);
282  node->children[1] = pf_kdtree_insert_node(self, node, NULL, node->key, node->value);
283  }
284  else
285  {
286  node->children[0] = pf_kdtree_insert_node(self, node, NULL, node->key, node->value);
287  node->children[1] = pf_kdtree_insert_node(self, node, NULL, key, value);
288  }
289 
290  node->leaf = 0;
291  self->leaf_count -= 1;
292  }
293  }
294 
295  // If the node exists, and it has children...
296  else
297  {
298  assert(node->children[0] != NULL);
299  assert(node->children[1] != NULL);
300 
301  if (key[node->pivot_dim] < node->pivot_value)
302  pf_kdtree_insert_node(self, node, node->children[0], key, value);
303  else
304  pf_kdtree_insert_node(self, node, node->children[1], key, value);
305  }
306 
307  return node;
308 }
309 
310 
312 // Recursive node search
314 {
315  if (node->leaf)
316  {
317  //printf("find : leaf %p %d %d %d\n", node, node->key[0], node->key[1], node->key[2]);
318 
319  // If the keys are the same...
320  if (pf_kdtree_equal(self, key, node->key))
321  return node;
322  else
323  return NULL;
324  }
325  else
326  {
327  //printf("find : brch %p %d %f\n", node, node->pivot_dim, node->pivot_value);
328 
329  assert(node->children[0] != NULL);
330  assert(node->children[1] != NULL);
331 
332  // If the keys are different...
333  if (key[node->pivot_dim] < node->pivot_value)
334  return pf_kdtree_find_node(self, node->children[0], key);
335  else
336  return pf_kdtree_find_node(self, node->children[1], key);
337  }
338 
339  return NULL;
340 }
341 
342 
344 // Recursive node printing
345 /*
346 void pf_kdtree_print_node(pf_kdtree_t *self, pf_kdtree_node_t *node)
347 {
348  if (node->leaf)
349  {
350  printf("(%+02d %+02d %+02d)\n", node->key[0], node->key[1], node->key[2]);
351  printf("%*s", node->depth * 11, "");
352  }
353  else
354  {
355  printf("(%+02d %+02d %+02d) ", node->key[0], node->key[1], node->key[2]);
356  pf_kdtree_print_node(self, node->children[0]);
357  pf_kdtree_print_node(self, node->children[1]);
358  }
359  return;
360 }
361 */
362 
363 
365 // Cluster the leaves in the tree
367 {
368  int i;
369  int queue_count, cluster_count;
370  pf_kdtree_node_t **queue, *node;
371 
372  queue_count = 0;
373  queue = calloc(self->node_count, sizeof(queue[0]));
374 
375  // Put all the leaves in a queue
376  for (i = 0; i < self->node_count; i++)
377  {
378  node = self->nodes + i;
379  if (node->leaf)
380  {
381  node->cluster = -1;
382  assert(queue_count < self->node_count);
383  queue[queue_count++] = node;
384 
385  // TESTING; remove
386  assert(node == pf_kdtree_find_node(self, self->root, node->key));
387  }
388  }
389 
390  cluster_count = 0;
391 
392  // Do connected components for each node
393  while (queue_count > 0)
394  {
395  node = queue[--queue_count];
396 
397  // If this node has already been labelled, skip it
398  if (node->cluster >= 0)
399  continue;
400 
401  // Assign a label to this cluster
402  node->cluster = cluster_count++;
403 
404  // Recursively label nodes in this cluster
405  pf_kdtree_cluster_node(self, node, 0);
406  }
407 
408  free(queue);
409  return;
410 }
411 
412 
414 // Recursively label nodes in this cluster
416 {
417  int i;
418  int nkey[3];
419  pf_kdtree_node_t *nnode;
420 
421  for (i = 0; i < 3 * 3 * 3; i++)
422  {
423  nkey[0] = node->key[0] + (i / 9) - 1;
424  nkey[1] = node->key[1] + ((i % 9) / 3) - 1;
425  nkey[2] = node->key[2] + ((i % 9) % 3) - 1;
426 
427  nnode = pf_kdtree_find_node(self, self->root, nkey);
428  if (nnode == NULL)
429  continue;
430 
431  assert(nnode->leaf);
432 
433  // This node already has a label; skip it. The label should be
434  // consistent, however.
435  if (nnode->cluster >= 0)
436  {
437  assert(nnode->cluster == node->cluster);
438  continue;
439  }
440 
441  // Label this node and recurse
442  nnode->cluster = node->cluster;
443 
444  pf_kdtree_cluster_node(self, nnode, depth + 1);
445  }
446  return;
447 }
448 
449 
450 
451 #ifdef INCLUDE_RTKGUI
452 
454 // Draw the tree
455 void pf_kdtree_draw(pf_kdtree_t *self, rtk_fig_t *fig)
456 {
457  if (self->root != NULL)
458  pf_kdtree_draw_node(self, self->root, fig);
459  return;
460 }
461 
462 
464 // Recursively draw nodes
465 void pf_kdtree_draw_node(pf_kdtree_t *self, pf_kdtree_node_t *node, rtk_fig_t *fig)
466 {
467  double ox, oy;
468  char text[64];
469 
470  if (node->leaf)
471  {
472  ox = (node->key[0] + 0.5) * self->size[0];
473  oy = (node->key[1] + 0.5) * self->size[1];
474 
475  rtk_fig_rectangle(fig, ox, oy, 0.0, self->size[0], self->size[1], 0);
476 
477  //snprintf(text, sizeof(text), "%0.3f", node->value);
478  //rtk_fig_text(fig, ox, oy, 0.0, text);
479 
480  snprintf(text, sizeof(text), "%d", node->cluster);
481  rtk_fig_text(fig, ox, oy, 0.0, text);
482  }
483  else
484  {
485  assert(node->children[0] != NULL);
486  assert(node->children[1] != NULL);
487  pf_kdtree_draw_node(self, node->children[0], fig);
488  pf_kdtree_draw_node(self, node->children[1], fig);
489  }
490 
491  return;
492 }
493 
494 #endif
pf_kdtree_cluster
void pf_kdtree_cluster(pf_kdtree_t *self)
Definition: pf_kdtree.c:366
pf_kdtree_get_prob
double pf_kdtree_get_prob(pf_kdtree_t *self, pf_vector_t pose)
Definition: pf_kdtree.c:158
pf_kdtree.h
pf_kdtree_find_node
static pf_kdtree_node_t * pf_kdtree_find_node(pf_kdtree_t *self, pf_kdtree_node_t *node, int key[])
Definition: pf_kdtree.c:313
pf_vector_t
Definition: pf_vector.h:46
pf_kdtree_node::cluster
int cluster
Definition: pf_kdtree.h:66
pf_kdtree_clear
void pf_kdtree_clear(pf_kdtree_t *self)
Definition: pf_kdtree.c:108
pf_kdtree_node::pivot_value
double pivot_value
Definition: pf_kdtree.h:57
pf_kdtree_node::depth
int depth
Definition: pf_kdtree.h:53
pf_kdtree_free
void pf_kdtree_free(pf_kdtree_t *self)
Definition: pf_kdtree.c:98
pf_kdtree_get_cluster
int pf_kdtree_get_cluster(pf_kdtree_t *self, pf_vector_t pose)
Definition: pf_kdtree.c:176
pf_kdtree_node::leaf
int leaf
Definition: pf_kdtree.h:53
pf_kdtree_t
Definition: pf_kdtree.h:70
pf_kdtree_node
Definition: pf_kdtree.h:45
pf_kdtree_insert_node
static pf_kdtree_node_t * pf_kdtree_insert_node(pf_kdtree_t *self, pf_kdtree_node_t *parent, pf_kdtree_node_t *node, int key[], double value)
Definition: pf_kdtree.c:223
pf_kdtree_node::key
int key[3]
Definition: pf_kdtree.h:60
pf_kdtree_node::children
struct pf_kdtree_node * children[2]
Definition: pf_kdtree.h:69
pf_kdtree_alloc
pf_kdtree_t * pf_kdtree_alloc(int max_size)
Definition: pf_kdtree.c:74
pf_kdtree_insert
void pf_kdtree_insert(pf_kdtree_t *self, pf_vector_t pose, double value)
Definition: pf_kdtree.c:120
pf_kdtree_node::pivot_dim
int pivot_dim
Definition: pf_kdtree.h:56
pf_kdtree_node::value
double value
Definition: pf_kdtree.h:63
assert.h
pf_kdtree_cluster_node
static void pf_kdtree_cluster_node(pf_kdtree_t *self, pf_kdtree_node_t *node, int depth)
Definition: pf_kdtree.c:415
pf_vector_t::v
double v[3]
Definition: pf_vector.h:53
pf_kdtree_equal
static int pf_kdtree_equal(pf_kdtree_t *self, int key_a[], int key_b[])
Definition: pf_kdtree.c:194
pf_vector.h


gmcl
Author(s): Mhd Ali Alshikh Khalil, adler1994@gmail.com
autogenerated on Wed Mar 2 2022 00:20:14