X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FFDM%2FJSBSim%2FFGFDMExec.cpp;h=b61529229c40c3947ff50ab9792c1792907a8bb8;hb=69baf3a9d6adb645325e7bfc0305b09604379d9f;hp=616dd6ea6e2c893c859edb2ef25142996e99819a;hpb=43cf0254df9fd30ac4c4fcb03f654f53853d24a1;p=flightgear.git diff --git a/src/FDM/JSBSim/FGFDMExec.cpp b/src/FDM/JSBSim/FGFDMExec.cpp index 616dd6ea6..b61529229 100644 --- a/src/FDM/JSBSim/FGFDMExec.cpp +++ b/src/FDM/JSBSim/FGFDMExec.cpp @@ -1,3 +1,4 @@ + /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Module: FGFDMExec.cpp @@ -41,10 +42,13 @@ COMMENTS, REFERENCES, and NOTES INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ +#include +#include +#include + #include "FGFDMExec.h" -#include "models/FGAtmosphere.h" -#include "models/atmosphere/FGMSIS.h" -#include "models/atmosphere/FGMars.h" +#include "models/atmosphere/FGStandardAtmosphere.h" +#include "models/atmosphere/FGWinds.h" #include "models/FGFCS.h" #include "models/FGPropulsion.h" #include "models/FGMassBalance.h" @@ -54,80 +58,38 @@ INCLUDES #include "models/FGAerodynamics.h" #include "models/FGInertial.h" #include "models/FGAircraft.h" +#include "models/FGAccelerations.h" #include "models/FGPropagate.h" #include "models/FGAuxiliary.h" #include "models/FGInput.h" #include "models/FGOutput.h" #include "initialization/FGInitialCondition.h" -//#include "initialization/FGTrimAnalysis.h" // Remove until later +#include "initialization/FGSimplexTrim.h" +#include "initialization/FGLinearization.h" #include "input_output/FGPropertyManager.h" #include "input_output/FGScript.h" - -#include -#include -#include +#include "input_output/FGXMLFileRead.h" +#include "input_output/FGXMLElement.h" using namespace std; namespace JSBSim { -static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.82 2010/10/07 03:17:29 jberndt Exp $"; +static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.150 2013/11/24 11:40:55 bcoconni Exp $"; static const char *IdHdr = ID_FDMEXEC; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ -void checkTied ( FGPropertyManager *node ) -{ - int N = node->nChildren(); - string name; - - for (int i=0; igetChild(i)->nChildren() ) { - checkTied( (FGPropertyManager*)node->getChild(i) ); - } - if ( node->getChild(i)->isTied() ) { - name = ((FGPropertyManager*)node->getChild(i))->GetFullyQualifiedName(); - node->Untie(name); - } - } -} - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -// Constructors -FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root), delete_root(false) -{ - FDMctr = new unsigned int; - *FDMctr = 0; - Initialize(); - root_overload = (root != NULL); -} - -FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root), delete_root(false), FDMctr(fdmctr) -{ - Initialize(); - root_overload = (root != NULL); -} +// Constructor -void FGFDMExec::Initialize() +FGFDMExec::FGFDMExec(FGPropertyManager* root, unsigned int* fdmctr) : Root(root), FDMctr(fdmctr) { Frame = 0; Error = 0; - GroundCallback = 0; - Atmosphere = 0; - FCS = 0; - Propulsion = 0; - MassBalance = 0; - Aerodynamics = 0; - Inertial = 0; - GroundReactions = 0; - ExternalReactions = 0; - BuoyantForces = 0; - Aircraft = 0; - Propagate = 0; - Auxiliary = 0; - Input = 0; + SetGroundCallback(new FGDefaultGroundCallback()); IC = 0; Trim = 0; Script = 0; @@ -138,11 +100,19 @@ void FGFDMExec::Initialize() IsChild = false; holding = false; Terminate = false; + StandAlone = false; + + IncrementThenHolding = false; // increment then hold is off by default + TimeStepsUntilHold = -1; sim_time = 0.0; dT = 1.0/120.0; // a default timestep size. This is needed for when JSBSim is // run in standalone mode with no initialization file. + AircraftPath = "aircraft"; + EnginePath = "engine"; + SystemsPath = "systems"; + try { char* num = getenv("JSBSIM_DEBUG"); if (num) debug_lvl = atoi(num); // set debug level @@ -152,19 +122,22 @@ void FGFDMExec::Initialize() if (Root == 0) { // Then this is the root FDM Root = new FGPropertyManager; // Create the property manager - delete_root = true; - + StandAlone = true; + } + + if (FDMctr == 0) { FDMctr = new unsigned int; // Create and initialize the child FDM counter (*FDMctr) = 0; } // Store this FDM's ID IdFDM = (*FDMctr); // The main (parent) JSBSim instance is always the "zeroth" - + // Prepare FDMctr for the next child FDM id (*FDMctr)++; // instance. "child" instances are loaded last. - instance = Root->GetNode("/fdm/jsbsim",IdFDM,true); + FGPropertyNode* instanceRoot = Root->GetNode("/fdm/jsbsim",IdFDM,true); + instance = new FGPropertyManager(instanceRoot); Debug(0); // this is to catch errors in binding member functions to the property tree. try { @@ -179,12 +152,61 @@ void FGFDMExec::Initialize() Constructing = true; typedef int (FGFDMExec::*iPMF)(void) const; -// instance->Tie("simulation/do_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis); - instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim); - instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions); + typedef double (FGFDMExec::*dPMF)(void) const; +// typedef unsigned int (FGFDMExec::*uiPMF)(void) const; +// instance->Tie("simulation/do_trim_analysis", this, (iPMF)0, &FGFDMExec::DoTrimAnalysis, false); + instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim, false); + instance->Tie("simulation/do_simplex_trim", this, (iPMF)0, &FGFDMExec::DoSimplexTrim); + instance->Tie("simulation/do_linearization", this, (iPMF)0, &FGFDMExec::DoLinearization); + instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions, false); + instance->Tie("simulation/randomseed", this, (iPMF)0, &FGFDMExec::SRand, false); instance->Tie("simulation/terminate", (int *)&Terminate); instance->Tie("simulation/sim-time-sec", this, &FGFDMExec::GetSimTime); + instance->Tie("simulation/dt", this, &FGFDMExec::GetDeltaT); instance->Tie("simulation/jsbsim-debug", this, &FGFDMExec::GetDebugLevel, &FGFDMExec::SetDebugLevel); + instance->Tie("simulation/frame", (int *)&Frame, false); + + // simplex trim properties + instanceRoot->SetDouble("trim/solver/rtol",0.0001); + instanceRoot->SetDouble("trim/solver/speed",2); + instanceRoot->SetDouble("trim/solver/abstol",0.001); + instanceRoot->SetDouble("trim/solver/iterMax",2000); + instanceRoot->SetInt("trim/solver/debugLevel",0); + instanceRoot->SetDouble("trim/solver/random",0); + instanceRoot->SetBool("trim/solver/showSimplex",false); + instanceRoot->SetBool("trim/solver/showConvergence",false); + instanceRoot->SetBool("trim/solver/pause",false); + instanceRoot->SetBool("trim/solver/variablePropPitch",false); + + instanceRoot->SetDouble("trim/solver/throttleGuess",0.50); + instanceRoot->SetDouble("trim/solver/throttleMin",0.0); + instanceRoot->SetDouble("trim/solver/throttleMax",1.0); + instanceRoot->SetDouble("trim/solver/throttleStep",0.1); + + instanceRoot->SetDouble("trim/solver/aileronGuess",0); + instanceRoot->SetDouble("trim/solver/aileronMin",-1.00); + instanceRoot->SetDouble("trim/solver/aileronMax",1.00); + instanceRoot->SetDouble("trim/solver/aileronStep",0.1); + + instanceRoot->SetDouble("trim/solver/rudderGuess",0); + instanceRoot->SetDouble("trim/solver/rudderMin",-1.00); + instanceRoot->SetDouble("trim/solver/rudderMax",1.00); + instanceRoot->SetDouble("trim/solver/rudderStep",0.1); + + instanceRoot->SetDouble("trim/solver/elevatorGuess",-0.1); + instanceRoot->SetDouble("trim/solver/elevatorMin",-1.0); + instanceRoot->SetDouble("trim/solver/elevatorMax",1.0); + instanceRoot->SetDouble("trim/solver/elevatorStep",0.1); + + instanceRoot->SetDouble("trim/solver/alphaGuess",0.05); + instanceRoot->SetDouble("trim/solver/alphaMin",-0.1); + instanceRoot->SetDouble("trim/solver/alphaMax",.18); + instanceRoot->SetDouble("trim/solver/alphaStep",0.05); + + instanceRoot->SetDouble("trim/solver/betaGuess",0); + instanceRoot->SetDouble("trim/solver/betaMin",-0.1); + instanceRoot->SetDouble("trim/solver/betaMax",0.1); + instanceRoot->SetDouble("trim/solver/betaStep",0.0001); Constructing = false; } @@ -194,16 +216,18 @@ void FGFDMExec::Initialize() FGFDMExec::~FGFDMExec() { try { - checkTied( instance ); + Unbind(); DeAllocate(); - - if(FDMctr != 0 && !root_overload) { + + delete instance; + + if (IdFDM == 0) { // Meaning this is no child FDM if(Root != 0) { - if (delete_root) + if(StandAlone) delete Root; Root = 0; } - if (IdFDM == 0) { // Meaning this is no child FDM + if(FDMctr != 0) { delete FDMctr; FDMctr = 0; } @@ -217,7 +241,7 @@ FGFDMExec::~FGFDMExec() PropertyCatalog.clear(); - FDMctr--; + if (FDMctr > 0) (*FDMctr)--; Debug(1); } @@ -228,44 +252,57 @@ bool FGFDMExec::Allocate(void) { bool result=true; - Atmosphere = new FGAtmosphere(this); - FCS = new FGFCS(this); - Propulsion = new FGPropulsion(this); - MassBalance = new FGMassBalance(this); - Aerodynamics = new FGAerodynamics (this); - Inertial = new FGInertial(this); - - GroundCallback = new FGGroundCallback(Inertial->GetRefRadius()); - - GroundReactions = new FGGroundReactions(this); - ExternalReactions = new FGExternalReactions(this); - BuoyantForces = new FGBuoyantForces(this); - Aircraft = new FGAircraft(this); - Propagate = new FGPropagate(this); - Auxiliary = new FGAuxiliary(this); - Input = new FGInput(this); - - // Schedule a model. The second arg (the integer) is the pass number. For - // instance, the atmosphere model could get executed every fifth pass it is called. - - Schedule(Input, 1); - Schedule(Atmosphere, 1); - Schedule(FCS, 1); - Schedule(Propulsion, 1); - Schedule(MassBalance, 1); - Schedule(Aerodynamics, 1); - Schedule(Inertial, 1); - Schedule(GroundReactions, 1); - Schedule(ExternalReactions, 1); - Schedule(BuoyantForces, 1); - Schedule(Aircraft, 1); - Schedule(Propagate, 1); - Schedule(Auxiliary, 1); - - // Initialize models so they can communicate with each other - - vector ::iterator it; - for (it = Models.begin(); it != Models.end(); ++it) (*it)->InitModel(); + Models.resize(eNumStandardModels); + + // See the eModels enum specification in the header file. The order of the enums + // specifies the order of execution. The Models[] vector is the primary + // storage array for the list of models. + Models[ePropagate] = new FGPropagate(this); + Models[eInput] = new FGInput(this); + Models[eInertial] = new FGInertial(this); + Models[eAtmosphere] = new FGStandardAtmosphere(this); + Models[eWinds] = new FGWinds(this); + Models[eAuxiliary] = new FGAuxiliary(this); + Models[eSystems] = new FGFCS(this); + Models[ePropulsion] = new FGPropulsion(this); + Models[eAerodynamics] = new FGAerodynamics (this); + Models[eGroundReactions] = new FGGroundReactions(this); + Models[eExternalReactions] = new FGExternalReactions(this); + Models[eBuoyantForces] = new FGBuoyantForces(this); + Models[eMassBalance] = new FGMassBalance(this); + Models[eAircraft] = new FGAircraft(this); + Models[eAccelerations] = new FGAccelerations(this); + Models[eOutput] = new FGOutput(this); + + // Assign the Model shortcuts for internal executive use only. + Propagate = (FGPropagate*)Models[ePropagate]; + Inertial = (FGInertial*)Models[eInertial]; + Atmosphere = (FGAtmosphere*)Models[eAtmosphere]; + Winds = (FGWinds*)Models[eWinds]; + Auxiliary = (FGAuxiliary*)Models[eAuxiliary]; + FCS = (FGFCS*)Models[eSystems]; + Propulsion = (FGPropulsion*)Models[ePropulsion]; + Aerodynamics = (FGAerodynamics*)Models[eAerodynamics]; + GroundReactions = (FGGroundReactions*)Models[eGroundReactions]; + ExternalReactions = (FGExternalReactions*)Models[eExternalReactions]; + BuoyantForces = (FGBuoyantForces*)Models[eBuoyantForces]; + MassBalance = (FGMassBalance*)Models[eMassBalance]; + Aircraft = (FGAircraft*)Models[eAircraft]; + Accelerations = (FGAccelerations*)Models[eAccelerations]; + Output = (FGOutput*)Models[eOutput]; + + // Initialize planet (environment) constants + LoadPlanetConstants(); + GetGroundCallback()->SetSeaLevelRadius(Inertial->GetRefRadius()); + + // Initialize models + for (unsigned int i = 0; i < Models.size(); i++) { + // The Output model must not be initialized prior to IC loading + if (i == eOutput) continue; + + LoadInputs(i); + Models[i]->InitModel(); + } IC = new FGInitialCondition(this); @@ -278,48 +315,16 @@ bool FGFDMExec::Allocate(void) bool FGFDMExec::DeAllocate(void) { - delete Input; - delete Atmosphere; - delete FCS; - delete Propulsion; - delete MassBalance; - delete Aerodynamics; - delete Inertial; - delete GroundReactions; - delete ExternalReactions; - delete BuoyantForces; - delete Aircraft; - delete Propagate; - delete Auxiliary; - delete Script; - for (unsigned i=0; iAssignState(Propagate); // Transfer state to the child FDM + ChildFDMList[i]->AssignState( (FGPropagate*)Models[ePropagate] ); // Transfer state to the child FDM ChildFDMList[i]->Run(); } + IncrTime(); + // returns true if success, false if complete if (Script != 0 && !IntegrationSuspended()) success = Script->RunScript(); - vector ::iterator it; - for (it = Models.begin(); it != Models.end(); ++it) (*it)->Run(); + for (unsigned int i = 0; i < Models.size(); i++) { + LoadInputs(i); + Models[i]->Run(holding); + } - Frame++; - if (!Holding()) IncrTime(); if (Terminate) success = false; return (success); } +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGFDMExec::LoadInputs(unsigned int idx) +{ + switch(idx) { + case ePropagate: + Propagate->in.vPQRidot = Accelerations->GetPQRidot(); + Propagate->in.vQtrndot = Accelerations->GetQuaterniondot(); + Propagate->in.vUVWidot = Accelerations->GetUVWidot(); + Propagate->in.DeltaT = dT; + break; + case eInput: + break; + case eInertial: + Inertial->in.Radius = Propagate->GetRadius(); + Inertial->in.Latitude = Propagate->GetLatitude(); + break; + case eAtmosphere: + Atmosphere->in.altitudeASL = Propagate->GetAltitudeASL(); + break; + case eWinds: + Winds->in.AltitudeASL = Propagate->GetAltitudeASL(); + Winds->in.DistanceAGL = Propagate->GetDistanceAGL(); + Winds->in.Tl2b = Propagate->GetTl2b(); + Winds->in.Tw2b = Auxiliary->GetTw2b(); + Winds->in.V = Auxiliary->GetVt(); + Winds->in.totalDeltaT = dT * Winds->GetRate(); + break; + case eAuxiliary: + Auxiliary->in.Pressure = Atmosphere->GetPressure(); + Auxiliary->in.Density = Atmosphere->GetDensity(); + Auxiliary->in.DensitySL = Atmosphere->GetDensitySL(); + Auxiliary->in.PressureSL = Atmosphere->GetPressureSL(); + Auxiliary->in.Temperature = Atmosphere->GetTemperature(); + Auxiliary->in.SoundSpeed = Atmosphere->GetSoundSpeed(); + Auxiliary->in.KinematicViscosity = Atmosphere->GetKinematicViscosity(); + Auxiliary->in.DistanceAGL = Propagate->GetDistanceAGL(); + Auxiliary->in.Mass = MassBalance->GetMass(); + Auxiliary->in.Tl2b = Propagate->GetTl2b(); + Auxiliary->in.Tb2l = Propagate->GetTb2l(); + Auxiliary->in.vPQR = Propagate->GetPQR(); + Auxiliary->in.vPQRdot = Accelerations->GetPQRdot(); + Auxiliary->in.vUVW = Propagate->GetUVW(); + Auxiliary->in.vUVWdot = Accelerations->GetUVWdot(); + Auxiliary->in.vVel = Propagate->GetVel(); + Auxiliary->in.vBodyAccel = Accelerations->GetBodyAccel(); + Auxiliary->in.ToEyePt = MassBalance->StructuralToBody(Aircraft->GetXYZep()); + Auxiliary->in.VRPBody = MassBalance->StructuralToBody(Aircraft->GetXYZvrp()); + Auxiliary->in.RPBody = MassBalance->StructuralToBody(Aircraft->GetXYZrp()); + Auxiliary->in.vFw = Aerodynamics->GetvFw(); + Auxiliary->in.vLocation = Propagate->GetLocation(); + Auxiliary->in.CosTht = Propagate->GetCosEuler(eTht); + Auxiliary->in.SinTht = Propagate->GetSinEuler(eTht); + Auxiliary->in.CosPhi = Propagate->GetCosEuler(ePhi); + Auxiliary->in.SinPhi = Propagate->GetSinEuler(ePhi); + Auxiliary->in.Psi = Propagate->GetEuler(ePsi); + Auxiliary->in.TotalWindNED = Winds->GetTotalWindNED(); + Auxiliary->in.TurbPQR = Winds->GetTurbPQR(); + Auxiliary->in.WindPsi = Winds->GetWindPsi(); + Auxiliary->in.Vwind = Winds->GetTotalWindNED().Magnitude(); + break; + case eSystems: + // Dynamic inputs come into the components that FCS manages through properties + break; + case ePropulsion: + Propulsion->in.SLPressure = Atmosphere->GetPressureSL(); + Propulsion->in.Pressure = Atmosphere->GetPressure(); + Propulsion->in.PressureRatio = Atmosphere->GetPressureRatio(); + Propulsion->in.Temperature = Atmosphere->GetTemperature(); + Propulsion->in.DensityRatio = Atmosphere->GetDensityRatio(); + Propulsion->in.Density = Atmosphere->GetDensity(); + Propulsion->in.Soundspeed = Atmosphere->GetSoundSpeed(); + Propulsion->in.TotalPressure = Auxiliary->GetTotalPressure(); + Propulsion->in.TotalTempearture = Auxiliary->GetTotalTemperature(); + Propulsion->in.Vc = Auxiliary->GetVcalibratedKTS(); + Propulsion->in.Vt = Auxiliary->GetVt(); + Propulsion->in.qbar = Auxiliary->Getqbar(); + Propulsion->in.TAT_c = Auxiliary->GetTAT_C(); + Propulsion->in.AeroUVW = Auxiliary->GetAeroUVW(); + Propulsion->in.AeroPQR = Auxiliary->GetAeroPQR(); + Propulsion->in.alpha = Auxiliary->Getalpha(); + Propulsion->in.beta = Auxiliary->Getbeta(); + Propulsion->in.TotalDeltaT = dT * Propulsion->GetRate(); + Propulsion->in.ThrottlePos = FCS->GetThrottlePos(); + Propulsion->in.MixturePos = FCS->GetMixturePos(); + Propulsion->in.ThrottleCmd = FCS->GetThrottleCmd(); + Propulsion->in.MixtureCmd = FCS->GetMixtureCmd(); + Propulsion->in.PropAdvance = FCS->GetPropAdvance(); + Propulsion->in.PropFeather = FCS->GetPropFeather(); + Propulsion->in.H_agl = Propagate->GetDistanceAGL(); + Propulsion->in.PQR = Propagate->GetPQR(); + + break; + case eAerodynamics: + Aerodynamics->in.Alpha = Auxiliary->Getalpha(); + Aerodynamics->in.Beta = Auxiliary->Getbeta(); + Aerodynamics->in.Qbar = Auxiliary->Getqbar(); + Aerodynamics->in.Vt = Auxiliary->GetVt(); + Aerodynamics->in.Tb2w = Auxiliary->GetTb2w(); + Aerodynamics->in.Tw2b = Auxiliary->GetTw2b(); + Aerodynamics->in.RPBody = MassBalance->StructuralToBody(Aircraft->GetXYZrp()); + break; + case eGroundReactions: + // There are no external inputs to this model. + GroundReactions->in.Vground = Auxiliary->GetVground(); + GroundReactions->in.VcalibratedKts = Auxiliary->GetVcalibratedKTS(); + GroundReactions->in.Temperature = Atmosphere->GetTemperature(); + GroundReactions->in.TakeoffThrottle = (FCS->GetThrottlePos().size() > 0) ? (FCS->GetThrottlePos(0) > 0.90) : false; + GroundReactions->in.SteerPosDeg = FCS->GetSteerPosDeg(); + GroundReactions->in.BrakePos = FCS->GetBrakePos(); + GroundReactions->in.FCSGearPos = FCS->GetGearPos(); + GroundReactions->in.EmptyWeight = MassBalance->GetEmptyWeight(); + GroundReactions->in.Tb2l = Propagate->GetTb2l(); + GroundReactions->in.Tec2l = Propagate->GetTec2l(); + GroundReactions->in.Tec2b = Propagate->GetTec2b(); + GroundReactions->in.PQR = Propagate->GetPQR(); + GroundReactions->in.UVW = Propagate->GetUVW(); + GroundReactions->in.DistanceAGL = Propagate->GetDistanceAGL(); + GroundReactions->in.DistanceASL = Propagate->GetAltitudeASL(); + GroundReactions->in.TotalDeltaT = dT * GroundReactions->GetRate(); + GroundReactions->in.WOW = GroundReactions->GetWOW(); + GroundReactions->in.Location = Propagate->GetLocation(); + GroundReactions->in.vXYZcg = MassBalance->GetXYZcg(); + break; + case eExternalReactions: + // There are no external inputs to this model. + break; + case eBuoyantForces: + BuoyantForces->in.Density = Atmosphere->GetDensity(); + BuoyantForces->in.Pressure = Atmosphere->GetPressure(); + BuoyantForces->in.Temperature = Atmosphere->GetTemperature(); + BuoyantForces->in.gravity = Inertial->gravity(); + break; + case eMassBalance: + MassBalance->in.GasInertia = BuoyantForces->GetGasMassInertia(); + MassBalance->in.GasMass = BuoyantForces->GetGasMass(); + MassBalance->in.GasMoment = BuoyantForces->GetGasMassMoment(); + MassBalance->in.TanksWeight = Propulsion->GetTanksWeight(); + MassBalance->in.TanksMoment = Propulsion->GetTanksMoment(); + MassBalance->in.TankInertia = Propulsion->CalculateTankInertias(); + break; + case eAircraft: + Aircraft->in.AeroForce = Aerodynamics->GetForces(); + Aircraft->in.PropForce = Propulsion->GetForces(); + Aircraft->in.GroundForce = GroundReactions->GetForces(); + Aircraft->in.ExternalForce = ExternalReactions->GetForces(); + Aircraft->in.BuoyantForce = BuoyantForces->GetForces(); + Aircraft->in.AeroMoment = Aerodynamics->GetMoments(); + Aircraft->in.PropMoment = Propulsion->GetMoments(); + Aircraft->in.GroundMoment = GroundReactions->GetMoments(); + Aircraft->in.ExternalMoment = ExternalReactions->GetMoments(); + Aircraft->in.BuoyantMoment = BuoyantForces->GetMoments(); + break; + case eAccelerations: + Accelerations->in.J = MassBalance->GetJ(); + Accelerations->in.Jinv = MassBalance->GetJinv(); + Accelerations->in.Ti2b = Propagate->GetTi2b(); + Accelerations->in.Tb2i = Propagate->GetTb2i(); + Accelerations->in.Tec2b = Propagate->GetTec2b(); + Accelerations->in.Tec2i = Propagate->GetTec2i(); + Accelerations->in.qAttitudeECI = Propagate->GetQuaternionECI(); + Accelerations->in.Moment = Aircraft->GetMoments(); + Accelerations->in.GroundMoment = GroundReactions->GetMoments(); + Accelerations->in.Force = Aircraft->GetForces(); + Accelerations->in.GroundForce = GroundReactions->GetForces(); + Accelerations->in.GAccel = Inertial->GetGAccel(Propagate->GetRadius()); + Accelerations->in.J2Grav = Inertial->GetGravityJ2(Propagate->GetLocation()); + Accelerations->in.vPQRi = Propagate->GetPQRi(); + Accelerations->in.vPQR = Propagate->GetPQR(); + Accelerations->in.vUVW = Propagate->GetUVW(); + Accelerations->in.vInertialPosition = Propagate->GetInertialPosition(); + Accelerations->in.DeltaT = dT; + Accelerations->in.Mass = MassBalance->GetMass(); + Accelerations->in.MultipliersList = GroundReactions->GetMultipliersList(); + Accelerations->in.TerrainVelocity = Propagate->GetTerrainVelocity(); + Accelerations->in.TerrainAngularVel = Propagate->GetTerrainAngularVelocity(); + break; + default: + break; + } +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGFDMExec::LoadPlanetConstants(void) +{ + Propagate->in.vOmegaPlanet = Inertial->GetOmegaPlanet(); + Accelerations->in.vOmegaPlanet = Inertial->GetOmegaPlanet(); + Propagate->in.SemiMajor = Inertial->GetSemimajor(); + Propagate->in.SemiMinor = Inertial->GetSemiminor(); + Auxiliary->in.SLGravity = Inertial->SLgravity(); + Auxiliary->in.ReferenceRadius = Inertial->GetRefRadius(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +void FGFDMExec::LoadModelConstants(void) +{ + Winds->in.wingspan = Aircraft->GetWingSpan(); + FCS->in.NumGear = GroundReactions->GetNumGearUnits(); + Aerodynamics->in.Wingarea = Aircraft->GetWingArea(); + Aerodynamics->in.Wingchord = Aircraft->Getcbar(); + Aerodynamics->in.Wingincidence = Aircraft->GetWingIncidence(); + Aerodynamics->in.Wingspan = Aircraft->GetWingSpan(); + Auxiliary->in.Wingspan = Aircraft->GetWingSpan(); + Auxiliary->in.Wingchord = Aircraft->Getcbar(); + GroundReactions->in.vXYZcg = MassBalance->GetXYZcg(); + + LoadPlanetConstants(); +} + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // This call will cause the sim time to reset to 0.0 bool FGFDMExec::RunIC(void) { + FGPropulsion* propulsion = (FGPropulsion*)Models[ePropulsion]; + + Models[eOutput]->InitModel(); + SuspendIntegration(); // saves the integration rate, dt, then sets it to 0.0. Initialize(IC); Run(); ResumeIntegration(); // Restores the integration rate to what it was. + for (unsigned int i=0; iGetNumEnginesRunning(); i++) + propulsion->InitRunning(IC->GetEngineRunning(i)); + return true; } @@ -375,35 +600,17 @@ bool FGFDMExec::RunIC(void) void FGFDMExec::Initialize(FGInitialCondition *FGIC) { - Propagate->SetInitialState( FGIC ); - - Atmosphere->Run(); - Atmosphere->SetWindNED( FGIC->GetWindNFpsIC(), - FGIC->GetWindEFpsIC(), - FGIC->GetWindDFpsIC() ); - - FGColumnVector3 vAeroUVW; - vAeroUVW = Propagate->GetUVW() + Propagate->GetTl2b()*Atmosphere->GetTotalWindNED(); - - double alpha, beta; - if (vAeroUVW(eW) != 0.0) - alpha = vAeroUVW(eU)*vAeroUVW(eU) > 0.0 ? atan2(vAeroUVW(eW), vAeroUVW(eU)) : 0.0; - else - alpha = 0.0; - if (vAeroUVW(eV) != 0.0) - beta = vAeroUVW(eU)*vAeroUVW(eU)+vAeroUVW(eW)*vAeroUVW(eW) > 0.0 ? atan2(vAeroUVW(eV), (fabs(vAeroUVW(eU))/vAeroUVW(eU))*sqrt(vAeroUVW(eU)*vAeroUVW(eU) + vAeroUVW(eW)*vAeroUVW(eW))) : 0.0; - else - beta = 0.0; - - Auxiliary->SetAB(alpha, beta); - - double Vt = vAeroUVW.Magnitude(); - Auxiliary->SetVt(Vt); + Setsim_time(0.0); - Auxiliary->SetMach(Vt/Atmosphere->GetSoundSpeed()); - - double qbar = 0.5*Vt*Vt*Atmosphere->GetDensity(); - Auxiliary->Setqbar(qbar); + Propagate->SetInitialState( FGIC ); + LoadInputs(eAccelerations); + Accelerations->Run(false); + LoadInputs(ePropagate); + Propagate->InitializeDerivatives(); + LoadInputs(eAtmosphere); + Atmosphere->Run(false); + Winds->SetWindNED(FGIC->GetWindNEDFpsIC()); + Auxiliary->Run(false); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -413,12 +620,8 @@ void FGFDMExec::Initialize(FGInitialCondition *FGIC) void FGFDMExec::ResetToInitialConditions(int mode) { - if (mode == 1) { - for (unsigned int i=0; iSetStartNewFile(true); - } - } - + if (mode == 1) Output->SetStartNewOutput(); + ResetToInitialConditions(); } @@ -428,19 +631,17 @@ void FGFDMExec::ResetToInitialConditions(void) { if (Constructing) return; - vector ::iterator it; - for (it = Models.begin(); it != Models.end(); ++it) (*it)->InitModel(); + for (unsigned int i = 0; i < Models.size(); i++) { + // The Output model will be initialized during the RunIC() execution + if (i == eOutput) continue; - RunIC(); - if (Script) Script->ResetEvents(); -} + LoadInputs(i); + Models[i]->InitModel(); + } -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + RunIC(); -void FGFDMExec::SetGroundCallback(FGGroundCallback* p) -{ - delete GroundCallback; - GroundCallback = p; + if (Script) Script->ResetEvents(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -448,6 +649,7 @@ void FGFDMExec::SetGroundCallback(FGGroundCallback* p) vector FGFDMExec::EnumerateFDMs(void) { vector FDMList; + FGAircraft* Aircraft = (FGAircraft*)Models[eAircraft]; FDMList.push_back(Aircraft->GetAircraftName()); @@ -460,12 +662,12 @@ vector FGFDMExec::EnumerateFDMs(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -bool FGFDMExec::LoadScript(const string& script, double deltaT) +bool FGFDMExec::LoadScript(const string& script, double deltaT, const string initfile) { bool result; Script = new FGScript(this); - result = Script->LoadScript(RootDir + script, deltaT); + result = Script->LoadScript(RootDir + script, deltaT, initfile); return result; } @@ -509,8 +711,9 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) } int saved_debug_lvl = debug_lvl; + FGXMLFileRead XMLFileRead; + Element *document = XMLFileRead.LoadXMLDocument(aircraftCfgFileName); // "document" is a class member - document = LoadXMLDocument(aircraftCfgFileName); // "document" is a class member if (document) { if (IsChild) debug_lvl = 0; @@ -533,7 +736,7 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) // Process the metrics element. This element is REQUIRED. element = document->FindElement("metrics"); if (element) { - result = Aircraft->Load(element); + result = ((FGAircraft*)Models[eAircraft])->Load(element); if (!result) { cerr << endl << "Aircraft metrics element has problems in file " << aircraftCfgFileName << endl; return result; @@ -546,7 +749,7 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) // Process the mass_balance element. This element is REQUIRED. element = document->FindElement("mass_balance"); if (element) { - result = MassBalance->Load(element); + result = ((FGMassBalance*)Models[eMassBalance])->Load(element); if (!result) { cerr << endl << "Aircraft mass_balance element has problems in file " << aircraftCfgFileName << endl; return result; @@ -559,11 +762,12 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) // Process the ground_reactions element. This element is REQUIRED. element = document->FindElement("ground_reactions"); if (element) { - result = GroundReactions->Load(element); + result = ((FGGroundReactions*)Models[eGroundReactions])->Load(element); if (!result) { cerr << endl << "Aircraft ground_reactions element has problems in file " << aircraftCfgFileName << endl; return result; } + ((FGFCS*)Models[eSystems])->AddGear(((FGGroundReactions*)Models[eGroundReactions])->GetNumGearUnits()); } else { cerr << endl << "No ground_reactions element was found in the aircraft config file." << endl; return false; @@ -572,7 +776,7 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) // Process the external_reactions element. This element is OPTIONAL. element = document->FindElement("external_reactions"); if (element) { - result = ExternalReactions->Load(element); + result = ((FGExternalReactions*)Models[eExternalReactions])->Load(element); if (!result) { cerr << endl << "Aircraft external_reactions element has problems in file " << aircraftCfgFileName << endl; return result; @@ -582,7 +786,7 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) // Process the buoyant_forces element. This element is OPTIONAL. element = document->FindElement("buoyant_forces"); if (element) { - result = BuoyantForces->Load(element); + result = ((FGBuoyantForces*)Models[eBuoyantForces])->Load(element); if (!result) { cerr << endl << "Aircraft buoyant_forces element has problems in file " << aircraftCfgFileName << endl; return result; @@ -592,17 +796,19 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) // Process the propulsion element. This element is OPTIONAL. element = document->FindElement("propulsion"); if (element) { - result = Propulsion->Load(element); + result = ((FGPropulsion*)Models[ePropulsion])->Load(element); if (!result) { cerr << endl << "Aircraft propulsion element has problems in file " << aircraftCfgFileName << endl; return result; } + for (unsigned int i=0; i<((FGPropulsion*)Models[ePropulsion])->GetNumEngines(); i++) + ((FGFCS*)Models[eSystems])->AddThrottle(); } // Process the system element[s]. This element is OPTIONAL, and there may be more than one. element = document->FindElement("system"); while (element) { - result = FCS->Load(element, FGFCS::stSystem); + result = ((FGFCS*)Models[eSystems])->Load(element, FGFCS::stSystem); if (!result) { cerr << endl << "Aircraft system element has problems in file " << aircraftCfgFileName << endl; return result; @@ -613,7 +819,7 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) // Process the autopilot element. This element is OPTIONAL. element = document->FindElement("autopilot"); if (element) { - result = FCS->Load(element, FGFCS::stAutoPilot); + result = ((FGFCS*)Models[eSystems])->Load(element, FGFCS::stAutoPilot); if (!result) { cerr << endl << "Aircraft autopilot element has problems in file " << aircraftCfgFileName << endl; return result; @@ -623,7 +829,7 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) // Process the flight_control element. This element is OPTIONAL. element = document->FindElement("flight_control"); if (element) { - result = FCS->Load(element, FGFCS::stFCS); + result = ((FGFCS*)Models[eSystems])->Load(element, FGFCS::stFCS); if (!result) { cerr << endl << "Aircraft flight_control element has problems in file " << aircraftCfgFileName << endl; return result; @@ -633,7 +839,7 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) // Process the aerodynamics element. This element is OPTIONAL, but almost always expected. element = document->FindElement("aerodynamics"); if (element) { - result = Aerodynamics->Load(element); + result = ((FGAerodynamics*)Models[eAerodynamics])->Load(element); if (!result) { cerr << endl << "Aircraft aerodynamics element has problems in file " << aircraftCfgFileName << endl; return result; @@ -645,7 +851,7 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) // Process the input element. This element is OPTIONAL. element = document->FindElement("input"); if (element) { - result = Input->Load(element); + result = ((FGInput*)Models[eInput])->Load(element); if (!result) { cerr << endl << "Aircraft input element has problems in file " << aircraftCfgFileName << endl; return result; @@ -653,23 +859,20 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) } // Process the output element[s]. This element is OPTIONAL, and there may be more than one. - unsigned int idx=0; - typedef int (FGOutput::*iOPMF)(void) const; element = document->FindElement("output"); while (element) { - if (debug_lvl > 0) cout << endl << " Output data set: " << idx << " "; - FGOutput* Output = new FGOutput(this); - Output->InitModel(); - Schedule(Output, 1); - result = Output->Load(element); + string output_file_name = aircraftCfgFileName; + + if (!element->GetAttributeValue("file").empty()) { + output_file_name = RootDir + element->GetAttributeValue("file"); + result = ((FGOutput*)Models[eOutput])->SetDirectivesFile(output_file_name); + } + else + result = ((FGOutput*)Models[eOutput])->Load(element); + if (!result) { - cerr << endl << "Aircraft output element has problems in file " << aircraftCfgFileName << endl; + cerr << endl << "Aircraft output element has problems in file " << output_file_name << endl; return result; - } else { - Outputs.push_back(Output); - string outputProp = CreateIndexedPropertyName("simulation/output",idx); - instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate); - idx++; } element = document->FindNextElement("output"); } @@ -684,18 +887,27 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) } } + // Since all vehicle characteristics have been loaded, place the values in the Inputs + // structure for the FGModel-derived classes. + LoadModelConstants(); + modelLoaded = true; if (debug_lvl > 0) { - MassBalance->Run(); // Update all mass properties for the report. - MassBalance->GetMassPropertiesReport(); + LoadInputs(eMassBalance); // Update all input mass properties for the report. + Models[eMassBalance]->Run(false); // Update all mass properties for the report. + LoadInputs(ePropulsion); // Update propulsion properties for the report. + Models[ePropulsion]->Run(false); // Update propulsion properties for the report. + LoadInputs(eMassBalance); // Update all (one more time) input mass properties for the report. + Models[eMassBalance]->Run(false); // Update all (one more time) mass properties for the report. + ((FGMassBalance*)Models[eMassBalance])->GetMassPropertiesReport(); cout << endl << fgblue << highint << "End of vehicle configuration loading." << endl << "-------------------------------------------------------------------------------" << reset << endl; } - + if (IsChild) debug_lvl = saved_debug_lvl; } else { @@ -704,19 +916,12 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) << fgdef << endl; } - // Late bind previously undefined FCS inputs. - try { - FCS->LateBind(); - } catch (string prop) { - cerr << endl << fgred << " Could not late bind property " << prop - << ". Aborting." << endl; - result = false; - } + for (unsigned int i=0; i< Models.size(); i++) LoadInputs(i); if (result) { struct PropertyCatalogStructure masterPCS; masterPCS.base_string = ""; - masterPCS.node = (FGPropertyManager*)Root; + masterPCS.node = Root->GetNode(); BuildPropertyCatalog(&masterPCS); } @@ -725,24 +930,34 @@ bool FGFDMExec::LoadModel(const string& model, bool addModelToPath) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +string FGFDMExec::GetPropulsionTankReport() +{ + return ((FGPropulsion*)Models[ePropulsion])->GetPropulsionTankReport(); +} + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + void FGFDMExec::BuildPropertyCatalog(struct PropertyCatalogStructure* pcs) { struct PropertyCatalogStructure* pcsNew = new struct PropertyCatalogStructure; int node_idx = 0; for (int i=0; inode->nChildren(); i++) { + string access=""; pcsNew->base_string = pcs->base_string + "/" + pcs->node->getChild(i)->getName(); node_idx = pcs->node->getChild(i)->getIndex(); if (node_idx != 0) { pcsNew->base_string = CreateIndexedPropertyName(pcsNew->base_string, node_idx); } if (pcs->node->getChild(i)->nChildren() == 0) { - if (pcsNew->base_string.substr(0,11) == string("/fdm/jsbsim")) { + if (pcsNew->base_string.substr(0,12) == string("/fdm/jsbsim/")) { pcsNew->base_string = pcsNew->base_string.erase(0,12); } - PropertyCatalog.push_back(pcsNew->base_string); + if (pcs->node->getChild(i)->getAttribute(SGPropertyNode::READ)) access="R"; + if (pcs->node->getChild(i)->getAttribute(SGPropertyNode::WRITE)) access+="W"; + PropertyCatalog.push_back(pcsNew->base_string+" ("+access+")"); } else { - pcsNew->node = (FGPropertyManager*)pcs->node->getChild(i); + pcsNew->node = (FGPropertyNode*)pcs->node->getChild(i); BuildPropertyCatalog(pcsNew); } } @@ -806,7 +1021,7 @@ bool FGFDMExec::ReadPrologue(Element* el) // el for ReadPrologue is the document if (!el) return false; string AircraftName = el->GetAttributeValue("name"); - Aircraft->SetAircraftName(AircraftName); + ((FGAircraft*)Models[eAircraft])->SetAircraftName(AircraftName); if (debug_lvl & 1) cout << underon << "Reading Aircraft Configuration File" << underoff << ": " << highint << AircraftName << normint << endl; @@ -894,7 +1109,7 @@ bool FGFDMExec::ReadChild(Element* el) cerr << endl << highint << fgred << " No location was found for this child object!" << reset << endl; exit(-1); } - + Element* orientation = el->FindElement("orient"); if (orientation) { child->Orient = orientation->FindElementTripletConvertTo("RAD"); @@ -925,42 +1140,26 @@ FGTrim* FGFDMExec::GetTrim(void) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGFDMExec::DisableOutput(void) -{ - for (unsigned i=0; iDisable(); - } -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void FGFDMExec::EnableOutput(void) +void FGFDMExec::CheckIncrementalHold(void) { - for (unsigned i=0; iEnable(); - } -} + // Only check if increment then hold is on + if( IncrementThenHolding ) { -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + if (TimeStepsUntilHold == 0) { -bool FGFDMExec::SetOutputDirectives(const string& fname) -{ - bool result; + // Should hold simulation if TimeStepsUntilHold has reached zero + holding = true; - FGOutput* Output = new FGOutput(this); - Output->SetDirectivesFile(RootDir + fname); - Output->InitModel(); - Schedule(Output, 1); - result = Output->Load(0); + // Still need to decrement TimeStepsUntilHold as value of -1 + // indicates that incremental then hold is turned off + IncrementThenHolding = false; + TimeStepsUntilHold--; - if (result) { - Outputs.push_back(Output); - typedef int (FGOutput::*iOPMF)(void) const; - string outputProp = CreateIndexedPropertyName("simulation/output",Outputs.size()-1); - instance->Tie(outputProp+"/log_rate_hz", Output, (iOPMF)0, &FGOutput::SetRate); + } else if ( TimeStepsUntilHold > 0 ) { + // Keep decrementing until 0 is reached + TimeStepsUntilHold--; + } } - - return result; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -983,63 +1182,39 @@ void FGFDMExec::DoTrim(int mode) } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -/* -void FGFDMExec::DoTrimAnalysis(int mode) + +void FGFDMExec::DoSimplexTrim(int mode) { double saved_time; if (Constructing) return; - - if (mode < 0 || mode > JSBSim::taNone) { - cerr << endl << "Illegal trimming mode!" << endl << endl; - return; + if (mode < 0 || mode > JSBSim::tNone) { + cerr << endl << "Illegal trimming mode!" << endl << endl; + return; } saved_time = sim_time; - - FGTrimAnalysis trimAnalysis(this, (JSBSim::TrimAnalysisMode)mode); - - if ( !trimAnalysis.Load(IC->GetInitFile(), false) ) { - cerr << "A problem occurred with trim configuration file " << trimAnalysis.Load(IC->GetInitFile()) << endl; - exit(-1); - } - - bool result = trimAnalysis.DoTrim(); - - if ( !result ) cerr << endl << "Trim Failed" << endl << endl; - - trimAnalysis.Report(); + FGSimplexTrim trim(this, (JSBSim::TrimMode)mode); + sim_time = saved_time; Setsim_time(saved_time); - - EnableOutput(); - cout << "\nOutput: " << GetOutputFileName() << endl; - + std::cout << "dT: " << dT << std::endl; } -*/ + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGFDMExec::UseAtmosphereMSIS(void) +void FGFDMExec::DoLinearization(int mode) { - FGAtmosphere *oldAtmosphere = Atmosphere; - Atmosphere = new MSIS(this); - if (!Atmosphere->InitModel()) { - cerr << fgred << "MSIS Atmosphere model init failed" << fgdef << endl; - Error+=1; - } - delete oldAtmosphere; + double saved_time; + if (Constructing) return; + saved_time = sim_time; + FGLinearization lin(this,mode); + sim_time = saved_time; + Setsim_time(saved_time); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void FGFDMExec::UseAtmosphereMars(void) +void FGFDMExec::SRand(int sr) { -/* - FGAtmosphere *oldAtmosphere = Atmosphere; - Atmosphere = new FGMars(this); - if (!Atmosphere->InitModel()) { - cerr << fgred << "Mars Atmosphere model init failed" << fgdef << endl; - Error+=1; - } - delete oldAtmosphere; -*/ + srand(sr); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1067,10 +1242,10 @@ void FGFDMExec::Debug(int from) if (debug_lvl & 1 && IdFDM == 0) { // Standard console startup message output if (from == 0) { // Constructor - cout << "\n\n " << highint << underon << "JSBSim Flight Dynamics Model v" - << JSBSim_version << underoff << normint << endl; - cout << halfint << " [JSBSim-ML v" << needed_cfg_version << "]\n\n"; - cout << normint << "JSBSim startup beginning ...\n\n"; + cout << "\n\n " + << "JSBSim Flight Dynamics Model v" << JSBSim_version << endl; + cout << " [JSBSim-ML v" << needed_cfg_version << "]\n\n"; + cout << "JSBSim startup beginning ...\n\n"; } else if (from == 3) { cout << "\n\nJSBSim startup complete\n\n"; }