]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGLGear.cpp
Sync with current JSBSim devel code.
[flightgear.git] / src / FDM / JSBSim / FGLGear.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGLGear.cpp
4  Author:       Jon S. Berndt
5  Date started: 11/18/99
6  Purpose:      Encapsulates the landing gear elements
7  Called by:    FGAircraft
8
9  ------------- Copyright (C) 1999  Jon S. Berndt (jsb@hal-pc.org) -------------
10
11  This program is free software; you can redistribute it and/or modify it under
12  the terms of the GNU General Public License as published by the Free Software
13  Foundation; either version 2 of the License, or (at your option) any later
14  version.
15
16  This program is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
19  details.
20
21  You should have received a copy of the GNU General Public License along with
22  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23  Place - Suite 330, Boston, MA  02111-1307, USA.
24
25  Further information about the GNU General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30
31 HISTORY
32 --------------------------------------------------------------------------------
33 11/18/99   JSB   Created
34
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 INCLUDES
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
38
39 #include "FGLGear.h"
40 #include <algorithm>
41
42 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 DEFINITIONS
44 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
45
46 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
47 GLOBAL DATA
48 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
49
50 static const char *IdSrc = "$Header$";
51 static const char *IdHdr = ID_LGEAR;
52
53 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
54 CLASS IMPLEMENTATION
55 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
56
57 FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : vXYZ(3),
58                                                            vMoment(3),
59                                                            vWhlBodyVec(3),
60                                                            Exec(fdmex)
61 {
62   string tmp;
63   *AC_cfg >> tmp >> name >> vXYZ(1) >> vXYZ(2) >> vXYZ(3)  
64             >> kSpring >> bDamp>> dynamicFCoeff >> staticFCoeff
65                   >> SteerType >> BrakeGroup >> maxSteerAngle;
66     
67   cout << "    Name: " << name << endl;
68   cout << "      Location: " << vXYZ << endl;
69   cout << "      Spring Constant:  " << kSpring << endl;
70   cout << "      Damping Constant: " << bDamp << endl;
71   cout << "      Dynamic Friction: " << dynamicFCoeff << endl;
72   cout << "      Static Friction:  " << staticFCoeff << endl;
73   cout << "      Grouping:         " << BrakeGroup << endl;
74   cout << "      Steering Type:    " << SteerType << endl;
75   cout << "      Max Steer Angle:  " << maxSteerAngle << endl;
76
77   if      (BrakeGroup == "LEFT"  ) eBrakeGrp = bgLeft;
78   else if (BrakeGroup == "RIGHT" ) eBrakeGrp = bgRight;
79   else if (BrakeGroup == "CENTER") eBrakeGrp = bgCenter;
80   else if (BrakeGroup == "NOSE"  ) eBrakeGrp = bgNose;
81   else if (BrakeGroup == "TAIL"  ) eBrakeGrp = bgTail;
82   else if (BrakeGroup == "NONE"  ) eBrakeGrp = bgNone;
83   else {
84     cerr << "Improper braking group specification in config file: "
85          << BrakeGroup << " is undefined." << endl;
86   }
87
88 // add some AI here to determine if gear is located properly according to its
89 // brake group type
90
91   State       = Exec->GetState();
92   Aircraft    = Exec->GetAircraft();
93   Position    = Exec->GetPosition();
94   Rotation    = Exec->GetRotation();
95   
96   WOW = false;
97   ReportEnable=true;
98   FirstContact = false;
99   Reported = false;
100   DistanceTraveled = 0.0;
101   MaximumStrutForce = MaximumStrutTravel = 0.0;
102   
103   vWhlBodyVec     = (vXYZ - Aircraft->GetXYZcg()) / 12.0;
104   vWhlBodyVec(eX) = -vWhlBodyVec(eX);
105   vWhlBodyVec(eZ) = -vWhlBodyVec(eZ);
106
107   vLocalGear = State->GetTb2l() * vWhlBodyVec;
108 }
109
110 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
111
112 FGLGear::FGLGear(const FGLGear& lgear)
113 {
114   State    = lgear.State;
115   Aircraft = lgear.Aircraft;
116   Position = lgear.Position;
117   Rotation = lgear.Rotation;
118   Exec     = lgear.Exec;
119
120   vXYZ = lgear.vXYZ;
121   vMoment = lgear.vMoment;
122   vWhlBodyVec = lgear.vWhlBodyVec;
123   vLocalGear = lgear.vLocalGear;
124
125   WOW                = lgear.WOW;
126   ReportEnable       = lgear.ReportEnable;
127   FirstContact       = lgear.FirstContact;
128   DistanceTraveled   = lgear.DistanceTraveled;
129   MaximumStrutForce  = lgear.MaximumStrutForce;
130   MaximumStrutTravel = lgear.MaximumStrutTravel;
131
132   kSpring         = lgear.kSpring;
133   bDamp           = lgear.bDamp;
134   compressLength  = lgear.compressLength;
135   compressSpeed   = lgear.compressSpeed;
136   staticFCoeff    = lgear.staticFCoeff;
137   dynamicFCoeff   = lgear.dynamicFCoeff;
138   brakePct        = lgear.brakePct;
139   maxCompLen      = lgear.maxCompLen;
140   SinkRate        = lgear.SinkRate;
141   GroundSpeed     = lgear.GroundSpeed;
142   Reported        = lgear.Reported;
143   name            = lgear.name;
144   SteerType       = lgear.SteerType;
145   BrakeGroup      = lgear.BrakeGroup;
146   eBrakeGrp       = lgear.eBrakeGrp;
147   maxSteerAngle   = lgear.maxSteerAngle;
148 }
149
150 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
151
152 FGLGear::~FGLGear(void) {}
153
154 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
155
156 FGColumnVector FGLGear::Force(void)
157 {
158   FGColumnVector vForce(3);
159   FGColumnVector vLocalForce(3);
160   //FGColumnVector vLocalGear(3);     // Vector: CG to this wheel (Local)
161   FGColumnVector vWhlVelVec(3);     // Velocity of this wheel (Local)
162   
163   vWhlBodyVec     = (vXYZ - Aircraft->GetXYZcg()) / 12.0;
164   vWhlBodyVec(eX) = -vWhlBodyVec(eX);
165   vWhlBodyVec(eZ) = -vWhlBodyVec(eZ);
166
167   vLocalGear = State->GetTb2l() * vWhlBodyVec;
168   
169   compressLength = vLocalGear(eZ) - Position->GetDistanceAGL();
170
171   if (compressLength > 0.00) {
172      
173     WOW = true;
174     vWhlVelVec      =  State->GetTb2l() * (Rotation->GetPQR() * vWhlBodyVec);
175     vWhlVelVec     +=  Position->GetVel();
176
177     compressSpeed   =  vWhlVelVec(eZ);
178
179     if (!FirstContact) {
180       FirstContact  = true;
181       SinkRate      =  compressSpeed;
182       GroundSpeed   =  Position->GetVel().Magnitude();
183     }
184
185     // The following code normalizes the wheel velocity vector, reverses it, and zeroes out
186     // the z component of the velocity. The question is, should the Z axis velocity be zeroed
187     // out first before the normalization takes place or not? Subsequent to that, the Wheel
188     // Velocity vector now points as a unit vector backwards and parallel to the wheel
189     // velocity vector. It acts AT the wheel.
190
191     vWhlVelVec      = -1.0 * vWhlVelVec.Normalize();
192     vWhlVelVec(eZ)  =  0.00;
193
194 // the following needs work regarding friction coefficients and braking and steering
195
196     switch (eBrakeGrp) {
197     case bgLeft:
198
199       break;
200     case bgRight:
201       break;
202     case bgCenter:
203       break;
204     case bgNose:
205       break;
206     case bgTail:
207       break;
208     case bgNone:
209       break;
210     default:
211       cerr << "Improper brake group membership detected for this gear." << endl;
212       break;
213     }
214 //
215
216     vLocalForce(eZ) =  min(-compressLength * kSpring - compressSpeed * bDamp, (float)0.0);
217     vLocalForce(eX) =  fabs(vLocalForce(eZ) * staticFCoeff) * vWhlVelVec(eX);
218     vLocalForce(eY) =  fabs(vLocalForce(eZ) * staticFCoeff) * vWhlVelVec(eY);
219
220     MaximumStrutForce = max(MaximumStrutForce, fabs(vLocalForce(eZ)));
221     MaximumStrutTravel = max(MaximumStrutTravel, fabs(compressLength));
222
223     vForce  = State->GetTl2b() * vLocalForce ;
224     vMoment = vWhlBodyVec * vForce;
225
226   } else {
227
228     WOW = false;
229
230     if (Position->GetDistanceAGL() > 200.0) {
231       FirstContact = false;
232       Reported = false;
233       DistanceTraveled = 0.0;
234       MaximumStrutForce = MaximumStrutTravel = 0.0;
235     }
236
237     vForce.InitMatrix();
238     vMoment.InitMatrix();
239   }
240
241   if (FirstContact) {
242     DistanceTraveled += Position->GetVel().Magnitude()*State->Getdt()*Aircraft->GetRate();
243   }
244
245   if (ReportEnable && Position->GetVel().Magnitude() <= 0.05 && !Reported) {
246     Report();
247   }
248   return vForce;
249 }
250
251 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252
253 void FGLGear::Report(void)
254 {
255   cout << endl << "Touchdown report for " << name << endl;
256   cout << "  Sink rate at contact:  " << SinkRate                << " fps,    "
257                               << SinkRate*0.3408          << " mps"     << endl;
258   cout << "  Contact ground speed:  " << GroundSpeed*.5925       << " knots,  "
259                               << GroundSpeed*0.3408       << " mps"     << endl;
260   cout << "  Maximum contact force: " << MaximumStrutForce       << " lbs,    "
261                               << MaximumStrutForce*4.448  << " Newtons" << endl;
262   cout << "  Maximum strut travel:  " << MaximumStrutTravel*12.0 << " inches, "
263                               << MaximumStrutTravel*30.48 << " cm"      << endl;
264   cout << "  Distance traveled:     " << DistanceTraveled        << " ft,     "
265                               << DistanceTraveled*0.3408  << " meters"  << endl;
266   Reported = true;
267 }
268