00001 // ---------------------------------------------------------------------------- 00002 // 00003 // $Id$ 00004 // 00005 // Copyright 2008, 2009, 2010, 2011, 2012 Antonio Franchi and Paolo Stegagno 00006 // 00007 // This file is part of MIP. 00008 // 00009 // MIP is free software: you can redistribute it and/or modify 00010 // it under the terms of the GNU General Public License as published by 00011 // the Free Software Foundation, either version 3 of the License, or 00012 // (at your option) any later version. 00013 // 00014 // MIP is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with MIP. If not, see <http://www.gnu.org/licenses/>. 00021 // 00022 // Contact info: antonio.franchi@tuebingen.mpg.de stegagno@diag.uniroma1.it 00023 // 00024 // ---------------------------------------------------------------------------- 00025 00026 00030 00034 00035 00037 /* @{ */ 00038 00039 #ifndef __ODOMETRY_H 00040 #define __ODOMETRY_H 00041 00042 #ifdef MIP_HOST_APPLE 00043 #include <applePatch.h> 00044 #endif 00045 00046 #include "TrajControl.h" 00047 //TODO cancellare le define 00048 #define E_d 0.1 00049 #define E_b 0.1 00050 #define wheel_diameter 0.1 00051 #define axle_length 1.0 00052 00053 // ///\class DiffDriveOdometerPar 00054 // ///\brief Contains the parameters needed to compute the odometric update equations of a differential drive. 00055 // ///\author Antonio Franchi 00056 // ///\todo 00057 // class DiffDriveOdometerPar{ 00058 // private: 00059 // Decimal _leftWheelDiam; ///< Left-wheel diameter. 00060 // Decimal _rightWheelDiam; ///< Right-wheel diameter. 00061 // Decimal _axelTrack; ///< Axel track. 00062 // Decimal _encoderResol; ///< Encoder resolution. 00063 // 00064 // Decimal _leftRatio; ///< Left-wheel conversion-ratio between pulses and linear movement of the wheel. 00065 // Decimal _rightRatio; ///< Right-wheel conversion-ratio between pulses and linear movement of the wheel. 00066 // public: 00067 // /// \brief Constructor. 00068 // /// \param ld Left-wheel diameter (m). 00069 // /// \param rd Right-wheel diameter (m). 00070 // /// \param wb Axel track (m). 00071 // /// \param er Encoder resolution, number of pulses per radians (pulses/rad). 00072 // DiffDriveOdometerPar(Decimal ld=1.0,Decimal rd=1.0,Decimal wb=1.0,Decimal er=1.0); 00073 // /// \brief Copy constructor. 00074 // DiffDriveOdometerPar(const DiffDriveOdometerPar &p); 00075 // /// \brief Assigment operator =. 00076 // DiffDriveOdometerPar& operator=(const DiffDriveOdometerPar& p){ 00077 // if (this != &p){ 00078 // _leftWheelDiam = p._leftWheelDiam; 00079 // _rightWheelDiam = p._rightWheelDiam; 00080 // _axelTrack = p._axelTrack; 00081 // _encoderResol = p._encoderResol; 00082 // _leftRatio = p._leftRatio; 00083 // _rightRatio = p._rightRatio; 00084 // } 00085 // return *this; 00086 // } 00087 // 00088 // /// \brief Gets Left-wheel diameter (m). 00089 // Decimal getLeftWheelDiam(); 00090 // /// \brief Gets Right-wheel diameter (m). 00091 // Decimal getRightWheelDiam(); 00092 // /// \brief Gets Axel track (m). 00093 // Decimal getAxelTrack(); 00094 // /// \brief Gets Encoder resolution, number of pulses per radians (pulses/rad). 00095 // Decimal getEncoderResol(); 00096 // /// \brief Gets Left-wheel conversion-ratio between pulses and linear movement of the wheel. 00097 // Decimal getLeftRatio(); 00098 // /// \brief Gets Right-wheel conversion-ratio between pulses and linear movement of the wheel. 00099 // Decimal getRightRatio(); 00100 // /// \brief Prints the parameters. 00101 // string print(); 00102 // }; 00103 // 00104 // 00105 // ///\class DiffDriveEncoderReading 00106 // ///\brief Contains the readings of the encoders of a differential drive. 00107 // ///\author Antonio Franchi 00108 // ///\todo Public or private variables? 00109 // class DiffDriveEncoderReading{ 00110 // private: 00111 // public: 00112 // long int leftPulses; ///< Left-wheel/motor encoder pulses. 00113 // long int rightPulses; ///< Right-wheel/motor encoder pulses. 00114 // Time leftTime; ///< Time in which leftPulses was aquired. 00115 // Time rightTime; ///< Time in which rightPulses was aquired. 00116 // 00117 // /// \brief Constructor. 00118 // /// \param lp Left-wheel/motor encoder pulses. 00119 // /// \param rp Right-wheel/motor encoder pulses. 00120 // /// \param lt Time in which the left-wheel/motor encoder pulses is aquired. 00121 // /// \param lt Time in which the right-wheel/motor encoder pulses is aquired. 00122 // DiffDriveEncoderReading(long int lp=0,long int rp=0,Time lt=Time(0.0),Time rt=Time(0.0)); 00123 // /// \brief Copy constructor. 00124 // DiffDriveEncoderReading(const DiffDriveEncoderReading &p); 00125 // /// \brief Assigment operator =. 00126 // DiffDriveEncoderReading& operator=(const DiffDriveEncoderReading& p){ 00127 // if (this != &p){ 00128 // leftPulses = p.leftPulses; 00129 // rightPulses = p.rightPulses; 00130 // leftTime = p.leftTime; 00131 // rightTime = p.rightTime; 00132 // } 00133 // return *this; 00134 // } 00135 // /// \brief Prints the readings. 00136 // string print(); 00137 // }; 00138 // 00139 // 00140 // ///\class DiffDriveOdometerVar 00141 // ///\brief Contains the variables needed to compute the odometric update equations of a differential drive. 00142 // ///\author Antonio Franchi 00143 // ///\todo Public or private variables? 00144 // class DiffDriveOdometerVar{ 00145 // private: 00146 // public: 00147 // Pose pose; ///< Current Pose, x,y,theta. 00148 // DiffDriveEncoderReading encodRead; ///< Readings (pulses,times) of the encoders of the wheels. 00149 // 00150 // /// \brief default constructor. 00151 // // DiffDriveOdometerVar(Pose p, long int lp,long int rp,Time lt,Time rt); 00152 // /// \brief Constructor. 00153 // /// \param p Initial Pose of the unicycle: x,y,theta. 00154 // /// \param lp Initial left-wheel/motor encoder pulses. 00155 // /// \param rp Initial right-wheel/motor encoder pulses. 00156 // /// \param lt Time in which the initial left-wheel/motor encoder pulses was aquired. 00157 // /// \param lt Time in which the initial right-wheel/motor encoder pulses was aquired. 00158 // DiffDriveOdometerVar(Pose p=Pose(),DiffDriveEncoderReading r=DiffDriveEncoderReading()); 00159 // // DiffDriveOdometerVar(Pose p, long int lp,long int rp,Time lt,Time rt); 00160 // 00161 // /// \brief Copy constructor. 00162 // DiffDriveOdometerVar(const DiffDriveOdometerVar &p); 00163 // /// \brief Assigment operator =. 00164 // DiffDriveOdometerVar& operator=(const DiffDriveOdometerVar& p){ 00165 // if (this != &p){ 00166 // pose = p.pose; 00167 // encodRead = p.encodRead; 00168 // } 00169 // return *this; 00170 // } 00171 // /// \brief Prints the variables. 00172 // string print(); 00173 // }; 00174 // 00175 // 00176 // ///\class DiffDriveOdometerIn 00177 // ///\brief Contains the iputs needed to compute the odometric update equations of a differential drive. 00178 // ///\author Antonio Franchi 00179 // ///\todo 00180 // typedef DiffDriveEncoderReading DiffDriveOdometerIn; 00181 // 00182 // ///\class DiffDriveOdometerOut 00183 // ///\brief Contains the outputs returned by the odometric update equations of a differential drive. 00184 // ///\author Antonio Franchi 00185 // ///\todo Public or private variables? 00186 // class DiffDriveOdometerOut{ 00187 // private: 00188 // public: 00189 // Pose pose; ///< Pose, x,y,theta. 00190 // Decimal speed; ///< Current linear speed (m/sec). 00191 // Decimal turnrate; ///< Current angular velocity (rad/sec). 00192 // 00193 // /// \brief Constructor. 00194 // /// \param p New computed pose of the differntial drive: x,y,theta. 00195 // /// \param s New computed linear speed. 00196 // /// \param t New computed angular velocity. 00197 // DiffDriveOdometerOut(Pose p,Decimal s,Decimal t); 00198 // /// \brief Copy constructor. 00199 // DiffDriveOdometerOut(const DiffDriveOdometerOut &p); 00200 // /// \brief Assigment operator =. 00201 // DiffDriveOdometerOut& operator=(const DiffDriveOdometerOut& p){ 00202 // if (this != &p){ 00203 // pose = p.pose; 00204 // speed = p.speed; 00205 // turnrate = p.turnrate; 00206 // } 00207 // return *this; 00208 // } 00209 // /// \brief Prints the output. 00210 // string print(); 00211 // }; 00212 // 00213 // 00214 // ///\class DiffDriveOdometer 00215 // ///\brief Algorithm which may be used to update the state of a differential drive. It make use of the odometric equations. 00216 // ///\author Antonio Franchi 00217 // ///\todo Add logging. 00218 // class DiffDriveOdometer{ 00219 // private: 00220 // DiffDriveOdometerPar par; 00221 // DiffDriveOdometerVar var; 00222 // public: 00223 // /// \brief Constructor. 00224 // /// \param p Parameters. 00225 // /// \param v Initial variables (state). 00226 // DiffDriveOdometer(const DiffDriveOdometerPar& p,const DiffDriveOdometerVar& v); 00227 // 00228 // /// \brief Reset the pose to a certain value. 00229 // /// \param p New pose. 00230 // void poseReset(Pose p); 00231 // 00232 // /// \brief Reset the variables of the algorithm to a certain value. 00233 // /// \param p New variables. 00234 // void varReset(DiffDriveOdometerVar v); 00235 // 00236 // /// \brief Fundamental step of the algorithm. 00237 // /// \param in Inputs of the step (new pulses and times). 00238 // /// \return Output of the step (new pose, new linear speed, new angular speed). 00239 // DiffDriveOdometerOut step(DiffDriveOdometerIn in); 00240 // }; 00241 00242 00251 class Odometry{ 00252 private: 00253 bool first;//TODO si può omettere se inizializzo tutto nel costruttore? 00254 // long int N_LeftW_prec,N_RightW_prec;//Input di update 00255 long int _leastLeftRead, _leastRightRead; 00256 // Timer _encTimer; 00257 Time _leastLeftTime,_leastRightTime; 00258 public: 00259 00260 bool updateOdometry(long int currLeftRead, long int currRightRead, long int encRes, Time currLeftTime, Time currRightTime,TrajectoryState &trajStatus){ 00261 Decimal dT,dTR,dTL; 00262 Decimal vr, vl; 00263 long N_LeftW, N_RightW; 00264 Decimal vel_tick_r,vel_tick_l; 00265 // Time currLeftTime,currRightTime; 00266 00267 static Decimal Deltang=(2.0*M_PI/encRes); 00268 if(first){//TODO verifica 00269 _leastLeftRead = 0;//NOTE origine della lettura? 00270 _leastRightRead = 0;//NOTE origine della lettura? 00271 _leastLeftTime=Time(0,0); 00272 _leastRightTime=Time(0,0); 00273 // _encTimer.reset(); 00274 first = false; 00275 } 00276 00277 // wheelCountersL = getLeftEncoder();//NOTE nuova della lettura? 00278 // double ltime = leggiTempo3(tvl); 00279 // currLeftTime=_encTimer.get(); 00280 // wheelCountersR = getRightEncoder();//NOTE nuova della lettura? 00281 // // double rtime = leggiTempo3(tvr); 00282 // currRightTime=_encTimer.get(); 00283 00284 int tent = 0; 00285 int maxTent =2; 00286 while( ( (currLeftRead - _leastLeftRead > 200) || (currLeftRead - _leastLeftRead < -200) ) && (tent<maxTent) ){/*provo a filtrare letture fallaci*/ 00287 // wheelCountersL = getLeftEncoder(); 00288 // ltime = leggiTempo3(tvl); 00289 //TODO aggiornare comunque least readings?qui wheelCountersL 00290 tent++; 00291 return false; 00292 } 00293 tent=0; 00294 N_LeftW = currLeftRead - _leastLeftRead; 00295 while( ( (currRightRead - _leastRightRead > 200)|| (currRightRead - _leastRightRead < -200) ) && (tent<maxTent) ){/*provo a filtrare letture fallaci*/ 00296 // wheelCountersR = getRightEncoder(); 00297 // rtime = leggiTempo3(tvr); 00298 //TODO aggiornare comunque least readings?qui wheelCountersR 00299 tent++; 00300 return false; 00301 } 00302 N_RightW = currRightRead - _leastRightRead; 00304 // if(wheelCountersL > 2765){ 00305 // wheelCountersL = getLeftEncoder(); 00306 // ltime = leggiTempo3(tvl); 00307 // } 00308 // N_LeftW=wheelCountersL-N_LeftW_prec; 00309 // /*!filtraggio per evitare letture incoerenti (maggiori della risoluzione max dell'encoder)*/ 00310 // if(wheelCountersR > 2765){ 00311 // wheelCountersR = getRightEncoder(); 00312 // rtime = leggiTempo3(tvr); 00313 // } 00314 // N_RightW=wheelCountersR-N_RightW_prec; 00315 Time dtLeft=currLeftTime-_leastLeftTime; 00316 Time dtRight=currRightTime-_leastRightTime; 00317 dTL = dtLeft.dCast(); 00318 dTR =dtRight.dCast(); 00319 Time dTime=(Time)(dtRight+dtLeft)*0.5; 00320 dT=dTime.dCast(); 00321 00322 //Calcolo di vl, vr, v & omega 00323 vel_tick_l = rint(N_LeftW/dTL); //pulse/s 00324 vel_tick_r = rint(N_RightW/dTR); //pulse/s 00325 00326 _leastLeftTime = currLeftTime; 00327 _leastRightTime = currRightTime; 00328 vl=(2.0/ (E_d+1.0)) * (N_LeftW * Deltang * (wheel_diameter/2.0)) / dTL; // m/s 00329 vr=(2.0/ ( (1.0/E_d) +1.0) ) * (N_RightW * Deltang * (wheel_diameter/2.0)) / dTR; // m/s 00330 00331 trajStatus.setDtWheel((Position)(dTR,dTL)); 00332 // MState.dTL = dTL; 00333 // MState.dTR = dTR; 00334 trajStatus.setWheelVel((Position)(vr,vl)); 00335 // MState.vl = vl; 00336 // MState.vr = vr; 00337 trajStatus.setStatusVel(VelVec(0.5*(vr+vl),(vr-vl)/(E_b*axle_length),dTime)); 00338 // MState.V = 0.5*(vr+vl); 00339 // MState.W = (vr-vl)/(E_b*axle_length); 00340 // dT = 0.5*(dTR + dTL); 00341 00342 //Integrazione Runge-Kutta del II ordine 00343 Angle theta=trajStatus.statusPose().ori(); 00344 Decimal V=trajStatus.statusVel().linVel(); 00345 Decimal W=trajStatus.statusVel().angVel(); 00346 // Pose dPose=Pose (cos(theta.dCast() + W*dT*0.5 )*V*dT,sin(theta.dCast() + W*dT*0.5 )*V*dT,(Angle)(normalize(theta.dCast()+(W*dT)))); 00347 Pose dPose=Pose (cos(theta.dCast2Pi() + W*dT*0.5 )*V*dT,sin(theta.dCast2Pi() + W*dT*0.5 )*V*dT,(Angle)(theta.dCast2Pi()+(W*dT))); 00348 trajStatus.setStatusPose(trajStatus.statusPose()+dPose); 00349 00350 // MState.x += cos( MState.theta + MState.W*dT*0.5 )*MState.V*dT.dCast(); 00351 // MState.y += sin( MState.theta + MState.W*dT*0.5 )*MState.V*dT.dCast(); 00352 // MState.theta = normalizza( MState.theta + MState.W * dT); 00353 00354 //Aggiornamento dello stato 00355 _leastLeftRead = currLeftRead; 00356 _leastRightRead = currRightRead; 00357 00358 // if(log_flag){ 00359 // MLogState.x = MState.x; 00360 // MLogState.y = MState.y; 00361 // MLogState.theta = MState.theta; 00362 // MLogState.leftTicks = wheelCountersL; 00363 // MLogState.rightTicks = wheelCountersR; 00364 // MLogState.leftTv = tvl; 00365 // MLogState.rightTv = tvr; 00366 // } 00367 return true; 00368 } 00369 }; 00370 00371 00372 #endif 00373 00374 00375 /* @} */ 00376 00377