📄 fglgear.cpp
字号:
WOW = false; compressLength = 0.0; // Return to neutral position between 1.0 and 0.8 gear pos. SteerAngle *= max(GetGearUnitPos()-0.8, 0.0)/0.2; ResetReporting(); } ReportTakeoffOrLanding(); // Require both WOW and LastWOW to be true before checking crash conditions // to allow the WOW flag to be used in terminating a scripted run. if (WOW && lastWOW) CrashDetect(); lastWOW = WOW; return vForce;}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%void FGLGear::ComputeRetractionState(void){ double gearPos = GetGearUnitPos(); if (gearPos < 0.01) { GearUp = true; GearDown = false; } else if (gearPos > 0.99) { GearDown = true; GearUp = false; } else { GearUp = false; GearDown = false; }}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%void FGLGear::ComputeSlipAngle(void){ // Transform the wheel velocities from the local axis system to the wheel axis system. RollingWhlVel = vWhlVelVec(eX)*CosWheel + vWhlVelVec(eY)*SinWheel; SideWhlVel = vWhlVelVec(eY)*CosWheel - vWhlVelVec(eX)*SinWheel; // Calculate tire slip angle. WheelSlip = atan2(SideWhlVel, fabs(RollingWhlVel))*radtodeg; // Filter the wheel slip angle double SlipOutput, ca, cb, denom; if (WheelSlipLagFilterCoeff > 0) { denom = 2.00 + dT*WheelSlipLagFilterCoeff; ca = dT*WheelSlipLagFilterCoeff / denom; cb = (2.00 - dT*WheelSlipLagFilterCoeff) / denom; SlipOutput = ca * (WheelSlip + prevSlipIn) + cb * prevSlipOut; prevSlipIn = WheelSlip; WheelSlip = prevSlipOut = SlipOutput; }}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%// Compute the steering angle in any case.// This will also make sure that animations will look right.void FGLGear::ComputeSteeringAngle(void){ double casterLocalFrameAngleRad = 0.0; double casterAngle = 0.0; switch (eSteerType) { case stSteer: SteerAngle = degtorad * FCS->GetSteerPosDeg(GearNumber); break; case stFixed: SteerAngle = 0.0; break; case stCaster: // This is not correct for castering gear. Should make steer angle parallel // to the actual velocity vector of the wheel, given aircraft velocity vector // and omega. SteerAngle = 0.0; casterLocalFrameAngleRad = acos(vWhlVelVec(eX)/vWhlVelVec.Magnitude()); casterAngle = casterLocalFrameAngleRad - Propagate->GetEuler(ePsi); break; default: cerr << "Improper steering type membership detected for this gear." << endl; break; } SinWheel = sin(Propagate->GetEuler(ePsi) + SteerAngle); CosWheel = cos(Propagate->GetEuler(ePsi) + SteerAngle);}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%// Reset reporting functionality after takeoffvoid FGLGear::ResetReporting(void){ if (Propagate->GetDistanceAGL() > 200.0) { FirstContact = false; StartedGroundRun = false; LandingReported = false; TakeoffReported = true; LandingDistanceTraveled = 0.0; MaximumStrutForce = MaximumStrutTravel = 0.0; }}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%void FGLGear::InitializeReporting(void){ // If this is the first time the wheel has made contact, remember some values // for later printout. if (!FirstContact) { FirstContact = true; SinkRate = compressSpeed; GroundSpeed = Propagate->GetVel().Magnitude(); TakeoffReported = false; } // If the takeoff run is starting, initialize. if ((Propagate->GetVel().Magnitude() > 0.1) && (FCS->GetBrake(bgLeft) == 0) && (FCS->GetBrake(bgRight) == 0) && (FCS->GetThrottlePos(0) > 0.90) && !StartedGroundRun) { TakeoffDistanceTraveled = 0; TakeoffDistanceTraveled50ft = 0; StartedGroundRun = true; }}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%// Takeoff and landing reporting functionalityvoid FGLGear::ReportTakeoffOrLanding(void){ double deltaT = State->Getdt()*Exec->GetGroundReactions()->GetRate(); if (FirstContact) LandingDistanceTraveled += Auxiliary->GetVground()*deltaT; if (StartedGroundRun) { TakeoffDistanceTraveled50ft += Auxiliary->GetVground()*deltaT; if (WOW) TakeoffDistanceTraveled += Auxiliary->GetVground()*deltaT; } if ( ReportEnable && Auxiliary->GetVground() <= 0.05 && !LandingReported && Exec->GetGroundReactions()->GetWOW()) { if (debug_lvl > 0) Report(erLand); } if ( ReportEnable && !TakeoffReported && (Propagate->GetDistanceAGL() - vLocalGear(eZ)) > 50.0 && !Exec->GetGroundReactions()->GetWOW()) { if (debug_lvl > 0) Report(erTakeoff); } if (lastWOW != WOW) PutMessage("GEAR_CONTACT: " + name, WOW);}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%// Crash detection logic (really out-of-bounds detection)void FGLGear::CrashDetect(void){ if ( (compressLength > 500.0 || vForce.Magnitude() > 100000000.0 || vMoment.Magnitude() > 5000000000.0 || SinkRate > 1.4666*30 ) && !State->IntegrationSuspended()) { PutMessage("Crash Detected: Simulation FREEZE."); State->SuspendIntegration(); }}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%// 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.// [JSB] The braking force coefficients include normal rolling coefficient +// a percentage of the static friction coefficient based on braking applied.void FGLGear::ComputeBrakeForceCoefficient(void){ switch (eBrakeGrp) { case bgLeft: BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgLeft)) + staticFCoeff*FCS->GetBrake(bgLeft) ); break; case bgRight: BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgRight)) + staticFCoeff*FCS->GetBrake(bgRight) ); break; case bgCenter: BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) + staticFCoeff*FCS->GetBrake(bgCenter) ); break; case bgNose: BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) + staticFCoeff*FCS->GetBrake(bgCenter) ); break; case bgTail: BrakeFCoeff = ( rollingFCoeff*(1.0 - FCS->GetBrake(bgCenter)) + staticFCoeff*FCS->GetBrake(bgCenter) ); break; case bgNone: BrakeFCoeff = rollingFCoeff; break; default: cerr << "Improper brake group membership detected for this gear." << endl; break; }}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%// 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 (similar to Pacejka). Will fix this later.void FGLGear::ComputeSideForceCoefficient(void){ if (ForceY_Table) { FCoeff = ForceY_Table->GetValue(WheelSlip); } else { if (fabs(WheelSlip) <= 10.0) { FCoeff = staticFCoeff*WheelSlip/10.0; } else if (fabs(WheelSlip) <= 40.0) { FCoeff = (dynamicFCoeff*(fabs(WheelSlip) - 10.0)/10.0 + staticFCoeff*(40.0 - fabs(WheelSlip))/10.0)*(WheelSlip>=0?1.0:-1.0); } else { FCoeff = dynamicFCoeff*(WheelSlip>=0?1.0:-1.0); } }}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%// 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.void FGLGear::ComputeVerticalStrutForce(void){ double springForce = 0; double dampForce = 0; springForce = -compressLength * kSpring; if (compressSpeed >= 0.0) { if (eDampType == dtLinear) dampForce = -compressSpeed * bDamp; else dampForce = -compressSpeed * compressSpeed * bDamp; } else { if (eDampTypeRebound == dtLinear) dampForce = -compressSpeed * bDampRebound; else dampForce = compressSpeed * compressSpeed * bDampRebound; } vLocalForce(eZ) = min(springForce + dampForce, (double)0.0); // Remember these values for reporting MaximumStrutForce = max(MaximumStrutForce, fabs(vLocalForce(eZ))); MaximumStrutTravel = max(MaximumStrutTravel, fabs(compressLength));}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%double FGLGear::GetGearUnitPos(void){ // hack to provide backward compatibility to gear/gear-pos-norm property if( useFCSGearPos || FCS->GetGearPos() != 1.0 ) { useFCSGearPos = true; return FCS->GetGearPos(); } return GearPos;}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%void FGLGear::bind(void){ char property_name[80]; if (eContactType == ctBOGEY) { snprintf(property_name, 80, "gear/unit[%d]/slip-angle-deg", GearNumber); Exec->GetPropertyManager()->Tie( property_name, &WheelSlip ); snprintf(property_name, 80, "gear/unit[%d]/WOW", GearNumber); Exec->GetPropertyManager()->Tie( property_name, &WOW ); snprintf(property_name, 80, "gear/unit[%d]/wheel-speed-fps", GearNumber); Exec->GetPropertyManager()->Tie( property_name, &RollingWhlVel ); snprintf(property_name, 80, "gear/unit[%d]/z-position", GearNumber); Exec->GetPropertyManager()->Tie( property_name, (FGLGear*)this, &FGLGear::GetZPosition, &FGLGear::SetZPosition); } if( isRetractable ) { snprintf(property_name, 80, "gear/unit[%d]/pos-norm", GearNumber); Exec->GetPropertyManager()->Tie( property_name, &GearPos ); }}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%void FGLGear::Report(ReportType repType){ switch(repType) { case erLand: cout << endl << "Touchdown report for " << name << endl; cout << " Sink rate at contact: " << SinkRate << " fps, " << SinkRate*0.3048 << " mps" << endl; cout << " Contact ground speed: " << GroundSpeed*.5925 << " knots, " << GroundSpeed*0.3048 << " 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: " << LandingDistanceTraveled << " ft, " << LandingDistanceTraveled*0.3048 << " meters" << endl; LandingReported = true; break; case erTakeoff: cout << endl << "Takeoff report for " << name << endl; cout << " Distance traveled: " << TakeoffDistanceTraveled << " ft, " << TakeoffDistanceTraveled*0.3048 << " meters" << endl; cout << " Distance traveled (over 50'): " << TakeoffDistanceTraveled50ft << " ft, " << TakeoffDistanceTraveled50ft*0.3048 << " meters" << endl; TakeoffReported = true; break; }}//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%// 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 boundsvoid FGLGear::Debug(int from){ if (debug_lvl <= 0) return; if (debug_lvl & 1) { // Standard console startup message output if (from == 0) { // Constructor - loading and initialization cout << " " << sContactType << " " << name << endl; cout << " Location: " << vXYZ << endl; cout << " Spring Constant: " << kSpring << endl; if (eDampType == dtLinear) cout << " Damping Constant: " << bDamp << " (linear)" << endl; else cout << " Damping Constant: " << bDamp << " (square law)" << endl; if (eDampTypeRebound == dtLinear) cout << " Rebound Damping Constant: " << bDampRebound << " (linear)" << endl; else cout << " Rebound Damping Constant: " << bDampRebound << " (square law)" << endl; cout << " Dynamic Friction: " << dynamicFCoeff << endl; cout << " Static Friction: " << staticFCoeff << endl; if (eContactType == ctBOGEY) { cout << " Rolling Friction: " << rollingFCoeff << endl; cout << " Steering Type: " << sSteerType << endl; cout << " Grouping: " << sBrakeGroup << endl; cout << " Max Steer Angle: " << maxSteerAngle << endl; cout << " Retractable: " << isRetractable << endl; cout << " Relaxation Velocities:" << endl; cout << " Rolling: " << RFRV << endl; cout << " Side: " << SFRV << endl; } } } 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 } if (debug_lvl & 64) { if (from == 0) { // Constructor cout << IdSrc << endl; cout << IdHdr << endl; } }}} // namespace JSBSim
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -