gmcl_laser.cpp
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  */
30 //
31 // Desc: AMCL laser routines
32 // Author: Andrew Howard
33 // Date: 6 Feb 2003
34 // CVS: $Id: amcl_laser.cc 7057 2008-10-02 00:44:06Z gbiggs $
35 //
37 #include "ros/ros.h"
38 #include <sys/types.h> // required by Darwin
39 #include <math.h>
40 #include <stdlib.h>
41 #include <assert.h>
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45 
47 
48 using namespace gmcl;
49 
51 // Default constructor
52 GMCLLaser::GMCLLaser(size_t max_beams, map_t* map) : GMCLSensor(),
53  max_samples(0), max_obs(0),
54  temp_obs(NULL)
55 {
56  this->time = 0.0;
57 
58  this->max_beams = max_beams;
59  this->map = map;
60 
61  return;
62 }
63 
65 {
66  if(temp_obs){
67  for(int k=0; k < max_samples; k++){
68  delete [] temp_obs[k];
69  }
70  delete []temp_obs;
71  }
72 }
73 
74 void
76  double z_short,
77  double z_max,
78  double z_rand,
79  double sigma_hit,
80  double lambda_short,
81  double chi_outlier)
82 {
84  this->z_hit = z_hit;
85  this->z_short = z_short;
86  this->z_max = z_max;
87  this->z_rand = z_rand;
88  this->sigma_hit = sigma_hit;
89  this->lambda_short = lambda_short;
90  this->chi_outlier = chi_outlier;
91 }
92 
93 void
95  double z_rand,
96  double sigma_hit,
97  double max_occ_dist)
98 {
100  this->z_hit = z_hit;
101  this->z_rand = z_rand;
102  this->sigma_hit = sigma_hit;
103 
104  map_update_cspace(this->map, max_occ_dist);
105 }
106 
107 void
109  double z_rand,
110  double sigma_hit,
111  double max_occ_dist,
112  bool do_beamskip,
113  double beam_skip_distance,
114  double beam_skip_threshold,
115  double beam_skip_error_threshold)
116 {
118  this->z_hit = z_hit;
119  this->z_rand = z_rand;
120  this->sigma_hit = sigma_hit;
121  this->do_beamskip = do_beamskip;
122  this->beam_skip_distance = beam_skip_distance;
123  this->beam_skip_threshold = beam_skip_threshold;
124  this->beam_skip_error_threshold = beam_skip_error_threshold;
125  map_update_cspace(this->map, max_occ_dist);
126 }
127 
128 
130 // Apply the laser sensor model
132 {
133  if (this->max_beams < 2)
134  return false;
135 
136  // Apply the laser sensor model
137  if(this->model_type == LASER_MODEL_BEAM)
139  else if(this->model_type == LASER_MODEL_LIKELIHOOD_FIELD)
143  else
145 
146  return true;
147 }
148 
149 
150 
151 
152 
154 {
155  GMCLLaser *self;
156  int i, j, step;
157  double z, pz;
158  double p;
159  double map_range;
160  double obs_range, obs_bearing;
161  double total_weight;
162 
163  self = (GMCLLaser*) data->sensor;
164 
165  pose = pf_vector_coord_add(self->laser_pose, pose);
166 
167  p = 1.0;
168 
169  step = (data->range_count - 1) / (self->max_beams - 1);
170  for (i = 0; i < data->range_count; i += step)
171  {
172  obs_range = data->ranges[i][0];
173  obs_bearing = data->ranges[i][1];
174 
175  // Compute the range according to the map
176  map_range = map_calc_range(self->map, pose.v[0], pose.v[1],
177  pose.v[2] + obs_bearing, self->range_max);
178  pz = 0.0;
179 
180  // Part 1: good, but noisy, hit
181  z = obs_range - map_range;
182  pz += self->z_hit * exp(-(z * z) / (2 * self->sigma_hit * self->sigma_hit));
183 
184  // Part 2: short reading from unexpected obstacle (e.g., a person)
185  if(z < 0)
186  pz += self->z_short * self->lambda_short * exp(-self->lambda_short*obs_range);
187 
188  // Part 3: Failure to detect obstacle, reported as max-range
189  if(obs_range == self->range_max)
190  pz += self->z_max * 1.0;
191 
192  // Part 4: Random measurements
193  if(obs_range < self->range_max)
194  pz += self->z_rand * 1.0/self->range_max;
195 
196  // TODO: outlier rejection for short readings
197 
198  assert(pz <= 1.0);
199  assert(pz >= 0.0);
200  // p *= pz;
201  // here we have an ad-hoc weighting scheme for combining beam probs
202  // works well, though...
203  p += pz*pz*pz;
204  }
205 
206  return p;
207 
208 }
210 // Determine the probability for the given pose
212 {
213  GMCLLaser *self;
214  int i, j, step;
215  double z, pz;
216  double p;
217  double map_range;
218  double obs_range, obs_bearing;
219  double total_weight;
220  pf_t *pf ;
221  pf_sample_t *sample, *aux_sample;
223  double group_weight;
224  self = (GMCLLaser*) data->sensor;
225 
226  pf = set->pf ;
227 
228 
229  int updated_count = set->updated_count;
230  int* updated_index = set->updated_index;
231 
232  double range_max = self->range_max;
233  int max_beams = self->max_beams;
234  int range_count = data->range_count;
235  if(updated_count > 0)
236  {// Compute the sample weights
237  for (j = 0; j < updated_count; j++)
238  {
239  sample = set->samples + updated_index[j];
240  pose = sample->pose;
241 
242  // Take account of the laser pose relative to the robot
243  pose = pf_vector_coord_add(self->laser_pose, pose);
244 
245  p = 1.0;
246 
247  step = (data->range_count - 1) / (self->max_beams - 1);
248  for (i = 0; i < data->range_count; i += step)
249  {
250  obs_range = data->ranges[i][0];
251  obs_bearing = data->ranges[i][1];
252 
253  // Compute the range according to the map
254  map_range = map_calc_range(self->map, pose.v[0], pose.v[1],
255  pose.v[2] + obs_bearing, self->range_max);
256  pz = 0.0;
257 
258  // Part 1: good, but noisy, hit
259  z = obs_range - map_range;
260  pz += self->z_hit * exp(-(z * z) / (2 * self->sigma_hit * self->sigma_hit));
261 
262  // Part 2: short reading from unexpected obstacle (e.g., a person)
263  if(z < 0)
264  pz += self->z_short * self->lambda_short * exp(-self->lambda_short*obs_range);
265 
266  // Part 3: Failure to detect obstacle, reported as max-range
267  if(obs_range == self->range_max)
268  pz += self->z_max * 1.0;
269 
270  // Part 4: Random measurements
271  if(obs_range < self->range_max)
272  pz += self->z_rand * 1.0/self->range_max;
273 
274  // TODO: outlier rejection for short readings
275 
276  assert(pz <= 1.0);
277  assert(pz >= 0.0);
278  // p *= pz;
279  // here we have an ad-hoc weighting scheme for combining beam probs
280  // works well, though...
281  p += pz*pz*pz;
282  }
283  sample->weight *= p;
284 
285  }
286  printf("Num of crossovered samples: %9.6d\n", updated_count);
287  }
288  else
289  if(pf->model.use_optimal_filter)
290  // Compute the sample weights
291  for (j = 0; j < set->sample_count; j++)
292  { group_weight = 0.0 ;
293  sample = set->samples + j;
294  for ( int loop=0 ; loop < pf->N_aux_particles ; loop++)
295  {
296  aux_sample = set->aux_samples + (j*pf->N_aux_particles+loop) ;
297  pose = aux_sample->pose;
298 
299  // Take account of the laser pose relative to the robot
300  pose = pf_vector_coord_add(self->laser_pose, pose);
301 
302  p = 1.0;
303 
304  step = (data->range_count - 1) / (self->max_beams - 1);
305  for (i = 0; i < data->range_count; i += step)
306  {
307  obs_range = data->ranges[i][0];
308  obs_bearing = data->ranges[i][1];
309 
310  // Compute the range according to the map
311  map_range = map_calc_range(self->map, pose.v[0], pose.v[1],
312  pose.v[2] + obs_bearing, self->range_max);
313  pz = 0.0;
314 
315  // Part 1: good, but noisy, hit
316  z = obs_range - map_range;
317  pz += self->z_hit * exp(-(z * z) / (2 * self->sigma_hit * self->sigma_hit));
318 
319  // Part 2: short reading from unexpected obstacle (e.g., a person)
320  if(z < 0)
321  pz += self->z_short * self->lambda_short * exp(-self->lambda_short*obs_range);
322 
323  // Part 3: Failure to detect obstacle, reported as max-range
324  if(obs_range == self->range_max)
325  pz += self->z_max * 1.0;
326 
327  // Part 4: Random measurements
328  if(obs_range < self->range_max)
329  pz += self->z_rand * 1.0/self->range_max;
330 
331  // TODO: outlier rejection for short readings
332 
333  assert(pz <= 1.0);
334  assert(pz >= 0.0);
335  // p *= pz;
336  // here we have an ad-hoc weighting scheme for combining beam probs
337  // works well, though...
338  p += pz*pz*pz;
339  }
340  aux_sample->weight = p ;
341  group_weight += aux_sample->weight ;
342  }
343  sample->weight *= group_weight/pf->N_aux_particles;
344  sample->last_obs = group_weight/pf->N_aux_particles;
345  //printf(" group weight %f ", group_weight );
346  }
347  else if(pf->model.use_crossover_mutation)
348  // Compute the sample weights
349  for (j = 0; j < set->sample_count; j++)
350  {
351  sample = set->samples + j;
352  pose = sample->pose;
353 
354  // Take account of the laser pose relative to the robot
355  pose = pf_vector_coord_add(self->laser_pose, pose);
356 
357  p = 1.0;
358 
359  step = (data->range_count - 1) / (self->max_beams - 1);
360  for (i = 0; i < data->range_count; i += step)
361  {
362  obs_range = data->ranges[i][0];
363  obs_bearing = data->ranges[i][1];
364 
365  // Compute the range according to the map
366  map_range = map_calc_range(self->map, pose.v[0], pose.v[1],
367  pose.v[2] + obs_bearing, self->range_max);
368  pz = 0.0;
369 
370  // Part 1: good, but noisy, hit
371  z = obs_range - map_range;
372  pz += self->z_hit * exp(-(z * z) / (2 * self->sigma_hit * self->sigma_hit));
373 
374  // Part 2: short reading from unexpected obstacle (e.g., a person)
375  if(z < 0)
376  pz += self->z_short * self->lambda_short * exp(-self->lambda_short*obs_range);
377 
378  // Part 3: Failure to detect obstacle, reported as max-range
379  if(obs_range == self->range_max)
380  pz += self->z_max * 1.0;
381 
382  // Part 4: Random measurements
383  if(obs_range < self->range_max)
384  pz += self->z_rand * 1.0/self->range_max;
385 
386  // TODO: outlier rejection for short readings
387 
388  assert(pz <= 1.0);
389  assert(pz >= 0.0);
390  // p *= pz;
391  // here we have an ad-hoc weighting scheme for combining beam probs
392  // works well, though...
393  p += pz*pz*pz;
394  }
395 
396  sample->weight *= p;
397 
398  sample->last_obs = p;
399  }
400  else
401  for (j = 0; j < set->sample_count; j++)
402  {
403  sample = set->samples + j;
404  pose = sample->pose;
405 
406  // Take account of the laser pose relative to the robot
407  pose = pf_vector_coord_add(self->laser_pose, pose);
408 
409  p = 1.0;
410 
411  step = (range_count - 1) / (max_beams - 1);
412  for (i = 0; i < data->range_count; i += step)
413  {
414  obs_range = data->ranges[i][0];
415  obs_bearing = data->ranges[i][1];
416 
417  // Compute the range according to the map
418  map_range = map_calc_range(self->map, pose.v[0], pose.v[1],
419  pose.v[2] + obs_bearing, range_max);
420  pz = 0.0;
421 // printf("obs_range: %9.6f\n", obs_range);
422  // printf("range_max: %9.6f\n", range_max);
423  // printf("max_beams: %9.6d\n", max_beams );
424  // printf("range_count: %9.6d\n", range_count );
425  // Part 1: good, but noisy, hit
426  z = obs_range - map_range;
427  pz += self->z_hit * exp(-(z * z) / (2 * self->sigma_hit * self->sigma_hit));
428 
429  // Part 2: short reading from unexpected obstacle (e.g., a person)
430  if(z < 0)
431  pz += self->z_short * self->lambda_short * exp(-self->lambda_short*obs_range);
432 
433  // Part 3: Failure to detect obstacle, reported as max-range
434  if(obs_range == range_max)
435  pz += self->z_max * 1.0;
436 
437  // Part 4: Random measurements
438  if(obs_range < range_max)
439  pz += self->z_rand * 1.0/range_max;
440 
441  // TODO: outlier rejection for short readings
442 
443  assert(pz <= 1.0);
444  assert(pz >= 0.0);
445  // p *= pz;
446  // here we have an ad-hoc weighting scheme for combining beam probs
447  // works well, though...
448  p += pz*pz*pz;
449 
450  }
451 
452  sample->weight *= p;
453  }
454 
455 
456 }
457 
459 {
460 
461  GMCLLaser *self;
462  int i, j, step;
463  double z, pz;
464  double p;
465  double obs_range, obs_bearing;
466  double total_weight;
467  pf_t *pf;
468  pf_sample_t *sample, *aux_sample;
470  pf_vector_t hit;
471  double group_weight;
472 
473  pf = set->pf ;
474 
475  self = (GMCLLaser*) data->sensor;
476 
477  int updated_count = set->updated_count;
478  int* updated_index = set->updated_index;
479 
480  double range_max = self->range_max;
481  int max_beams = self->max_beams;
482  int range_count = data->range_count;
483  // Pre-compute a couple of things
484  double z_hit_denom = 2 * self->sigma_hit * self->sigma_hit;
485  double z_rand_mult = 1.0/range_max;
486 
487 
488 if(updated_count > 0)
489  {// Compute the sample weights
490  for (j = 0; j < updated_count; j++)
491  {
492  sample = set->samples + updated_index[j];
493  pose = sample->pose;
494 
495  // Take account of the laser pose relative to the robot
496  pose = pf_vector_coord_add(self->laser_pose, pose);
497 
498  p = 1.0;
499 
500  step = (data->range_count - 1) / (self->max_beams - 1);
501  for (i = 0; i < data->range_count; i += step)
502  {
503  obs_range = data->ranges[i][0];
504  obs_bearing = data->ranges[i][1];
505 
506  if(obs_range >= range_max)
507  continue;
508 
509  // Check for NaN
510  if(obs_range != obs_range)
511  continue;
512 
513  pz = 0.0;
514 
515  // Compute the endpoint of the beam
516  hit.v[0] = pose.v[0] + obs_range * cos(pose.v[2] + obs_bearing);
517  hit.v[1] = pose.v[1] + obs_range * sin(pose.v[2] + obs_bearing);
518 
519  // Convert to map grid coords.
520  int mi, mj;
521  mi = MAP_GXWX(self->map, hit.v[0]);
522  mj = MAP_GYWY(self->map, hit.v[1]);
523 
524  // Part 1: Get distance from the hit to closest obstacle.
525  // Off-map penalized as max distance
526  if(!MAP_VALID(self->map, mi, mj))
527  z = self->map->max_occ_dist;
528  else
529  z = self->map->cells[MAP_INDEX(self->map,mi,mj)].occ_dist;
530  // Gaussian model
531  // NOTE: this should have a normalization of 1/(sqrt(2pi)*sigma)
532  pz += self->z_hit * exp(-(z * z) / z_hit_denom);
533  // Part 2: random measurements
534  pz += self->z_rand * z_rand_mult;
535  // TODO: outlier rejection for short readings
536 
537  assert(pz <= 1.0);
538  assert(pz >= 0.0);
539  // p *= pz;
540  // here we have an ad-hoc weighting scheme for combining beam probs
541  // works well, though...
542  p += pz*pz*pz;
543  }
544  sample->weight *= p;
545 
546  }
547  printf("Num of crossovered samples: %9.6d\n", updated_count);
548  }
549  else
550  if(pf->model.use_optimal_filter)
551  // Compute the sample weights
552  for (j = 0; j < set->sample_count; j++)
553  { group_weight = 0.0 ;
554  sample = set->samples + j;
555  for ( int loop=0 ; loop < pf->N_aux_particles ; loop++)
556  {
557  aux_sample = set->aux_samples + (j*pf->N_aux_particles+loop) ;
558  pose = aux_sample->pose;
559 
560  // Take account of the laser pose relative to the robot
561  pose = pf_vector_coord_add(self->laser_pose, pose);
562 
563  p = 1.0;
564 
565  step = (data->range_count - 1) / (self->max_beams - 1);
566  for (i = 0; i < data->range_count; i += step)
567  {
568  obs_range = data->ranges[i][0];
569  obs_bearing = data->ranges[i][1];
570 
571  if(obs_range >= range_max)
572  continue;
573 
574  // Check for NaN
575  if(obs_range != obs_range)
576  continue;
577 
578  pz = 0.0;
579 
580  // Compute the endpoint of the beam
581  hit.v[0] = pose.v[0] + obs_range * cos(pose.v[2] + obs_bearing);
582  hit.v[1] = pose.v[1] + obs_range * sin(pose.v[2] + obs_bearing);
583 
584  // Convert to map grid coords.
585  int mi, mj;
586  mi = MAP_GXWX(self->map, hit.v[0]);
587  mj = MAP_GYWY(self->map, hit.v[1]);
588 
589  // Part 1: Get distance from the hit to closest obstacle.
590  // Off-map penalized as max distance
591  if(!MAP_VALID(self->map, mi, mj))
592  z = self->map->max_occ_dist;
593  else
594  z = self->map->cells[MAP_INDEX(self->map,mi,mj)].occ_dist;
595  // Gaussian model
596  // NOTE: this should have a normalization of 1/(sqrt(2pi)*sigma)
597  pz += self->z_hit * exp(-(z * z) / z_hit_denom);
598  // Part 2: random measurements
599  pz += self->z_rand * z_rand_mult;
600 
601 
602  // TODO: outlier rejection for short readings
603 
604  assert(pz <= 1.0);
605  assert(pz >= 0.0);
606  // p *= pz;
607  // here we have an ad-hoc weighting scheme for combining beam probs
608  // works well, though...
609  p += pz*pz*pz;
610  }
611  aux_sample->weight = p ;
612  group_weight += aux_sample->weight ;
613  }
614  sample->weight *= group_weight/pf->N_aux_particles;
615  sample->last_obs = group_weight/pf->N_aux_particles;
616  //printf(" group weight %f ", group_weight );
617  }
618  else if(pf->model.use_crossover_mutation)
619  // Compute the sample weights
620  for (j = 0; j < set->sample_count; j++)
621  {
622  sample = set->samples + j;
623  pose = sample->pose;
624 
625  // Take account of the laser pose relative to the robot
626  pose = pf_vector_coord_add(self->laser_pose, pose);
627 
628  p = 1.0;
629 
630  step = (data->range_count - 1) / (self->max_beams - 1);
631  for (i = 0; i < data->range_count; i += step)
632  {
633  obs_range = data->ranges[i][0];
634  obs_bearing = data->ranges[i][1];
635 
636  // This model ignores max range readings
637  if(obs_range >= range_max)
638  continue;
639 
640  // Check for NaN
641  if(obs_range != obs_range)
642  continue;
643 
644  pz = 0.0;
645 
646  // Part 1: good, but noisy, hit
647  // Compute the endpoint of the beam
648  hit.v[0] = pose.v[0] + obs_range * cos(pose.v[2] + obs_bearing);
649  hit.v[1] = pose.v[1] + obs_range * sin(pose.v[2] + obs_bearing);
650 
651  // Convert to map grid coords.
652  int mi, mj;
653  mi = MAP_GXWX(self->map, hit.v[0]);
654  mj = MAP_GYWY(self->map, hit.v[1]);
655 
656  // Part 1: Get distance from the hit to closest obstacle.
657  // Off-map penalized as max distance
658  if(!MAP_VALID(self->map, mi, mj))
659  z = self->map->max_occ_dist;
660  else
661  z = self->map->cells[MAP_INDEX(self->map,mi,mj)].occ_dist;
662  // Gaussian model
663  // NOTE: this should have a normalization of 1/(sqrt(2pi)*sigma)
664  pz += self->z_hit * exp(-(z * z) / z_hit_denom);
665  // Part 2: random measurements
666  pz += self->z_rand * z_rand_mult;
667 
668  // TODO: outlier rejection for short readings
669 
670  assert(pz <= 1.0);
671  assert(pz >= 0.0);
672  // p *= pz;
673  // here we have an ad-hoc weighting scheme for combining beam probs
674  // works well, though...
675  p += pz*pz*pz;
676  }
677 
678  sample->weight *= p;
679 
680  sample->last_obs = p;
681  }
682  else
683  for (j = 0; j < set->sample_count; j++)
684  {
685  sample = set->samples + j;
686  pose = sample->pose;
687 
688  // Take account of the laser pose relative to the robot
689  pose = pf_vector_coord_add(self->laser_pose, pose);
690 
691  p = 1.0;
692 
693  step = (range_count - 1) / (max_beams - 1);
694  for (i = 0; i < data->range_count; i += step)
695  {
696  obs_range = data->ranges[i][0];
697  obs_bearing = data->ranges[i][1];
698 
699  if(obs_range >= range_max)
700  continue;
701 
702  // Check for NaN
703  if(obs_range != obs_range)
704  continue;
705 
706  pz = 0.0;
707 
708  // Compute the endpoint of the beam
709  hit.v[0] = pose.v[0] + obs_range * cos(pose.v[2] + obs_bearing);
710  hit.v[1] = pose.v[1] + obs_range * sin(pose.v[2] + obs_bearing);
711 
712  // Convert to map grid coords.
713  int mi, mj;
714  mi = MAP_GXWX(self->map, hit.v[0]);
715  mj = MAP_GYWY(self->map, hit.v[1]);
716 
717  // Part 1: Get distance from the hit to closest obstacle.
718  // Off-map penalized as max distance
719  if(!MAP_VALID(self->map, mi, mj))
720  z = self->map->max_occ_dist;
721  else
722  z = self->map->cells[MAP_INDEX(self->map,mi,mj)].occ_dist;
723  // Gaussian model
724  // NOTE: this should have a normalization of 1/(sqrt(2pi)*sigma)
725  pz += self->z_hit * exp(-(z * z) / z_hit_denom);
726  // Part 2: random measurements
727  pz += self->z_rand * z_rand_mult;
728 
729  // TODO: outlier rejection for short readings
730 
731  assert(pz <= 1.0);
732  assert(pz >= 0.0);
733  // p *= pz;
734  // here we have an ad-hoc weighting scheme for combining beam probs
735  // works well, though...
736  p += pz*pz*pz;
737 
738  }
739 
740  sample->weight *= p;
741  }
742 
743 
744 }
746 {
747  GMCLLaser *self;
748  int i, j, step;
749  double z, pz;
750  double log_p;
751  double obs_range, obs_bearing;
752  double group_weight;
753 
754  pf_sample_t *sample, *aux_sample;;
756  pf_vector_t hit;
757 
758  self = (GMCLLaser*) data->sensor;
759 
760  pf_t *pf;
761 
762  pf = set->pf ;
763 
764  int updated_count = set->updated_count;
765  int* updated_index = set->updated_index;
766 
767  double range_max = self->range_max;
768  int max_beams = self->max_beams;
769  int range_count = data->range_count;
770 
771  step = ceil((data->range_count) / static_cast<double>(self->max_beams));
772 
773  // Step size must be at least 1
774  if(step < 1)
775  step = 1;
776 
777  // Pre-compute a couple of things
778  double z_hit_denom = 2 * self->sigma_hit * self->sigma_hit;
779  double z_rand_mult = 1.0/self->range_max;
780 
781  double max_dist_prob = exp(-(self->map->max_occ_dist * self->map->max_occ_dist) / z_hit_denom);
782 
783  //Beam skipping - ignores beams for which a majoirty of particles do not agree with the map
784  //prevents correct particles from getting down weighted because of unexpected obstacles
785  //such as humans
786 
787  bool do_beamskip = self->do_beamskip;
788  double beam_skip_distance = self->beam_skip_distance;
789  double beam_skip_threshold = self->beam_skip_threshold;
790 
791  //we only do beam skipping if the filter has converged
792  if(do_beamskip && !set->converged){
793  do_beamskip = false;
794  }
795 
796  //we need a count the no of particles for which the beam agreed with the map
797  int *obs_count = new int[self->max_beams]();
798 
799  //we also need a mask of which observations to integrate (to decide which beams to integrate to all particles)
800  bool *obs_mask = new bool[self->max_beams]();
801 
802  int beam_ind = 0;
803 
804  //realloc indicates if we need to reallocate the temp data structure needed to do beamskipping
805  bool realloc = false;
806 
807  if(do_beamskip && updated_count == 0){
808  if(self->max_obs < self->max_beams){
809  realloc = true;
810  }
811 
812  if(self->max_samples < set->sample_count){
813  realloc = true;
814  }
815 
816  if(realloc){
817  self->reallocTempData(set->sample_count, self->max_beams);
818  fprintf(stderr, "Reallocing temp weights %d - %d\n", self->max_samples, self->max_obs);
819  }
820  }
821 
822 if(updated_count > 0)
823  {// Compute the sample weights
824  for (j = 0; j < updated_count; j++)
825  {
826  sample = set->samples + updated_index[j];
827  pose = sample->pose;
828 
829  // Take account of the laser pose relative to the robot
830  pose = pf_vector_coord_add(self->laser_pose, pose);
831 
832  log_p = 0;
833  beam_ind = 0;
834 
835  for (i = 0; i < data->range_count; i += step, beam_ind++)
836  {
837  obs_range = data->ranges[i][0];
838  obs_bearing = data->ranges[i][1];
839 
840  if(obs_range >= range_max)
841  continue;
842 
843  // Check for NaN
844  if(obs_range != obs_range)
845  continue;
846 
847  pz = 0.0;
848 
849  // Compute the endpoint of the beam
850  hit.v[0] = pose.v[0] + obs_range * cos(pose.v[2] + obs_bearing);
851  hit.v[1] = pose.v[1] + obs_range * sin(pose.v[2] + obs_bearing);
852 
853  // Convert to map grid coords.
854  int mi, mj;
855  mi = MAP_GXWX(self->map, hit.v[0]);
856  mj = MAP_GYWY(self->map, hit.v[1]);
857 
858  // Part 1: Get distance from the hit to closest obstacle.
859  // Off-map penalized as max distance
860  if(!MAP_VALID(self->map, mi, mj)){
861  pz += self->z_hit * max_dist_prob;
862  }
863  else{
864  z = self->map->cells[MAP_INDEX(self->map,mi,mj)].occ_dist;
865  if(z < beam_skip_distance){
866  obs_count[beam_ind] += 1;
867  }
868  pz += self->z_hit * exp(-(z * z) / z_hit_denom);
869  }
870  // Gaussian model
871  // NOTE: this should have a normalization of 1/(sqrt(2pi)*sigma)
872 
873  // Part 2: random measurements
874  pz += self->z_rand * z_rand_mult;
875  // TODO: outlier rejection for short readings
876 
877  assert(pz <= 1.0);
878  assert(pz >= 0.0);
879 
880  if(!do_beamskip){
881  log_p += log(pz);
882  }
883  else{
884  self->temp_obs[j][beam_ind] = pz;
885  }
886  }
887  if(!do_beamskip){
888  sample->weight *= exp(log_p);
889  }
890  }
891 
892  if(do_beamskip){
893  int skipped_beam_count = 0;
894  for (beam_ind = 0; beam_ind < self->max_beams; beam_ind++){
895  if((obs_count[beam_ind] / static_cast<double>(updated_count)) > beam_skip_threshold){
896  obs_mask[beam_ind] = true;
897  }
898  else{
899  obs_mask[beam_ind] = false;
900  skipped_beam_count++;
901  }
902  }
903 
904  //we check if there is at least a critical number of beams that agreed with the map
905  //otherwise it probably indicates that the filter converged to a wrong solution
906  //if that's the case we integrate all the beams and hope the filter might converge to
907  //the right solution
908  bool error = false;
909 
910  if(skipped_beam_count >= (beam_ind * self->beam_skip_error_threshold)){
911  fprintf(stderr, "Over %f%% of the observations were not in the map - pf may have converged to wrong pose - integrating all observations\n", (100 * self->beam_skip_error_threshold));
912  error = true;
913  }
914 
915  for (j = 0; j < updated_count; j++)
916  {
917  sample = set->samples + updated_index[j];
918  pose = sample->pose;
919 
920  log_p = 0;
921 
922  for (beam_ind = 0; beam_ind < self->max_beams; beam_ind++){
923  if(error || obs_mask[beam_ind]){
924  log_p += log(self->temp_obs[j][beam_ind]);
925  }
926  }
927 
928  sample->weight *= exp(log_p);
929 
930  }
931  }
932 
933  printf("Num of crossovered samples: %9.6d\n", updated_count);
934  }
935 
936  else
937  if(pf->model.use_optimal_filter)
938  { // Compute the sample weights
939  for (j = 0; j < set->sample_count; j++)
940  { group_weight = 0.0 ;
941  sample = set->samples + j;
942  for ( int loop=0 ; loop < pf->N_aux_particles ; loop++)
943  {
944  aux_sample = set->aux_samples + (j*pf->N_aux_particles+loop) ;
945  pose = aux_sample->pose;
946 
947  // Take account of the laser pose relative to the robot
948  pose = pf_vector_coord_add(self->laser_pose, pose);
949 
950  log_p = 0;
951 
952  beam_ind = 0;
953 
954  for (i = 0; i < data->range_count; i += step, beam_ind++)
955  {
956  obs_range = data->ranges[i][0];
957  obs_bearing = data->ranges[i][1];
958 
959  // This model ignores max range readings
960  if(obs_range >= range_max){
961  continue;
962  }
963 
964  // Check for NaN
965  if(obs_range != obs_range){
966  continue;
967  }
968 
969  pz = 0.0;
970 
971  // Compute the endpoint of the beam
972  hit.v[0] = pose.v[0] + obs_range * cos(pose.v[2] + obs_bearing);
973  hit.v[1] = pose.v[1] + obs_range * sin(pose.v[2] + obs_bearing);
974 
975  // Convert to map grid coords.
976  int mi, mj;
977  mi = MAP_GXWX(self->map, hit.v[0]);
978  mj = MAP_GYWY(self->map, hit.v[1]);
979 
980  // Part 1: Get distance from the hit to closest obstacle.
981  // Off-map penalized as max distance
982 
983  if(!MAP_VALID(self->map, mi, mj)){
984  pz += self->z_hit * max_dist_prob;
985  }
986  else{
987  z = self->map->cells[MAP_INDEX(self->map,mi,mj)].occ_dist;
988  if(z < beam_skip_distance){
989  obs_count[beam_ind] += 1;
990  }
991  pz += self->z_hit * exp(-(z * z) / z_hit_denom);
992  }
993 
994  // Gaussian model
995  // NOTE: this should have a normalization of 1/(sqrt(2pi)*sigma)
996 
997  // Part 2: random measurements
998  pz += self->z_rand * z_rand_mult;
999 
1000  assert(pz <= 1.0);
1001  assert(pz >= 0.0);
1002 
1003  // TODO: outlier rejection for short readings
1004 
1005  if(!do_beamskip){
1006  log_p += log(pz);
1007  }
1008  else{
1009  self->temp_obs[j][beam_ind] = pz;
1010  }
1011  }
1012  if(!do_beamskip){
1013  aux_sample->weight = exp(log_p);
1014  group_weight += aux_sample->weight ;
1015  }
1016  }
1017  if(!do_beamskip){
1018  sample->weight *= group_weight/pf->N_aux_particles;
1019  sample->last_obs = group_weight/pf->N_aux_particles;
1020  }
1021  }
1022 
1023  if(do_beamskip){
1024  int skipped_beam_count = 0;
1025  for (beam_ind = 0; beam_ind < self->max_beams; beam_ind++){
1026  if((obs_count[beam_ind] / static_cast<double>(set->sample_count)) > beam_skip_threshold){
1027  obs_mask[beam_ind] = true;
1028  }
1029  else{
1030  obs_mask[beam_ind] = false;
1031  skipped_beam_count++;
1032  }
1033  }
1034 
1035  //we check if there is at least a critical number of beams that agreed with the map
1036  //otherwise it probably indicates that the filter converged to a wrong solution
1037  //if that's the case we integrate all the beams and hope the filter might converge to
1038  //the right solution
1039  bool error = false;
1040 
1041  if(skipped_beam_count >= (beam_ind * self->beam_skip_error_threshold)){
1042  fprintf(stderr, "Over %f%% of the observations were not in the map - pf may have converged to wrong pose - integrating all observations\n", (100 * self->beam_skip_error_threshold));
1043  error = true;
1044  }
1045 
1046  for (j = 0; j < set->sample_count; j++)
1047  { group_weight = 0.0 ;
1048  sample = set->samples + j;
1049  for ( int loop=0 ; loop < pf->N_aux_particles ; loop++)
1050  {
1051  aux_sample = set->aux_samples + (j*pf->N_aux_particles+loop) ;
1052  pose = aux_sample->pose;
1053 
1054  sample = set->samples + j;
1055  pose = sample->pose;
1056 
1057  log_p = 0;
1058 
1059  for (beam_ind = 0; beam_ind < self->max_beams; beam_ind++){
1060  if(error || obs_mask[beam_ind]){
1061  log_p += log(self->temp_obs[j][beam_ind]);
1062  }
1063  }
1064 
1065  aux_sample->weight = exp(log_p);
1066  group_weight += aux_sample->weight ;
1067 
1068  }
1069  sample->weight *= group_weight/pf->N_aux_particles;
1070  sample->last_obs = group_weight/pf->N_aux_particles;
1071  }
1072 
1073  }
1074  }
1075 
1076  else if(pf->model.use_crossover_mutation)
1077  { // Compute the sample weights
1078  for (j = 0; j < set->sample_count; j++)
1079  {
1080  sample = set->samples + j;
1081  pose = sample->pose;
1082 
1083  // Take account of the laser pose relative to the robot
1084  pose = pf_vector_coord_add(self->laser_pose, pose);
1085 
1086  log_p = 0;
1087 
1088  beam_ind = 0;
1089 
1090  for (i = 0; i < data->range_count; i += step, beam_ind++)
1091  {
1092  obs_range = data->ranges[i][0];
1093  obs_bearing = data->ranges[i][1];
1094 
1095  // This model ignores max range readings
1096  if(obs_range >= range_max){
1097  continue;
1098  }
1099 
1100  // Check for NaN
1101  if(obs_range != obs_range){
1102  continue;
1103  }
1104 
1105  pz = 0.0;
1106 
1107  // Compute the endpoint of the beam
1108  hit.v[0] = pose.v[0] + obs_range * cos(pose.v[2] + obs_bearing);
1109  hit.v[1] = pose.v[1] + obs_range * sin(pose.v[2] + obs_bearing);
1110 
1111  // Convert to map grid coords.
1112  int mi, mj;
1113  mi = MAP_GXWX(self->map, hit.v[0]);
1114  mj = MAP_GYWY(self->map, hit.v[1]);
1115 
1116  // Part 1: Get distance from the hit to closest obstacle.
1117  // Off-map penalized as max distance
1118 
1119  if(!MAP_VALID(self->map, mi, mj)){
1120  pz += self->z_hit * max_dist_prob;
1121  }
1122  else{
1123  z = self->map->cells[MAP_INDEX(self->map,mi,mj)].occ_dist;
1124  if(z < beam_skip_distance){
1125  obs_count[beam_ind] += 1;
1126  }
1127  pz += self->z_hit * exp(-(z * z) / z_hit_denom);
1128  }
1129 
1130  // Gaussian model
1131  // NOTE: this should have a normalization of 1/(sqrt(2pi)*sigma)
1132 
1133  // Part 2: random measurements
1134  pz += self->z_rand * z_rand_mult;
1135 
1136  assert(pz <= 1.0);
1137  assert(pz >= 0.0);
1138 
1139  // TODO: outlier rejection for short readings
1140 
1141  if(!do_beamskip){
1142  log_p += log(pz);
1143  }
1144  else{
1145  self->temp_obs[j][beam_ind] = pz;
1146  }
1147  }
1148  if(!do_beamskip){
1149  sample->weight *= exp(log_p);
1150  sample->last_obs = exp(log_p);
1151  }
1152  }
1153 
1154  if(do_beamskip){
1155  int skipped_beam_count = 0;
1156  for (beam_ind = 0; beam_ind < self->max_beams; beam_ind++){
1157  if((obs_count[beam_ind] / static_cast<double>(set->sample_count)) > beam_skip_threshold){
1158  obs_mask[beam_ind] = true;
1159  }
1160  else{
1161  obs_mask[beam_ind] = false;
1162  skipped_beam_count++;
1163  }
1164  }
1165 
1166  //we check if there is at least a critical number of beams that agreed with the map
1167  //otherwise it probably indicates that the filter converged to a wrong solution
1168  //if that's the case we integrate all the beams and hope the filter might converge to
1169  //the right solution
1170  bool error = false;
1171 
1172  if(skipped_beam_count >= (beam_ind * self->beam_skip_error_threshold)){
1173  fprintf(stderr, "Over %f%% of the observations were not in the map - pf may have converged to wrong pose - integrating all observations\n", (100 * self->beam_skip_error_threshold));
1174  error = true;
1175  }
1176 
1177  for (j = 0; j < set->sample_count; j++)
1178  {
1179  sample = set->samples + j;
1180  pose = sample->pose;
1181 
1182  log_p = 0;
1183 
1184  for (beam_ind = 0; beam_ind < self->max_beams; beam_ind++){
1185  if(error || obs_mask[beam_ind]){
1186  log_p += log(self->temp_obs[j][beam_ind]);
1187  }
1188  }
1189 
1190  sample->weight *= exp(log_p);
1191  sample->last_obs = exp(log_p);
1192 
1193  }
1194  }
1195 
1196 }
1197  else
1198  { for (j = 0; j < set->sample_count; j++)
1199  {
1200  sample = set->samples + j;
1201  pose = sample->pose;
1202 
1203  // Take account of the laser pose relative to the robot
1204  pose = pf_vector_coord_add(self->laser_pose, pose);
1205 
1206  log_p = 0;
1207 
1208  beam_ind = 0;
1209 
1210  for (i = 0; i < data->range_count; i += step, beam_ind++)
1211  {
1212  obs_range = data->ranges[i][0];
1213  obs_bearing = data->ranges[i][1];
1214 
1215  // This model ignores max range readings
1216  if(obs_range >= range_max){
1217  continue;
1218  }
1219 
1220  // Check for NaN
1221  if(obs_range != obs_range){
1222  continue;
1223  }
1224 
1225  pz = 0.0;
1226 
1227  // Compute the endpoint of the beam
1228  hit.v[0] = pose.v[0] + obs_range * cos(pose.v[2] + obs_bearing);
1229  hit.v[1] = pose.v[1] + obs_range * sin(pose.v[2] + obs_bearing);
1230 
1231  // Convert to map grid coords.
1232  int mi, mj;
1233  mi = MAP_GXWX(self->map, hit.v[0]);
1234  mj = MAP_GYWY(self->map, hit.v[1]);
1235 
1236  // Part 1: Get distance from the hit to closest obstacle.
1237  // Off-map penalized as max distance
1238 
1239  if(!MAP_VALID(self->map, mi, mj)){
1240  pz += self->z_hit * max_dist_prob;
1241  }
1242  else{
1243  z = self->map->cells[MAP_INDEX(self->map,mi,mj)].occ_dist;
1244  if(z < beam_skip_distance){
1245  obs_count[beam_ind] += 1;
1246  }
1247  pz += self->z_hit * exp(-(z * z) / z_hit_denom);
1248  }
1249 
1250  // Gaussian model
1251  // NOTE: this should have a normalization of 1/(sqrt(2pi)*sigma)
1252 
1253  // Part 2: random measurements
1254  pz += self->z_rand * z_rand_mult;
1255 
1256  assert(pz <= 1.0);
1257  assert(pz >= 0.0);
1258 
1259  // TODO: outlier rejection for short readings
1260 
1261  if(!do_beamskip){
1262  log_p += log(pz);
1263  }
1264  else{
1265  self->temp_obs[j][beam_ind] = pz;
1266  }
1267  }
1268  if(!do_beamskip){
1269  sample->weight *= exp(log_p);
1270  }
1271  }
1272 
1273  if(do_beamskip){
1274  int skipped_beam_count = 0;
1275  for (beam_ind = 0; beam_ind < self->max_beams; beam_ind++){
1276  if((obs_count[beam_ind] / static_cast<double>(set->sample_count)) > beam_skip_threshold){
1277  obs_mask[beam_ind] = true;
1278  }
1279  else{
1280  obs_mask[beam_ind] = false;
1281  skipped_beam_count++;
1282  }
1283  }
1284 
1285  //we check if there is at least a critical number of beams that agreed with the map
1286  //otherwise it probably indicates that the filter converged to a wrong solution
1287  //if that's the case we integrate all the beams and hope the filter might converge to
1288  //the right solution
1289  bool error = false;
1290 
1291  if(skipped_beam_count >= (beam_ind * self->beam_skip_error_threshold)){
1292  fprintf(stderr, "Over %f%% of the observations were not in the map - pf may have converged to wrong pose - integrating all observations\n", (100 * self->beam_skip_error_threshold));
1293  error = true;
1294  }
1295 
1296  for (j = 0; j < set->sample_count; j++)
1297  {
1298  sample = set->samples + j;
1299  pose = sample->pose;
1300 
1301  log_p = 0;
1302 
1303  for (beam_ind = 0; beam_ind < self->max_beams; beam_ind++){
1304  if(error || obs_mask[beam_ind]){
1305  log_p += log(self->temp_obs[j][beam_ind]);
1306  }
1307  }
1308 
1309  sample->weight *= exp(log_p);
1310 
1311  }
1312  }
1313 
1314 }
1315 
1316  delete [] obs_count;
1317  delete [] obs_mask;
1318 }
1319 
1320 
1321 void GMCLLaser::reallocTempData(int new_max_samples, int new_max_obs){
1322  if(temp_obs){
1323  for(int k=0; k < max_samples; k++){
1324  delete [] temp_obs[k];
1325  }
1326  delete []temp_obs;
1327  }
1328  max_obs = new_max_obs;
1329  max_samples = fmax(max_samples, new_max_samples);
1330 
1331  temp_obs = new double*[max_samples]();
1332  for(int k=0; k < max_samples; k++){
1333  temp_obs[k] = new double[max_obs]();
1334  }
1335 }
gmcl::LASER_MODEL_LIKELIHOOD_FIELD_PROB
@ LASER_MODEL_LIKELIHOOD_FIELD_PROB
Definition: gmcl_laser.h:50
pf_sample_t::weight
double weight
Definition: pf.h:78
gmcl::GMCLLaser::PoseWeight
virtual double PoseWeight(pf_vector_t pose, GMCLLaserData *data)
Definition: gmcl_laser.cpp:153
gmcl::GMCLLaser::temp_obs
double ** temp_obs
Definition: gmcl_laser.h:162
gmcl
Definition: gmcl_laser.h:43
gmcl::GMCLLaser::map
map_t * map
Definition: gmcl_laser.h:139
pf_vector_t
Definition: pf_vector.h:46
gmcl::GMCLSensorData
Definition: gmcl_sensor.h:93
gmcl::GMCLLaser::sigma_hit
double sigma_hit
Definition: gmcl_laser.h:173
gmcl::GMCLLaser::beam_skip_error_threshold
double beam_skip_error_threshold
Definition: gmcl_laser.h:157
gmcl::GMCLLaser::SetModelLikelihoodFieldProb
void SetModelLikelihoodFieldProb(double z_hit, double z_rand, double sigma_hit, double max_occ_dist, bool do_beamskip, double beam_skip_distance, double beam_skip_threshold, double beam_skip_error_threshold)
Definition: gmcl_laser.cpp:108
ros.h
pf_laser_model_fn_t
void(* pf_laser_model_fn_t)(void *laser_data, struct _pf_sample_set_t *set)
Definition: pf.h:64
gmcl::GMCLLaser::LikelihoodFieldModel
static void LikelihoodFieldModel(GMCLLaserData *data, pf_sample_set_t *set)
Definition: gmcl_laser.cpp:458
gmcl::GMCLLaser::max_obs
int max_obs
Definition: gmcl_laser.h:161
_pf_sample_set_t
Definition: pf.h:107
step
unsigned int step
gmcl::GMCLLaser::range_max
float range_max
Definition: gmcl_laser.h:146
gmcl::GMCLSensor
Definition: gmcl_sensor.h:49
gmcl::GMCLLaser::SetModelBeam
void SetModelBeam(double z_hit, double z_short, double z_max, double z_rand, double sigma_hit, double lambda_short, double chi_outlier)
Definition: gmcl_laser.cpp:75
data
data
gmcl::GMCLLaser::do_beamskip
bool do_beamskip
Definition: gmcl_laser.h:152
gmcl::LASER_MODEL_LIKELIHOOD_FIELD
@ LASER_MODEL_LIKELIHOOD_FIELD
Definition: gmcl_laser.h:49
_pf_t
Definition: pf.h:150
gmcl::GMCLLaser::z_max
double z_max
Definition: gmcl_laser.h:169
gmcl::GMCLSensor::pose
pf_vector_t pose
Definition: gmcl_sensor.h:73
gmcl::GMCLLaser::lambda_short
double lambda_short
Definition: gmcl_laser.h:175
gmcl::GMCLLaser::~GMCLLaser
virtual ~GMCLLaser()
Definition: gmcl_laser.cpp:64
gmcl::GMCLLaser::model_type
laser_model_t model_type
Definition: gmcl_laser.h:133
MAP_INDEX
#define MAP_INDEX(map, i, j)
Definition: map.h:207
gmcl::GMCLLaser::UpdateSensor
virtual bool UpdateSensor(pf_t *pf, GMCLSensorData *data)
Definition: gmcl_laser.cpp:131
gmcl::GMCLLaser::z_rand
double z_rand
Definition: gmcl_laser.h:170
gmcl::GMCLLaser::max_samples
int max_samples
Definition: gmcl_laser.h:160
map_update_cspace
void map_update_cspace(map_t *map, double max_occ_dist)
Definition: map_cspace.cpp:128
gmcl::GMCLLaser::beam_skip_distance
double beam_skip_distance
Definition: gmcl_laser.h:153
_pf_t::model
pf_model_type model
Definition: pf.h:153
gmcl::GMCLLaser::time
double time
Definition: gmcl_laser.h:136
gmcl::GMCLLaser::reallocTempData
void reallocTempData(int max_samples, int max_obs)
Definition: gmcl_laser.cpp:1321
gmcl::GMCLLaser::LikelihoodFieldModelProb
static void LikelihoodFieldModelProb(GMCLLaserData *data, pf_sample_set_t *set)
Definition: gmcl_laser.cpp:745
pf_sample_t
Definition: pf.h:72
gmcl::GMCLLaser::BeamModel
static void BeamModel(GMCLLaserData *data, pf_sample_set_t *set)
Definition: gmcl_laser.cpp:211
set
ROSCPP_DECL void set(const std::string &key, bool b)
map_calc_range
double map_calc_range(map_t *map, double ox, double oy, double oa, double max_range)
Definition: map_range.c:46
gmcl::GMCLLaserData
Definition: gmcl_laser.h:54
gmcl_laser.h
gmcl::GMCLLaser::z_hit
double z_hit
Definition: gmcl_laser.h:167
gmcl::GMCLLaser::max_beams
int max_beams
Definition: gmcl_laser.h:149
pf_sample_t::last_obs
double last_obs
Definition: pf.h:81
gmcl::LASER_MODEL_BEAM
@ LASER_MODEL_BEAM
Definition: gmcl_laser.h:48
map_t
Definition: map.h:67
pf_sample_t::pose
pf_vector_t pose
Definition: pf.h:75
gmcl::GMCLLaser::SetModelLikelihoodField
void SetModelLikelihoodField(double z_hit, double z_rand, double sigma_hit, double max_occ_dist)
Definition: gmcl_laser.cpp:94
gmcl::GMCLLaser::z_short
double z_short
Definition: gmcl_laser.h:168
MAP_GXWX
#define MAP_GXWX(map, x)
Definition: map.h:200
_pf_t::N_aux_particles
int N_aux_particles
Definition: pf.h:155
MAP_GYWY
#define MAP_GYWY(map, y)
Definition: map.h:201
gmcl::GMCLLaser::chi_outlier
double chi_outlier
Definition: gmcl_laser.h:177
gmcl::GMCLLaser::GMCLLaser
GMCLLaser(size_t max_beams, map_t *map)
Definition: gmcl_laser.cpp:52
assert.h
gmcl::GMCLLaser::beam_skip_threshold
double beam_skip_threshold
Definition: gmcl_laser.h:154
pf_vector_coord_add
pf_vector_t pf_vector_coord_add(pf_vector_t a, pf_vector_t b)
Definition: pf_vector.c:114
_pf_model_type::use_optimal_filter
bool use_optimal_filter
Definition: pf.h:137
pf_vector_t::v
double v[3]
Definition: pf_vector.h:53
_pf_model_type::use_crossover_mutation
bool use_crossover_mutation
Definition: pf.h:140
gmcl::GMCLLaser
Definition: gmcl_laser.h:71
MAP_VALID
#define MAP_VALID(map, i, j)
Definition: map.h:204
pf_update_sensor
void pf_update_sensor(pf_t *pf, pf_laser_model_fn_t laser_fn, void *laser_data)
Definition: pf.c:329


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