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 <algorithm>
00031
00032 #include <sys/types.h>
00033 #include <math.h>
00034
00035 #include "amcl/sensors/amcl_odom.h"
00036
00037 using namespace amcl;
00038
00039 static double
00040 normalize(double z)
00041 {
00042 return atan2(sin(z),cos(z));
00043 }
00044 static double
00045 angle_diff(double a, double b)
00046 {
00047 double d1, d2;
00048 a = normalize(a);
00049 b = normalize(b);
00050 d1 = a-b;
00051 d2 = 2*M_PI - fabs(d1);
00052 if(d1 > 0)
00053 d2 *= -1.0;
00054 if(fabs(d1) < fabs(d2))
00055 return(d1);
00056 else
00057 return(d2);
00058 }
00059
00061
00062 AMCLOdom::AMCLOdom() : AMCLSensor()
00063 {
00064 this->time = 0.0;
00065 }
00066
00067 void
00068 AMCLOdom::SetModelDiff(double alpha1,
00069 double alpha2,
00070 double alpha3,
00071 double alpha4)
00072 {
00073 this->model_type = ODOM_MODEL_DIFF;
00074 this->alpha1 = alpha1;
00075 this->alpha2 = alpha2;
00076 this->alpha3 = alpha3;
00077 this->alpha4 = alpha4;
00078 }
00079
00080 void
00081 AMCLOdom::SetModelOmni(double alpha1,
00082 double alpha2,
00083 double alpha3,
00084 double alpha4,
00085 double alpha5)
00086 {
00087 this->model_type = ODOM_MODEL_OMNI;
00088 this->alpha1 = alpha1;
00089 this->alpha2 = alpha2;
00090 this->alpha3 = alpha3;
00091 this->alpha4 = alpha4;
00092 this->alpha5 = alpha5;
00093 }
00094
00095 void
00096 AMCLOdom::SetModel( odom_model_t type,
00097 double alpha1,
00098 double alpha2,
00099 double alpha3,
00100 double alpha4,
00101 double alpha5 )
00102 {
00103 this->model_type = type;
00104 this->alpha1 = alpha1;
00105 this->alpha2 = alpha2;
00106 this->alpha3 = alpha3;
00107 this->alpha4 = alpha4;
00108 this->alpha5 = alpha5;
00109 }
00110
00112
00113 bool AMCLOdom::UpdateAction(pf_t *pf, AMCLSensorData *data)
00114 {
00115 AMCLOdomData *ndata;
00116 ndata = (AMCLOdomData*) data;
00117
00118
00119 pf_sample_set_t *set;
00120
00121 set = pf->sets + pf->current_set;
00122 pf_vector_t old_pose = pf_vector_sub(ndata->pose, ndata->delta);
00123
00124 switch( this->model_type )
00125 {
00126 case ODOM_MODEL_OMNI:
00127 {
00128 double delta_trans, delta_rot, delta_bearing;
00129 double delta_trans_hat, delta_rot_hat, delta_strafe_hat;
00130
00131 delta_trans = sqrt(ndata->delta.v[0]*ndata->delta.v[0] +
00132 ndata->delta.v[1]*ndata->delta.v[1]);
00133 delta_rot = ndata->delta.v[2];
00134
00135
00136 double trans_hat_stddev = (alpha3 * (delta_trans*delta_trans) +
00137 alpha1 * (delta_rot*delta_rot));
00138 double rot_hat_stddev = (alpha4 * (delta_rot*delta_rot) +
00139 alpha2 * (delta_trans*delta_trans));
00140 double strafe_hat_stddev = (alpha1 * (delta_rot*delta_rot) +
00141 alpha5 * (delta_trans*delta_trans));
00142
00143 for (int i = 0; i < set->sample_count; i++)
00144 {
00145 pf_sample_t* sample = set->samples + i;
00146
00147 delta_bearing = angle_diff(atan2(ndata->delta.v[1], ndata->delta.v[0]),
00148 old_pose.v[2]) + sample->pose.v[2];
00149 double cs_bearing = cos(delta_bearing);
00150 double sn_bearing = sin(delta_bearing);
00151
00152
00153 delta_trans_hat = delta_trans + pf_ran_gaussian(trans_hat_stddev);
00154 delta_rot_hat = delta_rot + pf_ran_gaussian(rot_hat_stddev);
00155 delta_strafe_hat = 0 + pf_ran_gaussian(strafe_hat_stddev);
00156
00157 sample->pose.v[0] += (delta_trans_hat * cs_bearing +
00158 delta_strafe_hat * sn_bearing);
00159 sample->pose.v[1] += (delta_trans_hat * sn_bearing -
00160 delta_strafe_hat * cs_bearing);
00161 sample->pose.v[2] += delta_rot_hat ;
00162 }
00163 }
00164 break;
00165 case ODOM_MODEL_DIFF:
00166 {
00167
00168 double delta_rot1, delta_trans, delta_rot2;
00169 double delta_rot1_hat, delta_trans_hat, delta_rot2_hat;
00170 double delta_rot1_noise, delta_rot2_noise;
00171
00172
00173
00174 if(sqrt(ndata->delta.v[1]*ndata->delta.v[1] +
00175 ndata->delta.v[0]*ndata->delta.v[0]) < 0.01)
00176 delta_rot1 = 0.0;
00177 else
00178 delta_rot1 = angle_diff(atan2(ndata->delta.v[1], ndata->delta.v[0]),
00179 old_pose.v[2]);
00180 delta_trans = sqrt(ndata->delta.v[0]*ndata->delta.v[0] +
00181 ndata->delta.v[1]*ndata->delta.v[1]);
00182 delta_rot2 = angle_diff(ndata->delta.v[2], delta_rot1);
00183
00184
00185
00186
00187 delta_rot1_noise = std::min(fabs(angle_diff(delta_rot1,0.0)),
00188 fabs(angle_diff(delta_rot1,M_PI)));
00189 delta_rot2_noise = std::min(fabs(angle_diff(delta_rot2,0.0)),
00190 fabs(angle_diff(delta_rot2,M_PI)));
00191
00192 for (int i = 0; i < set->sample_count; i++)
00193 {
00194 pf_sample_t* sample = set->samples + i;
00195
00196
00197 delta_rot1_hat = angle_diff(delta_rot1,
00198 pf_ran_gaussian(this->alpha1*delta_rot1_noise*delta_rot1_noise +
00199 this->alpha2*delta_trans*delta_trans));
00200 delta_trans_hat = delta_trans -
00201 pf_ran_gaussian(this->alpha3*delta_trans*delta_trans +
00202 this->alpha4*delta_rot1_noise*delta_rot1_noise +
00203 this->alpha4*delta_rot2_noise*delta_rot2_noise);
00204 delta_rot2_hat = angle_diff(delta_rot2,
00205 pf_ran_gaussian(this->alpha1*delta_rot2_noise*delta_rot2_noise +
00206 this->alpha2*delta_trans*delta_trans));
00207
00208
00209 sample->pose.v[0] += delta_trans_hat *
00210 cos(sample->pose.v[2] + delta_rot1_hat);
00211 sample->pose.v[1] += delta_trans_hat *
00212 sin(sample->pose.v[2] + delta_rot1_hat);
00213 sample->pose.v[2] += delta_rot1_hat + delta_rot2_hat;
00214 }
00215 }
00216 break;
00217 case ODOM_MODEL_OMNI_CORRECTED:
00218 {
00219 double delta_trans, delta_rot, delta_bearing;
00220 double delta_trans_hat, delta_rot_hat, delta_strafe_hat;
00221
00222 delta_trans = sqrt(ndata->delta.v[0]*ndata->delta.v[0] +
00223 ndata->delta.v[1]*ndata->delta.v[1]);
00224 delta_rot = ndata->delta.v[2];
00225
00226
00227 double trans_hat_stddev = sqrt( alpha3 * (delta_trans*delta_trans) +
00228 alpha1 * (delta_rot*delta_rot) );
00229 double rot_hat_stddev = sqrt( alpha4 * (delta_rot*delta_rot) +
00230 alpha2 * (delta_trans*delta_trans) );
00231 double strafe_hat_stddev = sqrt( alpha1 * (delta_rot*delta_rot) +
00232 alpha5 * (delta_trans*delta_trans) );
00233
00234 for (int i = 0; i < set->sample_count; i++)
00235 {
00236 pf_sample_t* sample = set->samples + i;
00237
00238 delta_bearing = angle_diff(atan2(ndata->delta.v[1], ndata->delta.v[0]),
00239 old_pose.v[2]) + sample->pose.v[2];
00240 double cs_bearing = cos(delta_bearing);
00241 double sn_bearing = sin(delta_bearing);
00242
00243
00244 delta_trans_hat = delta_trans + pf_ran_gaussian(trans_hat_stddev);
00245 delta_rot_hat = delta_rot + pf_ran_gaussian(rot_hat_stddev);
00246 delta_strafe_hat = 0 + pf_ran_gaussian(strafe_hat_stddev);
00247
00248 sample->pose.v[0] += (delta_trans_hat * cs_bearing +
00249 delta_strafe_hat * sn_bearing);
00250 sample->pose.v[1] += (delta_trans_hat * sn_bearing -
00251 delta_strafe_hat * cs_bearing);
00252 sample->pose.v[2] += delta_rot_hat ;
00253 }
00254 }
00255 break;
00256 case ODOM_MODEL_DIFF_CORRECTED:
00257 {
00258
00259 double delta_rot1, delta_trans, delta_rot2;
00260 double delta_rot1_hat, delta_trans_hat, delta_rot2_hat;
00261 double delta_rot1_noise, delta_rot2_noise;
00262
00263
00264
00265 if(sqrt(ndata->delta.v[1]*ndata->delta.v[1] +
00266 ndata->delta.v[0]*ndata->delta.v[0]) < 0.01)
00267 delta_rot1 = 0.0;
00268 else
00269 delta_rot1 = angle_diff(atan2(ndata->delta.v[1], ndata->delta.v[0]),
00270 old_pose.v[2]);
00271 delta_trans = sqrt(ndata->delta.v[0]*ndata->delta.v[0] +
00272 ndata->delta.v[1]*ndata->delta.v[1]);
00273 delta_rot2 = angle_diff(ndata->delta.v[2], delta_rot1);
00274
00275
00276
00277
00278 delta_rot1_noise = std::min(fabs(angle_diff(delta_rot1,0.0)),
00279 fabs(angle_diff(delta_rot1,M_PI)));
00280 delta_rot2_noise = std::min(fabs(angle_diff(delta_rot2,0.0)),
00281 fabs(angle_diff(delta_rot2,M_PI)));
00282
00283 for (int i = 0; i < set->sample_count; i++)
00284 {
00285 pf_sample_t* sample = set->samples + i;
00286
00287
00288 delta_rot1_hat = angle_diff(delta_rot1,
00289 pf_ran_gaussian(sqrt(this->alpha1*delta_rot1_noise*delta_rot1_noise +
00290 this->alpha2*delta_trans*delta_trans)));
00291 delta_trans_hat = delta_trans -
00292 pf_ran_gaussian(sqrt(this->alpha3*delta_trans*delta_trans +
00293 this->alpha4*delta_rot1_noise*delta_rot1_noise +
00294 this->alpha4*delta_rot2_noise*delta_rot2_noise));
00295 delta_rot2_hat = angle_diff(delta_rot2,
00296 pf_ran_gaussian(sqrt(this->alpha1*delta_rot2_noise*delta_rot2_noise +
00297 this->alpha2*delta_trans*delta_trans)));
00298
00299
00300 sample->pose.v[0] += delta_trans_hat *
00301 cos(sample->pose.v[2] + delta_rot1_hat);
00302 sample->pose.v[1] += delta_trans_hat *
00303 sin(sample->pose.v[2] + delta_rot1_hat);
00304 sample->pose.v[2] += delta_rot1_hat + delta_rot2_hat;
00305 }
00306 }
00307 break;
00308 }
00309 return true;
00310 }