26 #include "nav2_amcl/sensors/laser/laser.hpp"
31 LikelihoodFieldModelProb::LikelihoodFieldModelProb(
32 double z_hit,
double z_rand,
double sigma_hit,
33 double max_occ_dist,
bool do_beamskip,
34 double beam_skip_distance,
35 double beam_skip_threshold,
36 double beam_skip_error_threshold,
37 size_t max_beams,
map_t * map)
38 : Laser(max_beams, map)
42 sigma_hit_ = sigma_hit;
43 do_beamskip_ = do_beamskip;
44 beam_skip_distance_ = beam_skip_distance;
45 beam_skip_threshold_ = beam_skip_threshold;
46 beam_skip_error_threshold_ = beam_skip_error_threshold;
47 map_update_cspace(map, max_occ_dist);
52 LikelihoodFieldModelProb::sensorFunction(LaserData * data,
pf_sample_set_t * set)
54 LikelihoodFieldModelProb *
self;
58 double obs_range, obs_bearing;
64 self =
reinterpret_cast<LikelihoodFieldModelProb *
>(data->laser);
68 step = ceil((data->range_count) /
static_cast<double>(self->max_beams_));
76 double z_hit_denom = 2 *
self->sigma_hit_ *
self->sigma_hit_;
77 double z_rand_mult = 1.0 / data->range_max;
79 double max_dist_prob = exp(-(self->map_->max_occ_dist * self->map_->max_occ_dist) / z_hit_denom);
85 bool do_beamskip =
self->do_beamskip_;
86 double beam_skip_distance =
self->beam_skip_distance_;
87 double beam_skip_threshold =
self->beam_skip_threshold_;
90 if (do_beamskip && !set->converged) {
95 int * obs_count =
new int[
self->max_beams_]();
99 bool * obs_mask =
new bool[
self->max_beams_]();
104 bool realloc =
false;
107 if (self->max_obs_ < self->max_beams_) {
111 if (self->max_samples_ < set->sample_count) {
116 self->reallocTempData(set->sample_count, self->max_beams_);
117 fprintf(stderr,
"Reallocing temp weights %d - %d\n", self->max_samples_, self->max_obs_);
122 for (j = 0; j < set->sample_count; j++) {
123 sample = set->samples + j;
127 pose = pf_vector_coord_add(self->laser_pose_, pose);
133 for (i = 0; i < data->range_count; i += step, beam_ind++) {
134 obs_range = data->ranges[i][0];
135 obs_bearing = data->ranges[i][1];
138 if (obs_range >= data->range_max) {
143 if (obs_range != obs_range) {
150 hit.v[0] = pose.v[0] + obs_range * cos(pose.v[2] + obs_bearing);
151 hit.v[1] = pose.v[1] + obs_range * sin(pose.v[2] + obs_bearing);
155 mi = MAP_GXWX(self->map_, hit.v[0]);
156 mj = MAP_GYWY(self->map_, hit.v[1]);
161 if (!MAP_VALID(self->map_, mi, mj)) {
162 pz +=
self->z_hit_ * max_dist_prob;
164 z =
self->map_->cells[MAP_INDEX(self->map_, mi, mj)].occ_dist;
165 if (z < beam_skip_distance) {
166 obs_count[beam_ind] += 1;
168 pz +=
self->z_hit_ * exp(-(z * z) / z_hit_denom);
175 pz +=
self->z_rand_ * z_rand_mult;
185 self->temp_obs_[j][beam_ind] = pz;
189 sample->weight *= exp(log_p);
190 total_weight += sample->weight;
195 int skipped_beam_count = 0;
196 for (beam_ind = 0; beam_ind <
self->max_beams_; beam_ind++) {
197 if ((obs_count[beam_ind] /
static_cast<double>(set->sample_count)) > beam_skip_threshold) {
198 obs_mask[beam_ind] =
true;
200 obs_mask[beam_ind] =
false;
201 skipped_beam_count++;
211 if (skipped_beam_count >= (beam_ind * self->beam_skip_error_threshold_)) {
214 "Over %f%% of the observations were not in the map - pf may have converged to wrong pose -"
215 " integrating all observations\n",
216 (100 * self->beam_skip_error_threshold_));
220 for (j = 0; j < set->sample_count; j++) {
221 sample = set->samples + j;
226 for (beam_ind = 0; beam_ind <
self->max_beams_; beam_ind++) {
227 if (error || obs_mask[beam_ind]) {
228 log_p += log(self->temp_obs_[j][beam_ind]);
232 sample->weight *= exp(log_p);
234 total_weight += sample->weight;
244 LikelihoodFieldModelProb::sensorUpdate(
pf_t * pf, LaserData * data)
246 if (max_beams_ < 2) {
249 pf_update_sensor(pf, (pf_sensor_model_fn_t) sensorFunction, data);