Nav2 Navigation Stack - rolling  main
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 <stdint.h>
31 #include <stdlib.h>
32 #include <string.h>
33 
34 
35 #include "nav2_amcl/pf/pf_vector.hpp"
36 #include "nav2_amcl/pf/pf_kdtree.hpp"
37 
38 
39 // Compare keys to see if they are equal
40 static int pf_kdtree_equal(pf_kdtree_t * self, int key_a[], int key_b[]);
41 
42 // Insert a node into the tree
43 static pf_kdtree_node_t * pf_kdtree_insert_node(
44  pf_kdtree_t * self, pf_kdtree_node_t * parent,
45  pf_kdtree_node_t * node, int key[], double value);
46 
47 // Recursive node search
48 static pf_kdtree_node_t * pf_kdtree_find_node(
49  pf_kdtree_t * self, pf_kdtree_node_t * node,
50  int key[]);
51 
52 // Add neighboring nodes in this cluster to the queue
53 static void pf_kdtree_cluster_node(
54  pf_kdtree_t * self, pf_kdtree_node_t * node,
55  pf_kdtree_node_t ** queue, int * queue_count);
56 
57 // Recursive node printing
58 // static void pf_kdtree_print_node(pf_kdtree_t *self, pf_kdtree_node_t *node);
59 
60 
61 #ifdef INCLUDE_RTKGUI
62 
63 // Recursively draw nodes
64 static void pf_kdtree_draw_node(pf_kdtree_t * self, pf_kdtree_node_t * node, rtk_fig_t * fig);
65 
66 #endif
67 
68 
70 // Create a tree
71 pf_kdtree_t * pf_kdtree_alloc(int max_size)
72 {
73  pf_kdtree_t * self;
74 
75  self = calloc(1, sizeof(pf_kdtree_t));
76 
77  self->size[0] = 0.50;
78  self->size[1] = 0.50;
79  self->size[2] = (10 * M_PI / 180);
80 
81  self->root = NULL;
82 
83  self->node_count = 0;
84  self->node_max_count = max_size;
85  self->nodes = calloc(self->node_max_count, sizeof(pf_kdtree_node_t));
86 
87  self->leaf_count = 0;
88 
89  return self;
90 }
91 
92 
94 // Destroy a tree
95 void pf_kdtree_free(pf_kdtree_t * self)
96 {
97  free(self->nodes);
98  free(self);
99 }
100 
101 
103 // Clear all entries from the tree
104 void pf_kdtree_clear(pf_kdtree_t * self)
105 {
106  self->root = NULL;
107  self->leaf_count = 0;
108  self->node_count = 0;
109 }
110 
111 
113 // Insert a pose into the tree.
114 void pf_kdtree_insert(pf_kdtree_t * self, pf_vector_t pose, double value)
115 {
116  int key[3];
117 
118  key[0] = floor(pose.v[0] / self->size[0]);
119  key[1] = floor(pose.v[1] / self->size[1]);
120  key[2] = floor(pose.v[2] / self->size[2]);
121 
122  self->root = pf_kdtree_insert_node(self, NULL, self->root, key, value);
123 
124  // Test code
125  /*
126  printf("find %d %d %d\n", key[0], key[1], key[2]);
127  assert(pf_kdtree_find_node(self, self->root, key) != NULL);
128 
129  pf_kdtree_print_node(self, self->root);
130 
131  printf("\n");
132 
133  for (i = 0; i < self->node_count; i++)
134  {
135  node = self->nodes + i;
136  if (node->leaf)
137  {
138  printf("find %d %d %d\n", node->key[0], node->key[1], node->key[2]);
139  assert(pf_kdtree_find_node(self, self->root, node->key) == node);
140  }
141  }
142  printf("\n\n");
143  */
144 }
145 
146 
148 // Determine the probability estimate for the given pose. TODO: this
149 // should do a kernel density estimate rather than a simple histogram.
150 // double pf_kdtree_get_prob(pf_kdtree_t * self, pf_vector_t pose)
151 // {
152 // int key[3];
153 // pf_kdtree_node_t * node;
154 
155 // key[0] = floor(pose.v[0] / self->size[0]);
156 // key[1] = floor(pose.v[1] / self->size[1]);
157 // key[2] = floor(pose.v[2] / self->size[2]);
158 
159 // node = pf_kdtree_find_node(self, self->root, key);
160 // if (node == NULL) {
161 // return 0.0;
162 // }
163 // return node->value;
164 // }
165 
166 
168 // Determine the cluster label for the given pose
169 int pf_kdtree_get_cluster(pf_kdtree_t * self, pf_vector_t pose)
170 {
171  int key[3];
172  pf_kdtree_node_t * node;
173 
174  key[0] = floor(pose.v[0] / self->size[0]);
175  key[1] = floor(pose.v[1] / self->size[1]);
176  key[2] = floor(pose.v[2] / self->size[2]);
177 
178  node = pf_kdtree_find_node(self, self->root, key);
179  if (node == NULL) {
180  return -1;
181  }
182  return node->cluster;
183 }
184 
185 
187 // Compare keys to see if they are equal
188 int pf_kdtree_equal(pf_kdtree_t * self, int key_a[], int key_b[])
189 {
190  (void)self;
191  // double a, b;
192 
193  if (key_a[0] != key_b[0]) {
194  return 0;
195  }
196  if (key_a[1] != key_b[1]) {
197  return 0;
198  }
199 
200  if (key_a[2] != key_b[2]) {
201  return 0;
202  }
203 
204  /* TODO: make this work (pivot selection needs fixing, too)
205  // Normalize angles
206  a = key_a[2] * self->size[2];
207  a = atan2(sin(a), cos(a)) / self->size[2];
208  b = key_b[2] * self->size[2];
209  b = atan2(sin(b), cos(b)) / self->size[2];
210 
211  if ((int) a != (int) b)
212  return 0;
213  */
214 
215  return 1;
216 }
217 
218 
220 // Insert a node into the tree
221 pf_kdtree_node_t * pf_kdtree_insert_node(
222  pf_kdtree_t * self, pf_kdtree_node_t * parent,
223  pf_kdtree_node_t * node, int key[], double value)
224 {
225  int i;
226  int64_t split, max_split;
227 
228  // If the node doesn't exist yet...
229  if (node == NULL) {
230  assert(self->node_count < self->node_max_count);
231  node = self->nodes + self->node_count++;
232  memset(node, 0, sizeof(pf_kdtree_node_t));
233 
234  node->leaf = 1;
235 
236  if (parent == NULL) {
237  node->depth = 0;
238  } else {
239  node->depth = parent->depth + 1;
240  }
241 
242  for (i = 0; i < 3; i++) {
243  node->key[i] = key[i];
244  }
245 
246  node->value = value;
247  self->leaf_count += 1;
248  } else if (node->leaf) { // If the node exists, and it is a leaf node...
249  // If the keys are equal, increment the value
250  if (pf_kdtree_equal(self, key, node->key)) {
251  node->value += value;
252  } else { // The keys are not equal, so split this node
253  // Find the dimension with the largest variance and do a mean
254  // split
255  max_split = 0;
256  node->pivot_dim = -1;
257  for (i = 0; i < 3; i++) {
258  split = llabs((int64_t)key[i] - node->key[i]);
259  if (split > max_split) {
260  max_split = split;
261  node->pivot_dim = i;
262  }
263  }
264  assert(node->pivot_dim >= 0);
265 
266  node->pivot_value =
267  ((double)key[node->pivot_dim] + node->key[node->pivot_dim]) / 2.0;
268 
269  if (key[node->pivot_dim] < node->pivot_value) {
270  node->children[0] = pf_kdtree_insert_node(self, node, NULL, key, value);
271  node->children[1] = pf_kdtree_insert_node(self, node, NULL, node->key, node->value);
272  } else {
273  node->children[0] = pf_kdtree_insert_node(self, node, NULL, node->key, node->value);
274  node->children[1] = pf_kdtree_insert_node(self, node, NULL, key, value);
275  }
276 
277  node->leaf = 0;
278  self->leaf_count -= 1;
279  }
280  } else { // If the node exists, and it has children...
281  assert(node->children[0] != NULL);
282  assert(node->children[1] != NULL);
283 
284  if (key[node->pivot_dim] < node->pivot_value) {
285  pf_kdtree_insert_node(self, node, node->children[0], key, value);
286  } else {
287  pf_kdtree_insert_node(self, node, node->children[1], key, value);
288  }
289  }
290 
291  return node;
292 }
293 
294 
296 // Recursive node search
297 pf_kdtree_node_t * pf_kdtree_find_node(pf_kdtree_t * self, pf_kdtree_node_t * node, int key[])
298 {
299  if (node->leaf) {
300  // printf("find : leaf %p %d %d %d\n", node, node->key[0], node->key[1], node->key[2]);
301 
302  // If the keys are the same...
303  if (pf_kdtree_equal(self, key, node->key)) {
304  return node;
305  } else {
306  return NULL;
307  }
308  } else {
309  // printf("find : brch %p %d %f\n", node, node->pivot_dim, node->pivot_value);
310 
311  assert(node->children[0] != NULL);
312  assert(node->children[1] != NULL);
313 
314  // If the keys are different...
315  if (key[node->pivot_dim] < node->pivot_value) {
316  return pf_kdtree_find_node(self, node->children[0], key);
317  } else {
318  return pf_kdtree_find_node(self, node->children[1], key);
319  }
320  }
321 
322  return NULL;
323 }
324 
325 
327 // Recursive node printing
328 /*
329 void pf_kdtree_print_node(pf_kdtree_t *self, pf_kdtree_node_t *node)
330 {
331  if (node->leaf)
332  {
333  printf("(%+02d %+02d %+02d)\n", node->key[0], node->key[1], node->key[2]);
334  printf("%*s", node->depth * 11, "");
335  }
336  else
337  {
338  printf("(%+02d %+02d %+02d) ", node->key[0], node->key[1], node->key[2]);
339  pf_kdtree_print_node(self, node->children[0]);
340  pf_kdtree_print_node(self, node->children[1]);
341  }
342  return;
343 }
344 */
345 
346 
348 // Cluster the leaves in the tree
349 void pf_kdtree_cluster(pf_kdtree_t * self)
350 {
351  int i;
352  int queue_count, cluster_count;
353  pf_kdtree_node_t ** queue, * node;
354 
355  queue_count = 0;
356  queue = calloc(self->node_count, sizeof(queue[0]));
357 
358  // Reset cluster labels
359  for (i = 0; i < self->node_count; i++) {
360  node = self->nodes + i;
361  if (node->leaf) {
362  node->cluster = -1;
363 
364  // TESTING; remove
365  assert(node == pf_kdtree_find_node(self, self->root, node->key));
366  }
367  }
368 
369  cluster_count = 0;
370 
371  // Do connected components for each node
372  for (i = self->node_count - 1; i >= 0; i--) {
373  node = self->nodes + i;
374 
375  // If this node has already been labelled, skip it
376  if (!node->leaf || node->cluster >= 0) {
377  continue;
378  }
379 
380  // Assign a label to this cluster
381  node->cluster = cluster_count++;
382 
383  // Iteratively label nodes in this cluster
384  assert(queue_count < self->node_count);
385  queue[queue_count++] = node;
386  while (queue_count > 0) {
387  node = queue[--queue_count];
388  pf_kdtree_cluster_node(self, node, queue, &queue_count);
389  }
390  }
391 
392  free(queue);
393 }
394 
395 
397 // Add neighboring nodes in this cluster to the queue
398 void pf_kdtree_cluster_node(
399  pf_kdtree_t * self, pf_kdtree_node_t * node,
400  pf_kdtree_node_t ** queue, int * queue_count)
401 {
402  int i;
403  int nkey[3];
404  pf_kdtree_node_t * nnode;
405 
406  for (i = 0; i < 3 * 3 * 3; i++) {
407  nkey[0] = node->key[0] + (i / 9) - 1;
408  nkey[1] = node->key[1] + ((i % 9) / 3) - 1;
409  nkey[2] = node->key[2] + ((i % 9) % 3) - 1;
410 
411  nnode = pf_kdtree_find_node(self, self->root, nkey);
412  if (nnode == NULL) {
413  continue;
414  }
415 
416  assert(nnode->leaf);
417 
418  // This node already has a label; skip it. The label should be
419  // consistent, however.
420  if (nnode->cluster >= 0) {
421  assert(nnode->cluster == node->cluster);
422  continue;
423  }
424 
425  // Label this node and add it to the work queue
426  nnode->cluster = node->cluster;
427  assert(*queue_count < self->node_count);
428  queue[(*queue_count)++] = nnode;
429  }
430 }
431 
432 
433 #ifdef INCLUDE_RTKGUI
434 
436 // Draw the tree
437 void pf_kdtree_draw(pf_kdtree_t * self, rtk_fig_t * fig)
438 {
439  if (self->root != NULL) {
440  pf_kdtree_draw_node(self, self->root, fig);
441  }
442 }
443 
444 
446 // Recursively draw nodes
447 void pf_kdtree_draw_node(pf_kdtree_t * self, pf_kdtree_node_t * node, rtk_fig_t * fig)
448 {
449  double ox, oy;
450  char text[64];
451 
452  if (node->leaf) {
453  ox = (node->key[0] + 0.5) * self->size[0];
454  oy = (node->key[1] + 0.5) * self->size[1];
455 
456  rtk_fig_rectangle(fig, ox, oy, 0.0, self->size[0], self->size[1], 0);
457 
458  // snprintf(text, sizeof(text), "%0.3f", node->value);
459  // rtk_fig_text(fig, ox, oy, 0.0, text);
460 
461  snprintf(text, sizeof(text), "%d", node->cluster);
462  rtk_fig_text(fig, ox, oy, 0.0, text);
463  } else {
464  assert(node->children[0] != NULL);
465  assert(node->children[1] != NULL);
466  pf_kdtree_draw_node(self, node->children[0], fig);
467  pf_kdtree_draw_node(self, node->children[1], fig);
468  }
469 }
470 
471 #endif