Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00022
00023
00024
00025
00026
00027
00029
00030 #include <sys/types.h>
00031 #include <math.h>
00032 #include <stdlib.h>
00033 #include <assert.h>
00034 #include <unistd.h>
00035
00036 #include "amcl_laser.h"
00037
00038 using namespace amcl;
00039
00041
00042 AMCLLaser::AMCLLaser(size_t max_beams, map_t* map) : AMCLSensor()
00043 {
00044 this->time = 0.0;
00045
00046 this->max_beams = max_beams;
00047 this->map = map;
00048
00049 return;
00050 }
00051
00052 void
00053 AMCLLaser::SetModelBeam(double z_hit,
00054 double z_short,
00055 double z_max,
00056 double z_rand,
00057 double sigma_hit,
00058 double lambda_short,
00059 double chi_outlier)
00060 {
00061 this->model_type = LASER_MODEL_BEAM;
00062 this->z_hit = z_hit;
00063 this->z_short = z_short;
00064 this->z_max = z_max;
00065 this->z_rand = z_rand;
00066 this->sigma_hit = sigma_hit;
00067 this->lambda_short = lambda_short;
00068 this->chi_outlier = chi_outlier;
00069 }
00070
00071 void
00072 AMCLLaser::SetModelLikelihoodField(double z_hit,
00073 double z_rand,
00074 double sigma_hit,
00075 double max_occ_dist)
00076 {
00077 this->model_type = LASER_MODEL_LIKELIHOOD_FIELD;
00078 this->z_hit = z_hit;
00079 this->z_max = z_max;
00080 this->z_rand = z_rand;
00081 this->sigma_hit = sigma_hit;
00082
00083 map_update_cspace(this->map, max_occ_dist);
00084 }
00085
00086
00088
00089 bool AMCLLaser::UpdateSensor(pf_t *pf, AMCLSensorData *data)
00090 {
00091 if (this->max_beams < 2)
00092 return false;
00093
00094
00095 if(this->model_type == LASER_MODEL_BEAM)
00096 pf_update_sensor(pf, (pf_sensor_model_fn_t) BeamModel, data);
00097 else if(this->model_type == LASER_MODEL_LIKELIHOOD_FIELD)
00098 pf_update_sensor(pf, (pf_sensor_model_fn_t) LikelihoodFieldModel, data);
00099 else
00100 pf_update_sensor(pf, (pf_sensor_model_fn_t) BeamModel, data);
00101
00102 return true;
00103 }
00104
00105
00107
00108 double AMCLLaser::BeamModel(AMCLLaserData *data, pf_sample_set_t* set)
00109 {
00110 AMCLLaser *self;
00111 int i, j, step;
00112 double z, pz;
00113 double p;
00114 double map_range;
00115 double obs_range, obs_bearing;
00116 double total_weight;
00117 pf_sample_t *sample;
00118 pf_vector_t pose;
00119
00120 self = (AMCLLaser*) data->sensor;
00121
00122 total_weight = 0.0;
00123
00124
00125 for (j = 0; j < set->sample_count; j++)
00126 {
00127 sample = set->samples + j;
00128 pose = sample->pose;
00129
00130
00131 pose = pf_vector_coord_add(self->laser_pose, pose);
00132
00133 p = 1.0;
00134
00135 step = (data->range_count - 1) / (self->max_beams - 1);
00136 for (i = 0; i < data->range_count; i += step)
00137 {
00138 obs_range = data->ranges[i][0];
00139 obs_bearing = data->ranges[i][1];
00140
00141
00142 map_range = map_calc_range(self->map, pose.v[0], pose.v[1],
00143 pose.v[2] + obs_bearing, data->range_max);
00144 pz = 0.0;
00145
00146
00147 z = obs_range - map_range;
00148 pz += self->z_hit * exp(-(z * z) / (2 * self->sigma_hit * self->sigma_hit));
00149
00150
00151 if(z < 0)
00152 pz += self->z_short * self->lambda_short * exp(-self->lambda_short*obs_range);
00153
00154
00155 if(obs_range == data->range_max)
00156 pz += self->z_max * 1.0;
00157
00158
00159 if(obs_range < data->range_max)
00160 pz += self->z_rand * 1.0/data->range_max;
00161
00162
00163
00164 assert(pz <= 1.0);
00165 assert(pz >= 0.0);
00166
00167
00168
00169 p += pz*pz*pz;
00170 }
00171
00172 sample->weight *= p;
00173 total_weight += sample->weight;
00174 }
00175
00176 return(total_weight);
00177 }
00178
00179 double AMCLLaser::LikelihoodFieldModel(AMCLLaserData *data, pf_sample_set_t* set)
00180 {
00181 AMCLLaser *self;
00182 int i, j, step;
00183 double z, pz;
00184 double p;
00185 double obs_range, obs_bearing;
00186 double total_weight;
00187 pf_sample_t *sample;
00188 pf_vector_t pose;
00189 pf_vector_t hit;
00190
00191 self = (AMCLLaser*) data->sensor;
00192
00193 total_weight = 0.0;
00194
00195
00196 for (j = 0; j < set->sample_count; j++)
00197 {
00198 sample = set->samples + j;
00199 pose = sample->pose;
00200
00201
00202 pose = pf_vector_coord_add(self->laser_pose, pose);
00203
00204 p = 1.0;
00205
00206
00207 double z_hit_denom = 2 * self->sigma_hit * self->sigma_hit;
00208 double z_rand_mult = 1.0/data->range_max;
00209
00210 step = (data->range_count - 1) / (self->max_beams - 1);
00211 for (i = 0; i < data->range_count; i += step)
00212 {
00213 obs_range = data->ranges[i][0];
00214 obs_bearing = data->ranges[i][1];
00215
00216
00217 if(obs_range >= data->range_max)
00218 continue;
00219
00220 pz = 0.0;
00221
00222
00223 hit.v[0] = pose.v[0] + obs_range * cos(pose.v[2] + obs_bearing);
00224 hit.v[1] = pose.v[1] + obs_range * sin(pose.v[2] + obs_bearing);
00225
00226
00227 int mi, mj;
00228 mi = MAP_GXWX(self->map, hit.v[0]);
00229 mj = MAP_GYWY(self->map, hit.v[1]);
00230
00231
00232
00233 if(!MAP_VALID(self->map, mi, mj))
00234 z = self->map->max_occ_dist;
00235 else
00236 z = self->map->cells[MAP_INDEX(self->map,mi,mj)].occ_dist;
00237
00238
00239 pz += self->z_hit * exp(-(z * z) / z_hit_denom);
00240
00241 pz += self->z_rand * z_rand_mult;
00242
00243
00244
00245 assert(pz <= 1.0);
00246 assert(pz >= 0.0);
00247
00248
00249
00250 p += pz*pz*pz;
00251 }
00252
00253 sample->weight *= p;
00254 total_weight += sample->weight;
00255 }
00256
00257 return(total_weight);
00258 }