2000-11-03 23:02:47 +00:00
|
|
|
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
1999-12-20 20:25:13 +00:00
|
|
|
|
|
|
|
Module: FGLGear.cpp
|
|
|
|
Author: Jon S. Berndt
|
2001-04-05 21:14:37 +00:00
|
|
|
Norman H. Princen
|
1999-12-20 20:25:13 +00:00
|
|
|
Date started: 11/18/99
|
|
|
|
Purpose: Encapsulates the landing gear elements
|
|
|
|
Called by: FGAircraft
|
|
|
|
|
|
|
|
------------- Copyright (C) 1999 Jon S. Berndt (jsb@hal-pc.org) -------------
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it under
|
|
|
|
the terms of the GNU General Public License as published by the Free Software
|
|
|
|
Foundation; either version 2 of the License, or (at your option) any later
|
|
|
|
version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
|
details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
|
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
|
|
Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
Further information about the GNU General Public License can also be found on
|
|
|
|
the world wide web at http://www.gnu.org.
|
|
|
|
|
|
|
|
FUNCTIONAL DESCRIPTION
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
HISTORY
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
11/18/99 JSB Created
|
2001-03-30 01:04:50 +00:00
|
|
|
01/30/01 NHP Extended gear model to properly simulate steering and braking
|
1999-12-20 20:25:13 +00:00
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
1999-12-20 20:25:13 +00:00
|
|
|
INCLUDES
|
2000-11-03 23:02:47 +00:00
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
1999-12-20 20:25:13 +00:00
|
|
|
|
|
|
|
#include "FGLGear.h"
|
2000-05-27 05:48:14 +00:00
|
|
|
#include <algorithm>
|
1999-12-20 20:25:13 +00:00
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
DEFINITIONS
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
|
|
|
|
|
|
|
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
GLOBAL DATA
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
|
|
|
|
2001-03-30 01:04:50 +00:00
|
|
|
|
|
|
|
static const char *IdSrc = "$Id$";
|
2000-10-14 02:10:10 +00:00
|
|
|
static const char *IdHdr = ID_LGEAR;
|
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
CLASS IMPLEMENTATION
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
|
1999-12-20 20:25:13 +00:00
|
|
|
|
2001-12-07 17:10:17 +00:00
|
|
|
FGLGear::FGLGear(FGConfigFile* AC_cfg, FGFDMExec* fdmex) : Exec(fdmex)
|
1999-12-20 20:25:13 +00:00
|
|
|
{
|
2000-04-24 23:49:06 +00:00
|
|
|
string tmp;
|
2001-12-03 22:24:40 +00:00
|
|
|
|
2001-04-05 21:14:37 +00:00
|
|
|
*AC_cfg >> tmp >> name >> vXYZ(1) >> vXYZ(2) >> vXYZ(3)
|
2000-10-09 21:16:21 +00:00
|
|
|
>> kSpring >> bDamp>> dynamicFCoeff >> staticFCoeff
|
2001-12-03 22:24:40 +00:00
|
|
|
>> rollingFCoeff >> sSteerType >> sBrakeGroup
|
2001-12-14 03:35:41 +00:00
|
|
|
>> maxSteerAngle >> sRetractable;
|
2001-04-05 21:14:37 +00:00
|
|
|
|
2001-03-30 01:04:50 +00:00
|
|
|
if (sBrakeGroup == "LEFT" ) eBrakeGrp = bgLeft;
|
|
|
|
else if (sBrakeGroup == "RIGHT" ) eBrakeGrp = bgRight;
|
|
|
|
else if (sBrakeGroup == "CENTER") eBrakeGrp = bgCenter;
|
|
|
|
else if (sBrakeGroup == "NOSE" ) eBrakeGrp = bgNose;
|
|
|
|
else if (sBrakeGroup == "TAIL" ) eBrakeGrp = bgTail;
|
|
|
|
else if (sBrakeGroup == "NONE" ) eBrakeGrp = bgNone;
|
2000-11-03 23:02:47 +00:00
|
|
|
else {
|
|
|
|
cerr << "Improper braking group specification in config file: "
|
2001-03-30 01:04:50 +00:00
|
|
|
<< sBrakeGroup << " is undefined." << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sSteerType == "STEERABLE") eSteerType = stSteer;
|
|
|
|
else if (sSteerType == "FIXED" ) eSteerType = stFixed;
|
|
|
|
else if (sSteerType == "CASTERED" ) eSteerType = stCaster;
|
|
|
|
else {
|
|
|
|
cerr << "Improper steering type specification in config file: "
|
|
|
|
<< sSteerType << " is undefined." << endl;
|
2000-11-03 23:02:47 +00:00
|
|
|
}
|
2001-12-03 22:24:40 +00:00
|
|
|
|
2001-12-14 03:35:41 +00:00
|
|
|
if ( sRetractable == "RETRACT" ) {
|
|
|
|
isRetractable = true;
|
2001-12-03 22:24:40 +00:00
|
|
|
} else {
|
2001-12-14 03:35:41 +00:00
|
|
|
isRetractable = false;
|
2001-12-03 22:24:40 +00:00
|
|
|
}
|
|
|
|
|
2001-12-14 03:35:41 +00:00
|
|
|
GearUp = false;
|
|
|
|
GearDown = true;
|
2000-11-03 23:02:47 +00:00
|
|
|
|
2001-03-30 01:04:50 +00:00
|
|
|
// Add some AI here to determine if gear is located properly according to its
|
|
|
|
// brake group type ??
|
2000-11-03 23:02:47 +00:00
|
|
|
|
2000-05-27 05:48:14 +00:00
|
|
|
State = Exec->GetState();
|
|
|
|
Aircraft = Exec->GetAircraft();
|
|
|
|
Position = Exec->GetPosition();
|
|
|
|
Rotation = Exec->GetRotation();
|
2001-03-30 01:04:50 +00:00
|
|
|
FCS = Exec->GetFCS();
|
2001-06-05 20:58:48 +00:00
|
|
|
MassBalance = Exec->GetMassBalance();
|
2001-04-05 21:14:37 +00:00
|
|
|
|
2001-11-20 22:34:24 +00:00
|
|
|
WOW = lastWOW = false;
|
2001-03-30 01:04:50 +00:00
|
|
|
ReportEnable = true;
|
2000-07-06 21:02:46 +00:00
|
|
|
FirstContact = false;
|
|
|
|
Reported = false;
|
|
|
|
DistanceTraveled = 0.0;
|
|
|
|
MaximumStrutForce = MaximumStrutTravel = 0.0;
|
2001-06-05 20:58:48 +00:00
|
|
|
SinkRate = GroundSpeed = 0.0;
|
2001-04-05 21:14:37 +00:00
|
|
|
|
2001-06-05 20:58:48 +00:00
|
|
|
vWhlBodyVec = (vXYZ - MassBalance->GetXYZcg()) / 12.0;
|
2000-11-03 23:02:47 +00:00
|
|
|
vWhlBodyVec(eX) = -vWhlBodyVec(eX);
|
|
|
|
vWhlBodyVec(eZ) = -vWhlBodyVec(eZ);
|
1999-12-20 20:25:13 +00:00
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
vLocalGear = State->GetTb2l() * vWhlBodyVec;
|
2001-03-30 01:04:50 +00:00
|
|
|
|
2001-12-13 04:48:34 +00:00
|
|
|
Debug(0);
|
2000-11-03 23:02:47 +00:00
|
|
|
}
|
1999-12-20 20:25:13 +00:00
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
Updates from the Jon and Tony show.
Tony submitted:
JSBsim:
Added trimming routine, it is longitudinal & in-air only at this point
Added support for taking wind & weather data from external source
Added support for flaps.
Added independently settable pitch trim
Added alphamin and max to config file, stall modeling and warning to
follow
c172.cfg:
Flaps!
Adjusted Cmo, model should be speed stable now
FG:
Hooked up Christian's weather code, should be using it soon.
Hooked up the trimming routine. Note that the X-15 will not trim.
This is not a model or trimming routine deficiency, just the
nature of the X-15
The trimming routine sets the pitch trim and and throttle at startup.
The throttle is set using Norman's code for the autothrottle so the
autothrottle is on by default. --notrim will turn it off.
Added --vc, --mach, and --notrim switches
(vc is airspeed in knots)
uBody, vBody, and wBody are still supported, last one entered
on the command line counts, i.e. you can set vc or mach or u,v,
and w but any combination will be ignored.
2000-05-16 21:35:11 +00:00
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
FGLGear::FGLGear(const FGLGear& lgear)
|
1999-12-20 20:25:13 +00:00
|
|
|
{
|
2000-11-03 23:02:47 +00:00
|
|
|
State = lgear.State;
|
|
|
|
Aircraft = lgear.Aircraft;
|
|
|
|
Position = lgear.Position;
|
|
|
|
Rotation = lgear.Rotation;
|
|
|
|
Exec = lgear.Exec;
|
2001-03-30 01:04:50 +00:00
|
|
|
FCS = lgear.FCS;
|
2001-06-05 20:58:48 +00:00
|
|
|
MassBalance = lgear.MassBalance;
|
2000-11-03 23:02:47 +00:00
|
|
|
|
|
|
|
vXYZ = lgear.vXYZ;
|
|
|
|
vMoment = lgear.vMoment;
|
|
|
|
vWhlBodyVec = lgear.vWhlBodyVec;
|
|
|
|
vLocalGear = lgear.vLocalGear;
|
|
|
|
|
|
|
|
WOW = lgear.WOW;
|
2001-11-20 22:34:24 +00:00
|
|
|
lastWOW = lgear.lastWOW;
|
2000-11-03 23:02:47 +00:00
|
|
|
ReportEnable = lgear.ReportEnable;
|
|
|
|
FirstContact = lgear.FirstContact;
|
|
|
|
DistanceTraveled = lgear.DistanceTraveled;
|
|
|
|
MaximumStrutForce = lgear.MaximumStrutForce;
|
|
|
|
MaximumStrutTravel = lgear.MaximumStrutTravel;
|
|
|
|
|
|
|
|
kSpring = lgear.kSpring;
|
|
|
|
bDamp = lgear.bDamp;
|
|
|
|
compressLength = lgear.compressLength;
|
|
|
|
compressSpeed = lgear.compressSpeed;
|
|
|
|
staticFCoeff = lgear.staticFCoeff;
|
|
|
|
dynamicFCoeff = lgear.dynamicFCoeff;
|
2001-03-30 01:04:50 +00:00
|
|
|
rollingFCoeff = lgear.rollingFCoeff;
|
2000-11-03 23:02:47 +00:00
|
|
|
brakePct = lgear.brakePct;
|
|
|
|
maxCompLen = lgear.maxCompLen;
|
|
|
|
SinkRate = lgear.SinkRate;
|
|
|
|
GroundSpeed = lgear.GroundSpeed;
|
|
|
|
Reported = lgear.Reported;
|
|
|
|
name = lgear.name;
|
2001-03-30 01:04:50 +00:00
|
|
|
sSteerType = lgear.sSteerType;
|
2001-12-14 03:35:41 +00:00
|
|
|
sRetractable = lgear.sRetractable;
|
2001-03-30 01:04:50 +00:00
|
|
|
eSteerType = lgear.eSteerType;
|
|
|
|
sBrakeGroup = lgear.sBrakeGroup;
|
2000-11-03 23:02:47 +00:00
|
|
|
eBrakeGrp = lgear.eBrakeGrp;
|
|
|
|
maxSteerAngle = lgear.maxSteerAngle;
|
2001-12-03 22:24:40 +00:00
|
|
|
isRetractable = lgear.isRetractable;
|
|
|
|
GearUp = lgear.GearUp;
|
|
|
|
GearDown = lgear.GearDown;
|
1999-12-20 20:25:13 +00:00
|
|
|
}
|
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
|
2001-03-30 01:04:50 +00:00
|
|
|
FGLGear::~FGLGear()
|
|
|
|
{
|
2001-12-13 04:48:34 +00:00
|
|
|
Debug(1);
|
2001-03-30 01:04:50 +00:00
|
|
|
}
|
2000-11-03 23:02:47 +00:00
|
|
|
|
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
Updates from the Jon and Tony show.
Tony submitted:
JSBsim:
Added trimming routine, it is longitudinal & in-air only at this point
Added support for taking wind & weather data from external source
Added support for flaps.
Added independently settable pitch trim
Added alphamin and max to config file, stall modeling and warning to
follow
c172.cfg:
Flaps!
Adjusted Cmo, model should be speed stable now
FG:
Hooked up Christian's weather code, should be using it soon.
Hooked up the trimming routine. Note that the X-15 will not trim.
This is not a model or trimming routine deficiency, just the
nature of the X-15
The trimming routine sets the pitch trim and and throttle at startup.
The throttle is set using Norman's code for the autothrottle so the
autothrottle is on by default. --notrim will turn it off.
Added --vc, --mach, and --notrim switches
(vc is airspeed in knots)
uBody, vBody, and wBody are still supported, last one entered
on the command line counts, i.e. you can set vc or mach or u,v,
and w but any combination will be ignored.
2000-05-16 21:35:11 +00:00
|
|
|
|
2001-10-05 20:19:59 +00:00
|
|
|
FGColumnVector3& FGLGear::Force(void)
|
1999-12-20 20:25:13 +00:00
|
|
|
{
|
2001-12-03 22:24:40 +00:00
|
|
|
vForce.InitMatrix();
|
|
|
|
vMoment.InitMatrix();
|
2001-12-07 17:10:17 +00:00
|
|
|
|
|
|
|
if (isRetractable) {
|
|
|
|
if (FCS->GetGearPos() < 0.01) {
|
|
|
|
GearUp = true;
|
|
|
|
GearDown = false;
|
|
|
|
} else if (FCS->GetGearPos() > 0.99) {
|
|
|
|
GearDown = true;
|
|
|
|
GearUp = false;
|
2001-12-03 22:24:40 +00:00
|
|
|
} else {
|
2001-12-07 17:10:17 +00:00
|
|
|
GearUp = false;
|
|
|
|
GearDown = false;
|
2001-12-03 22:24:40 +00:00
|
|
|
}
|
|
|
|
} else {
|
2001-12-07 17:10:17 +00:00
|
|
|
GearUp = false;
|
|
|
|
GearDown = true;
|
2001-12-03 22:24:40 +00:00
|
|
|
}
|
|
|
|
|
2001-12-07 17:10:17 +00:00
|
|
|
if (GearDown) {
|
2001-12-03 22:24:40 +00:00
|
|
|
double SteerGain = 0;
|
|
|
|
double SinWheel, CosWheel, SideWhlVel, RollingWhlVel;
|
|
|
|
double RollingForce, SideForce, FCoeff;
|
|
|
|
double WheelSlip;
|
|
|
|
|
|
|
|
vWhlBodyVec = (vXYZ - MassBalance->GetXYZcg()) / 12.0;
|
|
|
|
vWhlBodyVec(eX) = -vWhlBodyVec(eX);
|
|
|
|
vWhlBodyVec(eZ) = -vWhlBodyVec(eZ);
|
2000-05-27 05:48:14 +00:00
|
|
|
|
2001-04-05 21:14:37 +00:00
|
|
|
// vWhlBodyVec now stores the vector from the cg to this wheel
|
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
vLocalGear = State->GetTb2l() * vWhlBodyVec;
|
2001-04-05 21:14:37 +00:00
|
|
|
|
|
|
|
// vLocalGear now stores the vector from the cg to the wheel in local coords.
|
2001-03-30 01:04:50 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
compressLength = vLocalGear(eZ) - Position->GetDistanceAGL();
|
2000-05-27 05:48:14 +00:00
|
|
|
|
2001-04-05 21:14:37 +00:00
|
|
|
// The compression length is currently measured in the Z-axis, only, at this time.
|
|
|
|
// It should be measured along the strut axis. If the local-frame gear position
|
|
|
|
// "hangs down" below the CG greater than the altitude, then the compressLength
|
|
|
|
// will be positive - i.e. the gear will have made contact.
|
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
if (compressLength > 0.00) {
|
2001-04-05 21:14:37 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
WOW = true;// Weight-On-Wheels is true
|
2001-03-30 01:04:50 +00:00
|
|
|
|
|
|
|
// The next equation should really use the vector to the contact patch of the tire
|
|
|
|
// including the strut compression and not vWhlBodyVec. Will fix this later.
|
2001-04-05 21:14:37 +00:00
|
|
|
// As it stands, now, the following equation takes the aircraft body-frame
|
|
|
|
// rotational rate and calculates the cross-product with the vector from the CG
|
|
|
|
// to the wheel, thus producing the instantaneous velocity vector of the tire
|
|
|
|
// in Body coords. The frame is also converted to local coordinates. When the
|
|
|
|
// aircraft local-frame velocity is added to this quantity, the total velocity of
|
|
|
|
// the wheel in local frame is then known. Subsequently, the compression speed
|
|
|
|
// (used for calculating damping force) is found by taking the Z-component of the
|
|
|
|
// wheel velocity.
|
2001-03-30 01:04:50 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
vWhlVelVec = State->GetTb2l() * (Rotation->GetPQR() * vWhlBodyVec);
|
2001-10-05 20:19:59 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
vWhlVelVec += Position->GetVel();
|
2000-07-06 21:02:46 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
compressSpeed = vWhlVelVec(eZ);
|
2000-05-27 05:48:14 +00:00
|
|
|
|
2001-04-05 21:14:37 +00:00
|
|
|
// If this is the first time the wheel has made contact, remember some values
|
|
|
|
// for later printout.
|
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
if (!FirstContact) {
|
|
|
|
FirstContact = true;
|
|
|
|
SinkRate = compressSpeed;
|
|
|
|
GroundSpeed = Position->GetVel().Magnitude();
|
|
|
|
}
|
2000-07-06 21:02:46 +00:00
|
|
|
|
2001-03-30 01:04:50 +00:00
|
|
|
// The following needs work regarding friction coefficients and braking and
|
|
|
|
// steering The BrakeFCoeff formula assumes that an anti-skid system is used.
|
|
|
|
// It also assumes that we won't be turning and braking at the same time.
|
|
|
|
// Will fix this later.
|
2001-04-05 21:14:37 +00:00
|
|
|
// [JSB] The braking force coefficients include normal rolling coefficient +
|
|
|
|
// a percentage of the static friction coefficient based on braking applied.
|
2000-10-09 21:16:21 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
switch (eBrakeGrp) {
|
|
|
|
case bgLeft:
|
|
|
|
SteerGain = -0.10;
|
|
|
|
BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) +
|
|
|
|
staticFCoeff*FCS->GetBrake(bgLeft);
|
|
|
|
break;
|
|
|
|
case bgRight:
|
|
|
|
SteerGain = -0.10;
|
|
|
|
BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) +
|
|
|
|
staticFCoeff*FCS->GetBrake(bgRight);
|
|
|
|
break;
|
|
|
|
case bgCenter:
|
|
|
|
SteerGain = -0.10;
|
|
|
|
BrakeFCoeff = rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) +
|
|
|
|
staticFCoeff*FCS->GetBrake(bgCenter);
|
|
|
|
break;
|
|
|
|
case bgNose:
|
|
|
|
SteerGain = 0.10;
|
|
|
|
BrakeFCoeff = rollingFCoeff;
|
|
|
|
break;
|
|
|
|
case bgTail:
|
|
|
|
SteerGain = -0.10;
|
|
|
|
BrakeFCoeff = rollingFCoeff;
|
|
|
|
break;
|
|
|
|
case bgNone:
|
|
|
|
SteerGain = -0.10;
|
|
|
|
BrakeFCoeff = rollingFCoeff;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cerr << "Improper brake group membership detected for this gear." << endl;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (eSteerType) {
|
|
|
|
case stSteer:
|
|
|
|
SteerAngle = SteerGain*FCS->GetDrPos();
|
|
|
|
break;
|
|
|
|
case stFixed:
|
|
|
|
SteerAngle = 0.0;
|
|
|
|
break;
|
|
|
|
case stCaster:
|
|
|
|
// Note to Jon: This is not correct for castering gear. I'll fix it later.
|
|
|
|
SteerAngle = 0.0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cerr << "Improper steering type membership detected for this gear." << endl;
|
|
|
|
break;
|
|
|
|
}
|
2001-03-30 01:04:50 +00:00
|
|
|
|
|
|
|
// Transform the wheel velocities from the local axis system to the wheel axis system.
|
|
|
|
// For now, steering angle is assumed to happen in the Local Z axis,
|
|
|
|
// not the strut axis as it should be. Will fix this later.
|
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
SinWheel = sin(Rotation->Getpsi() + SteerAngle);
|
|
|
|
CosWheel = cos(Rotation->Getpsi() + SteerAngle);
|
|
|
|
RollingWhlVel = vWhlVelVec(eX)*CosWheel + vWhlVelVec(eY)*SinWheel;
|
|
|
|
SideWhlVel = vWhlVelVec(eY)*CosWheel - vWhlVelVec(eX)*SinWheel;
|
2001-03-30 01:04:50 +00:00
|
|
|
|
|
|
|
// Calculate tire slip angle.
|
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
if (RollingWhlVel == 0.0 && SideWhlVel == 0.0) {
|
|
|
|
WheelSlip = 0.0;
|
|
|
|
} else {
|
|
|
|
WheelSlip = radtodeg*atan2(SideWhlVel, RollingWhlVel);
|
|
|
|
}
|
2001-03-30 01:04:50 +00:00
|
|
|
|
2001-04-05 21:14:37 +00:00
|
|
|
// The following code normalizes the wheel velocity vector, reverses it, and zeroes out
|
|
|
|
// the z component of the velocity. The question is, should the Z axis velocity be zeroed
|
|
|
|
// out first before the normalization takes place or not? Subsequent to that, the Wheel
|
|
|
|
// Velocity vector now points as a unit vector backwards and parallel to the wheel
|
|
|
|
// velocity vector. It acts AT the wheel.
|
2001-03-30 01:04:50 +00:00
|
|
|
|
|
|
|
// Note to Jon: I commented out this line because I wasn't sure we want to do this.
|
|
|
|
// vWhlVelVec = -1.0 * vWhlVelVec.Normalize();
|
|
|
|
// vWhlVelVec(eZ) = 0.00;
|
|
|
|
|
|
|
|
// Compute the sideforce coefficients using similar assumptions to LaRCSim for now.
|
|
|
|
// Allow a maximum of 10 degrees tire slip angle before wheel slides. At that point,
|
|
|
|
// transition from static to dynamic friction. There are more complicated formulations
|
|
|
|
// of this that avoid the discrete jump. Will fix this later.
|
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
if (fabs(WheelSlip) <= 10.0) {
|
|
|
|
FCoeff = staticFCoeff*WheelSlip/10.0;
|
|
|
|
} else {
|
|
|
|
FCoeff = dynamicFCoeff*fabs(WheelSlip)/WheelSlip;
|
|
|
|
}
|
2001-03-30 01:04:50 +00:00
|
|
|
|
2001-04-17 21:19:54 +00:00
|
|
|
// Compute the vertical force on the wheel using square-law damping (per comment
|
|
|
|
// in paper AIAA-2000-4303 - see header prologue comments). We might consider
|
|
|
|
// allowing for both square and linear damping force calculation. Also need to
|
|
|
|
// possibly give a "rebound damping factor" that differs from the compression
|
|
|
|
// case. NOTE: SQUARE LAW DAMPING NO GOOD!
|
2000-11-03 23:02:47 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
vLocalForce(eZ) = min(-compressLength * kSpring
|
|
|
|
- compressSpeed * bDamp, (double)0.0);
|
2000-05-27 05:48:14 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
MaximumStrutForce = max(MaximumStrutForce, fabs(vLocalForce(eZ)));
|
|
|
|
MaximumStrutTravel = max(MaximumStrutTravel, fabs(compressLength));
|
2000-07-06 21:02:46 +00:00
|
|
|
|
2001-03-30 01:04:50 +00:00
|
|
|
// Compute the forces in the wheel ground plane.
|
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
RollingForce = 0;
|
|
|
|
if (fabs(RollingWhlVel) > 1E-3) {
|
|
|
|
RollingForce = vLocalForce(eZ) * BrakeFCoeff * fabs(RollingWhlVel)/RollingWhlVel;
|
|
|
|
}
|
|
|
|
SideForce = vLocalForce(eZ) * FCoeff;
|
2001-03-30 01:04:50 +00:00
|
|
|
|
|
|
|
// Transform these forces back to the local reference frame.
|
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
vLocalForce(eX) = RollingForce*CosWheel - SideForce*SinWheel;
|
|
|
|
vLocalForce(eY) = SideForce*CosWheel + RollingForce*SinWheel;
|
2001-03-30 01:04:50 +00:00
|
|
|
|
2001-04-17 21:19:54 +00:00
|
|
|
// Note to Jon: At this point the forces will be too big when the airplane is
|
|
|
|
// stopped or rolling to a stop. We need to make sure that the gear forces just
|
|
|
|
// balance out the non-gear forces when the airplane is stopped. That way the
|
|
|
|
// airplane won't start to accelerate until the non-gear/ forces are larger than
|
|
|
|
// the gear forces. I think that the proper fix should go into FGAircraft::FMGear.
|
|
|
|
// This routine would only compute the local strut forces and return them to
|
|
|
|
// FMGear. All of the gear forces would get adjusted in FMGear using the total
|
|
|
|
// non-gear forces. Then the gear moments would be calculated. If strange things
|
|
|
|
// start happening to the airplane during testing as it rolls to a stop, then we
|
|
|
|
// need to implement this change. I ran out of time to do it now but have the
|
|
|
|
// equations.
|
2001-03-30 01:04:50 +00:00
|
|
|
|
|
|
|
// Transform the forces back to the body frame and compute the moment.
|
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
vForce = State->GetTl2b() * vLocalForce;
|
|
|
|
vMoment = vWhlBodyVec * vForce;
|
2000-10-02 23:07:30 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
} else {
|
2000-05-27 05:48:14 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
WOW = false;
|
2000-07-06 21:02:46 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
if (Position->GetDistanceAGL() > 200.0) {
|
|
|
|
FirstContact = false;
|
|
|
|
Reported = false;
|
|
|
|
DistanceTraveled = 0.0;
|
|
|
|
MaximumStrutForce = MaximumStrutTravel = 0.0;
|
|
|
|
}
|
2000-07-06 21:02:46 +00:00
|
|
|
|
2001-12-13 04:48:34 +00:00
|
|
|
compressLength = 0.0; // reset compressLength to zero for data output validity
|
2001-12-03 22:24:40 +00:00
|
|
|
}
|
Updates from the Jon and Tony show.
Tony submitted:
JSBsim:
Added trimming routine, it is longitudinal & in-air only at this point
Added support for taking wind & weather data from external source
Added support for flaps.
Added independently settable pitch trim
Added alphamin and max to config file, stall modeling and warning to
follow
c172.cfg:
Flaps!
Adjusted Cmo, model should be speed stable now
FG:
Hooked up Christian's weather code, should be using it soon.
Hooked up the trimming routine. Note that the X-15 will not trim.
This is not a model or trimming routine deficiency, just the
nature of the X-15
The trimming routine sets the pitch trim and and throttle at startup.
The throttle is set using Norman's code for the autothrottle so the
autothrottle is on by default. --notrim will turn it off.
Added --vc, --mach, and --notrim switches
(vc is airspeed in knots)
uBody, vBody, and wBody are still supported, last one entered
on the command line counts, i.e. you can set vc or mach or u,v,
and w but any combination will be ignored.
2000-05-16 21:35:11 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
if (FirstContact) {
|
|
|
|
DistanceTraveled += Position->GetVel().Magnitude()*State->Getdt()*Aircraft->GetRate();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ReportEnable && Position->GetVel().Magnitude() <= 0.05 && !Reported) {
|
|
|
|
if (debug_lvl > 0) Report();
|
|
|
|
}
|
2000-07-06 21:02:46 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
if (lastWOW != WOW) {
|
|
|
|
PutMessage("GEAR_CONTACT", WOW);
|
|
|
|
}
|
2001-04-05 21:14:37 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
lastWOW = WOW;
|
2001-11-20 22:34:24 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
// Crash detection logic (really out-of-bounds detection)
|
2001-11-20 22:34:24 +00:00
|
|
|
|
2001-12-03 22:24:40 +00:00
|
|
|
if (compressLength > 500.0 ||
|
|
|
|
vForce.Magnitude() > 100000000.0 ||
|
|
|
|
vMoment.Magnitude() > 5000000000.0 ||
|
|
|
|
SinkRate > 1.4666*30)
|
|
|
|
{
|
|
|
|
PutMessage("Crash Detected");
|
|
|
|
Exec->Freeze();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return vForce;
|
1999-12-20 20:25:13 +00:00
|
|
|
}
|
|
|
|
|
2000-11-03 23:02:47 +00:00
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
1999-12-20 20:25:13 +00:00
|
|
|
|
2000-07-06 21:02:46 +00:00
|
|
|
void FGLGear::Report(void)
|
|
|
|
{
|
|
|
|
cout << endl << "Touchdown report for " << name << endl;
|
|
|
|
cout << " Sink rate at contact: " << SinkRate << " fps, "
|
|
|
|
<< SinkRate*0.3408 << " mps" << endl;
|
|
|
|
cout << " Contact ground speed: " << GroundSpeed*.5925 << " knots, "
|
|
|
|
<< GroundSpeed*0.3408 << " mps" << endl;
|
|
|
|
cout << " Maximum contact force: " << MaximumStrutForce << " lbs, "
|
|
|
|
<< MaximumStrutForce*4.448 << " Newtons" << endl;
|
|
|
|
cout << " Maximum strut travel: " << MaximumStrutTravel*12.0 << " inches, "
|
|
|
|
<< MaximumStrutTravel*30.48 << " cm" << endl;
|
|
|
|
cout << " Distance traveled: " << DistanceTraveled << " ft, "
|
|
|
|
<< DistanceTraveled*0.3408 << " meters" << endl;
|
|
|
|
Reported = true;
|
|
|
|
}
|
|
|
|
|
2001-03-30 01:04:50 +00:00
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
2001-12-13 04:48:34 +00:00
|
|
|
// The bitmasked value choices are as follows:
|
|
|
|
// unset: In this case (the default) JSBSim would only print
|
|
|
|
// out the normally expected messages, essentially echoing
|
|
|
|
// the config files as they are read. If the environment
|
|
|
|
// variable is not set, debug_lvl is set to 1 internally
|
|
|
|
// 0: This requests JSBSim not to output any messages
|
|
|
|
// whatsoever.
|
|
|
|
// 1: This value explicity requests the normal JSBSim
|
|
|
|
// startup messages
|
|
|
|
// 2: This value asks for a message to be printed out when
|
|
|
|
// a class is instantiated
|
|
|
|
// 4: When this value is set, a message is displayed when a
|
|
|
|
// FGModel object executes its Run() method
|
|
|
|
// 8: When this value is set, various runtime state variables
|
|
|
|
// are printed out periodically
|
|
|
|
// 16: When set various parameters are sanity checked and
|
|
|
|
// a message is printed out when they go out of bounds
|
|
|
|
|
|
|
|
void FGLGear::Debug(int from)
|
2001-03-30 01:04:50 +00:00
|
|
|
{
|
2001-12-13 04:48:34 +00:00
|
|
|
if (debug_lvl <= 0) return;
|
|
|
|
|
|
|
|
if (debug_lvl & 1) { // Standard console startup message output
|
|
|
|
if (from == 0) { // Constructor
|
2001-12-14 03:35:41 +00:00
|
|
|
cout << " Name: " << name << endl;
|
|
|
|
cout << " Location: " << vXYZ << endl;
|
|
|
|
cout << " Spring Constant: " << kSpring << endl;
|
|
|
|
cout << " Damping Constant: " << bDamp << endl;
|
2001-12-13 04:48:34 +00:00
|
|
|
cout << " Dynamic Friction: " << dynamicFCoeff << endl;
|
2001-12-14 03:35:41 +00:00
|
|
|
cout << " Static Friction: " << staticFCoeff << endl;
|
2001-12-13 04:48:34 +00:00
|
|
|
cout << " Rolling Friction: " << rollingFCoeff << endl;
|
2001-12-14 03:35:41 +00:00
|
|
|
cout << " Steering Type: " << sSteerType << endl;
|
|
|
|
cout << " Grouping: " << sBrakeGroup << endl;
|
2001-12-13 04:48:34 +00:00
|
|
|
cout << " Max Steer Angle: " << maxSteerAngle << endl;
|
2001-12-14 03:35:41 +00:00
|
|
|
cout << " Retractable: " << sRetractable << endl;
|
2001-12-13 04:48:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (debug_lvl & 2 ) { // Instantiation/Destruction notification
|
|
|
|
if (from == 0) cout << "Instantiated: FGLGear" << endl;
|
|
|
|
if (from == 1) cout << "Destroyed: FGLGear" << endl;
|
|
|
|
}
|
|
|
|
if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
|
|
|
|
}
|
|
|
|
if (debug_lvl & 8 ) { // Runtime state variables
|
|
|
|
}
|
|
|
|
if (debug_lvl & 16) { // Sanity checking
|
|
|
|
}
|
2001-12-24 13:54:55 +00:00
|
|
|
if (debug_lvl & 64) {
|
|
|
|
if (from == 0) { // Constructor
|
|
|
|
cout << IdSrc << endl;
|
|
|
|
cout << IdHdr << endl;
|
|
|
|
}
|
|
|
|
}
|
2001-03-30 01:04:50 +00:00
|
|
|
}
|
|
|
|
|