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_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
00097
00098 bool AMCLOdom::UpdateAction(pf_t *pf, AMCLSensorData *data)
00099 {
00100 AMCLOdomData *ndata;
00101 ndata = (AMCLOdomData*) data;
00102
00103
00104 pf_sample_set_t *set;
00105
00106 set = pf->sets + pf->current_set;
00107 pf_vector_t old_pose = pf_vector_sub(ndata->pose, ndata->delta);
00108
00109 if(this->model_type == ODOM_MODEL_OMNI)
00110 {
00111 double delta_trans, delta_rot, delta_bearing;
00112 double delta_trans_hat, delta_rot_hat, delta_strafe_hat;
00113
00114 delta_trans = sqrt(ndata->delta.v[0]*ndata->delta.v[0] +
00115 ndata->delta.v[1]*ndata->delta.v[1]);
00116 delta_rot = ndata->delta.v[2];
00117
00118
00119 double trans_hat_stddev = (alpha3 * (delta_trans*delta_trans) +
00120 alpha1 * (delta_rot*delta_rot));
00121 double rot_hat_stddev = (alpha4 * (delta_rot*delta_rot) +
00122 alpha2 * (delta_trans*delta_trans));
00123 double strafe_hat_stddev = (alpha1 * (delta_rot*delta_rot) +
00124 alpha5 * (delta_trans*delta_trans));
00125
00126 for (int i = 0; i < set->sample_count; i++)
00127 {
00128 pf_sample_t* sample = set->samples + i;
00129
00130 delta_bearing = angle_diff(atan2(ndata->delta.v[1], ndata->delta.v[0]),
00131 old_pose.v[2]) + sample->pose.v[2];
00132 double cs_bearing = cos(delta_bearing);
00133 double sn_bearing = sin(delta_bearing);
00134
00135
00136 delta_trans_hat = delta_trans + pf_ran_gaussian(trans_hat_stddev);
00137 delta_rot_hat = delta_rot + pf_ran_gaussian(rot_hat_stddev);
00138 delta_strafe_hat = 0 + pf_ran_gaussian(strafe_hat_stddev);
00139
00140 sample->pose.v[0] += (delta_trans_hat * cs_bearing +
00141 delta_strafe_hat * sn_bearing);
00142 sample->pose.v[1] += (delta_trans_hat * sn_bearing -
00143 delta_strafe_hat * cs_bearing);
00144 sample->pose.v[2] += delta_rot_hat ;
00145 sample->weight = 1.0 / set->sample_count;
00146 }
00147 }
00148 else
00149 {
00150
00151 double delta_rot1, delta_trans, delta_rot2;
00152 double delta_rot1_hat, delta_trans_hat, delta_rot2_hat;
00153 double delta_rot1_noise, delta_rot2_noise;
00154
00155
00156
00157 if(sqrt(ndata->delta.v[1]*ndata->delta.v[1] +
00158 ndata->delta.v[0]*ndata->delta.v[0]) < 0.01)
00159 delta_rot1 = 0.0;
00160 else
00161 delta_rot1 = angle_diff(atan2(ndata->delta.v[1], ndata->delta.v[0]),
00162 old_pose.v[2]);
00163 delta_trans = sqrt(ndata->delta.v[0]*ndata->delta.v[0] +
00164 ndata->delta.v[1]*ndata->delta.v[1]);
00165 delta_rot2 = angle_diff(ndata->delta.v[2], delta_rot1);
00166
00167
00168
00169
00170 delta_rot1_noise = std::min(fabs(angle_diff(delta_rot1,0.0)),
00171 fabs(angle_diff(delta_rot1,M_PI)));
00172 delta_rot2_noise = std::min(fabs(angle_diff(delta_rot2,0.0)),
00173 fabs(angle_diff(delta_rot2,M_PI)));
00174
00175 for (int i = 0; i < set->sample_count; i++)
00176 {
00177 pf_sample_t* sample = set->samples + i;
00178
00179
00180 delta_rot1_hat = angle_diff(delta_rot1,
00181 pf_ran_gaussian(this->alpha1*delta_rot1_noise*delta_rot1_noise +
00182 this->alpha2*delta_trans*delta_trans));
00183 delta_trans_hat = delta_trans -
00184 pf_ran_gaussian(this->alpha3*delta_trans*delta_trans +
00185 this->alpha4*delta_rot1_noise*delta_rot1_noise +
00186 this->alpha4*delta_rot2_noise*delta_rot2_noise);
00187 delta_rot2_hat = angle_diff(delta_rot2,
00188 pf_ran_gaussian(this->alpha1*delta_rot2_noise*delta_rot2_noise +
00189 this->alpha2*delta_trans*delta_trans));
00190
00191
00192 sample->pose.v[0] += delta_trans_hat *
00193 cos(sample->pose.v[2] + delta_rot1_hat);
00194 sample->pose.v[1] += delta_trans_hat *
00195 sin(sample->pose.v[2] + delta_rot1_hat);
00196 sample->pose.v[2] += delta_rot1_hat + delta_rot2_hat;
00197 sample->weight = 1.0 / set->sample_count;
00198 }
00199 }
00200
00201 return true;
00202 }