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_undercarriage_ctrl/UndercarriageCtrlGeom.h>
00019 
00020 // Constructor
00021 UndercarriageCtrlGeom::UndercarriageCtrlGeom(std::string sIniDirectory)
00022 {
00023         m_sIniDirectory = sIniDirectory;
00024 
00025         // init EMStop flag
00026         m_bEMStopActive = false;
00027 
00028         IniFile iniFile;
00029         iniFile.SetFileName(m_sIniDirectory + "Platform.ini", "UnderCarriageCtrlGeom.cpp");
00030         iniFile.GetKeyInt("Config", "NumberOfWheels", &m_iNumberOfDrives, true);
00031 
00032         // init vectors
00033         m_vdVelGearDriveRadS.assign(4,0);
00034         m_vdVelGearSteerRadS.assign(4,0);
00035         m_vdDltAngGearDriveRad.assign(4,0);
00036         m_vdAngGearSteerRad.assign(4,0);
00037 
00038         //m_vdVelGearDriveIntpRadS.assign(4,0);
00039         //m_vdVelGearSteerIntpRadS.assign(4,0);
00040         //m_vdAngGearSteerIntpRad.assign(4,0);
00041 
00042         m_vdVelGearDriveCmdRadS.assign(4,0);
00043         m_vdVelGearSteerCmdRadS.assign(4,0);
00044         m_vdAngGearSteerCmdRad.assign(4,0);
00045 
00046         m_vdWheelXPosMM.assign(4,0);
00047         m_vdWheelYPosMM.assign(4,0);
00048         m_vdWheelDistMM.assign(4,0);
00049         m_vdWheelAngRad.assign(4,0);
00050 
00051         m_vdExWheelXPosMM.assign(4,0);
00052         m_vdExWheelYPosMM.assign(4,0);
00053         m_vdExWheelDistMM.assign(4,0);
00054         m_vdExWheelAngRad.assign(4,0);
00055 
00056         m_vdAngGearSteerTarget1Rad.assign(4,0);
00057         m_vdVelGearDriveTarget1RadS.assign(4,0);
00058         m_vdAngGearSteerTarget2Rad.assign(4,0);
00059         m_vdVelGearDriveTarget2RadS.assign(4,0);
00060         m_vdAngGearSteerTargetRad.assign(4,0);
00061         m_vdVelGearDriveTargetRadS.assign(4,0);
00062 
00063         m_dCmdVelLongMMS = 0;
00064         m_dCmdVelLatMMS = 0;
00065         m_dCmdRotRobRadS = 0;
00066         m_dCmdRotVelRadS = 0;
00067 
00068         m_UnderCarriagePrms.WheelNeutralPos.assign(4,0);
00069         m_UnderCarriagePrms.vdSteerDriveCoupling.assign(4,0);
00070         m_UnderCarriagePrms.vdFactorVel.assign(4,0);
00071 
00072         m_vdCtrlVal.assign( 4, std::vector<double> (2,0.0) );
00073 
00074         //m_vdDeltaAngIntpRad.assign(4,0);
00075         //m_vdDeltaDriveIntpRadS.assign(4,0);
00076 
00077         // init Prms of Impedance-Ctrlr
00078         m_dSpring = 10.0;
00079         m_dDamp = 2.5;
00080         m_dVirtM = 0.1;
00081         m_dDPhiMax = 12.0;
00082         m_dDDPhiMax = 100.0;
00083 
00084         /*// Logging for debugging
00085         // Init timestamp for startup of the robot
00086         m_StartTime.SetNow();
00087         // open Files for PltfVel
00088         m_pfileDesVel = fopen("LogCtrl/DesPltfVel.txt","w");
00089         m_pfileMeasVel = fopen("LogCtrl/MeasPltfVel.txt","w");
00090         // open Files for corresponding Joint-Configuration
00091         m_pfileSteerAngTarget1 = fopen("LogCtrl/SteerAngTarget1.txt","w");
00092         m_pfileSteerAngTarget2 = fopen("LogCtrl/SteerAngTarget2.txt","w");
00093         m_pfileSteerAngTarget = fopen("LogCtrl/SteerAngTarget.txt","w");
00094         m_pfileDriveVelTarget = fopen("LogCtrl/DriveVelTarget.txt","w");
00095         // open Files for resulting Joint-Commands
00096         m_pfileSteerAngCmd = fopen("LogCtrl/SteerAngCmd.txt","w");
00097         m_pfileSteerVelCmd = fopen("LogCtrl/SteerVelCmd.txt","w");
00098         m_pfileDriveVelCmd = fopen("LogCtrl/DriveVelCmd.txt","w");*/
00099 
00100 }
00101 
00102 // Destructor
00103 UndercarriageCtrlGeom::~UndercarriageCtrlGeom(void)
00104 {
00105                 /*fclose(m_pfileDesVel);
00106                 fclose(m_pfileMeasVel);
00107 
00108                 fclose(m_pfileSteerAngTarget1);
00109                 fclose(m_pfileSteerAngTarget2);
00110 
00111                 fclose(m_pfileSteerAngTarget);
00112                 fclose(m_pfileDriveVelTarget);
00113 
00114                 fclose(m_pfileSteerAngCmd);
00115                 fclose(m_pfileSteerVelCmd);
00116                 fclose(m_pfileDriveVelCmd);*/
00117 }
00118 
00119 // Initialize Parameters for Controller and Kinematics
00120 void UndercarriageCtrlGeom::InitUndercarriageCtrl(void)
00121 {
00122         //LOG_OUT("Initializing Undercarriage-Controller (Geom)");
00123 
00124         IniFile iniFile;
00125 
00126         iniFile.SetFileName(m_sIniDirectory + "Platform.ini", "UnderCarriageCtrlGeom.cpp");
00127         iniFile.GetKeyInt("Geom", "DistWheels", &m_UnderCarriagePrms.iDistWheels, true);
00128         iniFile.GetKeyInt("Geom", "RadiusWheel", &m_UnderCarriagePrms.iRadiusWheelMM, true);
00129         iniFile.GetKeyInt("Geom", "DistSteerAxisToDriveWheelCenter", &m_UnderCarriagePrms.iDistSteerAxisToDriveWheelMM, true);
00130 
00131         iniFile.GetKeyDouble("Geom", "Wheel1XPos", &m_vdWheelXPosMM[0], true);
00132         iniFile.GetKeyDouble("Geom", "Wheel1YPos", &m_vdWheelYPosMM[0], true);
00133         iniFile.GetKeyDouble("Geom", "Wheel2XPos", &m_vdWheelXPosMM[1], true);
00134         iniFile.GetKeyDouble("Geom", "Wheel2YPos", &m_vdWheelYPosMM[1], true);
00135         iniFile.GetKeyDouble("Geom", "Wheel3XPos", &m_vdWheelXPosMM[2], true);
00136         iniFile.GetKeyDouble("Geom", "Wheel3YPos", &m_vdWheelYPosMM[2], true);
00137         iniFile.GetKeyDouble("Geom", "Wheel4XPos", &m_vdWheelXPosMM[3], true);
00138         iniFile.GetKeyDouble("Geom", "Wheel4YPos", &m_vdWheelYPosMM[3], true);
00139 
00140         iniFile.GetKeyDouble("DrivePrms", "MaxDriveRate", &m_UnderCarriagePrms.dMaxDriveRateRadpS, true);
00141         iniFile.GetKeyDouble("DrivePrms", "MaxSteerRate", &m_UnderCarriagePrms.dMaxSteerRateRadpS, true);
00142 
00143         iniFile.GetKeyDouble("DrivePrms", "Wheel1SteerDriveCoupling", &m_UnderCarriagePrms.vdSteerDriveCoupling[0], true);
00144         iniFile.GetKeyDouble("DrivePrms", "Wheel2SteerDriveCoupling", &m_UnderCarriagePrms.vdSteerDriveCoupling[1], true);
00145         iniFile.GetKeyDouble("DrivePrms", "Wheel3SteerDriveCoupling", &m_UnderCarriagePrms.vdSteerDriveCoupling[2], true);
00146         iniFile.GetKeyDouble("DrivePrms", "Wheel4SteerDriveCoupling", &m_UnderCarriagePrms.vdSteerDriveCoupling[3], true);
00147 
00148         iniFile.GetKeyDouble("DrivePrms", "Wheel1NeutralPosition", &m_UnderCarriagePrms.WheelNeutralPos[0], true);
00149         iniFile.GetKeyDouble("DrivePrms", "Wheel2NeutralPosition", &m_UnderCarriagePrms.WheelNeutralPos[1], true);
00150         iniFile.GetKeyDouble("DrivePrms", "Wheel3NeutralPosition", &m_UnderCarriagePrms.WheelNeutralPos[2], true);
00151         iniFile.GetKeyDouble("DrivePrms", "Wheel4NeutralPosition", &m_UnderCarriagePrms.WheelNeutralPos[3], true);
00152 
00153         for(int i = 0; i<4; i++)
00154         {
00155                 m_UnderCarriagePrms.WheelNeutralPos[i] = MathSup::convDegToRad(m_UnderCarriagePrms.WheelNeutralPos[i]);
00156                 // provisorial --> skip interpolation
00157                 m_vdAngGearSteerCmdRad[i] = m_UnderCarriagePrms.WheelNeutralPos[i];
00158                 //m_vdAngGearSteerIntpRad[i] = m_UnderCarriagePrms.WheelNeutralPos[i];
00159 
00160                 // also Init choosen Target angle
00161                 m_vdAngGearSteerTargetRad[i] = m_UnderCarriagePrms.WheelNeutralPos[i];
00162         }
00163 
00164         iniFile.GetKeyDouble("Thread", "ThrUCarrCycleTimeS", &m_UnderCarriagePrms.dCmdRateS, true);
00165 
00166         // Read Values for Steering Position Controller from IniFile
00167         iniFile.SetFileName(m_sIniDirectory + "MotionCtrl.ini", "PltfHardwareCoB3.h");
00168         // Prms of Impedance-Ctrlr
00169         iniFile.GetKeyDouble("SteerCtrl", "Spring", &m_dSpring, true);
00170         iniFile.GetKeyDouble("SteerCtrl", "Damp", &m_dDamp, true);
00171         iniFile.GetKeyDouble("SteerCtrl", "VirtMass", &m_dVirtM, true);
00172         iniFile.GetKeyDouble("SteerCtrl", "DPhiMax", &m_dDPhiMax, true);
00173         iniFile.GetKeyDouble("SteerCtrl", "DDPhiMax", &m_dDDPhiMax, true);
00174 
00175         // calculate polar coords of Wheel Axis in robot coordinate frame
00176         for(int i=0; i<4; i++)
00177         {
00178                 m_vdWheelDistMM[i] = sqrt( (m_vdWheelXPosMM[i] * m_vdWheelXPosMM[i]) + (m_vdWheelYPosMM[i] * m_vdWheelYPosMM[i]) );
00179                 m_vdWheelAngRad[i] = MathSup::atan4quad(m_vdWheelXPosMM[i], m_vdWheelYPosMM[i]);
00180         }
00181 
00182         // Calculate exact position of wheels in cart. and polar coords in robot coordinate frame
00183         CalcExWheelPos();
00184 
00185         // calculate compensation factor for velocity
00186         for(int i = 0; i<4; i++)
00187         {
00188                 m_UnderCarriagePrms.vdFactorVel[i] = - m_UnderCarriagePrms.vdSteerDriveCoupling[i]
00189                                      +(double(m_UnderCarriagePrms.iDistSteerAxisToDriveWheelMM) / double(m_UnderCarriagePrms.iRadiusWheelMM));
00190         }
00191 
00192 }
00193 
00194 // Set desired value for Plattfrom Velocity to UndercarriageCtrl (Sollwertvorgabe)
00195 void UndercarriageCtrlGeom::SetDesiredPltfVelocity(double dCmdVelLongMMS, double dCmdVelLatMMS, double dCmdRotRobRadS, double dCmdRotVelRadS)
00196 {
00197         // declare auxiliary variables
00198         double dCurrentPosWheelRAD;
00199         double dtempDeltaPhi1RAD, dtempDeltaPhi2RAD;    // difference between possible steering angels and current steering angle
00200         double dtempDeltaPhiCmd1RAD, dtempDeltaPhiCmd2RAD;      // difference between possible steering angels and last target steering angle
00201         double dtempWeightedDelta1RAD, dtempWeightedDelta2RAD; // weighted Summ of the two distance values
00202 
00203         // copy function parameters to member variables
00204         m_dCmdVelLongMMS = dCmdVelLongMMS;
00205         m_dCmdVelLatMMS = dCmdVelLatMMS;
00206         m_dCmdRotRobRadS = dCmdRotRobRadS;
00207         m_dCmdRotVelRadS = dCmdRotVelRadS;
00208 
00209         CalcInverse();
00210 
00211         // determine optimal Pltf-Configuration
00212         for (int i = 0; i<4; i++)
00213         {
00214                 // Normalize Actual Wheel Position before calculation
00215                 dCurrentPosWheelRAD = m_vdAngGearSteerRad[i];
00216                 MathSup::normalizePi(dCurrentPosWheelRAD);
00217 
00218                 // Calculate differences between current config to possible set-points
00219                 dtempDeltaPhi1RAD = m_vdAngGearSteerTarget1Rad[i] - dCurrentPosWheelRAD;
00220                 dtempDeltaPhi2RAD = m_vdAngGearSteerTarget2Rad[i] - dCurrentPosWheelRAD;
00221                 MathSup::normalizePi(dtempDeltaPhi1RAD);
00222                 MathSup::normalizePi(dtempDeltaPhi2RAD);
00223                 // Calculate differences between last steering target to possible set-points
00224                 dtempDeltaPhiCmd1RAD = m_vdAngGearSteerTarget1Rad[i] - m_vdAngGearSteerTargetRad[i];
00225                 dtempDeltaPhiCmd2RAD = m_vdAngGearSteerTarget2Rad[i] - m_vdAngGearSteerTargetRad[i];
00226                 MathSup::normalizePi(dtempDeltaPhiCmd1RAD);
00227                 MathSup::normalizePi(dtempDeltaPhiCmd2RAD);
00228 
00229                 // determine optimal setpoint value
00230                 // 1st which set point is closest to current cinfog
00231                 //     but: avoid permanent switching (if next target is about PI/2 from current config)
00232                 // 2nd which set point is closest to last set point
00233                 // "fitness criteria" to choose optimal set point:
00234                 // calculate accumulted (+ weighted) difference between targets, current config. and last command
00235                 dtempWeightedDelta1RAD = 0.6*fabs(dtempDeltaPhi1RAD) + 0.4*fabs(dtempDeltaPhiCmd1RAD);
00236                 dtempWeightedDelta2RAD = 0.6*fabs(dtempDeltaPhi2RAD) + 0.4*fabs(dtempDeltaPhiCmd2RAD);
00237 
00238                 // check which set point "minimizes fitness criteria"
00239                 if (dtempWeightedDelta1RAD <= dtempWeightedDelta2RAD)
00240                 {
00241                         // Target1 is "optimal"
00242                         m_vdVelGearDriveTargetRadS[i] = m_vdVelGearDriveTarget1RadS[i];
00243                         m_vdAngGearSteerTargetRad[i] = m_vdAngGearSteerTarget1Rad[i];
00244                 }
00245                 else
00246                 {
00247                         // Target2 is "optimal"
00248                         m_vdVelGearDriveTargetRadS[i] = m_vdVelGearDriveTarget2RadS[i];
00249                         m_vdAngGearSteerTargetRad[i] = m_vdAngGearSteerTarget2Rad[i];
00250                 }
00251 
00252                 // provisorial --> skip interpolation and always take Target1
00253                 //m_vdVelGearDriveCmdRadS[i] = m_vdVelGearDriveTarget1RadS[i];
00254                 //m_vdAngGearSteerCmdRad[i] = m_vdAngGearSteerTarget1Rad[i];
00255 
00256                 /*// interpolate between last setpoint and theone of the new setpoint, which is closest to the current configuration
00257                 if (fabs(dtempDeltaPhi1RAD) <= fabs(dtempDeltaPhi2RAD))
00258                 {
00259                         // difference between new target orientation and last (interpolated) target orientation
00260                         dtempDeltaPhi1RAD = m_vdAngGearSteerTarget1Rad[i] - m_vdAngGearSteerIntpRad[i];
00261                         MathSup::normalizePi(dtempDeltaPhi1RAD);
00262 
00263                         // calculate interpolation step sizes, to reach target at end of the cycle
00264                         m_vdDeltaAngIntpRad[i] = dtempDeltaPhi1RAD;
00265                         m_vdDeltaDriveIntpRadS[i] = (m_vdVelGearDriveTarget1RadS[i] - m_vdVelGearDriveIntpRadS[i]);
00266 
00267                         // additionally calculate meen change in angular config for feedforward cmd
00268                         //m_vdVelGearSteerIntpRadS[i] = dtempDeltaPhi1RAD/m_UnderCarriagePrms.dCmdRateS;
00269                 }
00270                 else
00271                 {
00272                         // difference between new target orientation and last (interpolated) target orientation
00273                         dtempDeltaPhi2RAD = m_vdAngGearSteerTarget2Rad[i] - m_vdAngGearSteerIntpRad[i];
00274                         MathSup::normalizePi(dtempDeltaPhi2RAD);
00275 
00276                         // calculate interpolation step sizes, to reach target at end of the cycle
00277                         m_vdDeltaAngIntpRad[i] = dtempDeltaPhi2RAD;
00278                         m_vdDeltaDriveIntpRadS[i] = (m_vdVelGearDriveTarget2RadS[i] - m_vdVelGearDriveIntpRadS[i]);
00279 
00280                         // additionally calculate meen change in angular config for feedforward cmd
00281                         //m_vdVelGearSteerIntpRadS[i] = dtempDeltaPhi2RAD/m_UnderCarriagePrms.dCmdRateS;
00282                 }*/
00283         }
00284 
00285         /*// Logging for debugging
00286         // get current time
00287         m_RawTime.SetNow();
00288         m_dNowTime = m_RawTime - m_StartTime;
00289         // Log out Pltf-Velocities
00290         fprintf(m_pfileDesVel, "%f %f %f %f \n", m_dNowTime, dCmdVelLongMMS, dCmdVelLatMMS, dCmdRotRobRadS);
00291         fprintf(m_pfileMeasVel, "%f %f %f %f \n", m_dNowTime, m_dVelLongMMS, m_dVelLatMMS, m_dRotRobRadS);
00292         // Log out corresponding Joint-Configuration
00293         fprintf(m_pfileSteerAngTarget1, "%f %f %f %f %f \n", m_dNowTime, m_vdAngGearSteerTarget1Rad[0], m_vdAngGearSteerTarget1Rad[1], m_vdAngGearSteerTarget1Rad[2], m_vdAngGearSteerTarget1Rad[3]);
00294         fprintf(m_pfileSteerAngTarget2, "%f %f %f %f %f \n", m_dNowTime, m_vdAngGearSteerTarget2Rad[0], m_vdAngGearSteerTarget2Rad[1], m_vdAngGearSteerTarget2Rad[2], m_vdAngGearSteerTarget2Rad[3]);
00295         fprintf(m_pfileSteerAngTarget, "%f %f %f %f %f \n", m_dNowTime, m_vdAngGearSteerTargetRad[0], m_vdAngGearSteerTargetRad[1], m_vdAngGearSteerTargetRad[2], m_vdAngGearSteerTargetRad[3]);
00296         fprintf(m_pfileDriveVelTarget, "%f %f %f %f %f \n", m_dNowTime, m_vdVelGearDriveTargetRadS[0], m_vdVelGearDriveTargetRadS[1], m_vdVelGearDriveTargetRadS[2], m_vdVelGearDriveTargetRadS[3]);*/
00297 }
00298 
00299 // Set actual values of wheels (steer/drive velocity/position) (Istwerte)
00300 void UndercarriageCtrlGeom::SetActualWheelValues(std::vector<double> vdVelGearDriveRadS, std::vector<double> vdVelGearSteerRadS, std::vector<double> vdDltAngGearDriveRad, std::vector<double> vdAngGearSteerRad)
00301 {
00302         //LOG_OUT("Set Wheel Position to Controller");
00303 
00304         m_vdVelGearDriveRadS = vdVelGearDriveRadS;
00305         m_vdVelGearSteerRadS = vdVelGearSteerRadS;
00306         m_vdDltAngGearDriveRad = vdDltAngGearDriveRad;
00307         m_vdAngGearSteerRad = vdAngGearSteerRad;
00308 
00309         // calc exact Wheel Positions (taking into account lever arm)
00310         CalcExWheelPos();
00311 
00312         // Peform calculation of direct kinematics (approx.) based on corrected Wheel Positions
00313         CalcDirect();
00314 }
00315 
00316 // Get result of inverse kinematics (without controller)
00317 void UndercarriageCtrlGeom::GetSteerDriveSetValues(std::vector<double> & vdVelGearDriveRadS, std::vector<double> & vdAngGearSteerRad)
00318 {
00319         //LOG_OUT("Calculate Inverse for given Velocity Command");
00320 
00321         CalcInverse();
00322 
00323         vdVelGearDriveRadS = m_vdVelGearDriveTarget1RadS;
00324         vdAngGearSteerRad = m_vdAngGearSteerTarget1Rad;
00325 }
00326 
00327 // Get set point values for the Wheels (including controller) from UndercarriangeCtrl
00328 void UndercarriageCtrlGeom::GetNewCtrlStateSteerDriveSetValues(std::vector<double> & vdVelGearDriveRadS, std::vector<double> & vdVelGearSteerRadS, std::vector<double> & vdAngGearSteerRad,
00329                                                                  double & dVelLongMMS, double & dVelLatMMS, double & dRotRobRadS, double & dRotVelRadS)
00330 {
00331 
00332         if(m_bEMStopActive == false)
00333         {
00334                 //Calculate next step
00335                 CalcControlStep();
00336         }
00337 
00338         vdVelGearDriveRadS = m_vdVelGearDriveCmdRadS;
00339         vdVelGearSteerRadS = m_vdVelGearSteerCmdRadS;
00340         vdAngGearSteerRad = m_vdAngGearSteerCmdRad;
00341 
00342         dVelLongMMS = m_dCmdVelLongMMS;
00343         dVelLatMMS = m_dCmdVelLatMMS;
00344         dRotRobRadS = m_dCmdRotRobRadS;
00345         dRotVelRadS = m_dCmdRotVelRadS;
00346 
00347         /*// Logging for debugging
00348         // get current time
00349         m_RawTime.SetNow();
00350         m_dNowTime = m_RawTime - m_StartTime;
00351         // Log out resulting joint-commands
00352         fprintf(m_pfileSteerAngCmd, "%f %f %f %f %f \n", m_dNowTime, m_vdAngGearSteerCmdRad[0], m_vdAngGearSteerCmdRad[1], m_vdAngGearSteerCmdRad[2], m_vdAngGearSteerCmdRad[3]);
00353         fprintf(m_pfileSteerVelCmd, "%f %f %f %f %f \n", m_dNowTime, m_vdVelGearSteerCmdRadS[0], m_vdVelGearSteerCmdRadS[1], m_vdVelGearSteerCmdRadS[2], m_vdVelGearSteerCmdRadS[3]);
00354         fprintf(m_pfileDriveVelCmd, "%f %f %f %f %f \n", m_dNowTime, m_vdVelGearDriveCmdRadS[0], m_vdVelGearDriveCmdRadS[1], m_vdVelGearDriveCmdRadS[2], m_vdVelGearDriveCmdRadS[3]);*/
00355 }
00356 
00357 // Get result of direct kinematics
00358 void UndercarriageCtrlGeom::GetActualPltfVelocity(double & dDeltaLongMM, double & dDeltaLatMM, double & dDeltaRotRobRad, double & dDeltaRotVelRad,
00359                                                                                                   double & dVelLongMMS, double & dVelLatMMS, double & dRotRobRadS, double & dRotVelRadS)
00360 {
00361         dVelLongMMS = m_dVelLongMMS;
00362         dVelLatMMS = m_dVelLatMMS;
00363         dRotRobRadS = m_dRotRobRadS;
00364         dRotVelRadS = m_dRotVelRadS;
00365 
00366         // calculate travelled distance and angle (from velocity) for output
00367         // ToDo: make sure this corresponds to cycle-freqnecy of calling node
00368         //       --> specify via config file
00369         dDeltaLongMM = dVelLongMMS * m_UnderCarriagePrms.dCmdRateS;
00370         dDeltaLatMM = dVelLatMMS * m_UnderCarriagePrms.dCmdRateS;
00371         dDeltaRotRobRad = dRotRobRadS * m_UnderCarriagePrms.dCmdRateS;
00372         dDeltaRotVelRad = dRotVelRadS * m_UnderCarriagePrms.dCmdRateS;
00373 }
00374 
00375 // calculate inverse kinematics
00376 void UndercarriageCtrlGeom::CalcInverse(void)
00377 {
00378         // help variable to store velocities of the steering axis in mm/s
00379         double dtempAxVelXRobMMS, dtempAxVelYRobMMS;
00380 
00381         // check if zero movement commanded -> keep orientation of wheels, set wheel velocity to zero
00382         if((m_dCmdVelLongMMS == 0) && (m_dCmdVelLatMMS == 0) && (m_dCmdRotRobRadS == 0) && (m_dCmdRotVelRadS == 0))
00383         {
00384                 for(int i = 0; i<4; i++)
00385                 {
00386                         m_vdAngGearSteerTarget1Rad[i] = m_vdAngGearSteerRad[i];
00387                         m_vdVelGearDriveTarget1RadS[i] = 0.0;
00388                         m_vdAngGearSteerTarget2Rad[i] = m_vdAngGearSteerRad[i];
00389                         m_vdVelGearDriveTarget2RadS[i] = 0.0;
00390                 }
00391                 return;
00392         }
00393 
00394         // calculate sets of possible Steering Angle // Drive-Velocity combinations
00395         for (int i = 0; i<4; i++)
00396         {
00397                 // calculate velocity and direction of single wheel motion
00398                 // Translational Portion
00399                 dtempAxVelXRobMMS = m_dCmdVelLongMMS;
00400                 dtempAxVelYRobMMS = m_dCmdVelLatMMS;
00401                 // Rotational Portion
00402                 dtempAxVelXRobMMS += m_dCmdRotRobRadS * m_vdExWheelDistMM[i] * -sin(m_vdExWheelAngRad[i]);
00403                 dtempAxVelYRobMMS += m_dCmdRotRobRadS * m_vdExWheelDistMM[i] * cos(m_vdExWheelAngRad[i]);
00404 
00405                 // calculate resulting steering angle
00406                 // Wheel has to move in direction of resulting velocity vector of steering axis
00407                 m_vdAngGearSteerTarget1Rad[i] = MathSup::atan4quad(dtempAxVelYRobMMS, dtempAxVelXRobMMS);
00408                 // calculate corresponding angle in opposite direction (+180 degree)
00409                 m_vdAngGearSteerTarget2Rad[i] = m_vdAngGearSteerTarget1Rad[i] + MathSup::PI;
00410                 MathSup::normalizePi(m_vdAngGearSteerTarget2Rad[i]);
00411 
00412                 // calculate absolute value of rotational rate of driving wheels in rad/s
00413                 m_vdVelGearDriveTarget1RadS[i] = sqrt( (dtempAxVelXRobMMS * dtempAxVelXRobMMS) +
00414                                                    (dtempAxVelYRobMMS * dtempAxVelYRobMMS) ) / (double)m_UnderCarriagePrms.iRadiusWheelMM;
00415                 // now adapt to direction (forward/backward) of wheel
00416                 m_vdVelGearDriveTarget2RadS[i] = - m_vdVelGearDriveTarget1RadS[i];
00417         }
00418 }
00419 
00420 // calculate direct kinematics
00421 void UndercarriageCtrlGeom::CalcDirect(void)
00422 {
00423         // declare auxilliary variables
00424         double dtempVelXRobMMS;         // Robot-Velocity in x-Direction (longitudinal) in mm/s (in Robot-Coordinateframe)
00425         double dtempVelYRobMMS;         // Robot-Velocity in y-Direction (lateral) in mm/s (in Robot-Coordinateframe)
00426         double dtempRotRobRADPS;        // Robot-Rotation-Rate in rad/s (in Robot-Coordinateframe)
00427         double dtempDiffXMM;            // Difference in X-Coordinate of two wheels in mm
00428         double dtempDiffYMM;            // Difference in Y-Coordinate of two wheels in mm
00429         double dtempRelPhiWheelsRAD;    // Angle between axis of two wheels w.r.t the X-Axis of the Robot-Coordinate-System in rad
00430         double dtempRelDistWheelsMM;    // distance of two wheels in mm
00431         double dtempRelPhiWheel1RAD;    // Steering Angle of (im math. pos. direction) first Wheel w.r.t. the linking axis of the two wheels
00432         double dtempRelPhiWheel2RAD;    // Steering Angle of (im math. pos. direction) first Wheel w.r.t. the linking axis of the two wheels
00433         std::vector<double> vdtempVelWheelMMS(4);       // Wheel-Velocities (all Wheels) in mm/s
00434 
00435         // initial values
00436         dtempVelXRobMMS = 0;                    // Robot-Velocity in x-Direction (longitudinal) in mm/s (in Robot-Coordinateframe)
00437         dtempVelYRobMMS = 0;                    // Robot-Velocity in y-Direction (lateral) in mm/s (in Robot-Coordinateframe)
00438         dtempRotRobRADPS = 0;
00439 
00440 
00441 
00442         // calculate corrected wheel velocities
00443         for(int i = 0; i<m_iNumberOfDrives; i++)
00444         {
00445                 // calc effective Driving-Velocity
00446                 vdtempVelWheelMMS[i] = m_UnderCarriagePrms.iRadiusWheelMM * (m_vdVelGearDriveRadS[i] - m_UnderCarriagePrms.vdFactorVel[i]* m_vdVelGearSteerRadS[i]);
00447         }
00448 
00449         // calculate rotational rate of robot and current "virtual" axis between all wheels
00450         for(int i = 0; i< (m_iNumberOfDrives-1) ; i++)
00451         {
00452                 // calc Parameters (Dist,Phi) of virtual linking axis of the two considered wheels
00453                 dtempDiffXMM = m_vdExWheelXPosMM[i+1] - m_vdExWheelXPosMM[i];
00454                 dtempDiffYMM = m_vdExWheelYPosMM[i+1] - m_vdExWheelYPosMM[i];
00455                 dtempRelDistWheelsMM = sqrt( dtempDiffXMM*dtempDiffXMM + dtempDiffYMM*dtempDiffYMM );
00456                 dtempRelPhiWheelsRAD = MathSup::atan4quad( dtempDiffYMM, dtempDiffXMM );
00457 
00458                 // transform velocity of wheels into relative coordinate frame of linking axes -> subtract angles
00459                 dtempRelPhiWheel1RAD = m_vdAngGearSteerRad[i] - dtempRelPhiWheelsRAD;
00460                 dtempRelPhiWheel2RAD = m_vdAngGearSteerRad[i+1] - dtempRelPhiWheelsRAD;
00461 
00462                 dtempRotRobRADPS += (vdtempVelWheelMMS[i+1] * sin(dtempRelPhiWheel2RAD) - vdtempVelWheelMMS[i] * sin(dtempRelPhiWheel1RAD))/dtempRelDistWheelsMM;
00463         }
00464 
00465         // calculate last missing axis (between last wheel and 1.)
00466         // calc. Parameters (Dist,Phi) of virtual linking axis of the two considered wheels
00467         dtempDiffXMM = m_vdExWheelXPosMM[0] - m_vdExWheelXPosMM[m_iNumberOfDrives-1];
00468         dtempDiffYMM = m_vdExWheelYPosMM[0] - m_vdExWheelYPosMM[m_iNumberOfDrives-1];
00469         dtempRelDistWheelsMM = sqrt( dtempDiffXMM*dtempDiffXMM + dtempDiffYMM*dtempDiffYMM );
00470         dtempRelPhiWheelsRAD = MathSup::atan4quad( dtempDiffYMM, dtempDiffXMM );
00471 
00472         // transform velocity of wheels into relative coordinate frame of linking axes -> subtract angles
00473         dtempRelPhiWheel1RAD = m_vdAngGearSteerRad[m_iNumberOfDrives-1] - dtempRelPhiWheelsRAD;
00474         dtempRelPhiWheel2RAD = m_vdAngGearSteerRad[0] - dtempRelPhiWheelsRAD;
00475 
00476         // close calculation of robots rotational velocity
00477         dtempRotRobRADPS += (vdtempVelWheelMMS[0]*sin(dtempRelPhiWheel2RAD) - vdtempVelWheelMMS[m_iNumberOfDrives-1]*sin(dtempRelPhiWheel1RAD))/dtempRelDistWheelsMM;
00478 
00479         // calculate linear velocity of robot
00480         for(int i = 0; i<m_iNumberOfDrives; i++)
00481         {
00482                 dtempVelXRobMMS += vdtempVelWheelMMS[i]*cos(m_vdAngGearSteerRad[i]);
00483                 dtempVelYRobMMS += vdtempVelWheelMMS[i]*sin(m_vdAngGearSteerRad[i]);
00484         }
00485 
00486         // assign rotational velocities for output
00487         m_dRotRobRadS = dtempRotRobRADPS/m_iNumberOfDrives;
00488         m_dRotVelRadS = 0; // currently not used to represent 3rd degree of freedom -> set to zero
00489 
00490         // assign linear velocity of robot for output
00491         m_dVelLongMMS = dtempVelXRobMMS/m_iNumberOfDrives;
00492         m_dVelLatMMS = dtempVelYRobMMS/m_iNumberOfDrives;
00493 
00494 
00495 
00496 }
00497 
00498 // calculate Exact Wheel Position in robot coordinates
00499 void UndercarriageCtrlGeom::CalcExWheelPos(void)
00500 {
00501         // calculate wheel position and velocity
00502         for(int i = 0; i<4; i++)
00503         {
00504                 // calculate current geometry of robot (exact wheel position, taking into account steering offset of wheels)
00505                 m_vdExWheelXPosMM[i] = m_vdWheelXPosMM[i] + m_UnderCarriagePrms.iDistSteerAxisToDriveWheelMM * sin(m_vdAngGearSteerRad[i]);
00506                 m_vdExWheelYPosMM[i] = m_vdWheelYPosMM[i] - m_UnderCarriagePrms.iDistSteerAxisToDriveWheelMM * cos(m_vdAngGearSteerRad[i]);
00507 
00508                 // calculate distance from platform center to wheel center
00509                 m_vdExWheelDistMM[i] = sqrt( (m_vdExWheelXPosMM[i] * m_vdExWheelXPosMM[i]) + (m_vdExWheelYPosMM[i] * m_vdExWheelYPosMM[i]) );
00510 
00511                 // calculate direction of rotational vector
00512                 m_vdExWheelAngRad[i] = MathSup::atan4quad( m_vdExWheelYPosMM[i], m_vdExWheelXPosMM[i]);
00513         }
00514 }
00515 
00516 // perform one discrete Control Step (controls steering angle)
00517 void UndercarriageCtrlGeom::CalcControlStep(void)
00518 {
00519         // check if zero movement commanded -> keep orientation of wheels, set steer velocity to zero
00520         if ((m_dCmdVelLongMMS == 0) && (m_dCmdVelLatMMS == 0) && (m_dCmdRotRobRadS == 0) && (m_dCmdRotVelRadS == 0))
00521         {
00522                 m_vdVelGearDriveCmdRadS.assign(4,0.0);          // set velocity for drives to zero
00523                 m_vdVelGearSteerCmdRadS.assign(4,0.0);          // set velocity for steers to zero
00524 
00525                 // set internal states of controller to zero
00526                 for(int i=0; i<4; i++)
00527                 {
00528                         m_vdCtrlVal[i][0] = 0.0;
00529                         m_vdCtrlVal[i][1] = 0.0;
00530                 }
00531                 return;
00532         }
00533 
00534         // declare auxilliary variables
00535         double dCurrentPosWheelRAD;
00536         double dDeltaPhi;
00537         double dForceDamp, dForceProp, dAccCmd, dVelCmdInt; // PI- and Impedance-Ctrl
00538 
00539         for (int i=0; i<4; i++)
00540         {
00541                 // provisorial --> skip interpolation and always take Target
00542                 m_vdVelGearDriveCmdRadS[i] = m_vdVelGearDriveTargetRadS[i];
00543                 m_vdAngGearSteerCmdRad[i] = m_vdAngGearSteerTargetRad[i];
00544 
00545                 // provisorial --> skip interpolation and always take Target1
00546                 //m_vdVelGearDriveCmdRadS[i] = m_vdVelGearDriveTarget1RadS[i];
00547                 //m_vdAngGearSteerCmdRad[i] = m_vdAngGearSteerTarget1Rad[i];
00548 
00549                 /*m_vdAngGearSteerIntpRad[i] += m_vdDeltaAngIntpRad[i];
00550                 MathSup::normalizePi(m_vdAngGearSteerIntpRad[i]);
00551                 m_vdVelGearDriveIntpRadS[i] += m_vdDeltaDriveIntpRadS[i];
00552 
00553                 m_vdVelGearDriveCmdRadS[i] = m_vdVelGearDriveIntpRadS[i];
00554                 m_vdAngGearSteerCmdRad[i] = m_vdAngGearSteerIntpRad[i];*/
00555         }
00556 
00557 
00558         for (int i = 0; i<4; i++)
00559         {
00560                 // Normalize Actual Wheel Position before calculation
00561                 dCurrentPosWheelRAD = m_vdAngGearSteerRad[i];
00562                 MathSup::normalizePi(dCurrentPosWheelRAD);
00563                 dDeltaPhi = m_vdAngGearSteerCmdRad[i] - dCurrentPosWheelRAD;
00564                 MathSup::normalizePi(dDeltaPhi);
00565 
00566                 // Impedance-Ctrl
00567                 // Calculate resulting desired forces, velocities
00568                 // double dForceDamp, dForceProp, dAccCmd, dVelCmdInt;
00569                 dForceDamp = - m_dDamp * m_vdCtrlVal[i][1];
00570                 dForceProp = m_dSpring * dDeltaPhi;
00571                 dAccCmd = (dForceDamp + dForceProp) / m_dVirtM;
00572                 if (dAccCmd > m_dDDPhiMax)
00573                 {
00574                         dAccCmd = m_dDDPhiMax;
00575                 }
00576                 else if (dAccCmd < -m_dDDPhiMax)
00577                 {
00578                         dAccCmd = -m_dDDPhiMax;
00579                 }
00580                 dVelCmdInt = m_vdCtrlVal[i][1] + m_UnderCarriagePrms.dCmdRateS * dAccCmd;
00581                 if (dVelCmdInt > m_dDPhiMax)
00582                 {
00583                         dVelCmdInt = m_dDPhiMax;
00584                 }
00585                 else if (dVelCmdInt < -m_dDPhiMax)
00586                 {
00587                         dVelCmdInt = -m_dDPhiMax;
00588                 }
00589                 // Store internal ctrlr-states
00590                 m_vdCtrlVal[i][0] = dDeltaPhi;
00591                 m_vdCtrlVal[i][1] = dVelCmdInt;
00592                 // set outputs
00593                 m_vdVelGearSteerCmdRadS[i] = dVelCmdInt;
00594 
00595                 // Check if Steeringvelocity overgo maximum allowed rates.
00596                 if(fabs(m_vdVelGearSteerCmdRadS[i]) > m_UnderCarriagePrms.dMaxSteerRateRadpS)
00597                 {
00598                         if (m_vdVelGearSteerCmdRadS[i] > 0)
00599                                 m_vdVelGearSteerCmdRadS[i] = m_UnderCarriagePrms.dMaxSteerRateRadpS;
00600                         else
00601                                 m_vdVelGearSteerCmdRadS[i] = -m_UnderCarriagePrms.dMaxSteerRateRadpS;
00602                 }
00603         }
00604 
00605         // Correct Driving-Wheel-Velocity, because of coupling and axis-offset
00606         for (int i = 0; i<4; i++)
00607         {
00608                 m_vdVelGearDriveCmdRadS[i] += m_vdVelGearSteerCmdRadS[i] * m_UnderCarriagePrms.vdFactorVel[i];
00609         }
00610 
00611 }
00612 
00613 // operator overloading
00614 void UndercarriageCtrlGeom::operator=(const UndercarriageCtrlGeom & GeomCtrl)
00615 {
00616         // Actual Values for PltfMovement (calculated from Actual Wheelspeeds)
00617         m_dVelLongMMS = GeomCtrl.m_dVelLongMMS;
00618         m_dVelLatMMS = GeomCtrl.m_dVelLatMMS;
00619         m_dRotRobRadS = GeomCtrl.m_dRotRobRadS;
00620         m_dRotVelRadS = GeomCtrl.m_dRotVelRadS;
00621 
00622         // Actual Wheelspeed (read from Motor-Ctrls)
00623         m_vdVelGearDriveRadS = GeomCtrl.m_vdVelGearDriveRadS;
00624         m_vdVelGearSteerRadS = GeomCtrl.m_vdVelGearSteerRadS;
00625         m_vdDltAngGearDriveRad = GeomCtrl.m_vdDltAngGearDriveRad;
00626         m_vdAngGearSteerRad = GeomCtrl.m_vdAngGearSteerRad;
00627 
00628         // Desired Pltf-Movement (set from PltfHwItf)
00629         m_dCmdVelLongMMS = GeomCtrl.m_dCmdVelLongMMS;
00630         m_dCmdVelLatMMS = GeomCtrl.m_dCmdVelLatMMS;
00631         m_dCmdRotRobRadS = GeomCtrl.m_dCmdRotRobRadS;
00632         m_dCmdRotVelRadS = GeomCtrl.m_dCmdRotVelRadS;
00633 
00634         // Desired Wheelspeeds (calculated from desired ICM-configuration)
00635         m_vdVelGearDriveCmdRadS = GeomCtrl.m_vdVelGearDriveCmdRadS;
00636         m_vdVelGearSteerCmdRadS = GeomCtrl.m_vdVelGearSteerCmdRadS;
00637         m_vdAngGearSteerCmdRad = GeomCtrl.m_vdAngGearSteerCmdRad;
00638 
00639         // Target Wheelspeed and -angle (calculated from desired Pltf-Movement with Inverse without controle!)
00640         // alternativ 1 for steering angle
00641         m_vdAngGearSteerTarget1Rad = GeomCtrl.m_vdAngGearSteerTarget1Rad;
00642         m_vdVelGearDriveTarget1RadS = GeomCtrl.m_vdVelGearDriveTarget1RadS;
00643         // alternativ 2 for steering angle (+/- PI)
00644         m_vdAngGearSteerTarget2Rad = GeomCtrl.m_vdAngGearSteerTarget2Rad;
00645         m_vdVelGearDriveTarget2RadS = GeomCtrl.m_vdVelGearDriveTarget2RadS;
00646 
00647         // Position of the Wheels' Steering Axis'
00648         m_vdWheelXPosMM = GeomCtrl.m_vdWheelXPosMM;
00649         m_vdWheelYPosMM = GeomCtrl.m_vdWheelYPosMM;
00650         m_vdWheelDistMM = GeomCtrl.m_vdWheelDistMM;
00651         m_vdWheelAngRad = GeomCtrl.m_vdWheelAngRad;
00652 
00653         // Exact Position of the Wheels' itself
00654         m_vdExWheelXPosMM = GeomCtrl.m_vdExWheelXPosMM;
00655         m_vdExWheelYPosMM = GeomCtrl.m_vdExWheelYPosMM;
00656         m_vdExWheelDistMM = GeomCtrl.m_vdExWheelDistMM;
00657         m_vdExWheelAngRad = GeomCtrl.m_vdExWheelAngRad;
00658 
00659         // Prms
00660         m_UnderCarriagePrms = GeomCtrl.m_UnderCarriagePrms;
00661 
00662         // Position Controller Steer Wheels
00663         // Impedance-Ctrlr
00664         m_dSpring = GeomCtrl.m_dSpring;
00665         m_dDamp = GeomCtrl.m_dDamp;
00666         m_dVirtM = GeomCtrl.m_dDPhiMax;
00667         m_dDPhiMax = GeomCtrl.m_dDPhiMax;
00668         m_dDDPhiMax = GeomCtrl.m_dDDPhiMax;
00669         // Storage for internal controller states
00670         m_vdCtrlVal = GeomCtrl.m_vdCtrlVal;
00671 }
00672 
00673 // set EM Flag and stop ctrlr if active
00674 void UndercarriageCtrlGeom::setEMStopActive(bool bEMStopActive)
00675 {
00676         m_bEMStopActive = bEMStopActive;
00677 
00678         // if emergency stop reset ctrlr to zero
00679         if(m_bEMStopActive)
00680         {
00681                 // Steermodules
00682                 for(int i=0; i<4; i++)
00683                 {
00684                         for(int j=0; j< 2; j++)
00685                         {
00686                                 m_vdCtrlVal[i][j] = 0.0;
00687                         }
00688                 }
00689                 // Outputs
00690                 for(int i=0; i<4; i++)
00691                 {
00692                         m_vdVelGearDriveCmdRadS[i] = 0.0;
00693                         m_vdVelGearSteerCmdRadS[i] = 0.0;
00694                 }
00695         }
00696 
00697 }


cob_undercarriage_ctrl
Author(s): Christian Connette
autogenerated on Sat Jun 8 2019 21:02:32