bool FGAuxiliary::InitModel(void) { if (!FGModel::InitModel()) return false; pt = in.Pressure; tat = in.Temperature; tatc = RankineToCelsius(tat); vcas = veas = 0.0; qbar = qbarUW = qbarUV = 0.0; Mach = MachU = 0.0; alpha = beta = 0.0; adot = bdot = 0.0; gamma = Vt = Vground = 0.0; psigt = 0.0; day_of_year = 1; seconds_in_day = 0.0; hoverbmac = hoverbcg = 0.0; Re = 0.0; Nz = Ny = 0.0; lon_relative_position = lat_relative_position = relative_position = 0.0; vPilotAccel.InitMatrix(); vPilotAccelN.InitMatrix(); vAeroUVW.InitMatrix(); vAeroPQR.InitMatrix(); vMachUVW.InitMatrix(); vEuler.InitMatrix(); vEulerRates.InitMatrix(); return true; }
FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex) { Name = "FGAuxiliary"; pt = 1.0; tat = 1.0; tatc = RankineToCelsius(tat); vcas = veas = 0.0; qbar = qbarUW = qbarUV = 0.0; Mach = MachU = 0.0; alpha = beta = 0.0; adot = bdot = 0.0; gamma = Vt = Vground = 0.0; psigt = 0.0; day_of_year = 1; seconds_in_day = 0.0; hoverbmac = hoverbcg = 0.0; Re = 0.0; Nz = Ny = 0.0; lon_relative_position = lat_relative_position = relative_position = 0.0; vPilotAccel.InitMatrix(); vPilotAccelN.InitMatrix(); vAeroUVW.InitMatrix(); vAeroPQR.InitMatrix(); vMachUVW.InitMatrix(); vEuler.InitMatrix(); vEulerRates.InitMatrix(); bind(); Debug(0); }
FGAuxiliary::FGAuxiliary(FGFDMExec* fdmex) : FGModel(fdmex) { Name = "FGAuxiliary"; vcas = veas = pt = tat = 0; psl = rhosl = 1; qbar = 0; qbarUW = 0.0; qbarUV = 0.0; Re = 0.0; Mach = 0.0; alpha = beta = 0.0; adot = bdot = 0.0; gamma = Vt = Vground = 0.0; psigt = 0.0; day_of_year = 1; seconds_in_day = 0.0; hoverbmac = hoverbcg = 0.0; tatc = RankineToCelsius(tat); vPilotAccel.InitMatrix(); vPilotAccelN.InitMatrix(); vToEyePt.InitMatrix(); vAeroPQR.InitMatrix(); vEulerRates.InitMatrix(); bind(); Debug(0); }
//========================================================================= // Update Temperature, pressure and density from altitude // NOTE: Temperature is adjusted with the local conditions // if local condition say 20°C, then temperature is adusted // by the delta (20 - 15) because 15°C is the standard temperature // at sea level; We just make a (certainly) wrong supposition by // saying that temperature is 5° higgher at all altitude //========================================================================= void CAtmosphereModelJSBSim::TimeSlice(float dt,double altitude) { //---Compute temperature and pressure ----------------------- // slot.U = slope // slot.V = Temperature in Rankine // slot.W = pressure (psf) C3valSlot *slot = stdATMOS.Getfloor(altitude); float slp = slot->GetU(); float rfT = slot->GetV(); float rfP = slot->GetW(); float da = altitude - slot->GetX(); float tp = 0; float pr = 0; float dn = 0; //---Compute new targets --------------------- if (0 == slp) { tp = rfT; pr = rfP * exp(-pInertial->SLgravity()/(rfT*Reng)* da); dn = pr/ (Reng*tp); } else { tp = rfT + (slp * da); pr = rfP * pow(float(tp/rfT),float(-pInertial->SLgravity()/(slp*Reng))); dn = pr/(Reng*tp); } //--- Get final values ----------------------------------------------- tempR = tVAL.TimeSlice(dt); presS = pVAL.TimeSlice(dt); densD = dVAL.TimeSlice(dt); //--- Set Target value ----------------------------------------------- tVAL.Set(tp); pVAL.Set(pr); dVAL.Set(dn); //---Update temperature to various units ----------------------------- tempC = RankineToCelsius(tempR) + dtaTC; tempF = CelsiusToFahrenheit(tempC); //---Update pressure to various units -------------------------------- presS += dtaPS; // Add local deviation presH = presS * PSF_TO_INHG; presB = presS * PFS_TO_HPA; //--- Update sound speed --------------------------------------------- soundspeed = sqrt(SHRatio*Reng*(tempR)); //-------------------------------------------------------------------- // test others density //densD *= 10.0; //cout << "Atmosphere: h=" << altitude << " rho= " << densD << endl; // #ifdef _DEBUG // FILE *fp_debug; // if(!(fp_debug = fopen("__DDEBUG_atmosphere.txt", "a")) == NULL) // { // int test = 0; // fprintf(fp_debug, "TPD = %f %f %f\n", tempR, presS, densD); // fprintf(fp_debug, "TPD = %f %f %f\n", // RankineToCelsius (tempR), // presS * PSF_TO_INHG, // densD); // fclose(fp_debug); // } // #endif }
//========================================================================= // Update Temperature, pressure and density from altitude // NOTE: Temperature is adjusted with the local conditions // if local condition say 20°C, then temperature is adusted // by the delta (20 - 15) because 15°C is the standard temperature // at sea level; We just make a (certainly) wrong supposition by // saying that temperature is 5° higgher at all altitude //========================================================================= int CAtmosphereModelJSBSim::TimeSlice(float dt,U_INT frame) { double altitude = globals->geop.alt; //---Compute temperature and pressure ----------------------- C3valSlot *slot = stdATMOS.Getfloor(altitude); float slp = slot->GetU(); float rfT = slot->GetV(); float rfP = slot->GetW(); float da = altitude - slot->GetX(); float tp = 0; float pr = 0; float dn = 0; //---Compute new targets --------------------- if (0 == slp) { tp = rfT; pr = rfP * exp(-pInertial->SLgravity()/(rfT*Reng)* da); dn = pr/ (Reng*tp); } else { tp = rfT + (slp * da); pr = rfP * pow(float(tp/rfT),float(-pInertial->SLgravity()/(slp*Reng))); dn = pr/(Reng*tp); } //--- Get final values ----------------------------------------------- tempR = tVAL.TimeSlice(dt); presS = pVAL.TimeSlice(dt); densD = dVAL.TimeSlice(dt); //--- Set Target value ----------------------------------------------- tVAL.Set(tp); pVAL.Set(pr); dVAL.Set(dn); //---Update temperature to various units ----------------------------- tempC = RankineToCelsius(tempR) + dtaTC; tempF = CelsiusToFahrenheit(tempC); //---Update pressure to various units -------------------------------- presS += dtaPS; // Add local deviation presH = presS * PSF_TO_INHG; presB = presS * PFS_TO_HPA; //--- Update sound speed --------------------------------------------- soundspeed = sqrt(SHRatio*Reng*(tempR)); return 1; }
bool FGAuxiliary::Run(bool Holding) { double A,B,D; if (FGModel::Run(Holding)) return true; // return true if error returned from base class if (Holding) return false; // Rotation vEulerRates(eTht) = in.vPQR(eQ)*in.CosPhi - in.vPQR(eR)*in.SinPhi; if (in.CosTht != 0.0) { vEulerRates(ePsi) = (in.vPQR(eQ)*in.SinPhi + in.vPQR(eR)*in.CosPhi)/in.CosTht; vEulerRates(ePhi) = in.vPQR(eP) + vEulerRates(ePsi)*in.SinTht; } // Combine the wind speed with aircraft speed to obtain wind relative speed vAeroPQR = in.vPQR - in.TurbPQR; vAeroUVW = in.vUVW - in.Tl2b * in.TotalWindNED; Vt = vAeroUVW.Magnitude(); alpha = beta = adot = bdot = 0; double AeroU2 = vAeroUVW(eU)*vAeroUVW(eU); double AeroV2 = vAeroUVW(eV)*vAeroUVW(eV); double AeroW2 = vAeroUVW(eW)*vAeroUVW(eW); double mUW = AeroU2 + AeroW2; double Vtdot = (vAeroUVW(eU)*in.vUVWdot(eU) + vAeroUVW(eV)*in.vUVWdot(eV) + vAeroUVW(eW)*in.vUVWdot(eW))/Vt; double Vt2 = Vt*Vt; if ( Vt > 0.001 ) { if (vAeroUVW(eW) != 0.0) alpha = AeroU2 > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0; if (vAeroUVW(eV) != 0.0) beta = mUW > 0.0 ? atan2(vAeroUVW(eV), sqrt(mUW)) : 0.0; //double signU=1; //if (vAeroUVW(eU) < 0.0) signU=-1; if ( mUW >= 0.001 ) { adot = (vAeroUVW(eU)*in.vUVWdot(eW) - vAeroUVW(eW)*in.vUVWdot(eU))/mUW; // bdot = (signU*mUW*in.vUVWdot(eV) // - vAeroUVW(eV)*(vAeroUVW(eU)*in.vUVWdot(eU) + vAeroUVW(eW)*in.vUVWdot(eW)))/(Vt2*sqrt(mUW)); bdot = (in.vUVWdot(eV)*Vt - vAeroUVW(eV)*Vtdot)/(Vt*sqrt(mUW)); } } UpdateWindMatrices(); Re = Vt * in.Wingchord / in.KinematicViscosity; double densityD2 = 0.5*in.Density; qbar = densityD2 * Vt2; qbarUW = densityD2 * (mUW); qbarUV = densityD2 * (AeroU2 + AeroV2); Mach = Vt / in.SoundSpeed; MachU = vMachUVW(eU) = vAeroUVW(eU) / in.SoundSpeed; vMachUVW(eV) = vAeroUVW(eV) / in.SoundSpeed; vMachUVW(eW) = vAeroUVW(eW) / in.SoundSpeed; double MachU2 = MachU * MachU; // Position Vground = sqrt( in.vVel(eNorth)*in.vVel(eNorth) + in.vVel(eEast)*in.vVel(eEast) ); psigt = atan2(in.vVel(eEast), in.vVel(eNorth)); if (psigt < 0.0) psigt += 2*M_PI; gamma = atan2(-in.vVel(eDown), Vground); tat = in.Temperature*(1 + 0.2*Mach*Mach); // Total Temperature, isentropic flow tatc = RankineToCelsius(tat); if (MachU < 1) { // Calculate total pressure assuming isentropic flow pt = in.Pressure*pow((1 + 0.2*MachU2),3.5); } else { // Use Rayleigh pitot tube formula for normal shock in front of pitot tube B = 5.76 * MachU2 / (5.6*MachU2 - 0.8); D = (2.8 * MachU2 - 0.4) * 0.4167; pt = in.Pressure*pow(B,3.5)*D; } A = pow(((pt-in.Pressure)/in.PressureSL + 1),0.28571); if (abs(MachU) > 0.0) { vcas = sqrt(7 * in.PressureSL / in.DensitySL * (A-1)); veas = sqrt(2 * qbar / in.DensitySL); vtrue = 1116.43559 * Mach * sqrt(in.Temperature / 518.67); } else { vcas = veas = vtrue = 0.0; } vPilotAccel.InitMatrix(); vNcg = in.vBodyAccel/in.SLGravity; // Nz is Acceleration in "g's", along normal axis (-Z body axis) Nz = -vNcg(eZ); Ny = vNcg(eY); vPilotAccel = in.vBodyAccel + in.vPQRdot * in.ToEyePt; vPilotAccel += in.vPQR * (in.vPQR * in.ToEyePt); vNwcg = mTb2w * vNcg; vNwcg(eZ) = 1.0 - vNwcg(eZ); vPilotAccelN = vPilotAccel / in.SLGravity; // VRP computation vLocationVRP = in.vLocation.LocalToLocation( in.Tb2l * in.VRPBody ); // Recompute some derived values now that we know the dependent parameters values ... hoverbcg = in.DistanceAGL / in.Wingspan; FGColumnVector3 vMac = in.Tb2l * in.RPBody; hoverbmac = (in.DistanceAGL + vMac(3)) / in.Wingspan; // When all models are executed calculate the distance from the initial point. CalculateRelativePosition(); return false; }
bool FGAuxiliary::Run() { double A,B,D; if (FGModel::Run()) return true; // return true if error returned from base class if (FDMExec->Holding()) return false; const FGColumnVector3& vPQR = Propagate->GetPQR(); const FGColumnVector3& vUVW = Propagate->GetUVW(); const FGColumnVector3& vUVWdot = Propagate->GetUVWdot(); const FGColumnVector3& vVel = Propagate->GetVel(); p = Atmosphere->GetPressure(); rhosl = Atmosphere->GetDensitySL(); psl = Atmosphere->GetPressureSL(); sat = Atmosphere->GetTemperature(); // Rotation double cTht = Propagate->GetCosEuler(eTht); double sTht = Propagate->GetSinEuler(eTht); double cPhi = Propagate->GetCosEuler(ePhi); double sPhi = Propagate->GetSinEuler(ePhi); vEulerRates(eTht) = vPQR(eQ)*cPhi - vPQR(eR)*sPhi; if (cTht != 0.0) { vEulerRates(ePsi) = (vPQR(eQ)*sPhi + vPQR(eR)*cPhi)/cTht; vEulerRates(ePhi) = vPQR(eP) + vEulerRates(ePsi)*sTht; } // 12/16/2005, JSB: For ground handling purposes, at this time, let's ramp // in the effects of wind from 10 fps to 30 fps when there is weight on the // landing gear wheels. if (GroundReactions->GetWOW() && vUVW(eU) < 10) { vAeroPQR = vPQR; vAeroUVW = vUVW; } else if (GroundReactions->GetWOW() && vUVW(eU) < 30) { double factor = (vUVW(eU) - 10.0)/20.0; vAeroPQR = vPQR - factor*Atmosphere->GetTurbPQR(); vAeroUVW = vUVW - factor*Propagate->GetTl2b()*Atmosphere->GetTotalWindNED(); } else { FGColumnVector3 wind = Propagate->GetTl2b()*Atmosphere->GetTotalWindNED(); vAeroPQR = vPQR - Atmosphere->GetTurbPQR(); vAeroUVW = vUVW - wind; } Vt = vAeroUVW.Magnitude(); if ( Vt > 0.05) { if (vAeroUVW(eW) != 0.0) alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0; if (vAeroUVW(eV) != 0.0) beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV), sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0; double mUW = (vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW)); double signU=1; if (vAeroUVW(eU) != 0.0) signU = vAeroUVW(eU)/fabs(vAeroUVW(eU)); if ( (mUW == 0.0) || (Vt == 0.0) ) { adot = 0.0; bdot = 0.0; } else { adot = (vAeroUVW(eU)*vUVWdot(eW) - vAeroUVW(eW)*vUVWdot(eU))/mUW; bdot = (signU*mUW*vUVWdot(eV) - vAeroUVW(eV)*(vAeroUVW(eU)*vUVWdot(eU) + vAeroUVW(eW)*vUVWdot(eW)))/(Vt*Vt*sqrt(mUW)); } } else { alpha = beta = adot = bdot = 0; } Re = Vt * Aircraft->Getcbar() / Atmosphere->GetKinematicViscosity(); qbar = 0.5*Atmosphere->GetDensity()*Vt*Vt; qbarUW = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW)); qbarUV = 0.5*Atmosphere->GetDensity()*(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eV)*vAeroUVW(eV)); Mach = Vt / Atmosphere->GetSoundSpeed(); MachU = vMachUVW(eU) = vAeroUVW(eU) / Atmosphere->GetSoundSpeed(); vMachUVW(eV) = vAeroUVW(eV) / Atmosphere->GetSoundSpeed(); vMachUVW(eW) = vAeroUVW(eW) / Atmosphere->GetSoundSpeed(); // Position Vground = sqrt( vVel(eNorth)*vVel(eNorth) + vVel(eEast)*vVel(eEast) ); psigt = atan2(vVel(eEast), vVel(eNorth)); if (psigt < 0.0) psigt += 2*M_PI; gamma = atan2(-vVel(eDown), Vground); tat = sat*(1 + 0.2*Mach*Mach); // Total Temperature, isentropic flow tatc = RankineToCelsius(tat); if (MachU < 1) { // Calculate total pressure assuming isentropic flow pt = p*pow((1 + 0.2*MachU*MachU),3.5); } else { // Use Rayleigh pitot tube formula for normal shock in front of pitot tube B = 5.76*MachU*MachU/(5.6*MachU*MachU - 0.8); D = (2.8*MachU*MachU-0.4)*0.4167; pt = p*pow(B,3.5)*D; } A = pow(((pt-p)/psl+1),0.28571); if (MachU > 0.0) { vcas = sqrt(7*psl/rhosl*(A-1)); veas = sqrt(2*qbar/rhosl); } else { vcas = veas = 0.0; } vPilotAccel.InitMatrix(); if ( Vt > 1.0 ) { vAircraftAccel = Aerodynamics->GetForces() + Propulsion->GetForces() + GroundReactions->GetForces() + ExternalReactions->GetForces() + BuoyantForces->GetForces(); vAircraftAccel /= MassBalance->GetMass(); // Nz is Acceleration in "g's", along normal axis (-Z body axis) Nz = -vAircraftAccel(eZ)/Inertial->gravity(); vToEyePt = MassBalance->StructuralToBody(Aircraft->GetXYZep()); vPilotAccel = vAircraftAccel + Propagate->GetPQRdot() * vToEyePt; vPilotAccel += vPQR * (vPQR * vToEyePt); } else { // The line below handles low velocity (and on-ground) cases, basically // representing the opposite of the force that the landing gear would // exert on the ground (which is just the total weight). This eliminates // any jitter that could be introduced by the landing gear. Theoretically, // this branch could be eliminated, with a penalty of having a short // transient at startup (lasting only a fraction of a second). vPilotAccel = Propagate->GetTl2b() * FGColumnVector3( 0.0, 0.0, -Inertial->gravity() ); Nz = -vPilotAccel(eZ)/Inertial->gravity(); } vPilotAccelN = vPilotAccel/Inertial->gravity(); // VRP computation const FGLocation& vLocation = Propagate->GetLocation(); FGColumnVector3 vrpStructural = Aircraft->GetXYZvrp(); FGColumnVector3 vrpBody = MassBalance->StructuralToBody( vrpStructural ); FGColumnVector3 vrpLocal = Propagate->GetTb2l() * vrpBody; vLocationVRP = vLocation.LocalToLocation( vrpLocal ); // Recompute some derived values now that we know the dependent parameters values ... hoverbcg = Propagate->GetDistanceAGL() / Aircraft->GetWingSpan(); FGColumnVector3 vMac = Propagate->GetTb2l()*MassBalance->StructuralToBody(Aircraft->GetXYZrp()); hoverbmac = (Propagate->GetDistanceAGL() + vMac(3)) / Aircraft->GetWingSpan(); // when all model are executed, // please calculate the distance from the initial point CalculateRelativePosition(); return false; }