25 #include "nav2_amcl/sensors/laser/laser.hpp"
30 LikelihoodFieldModelProb::LikelihoodFieldModelProb(
31 double z_hit,
double z_rand,
double sigma_hit,
32 double max_occ_dist,
bool do_beamskip,
33 double beam_skip_distance,
34 double beam_skip_threshold,
35 double beam_skip_error_threshold,
36 size_t max_beams,
map_t * map)
37 : Laser(max_beams, map)
41 sigma_hit_ = sigma_hit;
42 do_beamskip_ = do_beamskip;
43 beam_skip_distance_ = beam_skip_distance;
44 beam_skip_threshold_ = beam_skip_threshold;
45 beam_skip_error_threshold_ = beam_skip_error_threshold;
52 if (map->max_occ_dist != max_occ_dist) {
53 map_update_cspace(map, max_occ_dist);
59 LikelihoodFieldModelProb::sensorFunction(LaserData * data,
pf_sample_set_t * set)
61 LikelihoodFieldModelProb *
self;
65 double obs_range, obs_bearing;
71 self =
reinterpret_cast<LikelihoodFieldModelProb *
>(data->laser);
75 step = ceil((data->range_count) /
static_cast<double>(self->max_beams_));
83 double z_hit_denom = 2 *
self->sigma_hit_ *
self->sigma_hit_;
84 double z_rand_mult = 1.0 / data->range_max;
86 double max_dist_prob = exp(-(self->map_->max_occ_dist * self->map_->max_occ_dist) / z_hit_denom);
92 bool do_beamskip =
self->do_beamskip_;
93 double beam_skip_distance =
self->beam_skip_distance_;
94 double beam_skip_threshold =
self->beam_skip_threshold_;
97 if (do_beamskip && !set->converged) {
102 int * obs_count =
new int[
self->max_beams_]();
106 bool * obs_mask =
new bool[
self->max_beams_]();
111 bool realloc =
false;
114 if (self->max_obs_ < self->max_beams_) {
118 if (self->max_samples_ < set->sample_count) {
123 self->reallocTempData(set->sample_count, self->max_beams_);
124 fprintf(stderr,
"Reallocing temp weights %d - %d\n", self->max_samples_, self->max_obs_);
129 for (j = 0; j < set->sample_count; j++) {
130 sample = set->samples + j;
134 pose = pf_vector_coord_add(self->laser_pose_, pose);
140 for (i = 0; i < data->range_count; i += step, beam_ind++) {
141 obs_range = data->ranges[i][0];
142 obs_bearing = data->ranges[i][1];
145 if (obs_range >= data->range_max) {
150 if (obs_range != obs_range) {
157 hit.v[0] = pose.v[0] + obs_range * cos(pose.v[2] + obs_bearing);
158 hit.v[1] = pose.v[1] + obs_range * sin(pose.v[2] + obs_bearing);
162 mi = MAP_GXWX(self->map_, hit.v[0]);
163 mj = MAP_GYWY(self->map_, hit.v[1]);
168 if (!MAP_VALID(self->map_, mi, mj)) {
169 pz +=
self->z_hit_ * max_dist_prob;
171 z =
self->map_->cells[MAP_INDEX(self->map_, mi, mj)].occ_dist;
172 if (z < beam_skip_distance) {
173 obs_count[beam_ind] += 1;
175 pz +=
self->z_hit_ * exp(-(z * z) / z_hit_denom);
182 pz +=
self->z_rand_ * z_rand_mult;
192 self->temp_obs_[j][beam_ind] = pz;
196 sample->weight *= exp(log_p);
197 total_weight += sample->weight;
202 int skipped_beam_count = 0;
203 for (beam_ind = 0; beam_ind <
self->max_beams_; beam_ind++) {
204 if ((obs_count[beam_ind] /
static_cast<double>(set->sample_count)) > beam_skip_threshold) {
205 obs_mask[beam_ind] =
true;
207 obs_mask[beam_ind] =
false;
208 skipped_beam_count++;
218 if (skipped_beam_count >= (beam_ind * self->beam_skip_error_threshold_)) {
221 "Over %f%% of the observations were not in the map - pf may have converged to wrong pose -"
222 " integrating all observations\n",
223 (100 * self->beam_skip_error_threshold_));
227 for (j = 0; j < set->sample_count; j++) {
228 sample = set->samples + j;
233 for (beam_ind = 0; beam_ind <
self->max_beams_; beam_ind++) {
234 if (error || obs_mask[beam_ind]) {
235 log_p += log(self->temp_obs_[j][beam_ind]);
239 sample->weight *= exp(log_p);
241 total_weight += sample->weight;
251 LikelihoodFieldModelProb::sensorUpdate(
pf_t * pf, LaserData * data)
253 if (max_beams_ < 2) {
256 pf_update_sensor(pf, (pf_sensor_model_fn_t) sensorFunction, data);