UndercarriageCtrlGeom.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *   http://www.apache.org/licenses/LICENSE-2.0
00009 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
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; // special case (?)
00033         return atan2(y,x);
00034     }
00035 }
00036 
00037 double getWeightedDelta(double current_position, double old_target, double new_target){
00038     // current_position =  angles::normalize_angle(current_position); not needed if current Pos is alread normalized
00039 
00040     // Calculate differences between current config to possible set-points
00041     double dtempDeltaPhi1RAD = angles::normalize_angle( new_target - current_position );
00042     double dtempDeltaPhiCmd1RAD = angles::normalize_angle(new_target - old_target);
00043 
00044     // determine optimal setpoint value
00045     // 1st which set point is closest to current cinfog
00046     //     but: avoid permanent switching (if next target is about PI/2 from current config)
00047     // 2nd which set point is closest to last set point
00048     // "fitness criteria" to choose optimal set point:
00049     // calculate accumulted (+ weighted) difference between targets, current config. and last command
00050     return 0.6*fabs(dtempDeltaPhi1RAD) + 0.4*fabs(dtempDeltaPhiCmd1RAD);
00051 }
00052 
00053 void WheelData::updateState(const WheelState &state){
00054     state_ = state;
00055 
00056     // calculate current geometry of robot (exact wheel position, taking into account steering offset of wheels)
00057     m_dExWheelXPosMM = geom_.dWheelXPosMM + geom_.dDistSteerAxisToDriveWheelMM * sin(state_.dAngGearSteerRad);
00058     m_dExWheelYPosMM = geom_.dWheelYPosMM - geom_.dDistSteerAxisToDriveWheelMM * cos(state_.dAngGearSteerRad);
00059 
00060     // calculate distance from platform center to wheel center
00061     m_dExWheelDistMM = sqrt( (m_dExWheelXPosMM * m_dExWheelXPosMM) + (m_dExWheelYPosMM * m_dExWheelYPosMM) );
00062 
00063     // calculate direction of rotational vector
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     // calc Parameters (Dist,Phi) of virtual linking axis of the two considered wheels
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     // transform velocity of wheels into relative coordinate frame of linking axes -> subtract angles
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> &params){
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     // check if zero movement commanded -> keep orientation of wheels, set wheel velocity to zero
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     // calculate velocity and direction of single wheel motion
00114     // Translational Portion
00115     double dtempAxVelXRobMMS = plt_state.dVelLongMMS;
00116     double dtempAxVelYRobMMS = plt_state.dVelLatMMS;
00117     // Rotational Portion
00118     dtempAxVelXRobMMS += plt_state.dRotRobRadS * m_dExWheelDistMM * -sin(m_dExWheelAngRad);
00119     dtempAxVelYRobMMS += plt_state.dRotRobRadS * m_dExWheelDistMM * cos(m_dExWheelAngRad);
00120 
00121     // calculate resulting steering angle
00122     // Wheel has to move in direction of resulting velocity vector of steering axis
00123     double dAngGearSteerTarget1Rad = MathSup::atan4quad(dtempAxVelYRobMMS, dtempAxVelXRobMMS);
00124     // calculate corresponding angle in opposite direction (+180 degree)
00125     double dAngGearSteerTarget2Rad = dAngGearSteerTarget1Rad + MathSup::PI;
00126     MathSup::normalizePi(dAngGearSteerTarget2Rad);
00127 
00128     // calculate absolute value of rotational rate of driving wheels in rad/s
00129     double dVelGearDriveTarget1RadS = sqrt( (dtempAxVelXRobMMS * dtempAxVelXRobMMS) +
00130                                         (dtempAxVelYRobMMS * dtempAxVelYRobMMS) ) / geom_.dRadiusWheelMM;
00131     // now adapt to direction (forward/backward) of wheel
00132     double dVelGearDriveTarget2RadS = -dVelGearDriveTarget1RadS;
00133 
00134 
00135     if(getWeightedDelta(state_.dAngGearSteerRad,  m_dAngGearSteerTargetRad, dAngGearSteerTarget1Rad)
00136         <= getWeightedDelta(state_.dAngGearSteerRad, m_dAngGearSteerTargetRad, dAngGearSteerTarget2Rad))
00137     {
00138         // Target1 is "optimal"
00139         m_dVelGearDriveTargetRadS = dVelGearDriveTarget1RadS;
00140         m_dAngGearSteerTargetRad = dAngGearSteerTarget1Rad;
00141     }
00142     else
00143     {
00144         // Target2 is "optimal"
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     // Normalize Actual Wheel Position before calculation
00173     double dCurrentPosWheelRAD = angles::normalize_angle(state_.dAngGearSteerRad);
00174     command.dAngGearSteerRadDelta = angles::normalize_angle(m_dAngGearSteerTargetRad - dCurrentPosWheelRAD);
00175 
00176     // set outputs
00177     command.dVelGearDriveRadS = limitValue(m_dVelGearDriveTargetRadS + m_dAngGearSteerTargetRad * dFactorVel, params_.dMaxDriveRateRadpS);
00178 
00179     // provisorial --> skip interpolation and always take Target
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         // Impedance-Ctrl
00187         // Calculate resulting desired forces, velocities
00188         // double dForceDamp, dForceProp, dAccCmd, dVelCmdInt;
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         // Store internal ctrlr-states
00199         m_dCtrlVelCmdInt = dVelCmdInt;
00200 
00201         // set outputs
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 }


cob_omni_drive_controller
Author(s): Christian Connette, Mathias Lüdtke
autogenerated on Thu Jun 6 2019 21:19:19