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 #include <cob_omni_drive_controller/UndercarriageCtrlGeom.h>
00019
00020 #include <math.h>
00021 #include <angles/angles.h>
00022 #include <stdexcept>
00023 #include <boost/shared_ptr.hpp>
00024
00025
00026 namespace MathSup {
00027 const double PI = 3.14159265358979323846;
00028 void normalizePi(double &val) { val = angles::normalize_angle(val); }
00029
00030 double atan4quad(double y, double x)
00031 {
00032 if((x==0.0) && (y==0.0)) return 0;
00033 return atan2(y,x);
00034 }
00035 }
00036
00037 double getWeightedDelta(double current_position, double old_target, double new_target){
00038
00039
00040
00041 double dtempDeltaPhi1RAD = angles::normalize_angle( new_target - current_position );
00042 double dtempDeltaPhiCmd1RAD = angles::normalize_angle(new_target - old_target);
00043
00044
00045
00046
00047
00048
00049
00050 return 0.6*fabs(dtempDeltaPhi1RAD) + 0.4*fabs(dtempDeltaPhiCmd1RAD);
00051 }
00052
00053 void WheelData::updateState(const WheelState &state){
00054 state_ = state;
00055
00056
00057 m_dExWheelXPosMM = geom_.dWheelXPosMM + geom_.dDistSteerAxisToDriveWheelMM * sin(state_.dAngGearSteerRad);
00058 m_dExWheelYPosMM = geom_.dWheelYPosMM - geom_.dDistSteerAxisToDriveWheelMM * cos(state_.dAngGearSteerRad);
00059
00060
00061 m_dExWheelDistMM = sqrt( (m_dExWheelXPosMM * m_dExWheelXPosMM) + (m_dExWheelYPosMM * m_dExWheelYPosMM) );
00062
00063
00064 m_dExWheelAngRad = MathSup::atan4quad( m_dExWheelYPosMM, m_dExWheelXPosMM);
00065
00066 m_dVelWheelMMS = geom_.dRadiusWheelMM * (state_.dVelGearDriveRadS - dFactorVel* state_.dVelGearSteerRadS);
00067 }
00068
00069 double WheelData::mergeRotRobRadS(const WheelData &wheel1, const WheelData &wheel2){
00070
00071 double dtempDiffXMM = wheel2.m_dExWheelXPosMM - wheel1.m_dExWheelXPosMM;
00072 double dtempDiffYMM = wheel2.m_dExWheelYPosMM - wheel1.m_dExWheelYPosMM;
00073
00074 double dtempRelDistWheelsMM = sqrt( dtempDiffXMM*dtempDiffXMM + dtempDiffYMM*dtempDiffYMM );
00075 double dtempRelPhiWheelsRAD = MathSup::atan4quad( dtempDiffYMM, dtempDiffXMM );
00076
00077
00078 double dtempRelPhiWheel1RAD = wheel1.state_.dAngGearSteerRad - dtempRelPhiWheelsRAD;
00079 double dtempRelPhiWheel2RAD = wheel2.state_.dAngGearSteerRad - dtempRelPhiWheelsRAD;
00080
00081 return (wheel2.m_dVelWheelMMS * sin(dtempRelPhiWheel2RAD) - wheel1.m_dVelWheelMMS * sin(dtempRelPhiWheel1RAD))/dtempRelDistWheelsMM;
00082 }
00083
00084 double WheelData::getVelX() const {
00085 return m_dVelWheelMMS*cos(state_.dAngGearSteerRad);
00086 }
00087 double WheelData::getVelY() const {
00088 return m_dVelWheelMMS*sin(state_.dAngGearSteerRad);
00089 }
00090 UndercarriageGeom::UndercarriageGeom(const std::vector<WheelParams> ¶ms){
00091 for(std::vector<WheelParams>::const_iterator it = params.begin(); it != params.end(); ++it){
00092 wheels_.push_back(boost::make_shared<WheelData>(it->geom));
00093 }
00094 }
00095
00096 void UndercarriageGeom::calcDirect(PlatformState &state) const{
00097 UndercarriageGeomBase::calcDirect(state, wheels_);
00098 }
00099
00100 void UndercarriageGeom::updateWheelStates(const std::vector<WheelState> &states){
00101 UndercarriageGeomBase::updateWheelStates(wheels_, states);
00102 }
00103
00104 void CtrlData::setTarget(const PlatformState &plt_state){
00105
00106 if((plt_state.dVelLongMMS == 0) && (plt_state.dVelLatMMS == 0) && (plt_state.dRotRobRadS == 0))
00107 {
00108 m_dVelGearDriveTargetRadS = 0.0;
00109 m_dAngGearSteerTargetRad = state_.dAngGearSteerRad;
00110 return;
00111 }
00112
00113
00114
00115 double dtempAxVelXRobMMS = plt_state.dVelLongMMS;
00116 double dtempAxVelYRobMMS = plt_state.dVelLatMMS;
00117
00118 dtempAxVelXRobMMS += plt_state.dRotRobRadS * m_dExWheelDistMM * -sin(m_dExWheelAngRad);
00119 dtempAxVelYRobMMS += plt_state.dRotRobRadS * m_dExWheelDistMM * cos(m_dExWheelAngRad);
00120
00121
00122
00123 double dAngGearSteerTarget1Rad = MathSup::atan4quad(dtempAxVelYRobMMS, dtempAxVelXRobMMS);
00124
00125 double dAngGearSteerTarget2Rad = dAngGearSteerTarget1Rad + MathSup::PI;
00126 MathSup::normalizePi(dAngGearSteerTarget2Rad);
00127
00128
00129 double dVelGearDriveTarget1RadS = sqrt( (dtempAxVelXRobMMS * dtempAxVelXRobMMS) +
00130 (dtempAxVelYRobMMS * dtempAxVelYRobMMS) ) / geom_.dRadiusWheelMM;
00131
00132 double dVelGearDriveTarget2RadS = -dVelGearDriveTarget1RadS;
00133
00134
00135 if(getWeightedDelta(state_.dAngGearSteerRad, m_dAngGearSteerTargetRad, dAngGearSteerTarget1Rad)
00136 <= getWeightedDelta(state_.dAngGearSteerRad, m_dAngGearSteerTargetRad, dAngGearSteerTarget2Rad))
00137 {
00138
00139 m_dVelGearDriveTargetRadS = dVelGearDriveTarget1RadS;
00140 m_dAngGearSteerTargetRad = dAngGearSteerTarget1Rad;
00141 }
00142 else
00143 {
00144
00145 m_dVelGearDriveTargetRadS = dVelGearDriveTarget2RadS;
00146 m_dAngGearSteerTargetRad = dAngGearSteerTarget2Rad;
00147 }
00148
00149 }
00150
00151 double limitValue(double value, double limit){
00152 if(limit != 0){
00153 if (value > limit){
00154 value = limit;
00155 } else if (value < -limit) {
00156 value = -limit;
00157 }
00158 }
00159 return value;
00160 }
00161
00162 void CtrlData::calcControlStep(WheelCommand &command, double dCmdRateS, bool reset){
00163 if(reset){
00164 this->reset();
00165 command.dVelGearDriveRadS = 0.0;
00166 command.dVelGearSteerRadS = 0.0;
00167 command.dAngGearSteerRad = state_.dAngGearSteerRad;
00168 command.dAngGearSteerRadDelta = 0.0;
00169 return;
00170 }
00171
00172
00173 double dCurrentPosWheelRAD = angles::normalize_angle(state_.dAngGearSteerRad);
00174 command.dAngGearSteerRadDelta = angles::normalize_angle(m_dAngGearSteerTargetRad - dCurrentPosWheelRAD);
00175
00176
00177 command.dVelGearDriveRadS = limitValue(m_dVelGearDriveTargetRadS + m_dAngGearSteerTargetRad * dFactorVel, params_.dMaxDriveRateRadpS);
00178
00179
00180 command.dAngGearSteerRad = m_dAngGearSteerTargetRad;
00181 }
00182
00183 void PosCtrlData::calcControlStep(WheelCommand &command, double dCmdRateS, bool reset){
00184 CtrlData::calcControlStep(command, dCmdRateS, reset);
00185 if(!reset){
00186
00187
00188
00189 double dForceDamp = - pos_params_.dDamp *m_dCtrlVelCmdInt;
00190 double dForceProp = pos_params_.dSpring * command.dAngGearSteerRadDelta;
00191
00192 double dAccCmd = (dForceDamp + dForceProp) / pos_params_.dVirtM;
00193 dAccCmd = limitValue(dAccCmd, pos_params_.dDDPhiMax);
00194
00195 double dVelCmdInt =m_dCtrlVelCmdInt + dCmdRateS * dAccCmd;
00196 dVelCmdInt = limitValue(dVelCmdInt, pos_params_.dDPhiMax);
00197
00198
00199 m_dCtrlVelCmdInt = dVelCmdInt;
00200
00201
00202 command.dVelGearSteerRadS = limitValue(dVelCmdInt, params_.dMaxSteerRateRadpS);
00203 }
00204 }
00205 void CtrlData::reset(){
00206 }
00207 void PosCtrlData::reset(){
00208 m_dCtrlVelCmdInt = 0.0;
00209 }
00210
00211 void UndercarriageCtrl::configure(const std::vector<PosCtrlParams> &pos_ctrls){
00212 assert(wheels_.size() == pos_ctrls.size());
00213 for(size_t i = 0; i < wheels_.size(); ++i){
00214 wheels_[i]->pos_params_ = pos_ctrls[i];
00215 }
00216 }