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