📄 fglgear.cpp
字号:
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Module: FGLGear.cpp Author: Jon S. Berndt Norman H. Princen 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 Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser 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 Lesser General Public License can also be found on the world wide web at http://www.gnu.org.FUNCTIONAL DESCRIPTION--------------------------------------------------------------------------------HISTORY--------------------------------------------------------------------------------11/18/99 JSB Created01/30/01 NHP Extended gear model to properly simulate steering and braking/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%INCLUDES%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/#include "FGLGear.h"namespace JSBSim {/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%DEFINITIONS%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*//*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%GLOBAL DATA%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/static const char *IdSrc = "$Id$";static const char *IdHdr = ID_LGEAR;/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%CLASS IMPLEMENTATION%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) : Exec(fdmex), GearNumber(number){ Element *force_table=0; Element *dampCoeff=0; Element *dampCoeffRebound=0; string force_type=""; kSpring = bDamp = bDampRebound = dynamicFCoeff = staticFCoeff = rollingFCoeff = maxSteerAngle = 0; sSteerType = sBrakeGroup = sSteerType = ""; isRetractable = 0; eDampType = dtLinear; eDampTypeRebound = dtLinear; name = el->GetAttributeValue("name"); sContactType = el->GetAttributeValue("type"); if (sContactType == "BOGEY") { eContactType = ctBOGEY; } else if (sContactType == "STRUCTURE") { eContactType = ctSTRUCTURE; } else { eContactType = ctUNKNOWN; } if (el->FindElement("spring_coeff")) kSpring = el->FindElementValueAsNumberConvertTo("spring_coeff", "LBS/FT"); if (el->FindElement("damping_coeff")) { dampCoeff = el->FindElement("damping_coeff"); if (dampCoeff->GetAttributeValue("type") == "SQUARE") { eDampType = dtSquare; bDamp = el->FindElementValueAsNumberConvertTo("damping_coeff", "LBS/FT2/SEC2"); } else { bDamp = el->FindElementValueAsNumberConvertTo("damping_coeff", "LBS/FT/SEC"); } } if (el->FindElement("damping_coeff_rebound")) { dampCoeffRebound = el->FindElement("damping_coeff_rebound"); if (dampCoeffRebound->GetAttributeValue("type") == "SQUARE") { eDampTypeRebound = dtSquare; bDampRebound = el->FindElementValueAsNumberConvertTo("damping_coeff_rebound", "LBS/FT2/SEC2"); } else { bDampRebound = el->FindElementValueAsNumberConvertTo("damping_coeff_rebound", "LBS/FT/SEC"); } } else { bDampRebound = bDamp; eDampTypeRebound = eDampType; } if (el->FindElement("dynamic_friction")) dynamicFCoeff = el->FindElementValueAsNumber("dynamic_friction"); if (el->FindElement("static_friction")) staticFCoeff = el->FindElementValueAsNumber("static_friction"); if (el->FindElement("rolling_friction")) rollingFCoeff = el->FindElementValueAsNumber("rolling_friction"); if (el->FindElement("max_steer")) maxSteerAngle = el->FindElementValueAsNumberConvertTo("max_steer", "DEG"); if (el->FindElement("retractable")) isRetractable = ((unsigned int)el->FindElementValueAsNumber("retractable"))>0.0?true:false; ForceY_Table = 0; force_table = el->FindElement("table"); while (force_table) { force_type = force_table->GetAttributeValue("type"); if (force_type == "CORNERING_COEFF") { ForceY_Table = new FGTable(Exec->GetPropertyManager(), force_table); } else { cerr << "Undefined force table for " << name << " contact point" << endl; } force_table = el->FindNextElement("table"); } sBrakeGroup = el->FindElementValue("brake_group"); if (maxSteerAngle == 360) sSteerType = "CASTERED"; else if (maxSteerAngle == 0.0) sSteerType = "FIXED"; else sSteerType = "STEERABLE"; Element* element = el->FindElement("location"); if (element) vXYZ = element->FindElementTripletConvertTo("IN"); else {cerr << "No location given for contact " << name << endl; exit(-1);} 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; else if (sBrakeGroup.empty() ) {eBrakeGrp = bgNone; sBrakeGroup = "NONE (defaulted)";} else { cerr << "Improper braking group specification in config file: " << sBrakeGroup << " is undefined." << endl; } if (sSteerType == "STEERABLE") eSteerType = stSteer; else if (sSteerType == "FIXED" ) eSteerType = stFixed; else if (sSteerType == "CASTERED" ) eSteerType = stCaster; else if (sSteerType.empty() ) {eSteerType = stFixed; sSteerType = "FIXED (defaulted)";} else { cerr << "Improper steering type specification in config file: " << sSteerType << " is undefined." << endl; } RFRV = 0.7; // Rolling force relaxation velocity, default value SFRV = 0.7; // Side force relaxation velocity, default value Element* relax_vel = el->FindElement("relaxation_velocity"); if (relax_vel) { if (relax_vel->FindElement("rolling")) { RFRV = relax_vel->FindElementValueAsNumberConvertTo("rolling", "FT/SEC"); } if (relax_vel->FindElement("side")) { SFRV = relax_vel->FindElementValueAsNumberConvertTo("side", "FT/SEC"); } } State = Exec->GetState(); LongForceLagFilterCoeff = 1/State->Getdt(); // default longitudinal force filter coefficient LatForceLagFilterCoeff = 1/State->Getdt(); // default lateral force filter coefficient Element* force_lag_filter_elem = el->FindElement("force_lag_filter"); if (force_lag_filter_elem) { if (force_lag_filter_elem->FindElement("rolling")) { LongForceLagFilterCoeff = force_lag_filter_elem->FindElementValueAsNumber("rolling"); } if (force_lag_filter_elem->FindElement("side")) { LatForceLagFilterCoeff = force_lag_filter_elem->FindElementValueAsNumber("side"); } } WheelSlipLagFilterCoeff = 1/State->Getdt(); Element *wheel_slip_angle_lag_elem = el->FindElement("wheel_slip_filter"); if (wheel_slip_angle_lag_elem) { WheelSlipLagFilterCoeff = wheel_slip_angle_lag_elem->GetDataAsNumber(); } GearUp = false; GearDown = true; GearPos = 1.0; useFCSGearPos = false; Servicable = true;// Add some AI here to determine if gear is located properly according to its// brake group type ?? State = Exec->GetState(); Aircraft = Exec->GetAircraft(); Propagate = Exec->GetPropagate(); Auxiliary = Exec->GetAuxiliary(); FCS = Exec->GetFCS(); MassBalance = Exec->GetMassBalance(); WOW = lastWOW = false; ReportEnable = true; FirstContact = false; StartedGroundRun = false; TakeoffReported = LandingReported = false; LandingDistanceTraveled = TakeoffDistanceTraveled = TakeoffDistanceTraveled50ft = 0.0; MaximumStrutForce = MaximumStrutTravel = 0.0; SideForce = RollingForce = 0.0; SinkRate = GroundSpeed = 0.0; vWhlBodyVec = MassBalance->StructuralToBody(vXYZ); vLocalGear = Propagate->GetTb2l() * vWhlBodyVec; compressLength = 0.0; compressSpeed = 0.0; brakePct = 0.0; maxCompLen = 0.0; WheelSlip = 0.0; TirePressureNorm = 1.0; SideWhlVel = 0.0; RollingWhlVel = 0.0; SinWheel = 0.0; CosWheel = 0.0; prevSlipIn = 0.0; prevSlipOut = 0.0; Debug(0);}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%FGLGear::FGLGear(const FGLGear& lgear){ GearNumber = lgear.GearNumber; State = lgear.State; Aircraft = lgear.Aircraft; Propagate = lgear.Propagate; Auxiliary = lgear.Auxiliary; Exec = lgear.Exec; FCS = lgear.FCS; MassBalance = lgear.MassBalance; vXYZ = lgear.vXYZ; vMoment = lgear.vMoment; vWhlBodyVec = lgear.vWhlBodyVec; vLocalGear = lgear.vLocalGear; WOW = lgear.WOW; lastWOW = lgear.lastWOW; ReportEnable = lgear.ReportEnable; FirstContact = lgear.FirstContact; StartedGroundRun = lgear.StartedGroundRun; LandingDistanceTraveled = lgear.LandingDistanceTraveled; TakeoffDistanceTraveled = lgear.TakeoffDistanceTraveled; TakeoffDistanceTraveled50ft = lgear.TakeoffDistanceTraveled50ft; MaximumStrutForce = lgear.MaximumStrutForce; MaximumStrutTravel = lgear.MaximumStrutTravel; SideForce = lgear.SideForce; RollingForce = lgear.RollingForce; kSpring = lgear.kSpring; bDamp = lgear.bDamp; bDampRebound = lgear.bDampRebound; compressLength = lgear.compressLength; compressSpeed = lgear.compressSpeed; staticFCoeff = lgear.staticFCoeff; dynamicFCoeff = lgear.dynamicFCoeff; rollingFCoeff = lgear.rollingFCoeff; brakePct = lgear.brakePct; maxCompLen = lgear.maxCompLen; SinkRate = lgear.SinkRate; GroundSpeed = lgear.GroundSpeed; LandingReported = lgear.LandingReported; TakeoffReported = lgear.TakeoffReported; name = lgear.name; sSteerType = lgear.sSteerType; sRetractable = lgear.sRetractable; sContactType = lgear.sContactType; eContactType = lgear.eContactType; sBrakeGroup = lgear.sBrakeGroup; eSteerType = lgear.eSteerType; eBrakeGrp = lgear.eBrakeGrp; maxSteerAngle = lgear.maxSteerAngle; isRetractable = lgear.isRetractable; GearUp = lgear.GearUp; GearDown = lgear.GearDown; GearPos = lgear.GearPos; useFCSGearPos = lgear.useFCSGearPos; WheelSlip = lgear.WheelSlip; TirePressureNorm = lgear.TirePressureNorm; Servicable = lgear.Servicable; ForceY_Table = lgear.ForceY_Table; CosWheel = lgear.CosWheel; SinWheel = lgear.SinWheel; prevOut = lgear.prevOut; prevIn = lgear.prevIn; prevSlipIn = lgear.prevSlipIn; prevSlipOut = lgear.prevSlipOut; RFRV = lgear.RFRV; SFRV = lgear.SFRV; LongForceLagFilterCoeff = lgear.LongForceLagFilterCoeff; LatForceLagFilterCoeff = lgear.LatForceLagFilterCoeff; WheelSlipLagFilterCoeff = lgear.WheelSlipLagFilterCoeff;}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%FGLGear::~FGLGear(){ Debug(1);}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%FGColumnVector3& FGLGear::Force(void){ double t = Exec->GetState()->Getsim_time(); dT = State->Getdt()*Exec->GetGroundReactions()->GetRate(); vForce.InitMatrix(); vMoment.InitMatrix(); if (isRetractable) ComputeRetractionState(); if (!GearDown) return vForce; // return the null vForce column vector vWhlBodyVec = MassBalance->StructuralToBody(vXYZ); // Get wheel in body frame vLocalGear = Propagate->GetTb2l() * vWhlBodyVec; // Get local frame wheel location gearLoc = Propagate->GetLocation().LocalToLocation(vLocalGear); compressLength = -Exec->GetGroundCallback()->GetAGLevel(t, gearLoc, contact, normal, cvel); // The compression length is measured in the Z-axis, only, at this time. if (compressLength > 0.00) { WOW = true; // [The next equation should really use the vector to the contact patch of // the tire including the strut compression and not the original vWhlBodyVec.] vWhlVelVec = Propagate->GetTb2l() * (Propagate->GetPQR() * vWhlBodyVec); vWhlVelVec += Propagate->GetVel() - cvel; compressSpeed = vWhlVelVec(eZ); InitializeReporting(); ComputeBrakeForceCoefficient(); ComputeSteeringAngle(); ComputeSlipAngle(); ComputeSideForceCoefficient(); ComputeVerticalStrutForce(); // Compute the forces in the wheel ground plane. double sign = RollingWhlVel>0?1.0:(RollingWhlVel<0?-1.0:0.0); RollingForce = ((1.0 - TirePressureNorm) * 30 + vLocalForce(eZ) * BrakeFCoeff) * sign; SideForce = vLocalForce(eZ) * FCoeff; // Transform these forces back to the local reference frame. vLocalForce(eX) = RollingForce*CosWheel - SideForce*SinWheel; vLocalForce(eY) = SideForce*CosWheel + RollingForce*SinWheel; // Transform the forces back to the body frame and compute the moment. vForce = Propagate->GetTl2b() * vLocalForce;// Start experimental section for gear jitter reduction//// Lag and attenuate the XY-plane forces dependent on velocity double ca, cb, denom; FGColumnVector3 Output;// This code implements a lag filter, C/(s + C) where// "C" is the filter coefficient. When "C" is chosen at the // frame rate (in Hz), the jittering is significantly reduced. This is because// the jitter is present *at* the execution rate.// If a coefficient is set to something equal to or less than zero, the filter// is bypassed. if (LongForceLagFilterCoeff > 0) { denom = 2.00 + dT*LongForceLagFilterCoeff; ca = dT*LongForceLagFilterCoeff / denom; cb = (2.00 - dT*LongForceLagFilterCoeff) / denom; Output(eX) = vForce(eX) * ca + prevIn(eX) * ca + prevOut(eX) * cb; vForce(eX) = Output(eX); } if (LatForceLagFilterCoeff > 0) { denom = 2.00 + dT*LatForceLagFilterCoeff; ca = dT*LatForceLagFilterCoeff / denom; cb = (2.00 - dT*LatForceLagFilterCoeff) / denom; Output(eY) = vForce(eY) * ca + prevIn(eY) * ca + prevOut(eY) * cb; vForce(eY) = Output(eY); } prevIn = vForce; prevOut = Output; if ((fabs(RollingWhlVel) <= RFRV) && RFRV > 0) vForce(eX) *= fabs(RollingWhlVel)/RFRV; if ((fabs(SideWhlVel) <= SFRV) && SFRV > 0) vForce(eY) *= fabs(SideWhlVel)/SFRV;// End section for attentuating gear jitter vMoment = vWhlBodyVec * vForce; } else { // Gear is NOT compressed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -