UndercarriageCtrlGeom.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
19 
20 // Constructor
22 {
23  m_sIniDirectory = sIniDirectory;
24 
25  // init EMStop flag
26  m_bEMStopActive = false;
27 
28  IniFile iniFile;
29  iniFile.SetFileName(m_sIniDirectory + "Platform.ini", "UnderCarriageCtrlGeom.cpp");
30  iniFile.GetKeyInt("Config", "NumberOfWheels", &m_iNumberOfDrives, true);
31 
32  // init vectors
33  m_vdVelGearDriveRadS.assign(4,0);
34  m_vdVelGearSteerRadS.assign(4,0);
35  m_vdDltAngGearDriveRad.assign(4,0);
36  m_vdAngGearSteerRad.assign(4,0);
37 
38  //m_vdVelGearDriveIntpRadS.assign(4,0);
39  //m_vdVelGearSteerIntpRadS.assign(4,0);
40  //m_vdAngGearSteerIntpRad.assign(4,0);
41 
42  m_vdVelGearDriveCmdRadS.assign(4,0);
43  m_vdVelGearSteerCmdRadS.assign(4,0);
44  m_vdAngGearSteerCmdRad.assign(4,0);
45 
46  m_vdWheelXPosMM.assign(4,0);
47  m_vdWheelYPosMM.assign(4,0);
48  m_vdWheelDistMM.assign(4,0);
49  m_vdWheelAngRad.assign(4,0);
50 
51  m_vdExWheelXPosMM.assign(4,0);
52  m_vdExWheelYPosMM.assign(4,0);
53  m_vdExWheelDistMM.assign(4,0);
54  m_vdExWheelAngRad.assign(4,0);
55 
56  m_vdAngGearSteerTarget1Rad.assign(4,0);
57  m_vdVelGearDriveTarget1RadS.assign(4,0);
58  m_vdAngGearSteerTarget2Rad.assign(4,0);
59  m_vdVelGearDriveTarget2RadS.assign(4,0);
60  m_vdAngGearSteerTargetRad.assign(4,0);
61  m_vdVelGearDriveTargetRadS.assign(4,0);
62 
63  m_dCmdVelLongMMS = 0;
64  m_dCmdVelLatMMS = 0;
65  m_dCmdRotRobRadS = 0;
66  m_dCmdRotVelRadS = 0;
67 
70  m_UnderCarriagePrms.vdFactorVel.assign(4,0);
71 
72  m_vdCtrlVal.assign( 4, std::vector<double> (2,0.0) );
73 
74  //m_vdDeltaAngIntpRad.assign(4,0);
75  //m_vdDeltaDriveIntpRadS.assign(4,0);
76 
77  // init Prms of Impedance-Ctrlr
78  m_dSpring = 10.0;
79  m_dDamp = 2.5;
80  m_dVirtM = 0.1;
81  m_dDPhiMax = 12.0;
82  m_dDDPhiMax = 100.0;
83 
84  /*// Logging for debugging
85  // Init timestamp for startup of the robot
86  m_StartTime.SetNow();
87  // open Files for PltfVel
88  m_pfileDesVel = fopen("LogCtrl/DesPltfVel.txt","w");
89  m_pfileMeasVel = fopen("LogCtrl/MeasPltfVel.txt","w");
90  // open Files for corresponding Joint-Configuration
91  m_pfileSteerAngTarget1 = fopen("LogCtrl/SteerAngTarget1.txt","w");
92  m_pfileSteerAngTarget2 = fopen("LogCtrl/SteerAngTarget2.txt","w");
93  m_pfileSteerAngTarget = fopen("LogCtrl/SteerAngTarget.txt","w");
94  m_pfileDriveVelTarget = fopen("LogCtrl/DriveVelTarget.txt","w");
95  // open Files for resulting Joint-Commands
96  m_pfileSteerAngCmd = fopen("LogCtrl/SteerAngCmd.txt","w");
97  m_pfileSteerVelCmd = fopen("LogCtrl/SteerVelCmd.txt","w");
98  m_pfileDriveVelCmd = fopen("LogCtrl/DriveVelCmd.txt","w");*/
99 
100 }
101 
102 // Destructor
104 {
105  /*fclose(m_pfileDesVel);
106  fclose(m_pfileMeasVel);
107 
108  fclose(m_pfileSteerAngTarget1);
109  fclose(m_pfileSteerAngTarget2);
110 
111  fclose(m_pfileSteerAngTarget);
112  fclose(m_pfileDriveVelTarget);
113 
114  fclose(m_pfileSteerAngCmd);
115  fclose(m_pfileSteerVelCmd);
116  fclose(m_pfileDriveVelCmd);*/
117 }
118 
119 // Initialize Parameters for Controller and Kinematics
121 {
122  //LOG_OUT("Initializing Undercarriage-Controller (Geom)");
123 
124  IniFile iniFile;
125 
126  iniFile.SetFileName(m_sIniDirectory + "Platform.ini", "UnderCarriageCtrlGeom.cpp");
127  iniFile.GetKeyInt("Geom", "DistWheels", &m_UnderCarriagePrms.iDistWheels, true);
128  iniFile.GetKeyInt("Geom", "RadiusWheel", &m_UnderCarriagePrms.iRadiusWheelMM, true);
129  iniFile.GetKeyInt("Geom", "DistSteerAxisToDriveWheelCenter", &m_UnderCarriagePrms.iDistSteerAxisToDriveWheelMM, true);
130 
131  iniFile.GetKeyDouble("Geom", "Wheel1XPos", &m_vdWheelXPosMM[0], true);
132  iniFile.GetKeyDouble("Geom", "Wheel1YPos", &m_vdWheelYPosMM[0], true);
133  iniFile.GetKeyDouble("Geom", "Wheel2XPos", &m_vdWheelXPosMM[1], true);
134  iniFile.GetKeyDouble("Geom", "Wheel2YPos", &m_vdWheelYPosMM[1], true);
135  iniFile.GetKeyDouble("Geom", "Wheel3XPos", &m_vdWheelXPosMM[2], true);
136  iniFile.GetKeyDouble("Geom", "Wheel3YPos", &m_vdWheelYPosMM[2], true);
137  iniFile.GetKeyDouble("Geom", "Wheel4XPos", &m_vdWheelXPosMM[3], true);
138  iniFile.GetKeyDouble("Geom", "Wheel4YPos", &m_vdWheelYPosMM[3], true);
139 
140  iniFile.GetKeyDouble("DrivePrms", "MaxDriveRate", &m_UnderCarriagePrms.dMaxDriveRateRadpS, true);
141  iniFile.GetKeyDouble("DrivePrms", "MaxSteerRate", &m_UnderCarriagePrms.dMaxSteerRateRadpS, true);
142 
143  iniFile.GetKeyDouble("DrivePrms", "Wheel1SteerDriveCoupling", &m_UnderCarriagePrms.vdSteerDriveCoupling[0], true);
144  iniFile.GetKeyDouble("DrivePrms", "Wheel2SteerDriveCoupling", &m_UnderCarriagePrms.vdSteerDriveCoupling[1], true);
145  iniFile.GetKeyDouble("DrivePrms", "Wheel3SteerDriveCoupling", &m_UnderCarriagePrms.vdSteerDriveCoupling[2], true);
146  iniFile.GetKeyDouble("DrivePrms", "Wheel4SteerDriveCoupling", &m_UnderCarriagePrms.vdSteerDriveCoupling[3], true);
147 
148  iniFile.GetKeyDouble("DrivePrms", "Wheel1NeutralPosition", &m_UnderCarriagePrms.WheelNeutralPos[0], true);
149  iniFile.GetKeyDouble("DrivePrms", "Wheel2NeutralPosition", &m_UnderCarriagePrms.WheelNeutralPos[1], true);
150  iniFile.GetKeyDouble("DrivePrms", "Wheel3NeutralPosition", &m_UnderCarriagePrms.WheelNeutralPos[2], true);
151  iniFile.GetKeyDouble("DrivePrms", "Wheel4NeutralPosition", &m_UnderCarriagePrms.WheelNeutralPos[3], true);
152 
153  for(int i = 0; i<4; i++)
154  {
156  // provisorial --> skip interpolation
158  //m_vdAngGearSteerIntpRad[i] = m_UnderCarriagePrms.WheelNeutralPos[i];
159 
160  // also Init choosen Target angle
162  }
163 
164  iniFile.GetKeyDouble("Thread", "ThrUCarrCycleTimeS", &m_UnderCarriagePrms.dCmdRateS, true);
165 
166  // Read Values for Steering Position Controller from IniFile
167  iniFile.SetFileName(m_sIniDirectory + "MotionCtrl.ini", "PltfHardwareCoB3.h");
168  // Prms of Impedance-Ctrlr
169  iniFile.GetKeyDouble("SteerCtrl", "Spring", &m_dSpring, true);
170  iniFile.GetKeyDouble("SteerCtrl", "Damp", &m_dDamp, true);
171  iniFile.GetKeyDouble("SteerCtrl", "VirtMass", &m_dVirtM, true);
172  iniFile.GetKeyDouble("SteerCtrl", "DPhiMax", &m_dDPhiMax, true);
173  iniFile.GetKeyDouble("SteerCtrl", "DDPhiMax", &m_dDDPhiMax, true);
174 
175  // calculate polar coords of Wheel Axis in robot coordinate frame
176  for(int i=0; i<4; i++)
177  {
180  }
181 
182  // Calculate exact position of wheels in cart. and polar coords in robot coordinate frame
183  CalcExWheelPos();
184 
185  // calculate compensation factor for velocity
186  for(int i = 0; i<4; i++)
187  {
190  }
191 
192 }
193 
194 // Set desired value for Plattfrom Velocity to UndercarriageCtrl (Sollwertvorgabe)
195 void UndercarriageCtrlGeom::SetDesiredPltfVelocity(double dCmdVelLongMMS, double dCmdVelLatMMS, double dCmdRotRobRadS, double dCmdRotVelRadS)
196 {
197  // declare auxiliary variables
198  double dCurrentPosWheelRAD;
199  double dtempDeltaPhi1RAD, dtempDeltaPhi2RAD; // difference between possible steering angels and current steering angle
200  double dtempDeltaPhiCmd1RAD, dtempDeltaPhiCmd2RAD; // difference between possible steering angels and last target steering angle
201  double dtempWeightedDelta1RAD, dtempWeightedDelta2RAD; // weighted Summ of the two distance values
202 
203  // copy function parameters to member variables
204  m_dCmdVelLongMMS = dCmdVelLongMMS;
205  m_dCmdVelLatMMS = dCmdVelLatMMS;
206  m_dCmdRotRobRadS = dCmdRotRobRadS;
207  m_dCmdRotVelRadS = dCmdRotVelRadS;
208 
209  CalcInverse();
210 
211  // determine optimal Pltf-Configuration
212  for (int i = 0; i<4; i++)
213  {
214  // Normalize Actual Wheel Position before calculation
215  dCurrentPosWheelRAD = m_vdAngGearSteerRad[i];
216  MathSup::normalizePi(dCurrentPosWheelRAD);
217 
218  // Calculate differences between current config to possible set-points
219  dtempDeltaPhi1RAD = m_vdAngGearSteerTarget1Rad[i] - dCurrentPosWheelRAD;
220  dtempDeltaPhi2RAD = m_vdAngGearSteerTarget2Rad[i] - dCurrentPosWheelRAD;
221  MathSup::normalizePi(dtempDeltaPhi1RAD);
222  MathSup::normalizePi(dtempDeltaPhi2RAD);
223  // Calculate differences between last steering target to possible set-points
224  dtempDeltaPhiCmd1RAD = m_vdAngGearSteerTarget1Rad[i] - m_vdAngGearSteerTargetRad[i];
225  dtempDeltaPhiCmd2RAD = m_vdAngGearSteerTarget2Rad[i] - m_vdAngGearSteerTargetRad[i];
226  MathSup::normalizePi(dtempDeltaPhiCmd1RAD);
227  MathSup::normalizePi(dtempDeltaPhiCmd2RAD);
228 
229  // determine optimal setpoint value
230  // 1st which set point is closest to current cinfog
231  // but: avoid permanent switching (if next target is about PI/2 from current config)
232  // 2nd which set point is closest to last set point
233  // "fitness criteria" to choose optimal set point:
234  // calculate accumulted (+ weighted) difference between targets, current config. and last command
235  dtempWeightedDelta1RAD = 0.6*fabs(dtempDeltaPhi1RAD) + 0.4*fabs(dtempDeltaPhiCmd1RAD);
236  dtempWeightedDelta2RAD = 0.6*fabs(dtempDeltaPhi2RAD) + 0.4*fabs(dtempDeltaPhiCmd2RAD);
237 
238  // check which set point "minimizes fitness criteria"
239  if (dtempWeightedDelta1RAD <= dtempWeightedDelta2RAD)
240  {
241  // Target1 is "optimal"
243  m_vdAngGearSteerTargetRad[i] = m_vdAngGearSteerTarget1Rad[i];
244  }
245  else
246  {
247  // Target2 is "optimal"
249  m_vdAngGearSteerTargetRad[i] = m_vdAngGearSteerTarget2Rad[i];
250  }
251 
252  // provisorial --> skip interpolation and always take Target1
253  //m_vdVelGearDriveCmdRadS[i] = m_vdVelGearDriveTarget1RadS[i];
254  //m_vdAngGearSteerCmdRad[i] = m_vdAngGearSteerTarget1Rad[i];
255 
256  /*// interpolate between last setpoint and theone of the new setpoint, which is closest to the current configuration
257  if (fabs(dtempDeltaPhi1RAD) <= fabs(dtempDeltaPhi2RAD))
258  {
259  // difference between new target orientation and last (interpolated) target orientation
260  dtempDeltaPhi1RAD = m_vdAngGearSteerTarget1Rad[i] - m_vdAngGearSteerIntpRad[i];
261  MathSup::normalizePi(dtempDeltaPhi1RAD);
262 
263  // calculate interpolation step sizes, to reach target at end of the cycle
264  m_vdDeltaAngIntpRad[i] = dtempDeltaPhi1RAD;
265  m_vdDeltaDriveIntpRadS[i] = (m_vdVelGearDriveTarget1RadS[i] - m_vdVelGearDriveIntpRadS[i]);
266 
267  // additionally calculate meen change in angular config for feedforward cmd
268  //m_vdVelGearSteerIntpRadS[i] = dtempDeltaPhi1RAD/m_UnderCarriagePrms.dCmdRateS;
269  }
270  else
271  {
272  // difference between new target orientation and last (interpolated) target orientation
273  dtempDeltaPhi2RAD = m_vdAngGearSteerTarget2Rad[i] - m_vdAngGearSteerIntpRad[i];
274  MathSup::normalizePi(dtempDeltaPhi2RAD);
275 
276  // calculate interpolation step sizes, to reach target at end of the cycle
277  m_vdDeltaAngIntpRad[i] = dtempDeltaPhi2RAD;
278  m_vdDeltaDriveIntpRadS[i] = (m_vdVelGearDriveTarget2RadS[i] - m_vdVelGearDriveIntpRadS[i]);
279 
280  // additionally calculate meen change in angular config for feedforward cmd
281  //m_vdVelGearSteerIntpRadS[i] = dtempDeltaPhi2RAD/m_UnderCarriagePrms.dCmdRateS;
282  }*/
283  }
284 
285  /*// Logging for debugging
286  // get current time
287  m_RawTime.SetNow();
288  m_dNowTime = m_RawTime - m_StartTime;
289  // Log out Pltf-Velocities
290  fprintf(m_pfileDesVel, "%f %f %f %f \n", m_dNowTime, dCmdVelLongMMS, dCmdVelLatMMS, dCmdRotRobRadS);
291  fprintf(m_pfileMeasVel, "%f %f %f %f \n", m_dNowTime, m_dVelLongMMS, m_dVelLatMMS, m_dRotRobRadS);
292  // Log out corresponding Joint-Configuration
293  fprintf(m_pfileSteerAngTarget1, "%f %f %f %f %f \n", m_dNowTime, m_vdAngGearSteerTarget1Rad[0], m_vdAngGearSteerTarget1Rad[1], m_vdAngGearSteerTarget1Rad[2], m_vdAngGearSteerTarget1Rad[3]);
294  fprintf(m_pfileSteerAngTarget2, "%f %f %f %f %f \n", m_dNowTime, m_vdAngGearSteerTarget2Rad[0], m_vdAngGearSteerTarget2Rad[1], m_vdAngGearSteerTarget2Rad[2], m_vdAngGearSteerTarget2Rad[3]);
295  fprintf(m_pfileSteerAngTarget, "%f %f %f %f %f \n", m_dNowTime, m_vdAngGearSteerTargetRad[0], m_vdAngGearSteerTargetRad[1], m_vdAngGearSteerTargetRad[2], m_vdAngGearSteerTargetRad[3]);
296  fprintf(m_pfileDriveVelTarget, "%f %f %f %f %f \n", m_dNowTime, m_vdVelGearDriveTargetRadS[0], m_vdVelGearDriveTargetRadS[1], m_vdVelGearDriveTargetRadS[2], m_vdVelGearDriveTargetRadS[3]);*/
297 }
298 
299 // Set actual values of wheels (steer/drive velocity/position) (Istwerte)
300 void UndercarriageCtrlGeom::SetActualWheelValues(std::vector<double> vdVelGearDriveRadS, std::vector<double> vdVelGearSteerRadS, std::vector<double> vdDltAngGearDriveRad, std::vector<double> vdAngGearSteerRad)
301 {
302  //LOG_OUT("Set Wheel Position to Controller");
303 
304  m_vdVelGearDriveRadS = vdVelGearDriveRadS;
305  m_vdVelGearSteerRadS = vdVelGearSteerRadS;
306  m_vdDltAngGearDriveRad = vdDltAngGearDriveRad;
307  m_vdAngGearSteerRad = vdAngGearSteerRad;
308 
309  // calc exact Wheel Positions (taking into account lever arm)
310  CalcExWheelPos();
311 
312  // Peform calculation of direct kinematics (approx.) based on corrected Wheel Positions
313  CalcDirect();
314 }
315 
316 // Get result of inverse kinematics (without controller)
317 void UndercarriageCtrlGeom::GetSteerDriveSetValues(std::vector<double> & vdVelGearDriveRadS, std::vector<double> & vdAngGearSteerRad)
318 {
319  //LOG_OUT("Calculate Inverse for given Velocity Command");
320 
321  CalcInverse();
322 
323  vdVelGearDriveRadS = m_vdVelGearDriveTarget1RadS;
324  vdAngGearSteerRad = m_vdAngGearSteerTarget1Rad;
325 }
326 
327 // Get set point values for the Wheels (including controller) from UndercarriangeCtrl
328 void UndercarriageCtrlGeom::GetNewCtrlStateSteerDriveSetValues(std::vector<double> & vdVelGearDriveRadS, std::vector<double> & vdVelGearSteerRadS, std::vector<double> & vdAngGearSteerRad,
329  double & dVelLongMMS, double & dVelLatMMS, double & dRotRobRadS, double & dRotVelRadS)
330 {
331 
332  if(m_bEMStopActive == false)
333  {
334  //Calculate next step
335  CalcControlStep();
336  }
337 
338  vdVelGearDriveRadS = m_vdVelGearDriveCmdRadS;
339  vdVelGearSteerRadS = m_vdVelGearSteerCmdRadS;
340  vdAngGearSteerRad = m_vdAngGearSteerCmdRad;
341 
342  dVelLongMMS = m_dCmdVelLongMMS;
343  dVelLatMMS = m_dCmdVelLatMMS;
344  dRotRobRadS = m_dCmdRotRobRadS;
345  dRotVelRadS = m_dCmdRotVelRadS;
346 
347  /*// Logging for debugging
348  // get current time
349  m_RawTime.SetNow();
350  m_dNowTime = m_RawTime - m_StartTime;
351  // Log out resulting joint-commands
352  fprintf(m_pfileSteerAngCmd, "%f %f %f %f %f \n", m_dNowTime, m_vdAngGearSteerCmdRad[0], m_vdAngGearSteerCmdRad[1], m_vdAngGearSteerCmdRad[2], m_vdAngGearSteerCmdRad[3]);
353  fprintf(m_pfileSteerVelCmd, "%f %f %f %f %f \n", m_dNowTime, m_vdVelGearSteerCmdRadS[0], m_vdVelGearSteerCmdRadS[1], m_vdVelGearSteerCmdRadS[2], m_vdVelGearSteerCmdRadS[3]);
354  fprintf(m_pfileDriveVelCmd, "%f %f %f %f %f \n", m_dNowTime, m_vdVelGearDriveCmdRadS[0], m_vdVelGearDriveCmdRadS[1], m_vdVelGearDriveCmdRadS[2], m_vdVelGearDriveCmdRadS[3]);*/
355 }
356 
357 // Get result of direct kinematics
358 void UndercarriageCtrlGeom::GetActualPltfVelocity(double & dDeltaLongMM, double & dDeltaLatMM, double & dDeltaRotRobRad, double & dDeltaRotVelRad,
359  double & dVelLongMMS, double & dVelLatMMS, double & dRotRobRadS, double & dRotVelRadS)
360 {
361  dVelLongMMS = m_dVelLongMMS;
362  dVelLatMMS = m_dVelLatMMS;
363  dRotRobRadS = m_dRotRobRadS;
364  dRotVelRadS = m_dRotVelRadS;
365 
366  // calculate travelled distance and angle (from velocity) for output
367  // ToDo: make sure this corresponds to cycle-freqnecy of calling node
368  // --> specify via config file
369  dDeltaLongMM = dVelLongMMS * m_UnderCarriagePrms.dCmdRateS;
370  dDeltaLatMM = dVelLatMMS * m_UnderCarriagePrms.dCmdRateS;
371  dDeltaRotRobRad = dRotRobRadS * m_UnderCarriagePrms.dCmdRateS;
372  dDeltaRotVelRad = dRotVelRadS * m_UnderCarriagePrms.dCmdRateS;
373 }
374 
375 // calculate inverse kinematics
377 {
378  // help variable to store velocities of the steering axis in mm/s
379  double dtempAxVelXRobMMS, dtempAxVelYRobMMS;
380 
381  // check if zero movement commanded -> keep orientation of wheels, set wheel velocity to zero
382  if((m_dCmdVelLongMMS == 0) && (m_dCmdVelLatMMS == 0) && (m_dCmdRotRobRadS == 0) && (m_dCmdRotVelRadS == 0))
383  {
384  for(int i = 0; i<4; i++)
385  {
390  }
391  return;
392  }
393 
394  // calculate sets of possible Steering Angle // Drive-Velocity combinations
395  for (int i = 0; i<4; i++)
396  {
397  // calculate velocity and direction of single wheel motion
398  // Translational Portion
399  dtempAxVelXRobMMS = m_dCmdVelLongMMS;
400  dtempAxVelYRobMMS = m_dCmdVelLatMMS;
401  // Rotational Portion
402  dtempAxVelXRobMMS += m_dCmdRotRobRadS * m_vdExWheelDistMM[i] * -sin(m_vdExWheelAngRad[i]);
403  dtempAxVelYRobMMS += m_dCmdRotRobRadS * m_vdExWheelDistMM[i] * cos(m_vdExWheelAngRad[i]);
404 
405  // calculate resulting steering angle
406  // Wheel has to move in direction of resulting velocity vector of steering axis
407  m_vdAngGearSteerTarget1Rad[i] = MathSup::atan4quad(dtempAxVelYRobMMS, dtempAxVelXRobMMS);
408  // calculate corresponding angle in opposite direction (+180 degree)
411 
412  // calculate absolute value of rotational rate of driving wheels in rad/s
413  m_vdVelGearDriveTarget1RadS[i] = sqrt( (dtempAxVelXRobMMS * dtempAxVelXRobMMS) +
414  (dtempAxVelYRobMMS * dtempAxVelYRobMMS) ) / (double)m_UnderCarriagePrms.iRadiusWheelMM;
415  // now adapt to direction (forward/backward) of wheel
417  }
418 }
419 
420 // calculate direct kinematics
422 {
423  // declare auxilliary variables
424  double dtempVelXRobMMS; // Robot-Velocity in x-Direction (longitudinal) in mm/s (in Robot-Coordinateframe)
425  double dtempVelYRobMMS; // Robot-Velocity in y-Direction (lateral) in mm/s (in Robot-Coordinateframe)
426  double dtempRotRobRADPS; // Robot-Rotation-Rate in rad/s (in Robot-Coordinateframe)
427  double dtempDiffXMM; // Difference in X-Coordinate of two wheels in mm
428  double dtempDiffYMM; // Difference in Y-Coordinate of two wheels in mm
429  double dtempRelPhiWheelsRAD; // Angle between axis of two wheels w.r.t the X-Axis of the Robot-Coordinate-System in rad
430  double dtempRelDistWheelsMM; // distance of two wheels in mm
431  double dtempRelPhiWheel1RAD; // Steering Angle of (im math. pos. direction) first Wheel w.r.t. the linking axis of the two wheels
432  double dtempRelPhiWheel2RAD; // Steering Angle of (im math. pos. direction) first Wheel w.r.t. the linking axis of the two wheels
433  std::vector<double> vdtempVelWheelMMS(4); // Wheel-Velocities (all Wheels) in mm/s
434 
435  // initial values
436  dtempVelXRobMMS = 0; // Robot-Velocity in x-Direction (longitudinal) in mm/s (in Robot-Coordinateframe)
437  dtempVelYRobMMS = 0; // Robot-Velocity in y-Direction (lateral) in mm/s (in Robot-Coordinateframe)
438  dtempRotRobRADPS = 0;
439 
440 
441 
442  // calculate corrected wheel velocities
443  for(int i = 0; i<m_iNumberOfDrives; i++)
444  {
445  // calc effective Driving-Velocity
447  }
448 
449  // calculate rotational rate of robot and current "virtual" axis between all wheels
450  for(int i = 0; i< (m_iNumberOfDrives-1) ; i++)
451  {
452  // calc Parameters (Dist,Phi) of virtual linking axis of the two considered wheels
453  dtempDiffXMM = m_vdExWheelXPosMM[i+1] - m_vdExWheelXPosMM[i];
454  dtempDiffYMM = m_vdExWheelYPosMM[i+1] - m_vdExWheelYPosMM[i];
455  dtempRelDistWheelsMM = sqrt( dtempDiffXMM*dtempDiffXMM + dtempDiffYMM*dtempDiffYMM );
456  dtempRelPhiWheelsRAD = MathSup::atan4quad( dtempDiffYMM, dtempDiffXMM );
457 
458  // transform velocity of wheels into relative coordinate frame of linking axes -> subtract angles
459  dtempRelPhiWheel1RAD = m_vdAngGearSteerRad[i] - dtempRelPhiWheelsRAD;
460  dtempRelPhiWheel2RAD = m_vdAngGearSteerRad[i+1] - dtempRelPhiWheelsRAD;
461 
462  dtempRotRobRADPS += (vdtempVelWheelMMS[i+1] * sin(dtempRelPhiWheel2RAD) - vdtempVelWheelMMS[i] * sin(dtempRelPhiWheel1RAD))/dtempRelDistWheelsMM;
463  }
464 
465  // calculate last missing axis (between last wheel and 1.)
466  // calc. Parameters (Dist,Phi) of virtual linking axis of the two considered wheels
467  dtempDiffXMM = m_vdExWheelXPosMM[0] - m_vdExWheelXPosMM[m_iNumberOfDrives-1];
468  dtempDiffYMM = m_vdExWheelYPosMM[0] - m_vdExWheelYPosMM[m_iNumberOfDrives-1];
469  dtempRelDistWheelsMM = sqrt( dtempDiffXMM*dtempDiffXMM + dtempDiffYMM*dtempDiffYMM );
470  dtempRelPhiWheelsRAD = MathSup::atan4quad( dtempDiffYMM, dtempDiffXMM );
471 
472  // transform velocity of wheels into relative coordinate frame of linking axes -> subtract angles
473  dtempRelPhiWheel1RAD = m_vdAngGearSteerRad[m_iNumberOfDrives-1] - dtempRelPhiWheelsRAD;
474  dtempRelPhiWheel2RAD = m_vdAngGearSteerRad[0] - dtempRelPhiWheelsRAD;
475 
476  // close calculation of robots rotational velocity
477  dtempRotRobRADPS += (vdtempVelWheelMMS[0]*sin(dtempRelPhiWheel2RAD) - vdtempVelWheelMMS[m_iNumberOfDrives-1]*sin(dtempRelPhiWheel1RAD))/dtempRelDistWheelsMM;
478 
479  // calculate linear velocity of robot
480  for(int i = 0; i<m_iNumberOfDrives; i++)
481  {
482  dtempVelXRobMMS += vdtempVelWheelMMS[i]*cos(m_vdAngGearSteerRad[i]);
483  dtempVelYRobMMS += vdtempVelWheelMMS[i]*sin(m_vdAngGearSteerRad[i]);
484  }
485 
486  // assign rotational velocities for output
487  m_dRotRobRadS = dtempRotRobRADPS/m_iNumberOfDrives;
488  m_dRotVelRadS = 0; // currently not used to represent 3rd degree of freedom -> set to zero
489 
490  // assign linear velocity of robot for output
491  m_dVelLongMMS = dtempVelXRobMMS/m_iNumberOfDrives;
492  m_dVelLatMMS = dtempVelYRobMMS/m_iNumberOfDrives;
493 
494 
495 
496 }
497 
498 // calculate Exact Wheel Position in robot coordinates
500 {
501  // calculate wheel position and velocity
502  for(int i = 0; i<4; i++)
503  {
504  // calculate current geometry of robot (exact wheel position, taking into account steering offset of wheels)
507 
508  // calculate distance from platform center to wheel center
510 
511  // calculate direction of rotational vector
513  }
514 }
515 
516 // perform one discrete Control Step (controls steering angle)
518 {
519  // check if zero movement commanded -> keep orientation of wheels, set steer velocity to zero
520  if ((m_dCmdVelLongMMS == 0) && (m_dCmdVelLatMMS == 0) && (m_dCmdRotRobRadS == 0) && (m_dCmdRotVelRadS == 0))
521  {
522  m_vdVelGearDriveCmdRadS.assign(4,0.0); // set velocity for drives to zero
523  m_vdVelGearSteerCmdRadS.assign(4,0.0); // set velocity for steers to zero
524 
525  // set internal states of controller to zero
526  for(int i=0; i<4; i++)
527  {
528  m_vdCtrlVal[i][0] = 0.0;
529  m_vdCtrlVal[i][1] = 0.0;
530  }
531  return;
532  }
533 
534  // declare auxilliary variables
535  double dCurrentPosWheelRAD;
536  double dDeltaPhi;
537  double dForceDamp, dForceProp, dAccCmd, dVelCmdInt; // PI- and Impedance-Ctrl
538 
539  for (int i=0; i<4; i++)
540  {
541  // provisorial --> skip interpolation and always take Target
544 
545  // provisorial --> skip interpolation and always take Target1
546  //m_vdVelGearDriveCmdRadS[i] = m_vdVelGearDriveTarget1RadS[i];
547  //m_vdAngGearSteerCmdRad[i] = m_vdAngGearSteerTarget1Rad[i];
548 
549  /*m_vdAngGearSteerIntpRad[i] += m_vdDeltaAngIntpRad[i];
550  MathSup::normalizePi(m_vdAngGearSteerIntpRad[i]);
551  m_vdVelGearDriveIntpRadS[i] += m_vdDeltaDriveIntpRadS[i];
552 
553  m_vdVelGearDriveCmdRadS[i] = m_vdVelGearDriveIntpRadS[i];
554  m_vdAngGearSteerCmdRad[i] = m_vdAngGearSteerIntpRad[i];*/
555  }
556 
557 
558  for (int i = 0; i<4; i++)
559  {
560  // Normalize Actual Wheel Position before calculation
561  dCurrentPosWheelRAD = m_vdAngGearSteerRad[i];
562  MathSup::normalizePi(dCurrentPosWheelRAD);
563  dDeltaPhi = m_vdAngGearSteerCmdRad[i] - dCurrentPosWheelRAD;
564  MathSup::normalizePi(dDeltaPhi);
565 
566  // Impedance-Ctrl
567  // Calculate resulting desired forces, velocities
568  // double dForceDamp, dForceProp, dAccCmd, dVelCmdInt;
569  dForceDamp = - m_dDamp * m_vdCtrlVal[i][1];
570  dForceProp = m_dSpring * dDeltaPhi;
571  dAccCmd = (dForceDamp + dForceProp) / m_dVirtM;
572  if (dAccCmd > m_dDDPhiMax)
573  {
574  dAccCmd = m_dDDPhiMax;
575  }
576  else if (dAccCmd < -m_dDDPhiMax)
577  {
578  dAccCmd = -m_dDDPhiMax;
579  }
580  dVelCmdInt = m_vdCtrlVal[i][1] + m_UnderCarriagePrms.dCmdRateS * dAccCmd;
581  if (dVelCmdInt > m_dDPhiMax)
582  {
583  dVelCmdInt = m_dDPhiMax;
584  }
585  else if (dVelCmdInt < -m_dDPhiMax)
586  {
587  dVelCmdInt = -m_dDPhiMax;
588  }
589  // Store internal ctrlr-states
590  m_vdCtrlVal[i][0] = dDeltaPhi;
591  m_vdCtrlVal[i][1] = dVelCmdInt;
592  // set outputs
593  m_vdVelGearSteerCmdRadS[i] = dVelCmdInt;
594 
595  // Check if Steeringvelocity overgo maximum allowed rates.
597  {
598  if (m_vdVelGearSteerCmdRadS[i] > 0)
600  else
602  }
603  }
604 
605  // Correct Driving-Wheel-Velocity, because of coupling and axis-offset
606  for (int i = 0; i<4; i++)
607  {
609  }
610 
611 }
612 
613 // operator overloading
615 {
616  // Actual Values for PltfMovement (calculated from Actual Wheelspeeds)
617  m_dVelLongMMS = GeomCtrl.m_dVelLongMMS;
618  m_dVelLatMMS = GeomCtrl.m_dVelLatMMS;
619  m_dRotRobRadS = GeomCtrl.m_dRotRobRadS;
620  m_dRotVelRadS = GeomCtrl.m_dRotVelRadS;
621 
622  // Actual Wheelspeed (read from Motor-Ctrls)
627 
628  // Desired Pltf-Movement (set from PltfHwItf)
630  m_dCmdVelLatMMS = GeomCtrl.m_dCmdVelLatMMS;
633 
634  // Desired Wheelspeeds (calculated from desired ICM-configuration)
638 
639  // Target Wheelspeed and -angle (calculated from desired Pltf-Movement with Inverse without controle!)
640  // alternativ 1 for steering angle
643  // alternativ 2 for steering angle (+/- PI)
646 
647  // Position of the Wheels' Steering Axis'
648  m_vdWheelXPosMM = GeomCtrl.m_vdWheelXPosMM;
649  m_vdWheelYPosMM = GeomCtrl.m_vdWheelYPosMM;
650  m_vdWheelDistMM = GeomCtrl.m_vdWheelDistMM;
651  m_vdWheelAngRad = GeomCtrl.m_vdWheelAngRad;
652 
653  // Exact Position of the Wheels' itself
658 
659  // Prms
661 
662  // Position Controller Steer Wheels
663  // Impedance-Ctrlr
664  m_dSpring = GeomCtrl.m_dSpring;
665  m_dDamp = GeomCtrl.m_dDamp;
666  m_dVirtM = GeomCtrl.m_dDPhiMax;
667  m_dDPhiMax = GeomCtrl.m_dDPhiMax;
668  m_dDDPhiMax = GeomCtrl.m_dDDPhiMax;
669  // Storage for internal controller states
670  m_vdCtrlVal = GeomCtrl.m_vdCtrlVal;
671 }
672 
673 // set EM Flag and stop ctrlr if active
675 {
676  m_bEMStopActive = bEMStopActive;
677 
678  // if emergency stop reset ctrlr to zero
679  if(m_bEMStopActive)
680  {
681  // Steermodules
682  for(int i=0; i<4; i++)
683  {
684  for(int j=0; j< 2; j++)
685  {
686  m_vdCtrlVal[i][j] = 0.0;
687  }
688  }
689  // Outputs
690  for(int i=0; i<4; i++)
691  {
692  m_vdVelGearDriveCmdRadS[i] = 0.0;
693  m_vdVelGearSteerCmdRadS[i] = 0.0;
694  }
695  }
696 
697 }
std::vector< double > m_vdWheelXPosMM
std::vector< std::vector< double > > m_vdCtrlVal
void setEMStopActive(bool bEMStopActive)
std::vector< double > m_vdExWheelDistMM
static double atan4quad(double y, double x)
std::vector< double > m_vdAngGearSteerCmdRad
std::vector< double > m_vdAngGearSteerTargetRad
std::vector< double > m_vdVelGearDriveCmdRadS
static const double PI
void operator=(const UndercarriageCtrlGeom &GeomCtrl)
std::vector< double > m_vdDltAngGearDriveRad
std::vector< double > m_vdAngGearSteerTarget2Rad
std::vector< double > m_vdAngGearSteerTarget1Rad
static void normalizePi(double &angle)
std::vector< double > vdSteerDriveCoupling
void GetNewCtrlStateSteerDriveSetValues(std::vector< double > &vdVelGearDriveRadS, std::vector< double > &vdVelGearSteerRadS, std::vector< double > &vdAngGearSteerRad, double &dVelLongMMS, double &dVelLatMMS, double &dRotRobRadS, double &dRotVelRadS)
std::vector< double > m_vdVelGearDriveRadS
int GetKeyInt(const char *pSect, const char *pKey, int *pValue, bool bWarnIfNotfound=true)
std::vector< double > m_vdExWheelYPosMM
std::vector< double > m_vdWheelDistMM
int GetKeyDouble(const char *pSect, const char *pKey, double *pValue, bool bWarnIfNotfound=true)
void SetDesiredPltfVelocity(double dCmdVelLongMMS, double dCmdVelLatMMS, double dCmdRotRobRadS, double dCmdRotVelRadS)
std::vector< double > m_vdVelGearDriveTarget2RadS
std::vector< double > m_vdVelGearSteerRadS
std::vector< double > m_vdVelGearDriveTargetRadS
int SetFileName(std::string fileName, std::string strIniFileUsedBy="", bool bCreate=false)
std::vector< double > m_vdAngGearSteerRad
std::vector< double > m_vdExWheelAngRad
std::vector< double > m_vdExWheelXPosMM
static double convDegToRad(const double &dAngDeg)
void SetActualWheelValues(std::vector< double > vdVelGearDriveRadS, std::vector< double > vdVelGearSteerRadS, std::vector< double > vdDltAngGearDriveRad, std::vector< double > vdAngGearSteerRad)
void GetSteerDriveSetValues(std::vector< double > &vdVelGearDriveRadS, std::vector< double > &vdAngGearSteerRad)
std::vector< double > m_vdWheelYPosMM
std::vector< double > m_vdVelGearSteerCmdRadS
void GetActualPltfVelocity(double &dDeltaLongMM, double &dDeltaLatMM, double &dDeltaRotRobRad, double &dDeltaRotVelRad, double &dVelLongMMS, double &dVelLatMMS, double &dRotRobRadS, double &dRotVelRadS)
std::vector< double > m_vdVelGearDriveTarget1RadS
std::vector< double > m_vdWheelAngRad
UndercarriageCtrlGeom(std::string sIniDirectory)


cob_undercarriage_ctrl
Author(s): Christian Connette
autogenerated on Wed Apr 7 2021 02:11:56