]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGLGear.cpp
Sync. with JSBSim CVS.
[flightgear.git] / src / FDM / JSBSim / FGLGear.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
2 \r
3  Module:       FGLGear.cpp\r
4  Author:       Jon S. Berndt\r
5                Norman H. Princen\r
6  Date started: 11/18/99\r
7  Purpose:      Encapsulates the landing gear elements\r
8  Called by:    FGAircraft\r
9 \r
10  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------\r
11 \r
12  This program is free software; you can redistribute it and/or modify it under\r
13  the terms of the GNU General Public License as published by the Free Software\r
14  Foundation; either version 2 of the License, or (at your option) any later\r
15  version.\r
16 \r
17  This program is distributed in the hope that it will be useful, but WITHOUT\r
18  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
19  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\r
20  details.\r
21 \r
22  You should have received a copy of the GNU General Public License along with\r
23  this program; if not, write to the Free Software Foundation, Inc., 59 Temple\r
24  Place - Suite 330, Boston, MA  02111-1307, USA.\r
25 \r
26  Further information about the GNU General Public License can also be found on\r
27  the world wide web at http://www.gnu.org.\r
28 \r
29 FUNCTIONAL DESCRIPTION\r
30 --------------------------------------------------------------------------------\r
31 \r
32 HISTORY\r
33 --------------------------------------------------------------------------------\r
34 11/18/99   JSB   Created\r
35 01/30/01   NHP   Extended gear model to properly simulate steering and braking\r
36 \r
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
38 INCLUDES\r
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
40 \r
41 #include "FGLGear.h"\r
42 \r
43 namespace JSBSim {\r
44 \r
45 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
46 DEFINITIONS\r
47 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
48 \r
49 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
50 GLOBAL DATA\r
51 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
52 \r
53 static const char *IdSrc = "$Id$";\r
54 static const char *IdHdr = ID_LGEAR;\r
55 \r
56 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
57 CLASS IMPLEMENTATION\r
58 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/\r
59 \r
60 FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : Exec(fdmex)\r
61 {\r
62   string tmp;\r
63   \r
64   *AC_cfg >> tmp >> name >> vXYZ(1) >> vXYZ(2) >> vXYZ(3)\r
65             >> kSpring >> bDamp>> dynamicFCoeff >> staticFCoeff\r
66                   >> rollingFCoeff >> sSteerType >> sBrakeGroup \r
67                      >> maxSteerAngle >> sRetractable;\r
68 \r
69   if      (sBrakeGroup == "LEFT"  ) eBrakeGrp = bgLeft;\r
70   else if (sBrakeGroup == "RIGHT" ) eBrakeGrp = bgRight;\r
71   else if (sBrakeGroup == "CENTER") eBrakeGrp = bgCenter;\r
72   else if (sBrakeGroup == "NOSE"  ) eBrakeGrp = bgNose;\r
73   else if (sBrakeGroup == "TAIL"  ) eBrakeGrp = bgTail;\r
74   else if (sBrakeGroup == "NONE"  ) eBrakeGrp = bgNone;\r
75   else {\r
76     cerr << "Improper braking group specification in config file: "\r
77          << sBrakeGroup << " is undefined." << endl;\r
78   }\r
79 \r
80   if      (sSteerType == "STEERABLE") eSteerType = stSteer;\r
81   else if (sSteerType == "FIXED"    ) eSteerType = stFixed;\r
82   else if (sSteerType == "CASTERED" ) eSteerType = stCaster;\r
83   else {\r
84     cerr << "Improper steering type specification in config file: "\r
85          << sSteerType << " is undefined." << endl;\r
86   }\r
87   \r
88   if ( sRetractable == "RETRACT" ) {\r
89     isRetractable = true;\r
90   } else  {\r
91     isRetractable = false;\r
92   }  \r
93   \r
94   GearUp = false;\r
95   GearDown = true;\r
96   Servicable = true;\r
97 \r
98 // Add some AI here to determine if gear is located properly according to its\r
99 // brake group type ??\r
100 \r
101   State       = Exec->GetState();\r
102   Aircraft    = Exec->GetAircraft();\r
103   Position    = Exec->GetPosition();\r
104   Rotation    = Exec->GetRotation();\r
105   FCS         = Exec->GetFCS();\r
106   MassBalance = Exec->GetMassBalance();\r
107 \r
108   WOW = lastWOW = true; // should the value be initialized to true?\r
109   ReportEnable = true;\r
110   FirstContact = false;\r
111   StartedGroundRun = false;\r
112   TakeoffReported = LandingReported = false;\r
113   LandingDistanceTraveled = TakeoffDistanceTraveled = TakeoffDistanceTraveled50ft = 0.0;\r
114   MaximumStrutForce = MaximumStrutTravel = 0.0;\r
115   SideForce = RollingForce = 0.0;\r
116   SinkRate = GroundSpeed = 0.0;\r
117 \r
118   vWhlBodyVec = MassBalance->StructuralToBody(vXYZ);\r
119   \r
120   vLocalGear = State->GetTb2l() * vWhlBodyVec;\r
121 \r
122   compressLength  = 0.0;\r
123   compressSpeed   = 0.0;\r
124   brakePct        = 0.0;\r
125   maxCompLen      = 0.0;\r
126 \r
127   WheelSlip = lastWheelSlip = 0.0;\r
128 \r
129   compressLength  = 0.0;\r
130   compressSpeed   = 0.0;\r
131   brakePct        = 0.0;\r
132   maxCompLen      = 0.0;\r
133 \r
134   TirePressureNorm = 1.0;\r
135 \r
136   Debug(0);\r
137 }\r
138 \r
139 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
140 \r
141 FGLGear::FGLGear(const FGLGear& lgear)\r
142 {\r
143   State    = lgear.State;\r
144   Aircraft = lgear.Aircraft;\r
145   Position = lgear.Position;\r
146   Rotation = lgear.Rotation;\r
147   Exec     = lgear.Exec;\r
148   FCS      = lgear.FCS;\r
149   MassBalance = lgear.MassBalance;\r
150 \r
151   vXYZ = lgear.vXYZ;\r
152   vMoment = lgear.vMoment;\r
153   vWhlBodyVec = lgear.vWhlBodyVec;\r
154   vLocalGear = lgear.vLocalGear;\r
155 \r
156   WOW                = lgear.WOW;\r
157   lastWOW            = lgear.lastWOW;\r
158   ReportEnable       = lgear.ReportEnable;\r
159   FirstContact       = lgear.FirstContact;\r
160   StartedGroundRun   = lgear.StartedGroundRun;\r
161   LandingDistanceTraveled   = lgear.LandingDistanceTraveled;\r
162   TakeoffDistanceTraveled   = lgear.TakeoffDistanceTraveled;\r
163   TakeoffDistanceTraveled50ft   = lgear.TakeoffDistanceTraveled50ft;\r
164   MaximumStrutForce  = lgear.MaximumStrutForce;\r
165   MaximumStrutTravel = lgear.MaximumStrutTravel;\r
166   SideForce          = lgear.SideForce;\r
167   RollingForce       = lgear.RollingForce;\r
168 \r
169   kSpring         = lgear.kSpring;\r
170   bDamp           = lgear.bDamp;\r
171   compressLength  = lgear.compressLength;\r
172   compressSpeed   = lgear.compressSpeed;\r
173   staticFCoeff    = lgear.staticFCoeff;\r
174   dynamicFCoeff   = lgear.dynamicFCoeff;\r
175   rollingFCoeff   = lgear.rollingFCoeff;\r
176   brakePct        = lgear.brakePct;\r
177   maxCompLen      = lgear.maxCompLen;\r
178   SinkRate        = lgear.SinkRate;\r
179   GroundSpeed     = lgear.GroundSpeed;\r
180   LandingReported = lgear.LandingReported;\r
181   TakeoffReported = lgear.TakeoffReported;\r
182   name            = lgear.name;\r
183   sSteerType      = lgear.sSteerType;\r
184   sRetractable    = lgear.sRetractable;\r
185   eSteerType      = lgear.eSteerType;\r
186   sBrakeGroup     = lgear.sBrakeGroup;\r
187   eBrakeGrp       = lgear.eBrakeGrp;\r
188   maxSteerAngle   = lgear.maxSteerAngle;\r
189   isRetractable   = lgear.isRetractable;\r
190   GearUp          = lgear.GearUp;\r
191   GearDown        = lgear.GearDown;\r
192   WheelSlip       = lgear.WheelSlip;\r
193   lastWheelSlip   = lgear.lastWheelSlip;\r
194   TirePressureNorm = lgear.TirePressureNorm;\r
195   Servicable      = lgear.Servicable;\r
196 }\r
197 \r
198 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
199 \r
200 FGLGear::~FGLGear()\r
201 {\r
202   Debug(1);\r
203 }\r
204 \r
205 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
206 \r
207 FGColumnVector3& FGLGear::Force(void)\r
208 {\r
209   double SteerGain = 0;\r
210   double SinWheel, CosWheel;\r
211   double deltaSlip;\r
212   double deltaT = State->Getdt()*Aircraft->GetRate();\r
213 \r
214   vForce.InitMatrix();\r
215   vMoment.InitMatrix();\r
216 \r
217   if (isRetractable) {\r
218     if (FCS->GetGearPos() < 0.01) {\r
219       GearUp   = true;\r
220       GearDown = false;\r
221      } else if (FCS->GetGearPos() > 0.99) {\r
222       GearDown = true;\r
223       GearUp   = false;\r
224      } else {\r
225       GearUp   = false;\r
226       GearDown = false;\r
227      }\r
228   } else {\r
229       GearUp   = false;\r
230       GearDown = true;\r
231   }         \r
232       \r
233   if (GearDown) {\r
234 \r
235     vWhlBodyVec = MassBalance->StructuralToBody(vXYZ);\r
236 \r
237 // vWhlBodyVec now stores the vector from the cg to this wheel\r
238 \r
239     vLocalGear = State->GetTb2l() * vWhlBodyVec;\r
240 \r
241 // vLocalGear now stores the vector from the cg to the wheel in local coords.\r
242 \r
243     compressLength = vLocalGear(eZ) - Position->GetDistanceAGL();\r
244 \r
245 // The compression length is currently measured in the Z-axis, only, at this time.\r
246 // It should be measured along the strut axis. If the local-frame gear position\r
247 // "hangs down" below the CG greater than the altitude, then the compressLength\r
248 // will be positive - i.e. the gear will have made contact.\r
249 \r
250     if (compressLength > 0.00) {\r
251 \r
252       WOW = true; // Weight-On-Wheels is true\r
253 \r
254 // The next equation should really use the vector to the contact patch of the tire\r
255 // including the strut compression and not vWhlBodyVec.  Will fix this later.\r
256 // As it stands, now, the following equation takes the aircraft body-frame\r
257 // rotational rate and calculates the cross-product with the vector from the CG\r
258 // to the wheel, thus producing the instantaneous velocity vector of the tire\r
259 // in Body coords. The frame is also converted to local coordinates. When the\r
260 // aircraft local-frame velocity is added to this quantity, the total velocity of\r
261 // the wheel in local frame is then known. Subsequently, the compression speed\r
262 // (used for calculating damping force) is found by taking the Z-component of the\r
263 // wheel velocity.\r
264 \r
265       vWhlVelVec      =  State->GetTb2l() * (Rotation->GetPQR() * vWhlBodyVec);\r
266       vWhlVelVec     +=  Position->GetVel();\r
267       compressSpeed   =  vWhlVelVec(eZ);\r
268 \r
269 // If this is the first time the wheel has made contact, remember some values\r
270 // for later printout.\r
271 \r
272       if (!FirstContact) {\r
273         FirstContact  = true;\r
274         SinkRate      =  compressSpeed;\r
275         GroundSpeed   =  Position->GetVel().Magnitude();\r
276         TakeoffReported = false;\r
277       }\r
278 \r
279 // If the takeoff run is starting, initialize.\r
280 \r
281       if ((Position->GetVel().Magnitude() > 0.1) &&\r
282           (FCS->GetBrake(bgLeft) == 0) &&\r
283           (FCS->GetBrake(bgRight) == 0) &&\r
284           (FCS->GetThrottlePos(0) == 1) && !StartedGroundRun)\r
285       {\r
286         TakeoffDistanceTraveled = 0;\r
287         TakeoffDistanceTraveled50ft = 0;\r
288         StartedGroundRun = true;\r
289       }\r
290 \r
291 // The following needs work regarding friction coefficients and braking and\r
292 // steering The BrakeFCoeff formula assumes that an anti-skid system is used.\r
293 // It also assumes that we won't be turning and braking at the same time.\r
294 // Will fix this later.\r
295 // [JSB] The braking force coefficients include normal rolling coefficient +\r
296 // a percentage of the static friction coefficient based on braking applied.\r
297 \r
298       switch (eBrakeGrp) {\r
299       case bgLeft:\r
300          BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) +\r
301                         staticFCoeff*FCS->GetBrake(bgLeft) );\r
302         break;\r
303       case bgRight:\r
304         BrakeFCoeff =  ( rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) +\r
305                          staticFCoeff*FCS->GetBrake(bgRight) );\r
306         break;\r
307       case bgCenter:\r
308         BrakeFCoeff =  ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +\r
309                          staticFCoeff*FCS->GetBrake(bgCenter) );\r
310         break;\r
311       case bgNose:\r
312         BrakeFCoeff =  ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +\r
313                          staticFCoeff*FCS->GetBrake(bgCenter) );\r
314         break;\r
315       case bgTail:\r
316         BrakeFCoeff =  ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +\r
317                          staticFCoeff*FCS->GetBrake(bgCenter) );\r
318         break;\r
319       case bgNone:\r
320         BrakeFCoeff =  rollingFCoeff;\r
321         break;\r
322       default:\r
323         cerr << "Improper brake group membership detected for this gear." << endl;\r
324         break;\r
325       }\r
326 \r
327       switch (eSteerType) {\r
328       case stSteer:\r
329         SteerAngle = -maxSteerAngle * FCS->GetDrCmd() * 0.01745; \r
330         break;\r
331       case stFixed:\r
332         SteerAngle = 0.0;\r
333         break;\r
334       case stCaster:\r
335 // Note to Jon: This is not correct for castering gear.  I'll fix it later.\r
336         SteerAngle = 0.0;\r
337         break;\r
338       default:\r
339         cerr << "Improper steering type membership detected for this gear." << endl;\r
340         break;\r
341       }\r
342 \r
343 // Transform the wheel velocities from the local axis system to the wheel axis system.\r
344 // For now, steering angle is assumed to happen in the Local Z axis,\r
345 // not the strut axis as it should be.  Will fix this later.\r
346 \r
347       SinWheel      = sin(Rotation->Getpsi() + SteerAngle);\r
348       CosWheel      = cos(Rotation->Getpsi() + SteerAngle);\r
349       RollingWhlVel = vWhlVelVec(eX)*CosWheel + vWhlVelVec(eY)*SinWheel;\r
350       SideWhlVel    = vWhlVelVec(eY)*CosWheel - vWhlVelVec(eX)*SinWheel;\r
351 \r
352 // Calculate tire slip angle.\r
353 \r
354       if (RollingWhlVel == 0.0 && SideWhlVel == 0.0) {\r
355         WheelSlip = 0.0;\r
356       } else if (fabs(RollingWhlVel) < 1.0) {\r
357         WheelSlip = 0.05*radtodeg*atan2(SideWhlVel, RollingWhlVel) + 0.95*WheelSlip;\r
358       } else {\r
359         WheelSlip = radtodeg*atan2(SideWhlVel, RollingWhlVel);\r
360       }\r
361 /*\r
362       double maxdeltaSlip = 0.5*deltaT;\r
363 \r
364       if (RollingWhlVel == 0.0 && SideWhlVel == 0.0) {\r
365         WheelSlip = 0.0;\r
366       } else if (RollingWhlVel < 1.0) {\r
367         WheelSlip = radtodeg*atan2(SideWhlVel, RollingWhlVel);\r
368         deltaSlip = WheelSlip - lastWheelSlip;\r
369         if (fabs(deltaSlip) > maxdeltaSlip) {\r
370           if (WheelSlip > lastWheelSlip) {\r
371             WheelSlip = lastWheelSlip + maxdeltaSlip;\r
372           } else if (WheelSlip < lastWheelSlip) {\r
373             WheelSlip = lastWheelSlip - maxdeltaSlip;\r
374           }\r
375         }\r
376       } else {\r
377         WheelSlip = radtodeg*atan2(SideWhlVel, RollingWhlVel);\r
378       }\r
379 \r
380       if ((WheelSlip < 0.0 && lastWheelSlip > 0.0) ||\r
381           (WheelSlip > 0.0 && lastWheelSlip < 0.0))\r
382       {\r
383         WheelSlip = 0.0;\r
384       }\r
385 */    \r
386       lastWheelSlip = WheelSlip;\r
387 \r
388 // Compute the sideforce coefficients using similar assumptions to LaRCSim for now.\r
389 // Allow a maximum of 10 degrees tire slip angle before wheel slides.  At that point,\r
390 // transition from static to dynamic friction.  There are more complicated formulations\r
391 // of this that avoid the discrete jump.  Will fix this later.\r
392 \r
393       if (fabs(WheelSlip) <= 20.0) {\r
394         FCoeff = staticFCoeff*WheelSlip/20.0;\r
395       } else if (fabs(WheelSlip) <= 40.0) {\r
396 //        FCoeff = dynamicFCoeff*fabs(WheelSlip)/WheelSlip;\r
397         FCoeff = (dynamicFCoeff*(fabs(WheelSlip) - 20.0)/20.0 + \r
398                   staticFCoeff*(40.0 - fabs(WheelSlip))/20.0)*fabs(WheelSlip)/WheelSlip;\r
399       } else {\r
400         FCoeff = dynamicFCoeff*fabs(WheelSlip)/WheelSlip;\r
401       }\r
402 \r
403 // Compute the vertical force on the wheel using square-law damping (per comment\r
404 // in paper AIAA-2000-4303 - see header prologue comments). We might consider\r
405 // allowing for both square and linear damping force calculation. Also need to\r
406 // possibly give a "rebound damping factor" that differs from the compression\r
407 // case.\r
408 \r
409       vLocalForce(eZ) =  min(-compressLength * kSpring\r
410                              - compressSpeed * bDamp, (double)0.0);\r
411 \r
412       MaximumStrutForce = max(MaximumStrutForce, fabs(vLocalForce(eZ)));\r
413       MaximumStrutTravel = max(MaximumStrutTravel, fabs(compressLength));\r
414 \r
415 // Compute the forces in the wheel ground plane.\r
416 \r
417       RollingForce = 0;\r
418       if (fabs(RollingWhlVel) > 1E-3) {\r
419         RollingForce = (1.0 - TirePressureNorm) * 30\r
420                        + vLocalForce(eZ) * BrakeFCoeff\r
421                        * fabs(RollingWhlVel)/RollingWhlVel;\r
422       }\r
423       SideForce    = vLocalForce(eZ) * FCoeff;\r
424 \r
425 // Transform these forces back to the local reference frame.\r
426 \r
427       vLocalForce(eX) = RollingForce*CosWheel - SideForce*SinWheel;\r
428       vLocalForce(eY) = SideForce*CosWheel    + RollingForce*SinWheel;\r
429 \r
430 // Note to Jon: At this point the forces will be too big when the airplane is\r
431 // stopped or rolling to a stop.  We need to make sure that the gear forces just\r
432 // balance out the non-gear forces when the airplane is stopped.  That way the\r
433 // airplane won't start to accelerate until the non-gear/ forces are larger than\r
434 // the gear forces.  I think that the proper fix should go into FGAircraft::FMGear.\r
435 // This routine would only compute the local strut forces and return them to\r
436 // FMGear. All of the gear forces would get adjusted in FMGear using the total\r
437 // non-gear forces. Then the gear moments would be calculated. If strange things\r
438 // start happening to the airplane during testing as it rolls to a stop, then we\r
439 // need to implement this change.  I ran out of time to do it now but have the\r
440 // equations.\r
441 \r
442 // Transform the forces back to the body frame and compute the moment.\r
443 \r
444       vForce  = State->GetTl2b() * vLocalForce;\r
445       vMoment = vWhlBodyVec * vForce;\r
446 \r
447     } else { // Gear is NOT compressed\r
448 \r
449       WOW = false;\r
450 \r
451       if (Position->GetDistanceAGL() > 200.0) {\r
452         FirstContact = false;\r
453         StartedGroundRun = false;\r
454         LandingReported = false;\r
455         LandingDistanceTraveled = 0.0;\r
456         MaximumStrutForce = MaximumStrutTravel = 0.0;\r
457       }\r
458 \r
459       compressLength = 0.0; // reset compressLength to zero for data output validity\r
460     }\r
461 \r
462     if (FirstContact) LandingDistanceTraveled += Position->GetVground()*deltaT;\r
463   \r
464     if (StartedGroundRun) {\r
465        TakeoffDistanceTraveled50ft += Position->GetVground()*deltaT;\r
466       if (WOW) TakeoffDistanceTraveled += Position->GetVground()*deltaT;\r
467     }\r
468 \r
469     if (ReportEnable && Position->GetVground() <= 0.05 && !LandingReported) {\r
470       if (debug_lvl > 0) Report(erLand);\r
471     }\r
472 \r
473     if (ReportEnable && !TakeoffReported &&\r
474        (vLocalGear(eZ) - Position->GetDistanceAGL()) < -50.0)\r
475     {\r
476       if (debug_lvl > 0) Report(erTakeoff);\r
477     }\r
478 \r
479     if (lastWOW != WOW) {\r
480       PutMessage("GEAR_CONTACT: " + name, WOW);\r
481     }\r
482 \r
483     lastWOW = WOW;\r
484 \r
485 // Crash detection logic (really out-of-bounds detection)\r
486 \r
487     if (compressLength > 500.0 ||\r
488         vForce.Magnitude() > 100000000.0 ||\r
489         vMoment.Magnitude() > 5000000000.0 ||\r
490         SinkRate > 1.4666*30)\r
491     {\r
492       PutMessage("Crash Detected: Simulation FREEZE.");\r
493       Exec->Freeze();\r
494     }\r
495   } \r
496   return vForce; \r
497 }\r
498 \r
499 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
500 \r
501 void FGLGear::Report(ReportType repType)\r
502 {\r
503   switch(repType) {\r
504   case erLand:\r
505     cout << endl << "Touchdown report for " << name << endl;\r
506     cout << "  Sink rate at contact:  " << SinkRate                << " fps,    "\r
507                                 << SinkRate*0.3048          << " mps"     << endl;\r
508     cout << "  Contact ground speed:  " << GroundSpeed*.5925       << " knots,  "\r
509                                 << GroundSpeed*0.3048       << " mps"     << endl;\r
510     cout << "  Maximum contact force: " << MaximumStrutForce       << " lbs,    "\r
511                                 << MaximumStrutForce*4.448  << " Newtons" << endl;\r
512     cout << "  Maximum strut travel:  " << MaximumStrutTravel*12.0 << " inches, "\r
513                                 << MaximumStrutTravel*30.48 << " cm"      << endl;\r
514     cout << "  Distance traveled:     " << LandingDistanceTraveled        << " ft,     "\r
515                                 << LandingDistanceTraveled*0.3048  << " meters"  << endl;\r
516     LandingReported = true;\r
517     break;\r
518   case erTakeoff:\r
519     cout << endl << "Takeoff report for " << name << endl;\r
520     cout << "  Distance traveled:                " << TakeoffDistanceTraveled\r
521          << " ft,     " << TakeoffDistanceTraveled*0.3048  << " meters"  << endl;\r
522     cout << "  Distance traveled (over 50'):     " << TakeoffDistanceTraveled50ft\r
523          << " ft,     " << TakeoffDistanceTraveled50ft*0.3048 << " meters" << endl;\r
524     TakeoffReported = true;\r
525     break;\r
526   }\r
527 }\r
528 \r
529 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
530 //    The bitmasked value choices are as follows:\r
531 //    unset: In this case (the default) JSBSim would only print\r
532 //       out the normally expected messages, essentially echoing\r
533 //       the config files as they are read. If the environment\r
534 //       variable is not set, debug_lvl is set to 1 internally\r
535 //    0: This requests JSBSim not to output any messages\r
536 //       whatsoever.\r
537 //    1: This value explicity requests the normal JSBSim\r
538 //       startup messages\r
539 //    2: This value asks for a message to be printed out when\r
540 //       a class is instantiated\r
541 //    4: When this value is set, a message is displayed when a\r
542 //       FGModel object executes its Run() method\r
543 //    8: When this value is set, various runtime state variables\r
544 //       are printed out periodically\r
545 //    16: When set various parameters are sanity checked and\r
546 //       a message is printed out when they go out of bounds\r
547 \r
548 void FGLGear::Debug(int from)\r
549 {\r
550   if (debug_lvl <= 0) return;\r
551 \r
552   if (debug_lvl & 1) { // Standard console startup message output\r
553     if (from == 0) { // Constructor\r
554       cout << "    Name: "               << name          << endl;\r
555       cout << "      Location: "         << vXYZ          << endl;\r
556       cout << "      Spring Constant:  " << kSpring       << endl;\r
557       cout << "      Damping Constant: " << bDamp         << endl;\r
558       cout << "      Dynamic Friction: " << dynamicFCoeff << endl;\r
559       cout << "      Static Friction:  " << staticFCoeff  << endl;\r
560       cout << "      Rolling Friction: " << rollingFCoeff << endl;\r
561       cout << "      Steering Type:    " << sSteerType    << endl;\r
562       cout << "      Grouping:         " << sBrakeGroup   << endl;\r
563       cout << "      Max Steer Angle:  " << maxSteerAngle << endl;\r
564       cout << "      Retractable:      " << sRetractable  << endl;\r
565     }\r
566   }\r
567   if (debug_lvl & 2 ) { // Instantiation/Destruction notification\r
568     if (from == 0) cout << "Instantiated: FGLGear" << endl;\r
569     if (from == 1) cout << "Destroyed:    FGLGear" << endl;\r
570   }\r
571   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects\r
572   }\r
573   if (debug_lvl & 8 ) { // Runtime state variables\r
574   }\r
575   if (debug_lvl & 16) { // Sanity checking\r
576   }\r
577   if (debug_lvl & 64) {\r
578     if (from == 0) { // Constructor\r
579       cout << IdSrc << endl;\r
580       cout << IdHdr << endl;\r
581     }\r
582   }\r
583 }\r
584 \r
585 } // namespace JSBSim\r
586 \r