]> git.mxchange.org Git - flightgear.git/commitdiff
Sync with JSBSim CVS
authorErik Hofman <erik@ehofman.com>
Fri, 16 Jul 2010 09:05:59 +0000 (11:05 +0200)
committerErik Hofman <erik@ehofman.com>
Fri, 16 Jul 2010 09:05:59 +0000 (11:05 +0200)
142 files changed:
src/FDM/JSBSim/FGFDMExec.cpp
src/FDM/JSBSim/FGFDMExec.h
src/FDM/JSBSim/FGJSBBase.cpp
src/FDM/JSBSim/FGJSBBase.h
src/FDM/JSBSim/FGState.cpp
src/FDM/JSBSim/FGState.h
src/FDM/JSBSim/JSBSim.cxx
src/FDM/JSBSim/JSBSim.hxx
src/FDM/JSBSim/initialization/FGInitialCondition.cpp
src/FDM/JSBSim/initialization/FGInitialCondition.h
src/FDM/JSBSim/initialization/FGTrim.cpp
src/FDM/JSBSim/initialization/FGTrim.h
src/FDM/JSBSim/initialization/FGTrimAxis.cpp
src/FDM/JSBSim/initialization/FGTrimAxis.h
src/FDM/JSBSim/input_output/FGGroundCallback.cpp
src/FDM/JSBSim/input_output/FGGroundCallback.h
src/FDM/JSBSim/input_output/FGPropertyManager.cpp
src/FDM/JSBSim/input_output/FGPropertyManager.h
src/FDM/JSBSim/input_output/FGScript.cpp
src/FDM/JSBSim/input_output/FGScript.h
src/FDM/JSBSim/input_output/FGXMLElement.cpp
src/FDM/JSBSim/input_output/FGXMLElement.h
src/FDM/JSBSim/input_output/FGXMLFileRead.h
src/FDM/JSBSim/input_output/FGXMLParse.cpp
src/FDM/JSBSim/input_output/FGXMLParse.h
src/FDM/JSBSim/input_output/FGfdmSocket.cpp
src/FDM/JSBSim/input_output/FGfdmSocket.h
src/FDM/JSBSim/input_output/string_utilities.h
src/FDM/JSBSim/math/FGColumnVector3.cpp
src/FDM/JSBSim/math/FGColumnVector3.h
src/FDM/JSBSim/math/FGCondition.cpp
src/FDM/JSBSim/math/FGCondition.h
src/FDM/JSBSim/math/FGFunction.cpp
src/FDM/JSBSim/math/FGFunction.h
src/FDM/JSBSim/math/FGLocation.cpp
src/FDM/JSBSim/math/FGLocation.h
src/FDM/JSBSim/math/FGMatrix33.cpp
src/FDM/JSBSim/math/FGMatrix33.h
src/FDM/JSBSim/math/FGParameter.h
src/FDM/JSBSim/math/FGPropertyValue.cpp
src/FDM/JSBSim/math/FGPropertyValue.h
src/FDM/JSBSim/math/FGQuaternion.cpp
src/FDM/JSBSim/math/FGQuaternion.h
src/FDM/JSBSim/math/FGRealValue.cpp
src/FDM/JSBSim/math/FGRealValue.h
src/FDM/JSBSim/math/FGTable.cpp
src/FDM/JSBSim/math/FGTable.h
src/FDM/JSBSim/models/FGAerodynamics.cpp
src/FDM/JSBSim/models/FGAerodynamics.h
src/FDM/JSBSim/models/FGAircraft.cpp
src/FDM/JSBSim/models/FGAircraft.h
src/FDM/JSBSim/models/FGAtmosphere.cpp
src/FDM/JSBSim/models/FGAtmosphere.h
src/FDM/JSBSim/models/FGAuxiliary.cpp
src/FDM/JSBSim/models/FGAuxiliary.h
src/FDM/JSBSim/models/FGBuoyantForces.cpp
src/FDM/JSBSim/models/FGBuoyantForces.h
src/FDM/JSBSim/models/FGExternalForce.cpp
src/FDM/JSBSim/models/FGExternalForce.h
src/FDM/JSBSim/models/FGExternalReactions.cpp
src/FDM/JSBSim/models/FGExternalReactions.h
src/FDM/JSBSim/models/FGFCS.cpp
src/FDM/JSBSim/models/FGFCS.h
src/FDM/JSBSim/models/FGGasCell.cpp
src/FDM/JSBSim/models/FGGasCell.h
src/FDM/JSBSim/models/FGGroundReactions.cpp
src/FDM/JSBSim/models/FGGroundReactions.h
src/FDM/JSBSim/models/FGInertial.cpp
src/FDM/JSBSim/models/FGInertial.h
src/FDM/JSBSim/models/FGInput.cpp
src/FDM/JSBSim/models/FGInput.h
src/FDM/JSBSim/models/FGLGear.cpp
src/FDM/JSBSim/models/FGLGear.h
src/FDM/JSBSim/models/FGMassBalance.cpp
src/FDM/JSBSim/models/FGMassBalance.h
src/FDM/JSBSim/models/FGModel.cpp
src/FDM/JSBSim/models/FGModel.h
src/FDM/JSBSim/models/FGOutput.cpp
src/FDM/JSBSim/models/FGOutput.h
src/FDM/JSBSim/models/FGPropagate.cpp
src/FDM/JSBSim/models/FGPropagate.h
src/FDM/JSBSim/models/FGPropulsion.cpp
src/FDM/JSBSim/models/FGPropulsion.h
src/FDM/JSBSim/models/atmosphere/FGMSIS.cpp
src/FDM/JSBSim/models/atmosphere/FGMSIS.h
src/FDM/JSBSim/models/atmosphere/FGMars.cpp
src/FDM/JSBSim/models/atmosphere/FGMars.h
src/FDM/JSBSim/models/flight_control/FGAccelerometer.cpp
src/FDM/JSBSim/models/flight_control/FGAccelerometer.h
src/FDM/JSBSim/models/flight_control/FGActuator.cpp [changed mode: 0755->0644]
src/FDM/JSBSim/models/flight_control/FGActuator.h [changed mode: 0755->0644]
src/FDM/JSBSim/models/flight_control/FGDeadBand.cpp
src/FDM/JSBSim/models/flight_control/FGDeadBand.h
src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp
src/FDM/JSBSim/models/flight_control/FGFCSComponent.h
src/FDM/JSBSim/models/flight_control/FGFCSFunction.cpp
src/FDM/JSBSim/models/flight_control/FGFCSFunction.h
src/FDM/JSBSim/models/flight_control/FGFilter.cpp
src/FDM/JSBSim/models/flight_control/FGFilter.h
src/FDM/JSBSim/models/flight_control/FGGain.cpp
src/FDM/JSBSim/models/flight_control/FGGain.h
src/FDM/JSBSim/models/flight_control/FGGradient.cpp
src/FDM/JSBSim/models/flight_control/FGGradient.h
src/FDM/JSBSim/models/flight_control/FGGyro.cpp
src/FDM/JSBSim/models/flight_control/FGGyro.h
src/FDM/JSBSim/models/flight_control/FGKinemat.cpp
src/FDM/JSBSim/models/flight_control/FGKinemat.h
src/FDM/JSBSim/models/flight_control/FGMagnetometer.cpp
src/FDM/JSBSim/models/flight_control/FGMagnetometer.h
src/FDM/JSBSim/models/flight_control/FGPID.cpp
src/FDM/JSBSim/models/flight_control/FGPID.h
src/FDM/JSBSim/models/flight_control/FGSensor.cpp
src/FDM/JSBSim/models/flight_control/FGSensor.h
src/FDM/JSBSim/models/flight_control/FGSensorOrientation.h
src/FDM/JSBSim/models/flight_control/FGSummer.cpp
src/FDM/JSBSim/models/flight_control/FGSummer.h
src/FDM/JSBSim/models/flight_control/FGSwitch.cpp
src/FDM/JSBSim/models/flight_control/FGSwitch.h
src/FDM/JSBSim/models/propulsion/FGElectric.cpp
src/FDM/JSBSim/models/propulsion/FGElectric.h
src/FDM/JSBSim/models/propulsion/FGEngine.cpp
src/FDM/JSBSim/models/propulsion/FGEngine.h
src/FDM/JSBSim/models/propulsion/FGForce.cpp
src/FDM/JSBSim/models/propulsion/FGForce.h
src/FDM/JSBSim/models/propulsion/FGNozzle.cpp
src/FDM/JSBSim/models/propulsion/FGNozzle.h
src/FDM/JSBSim/models/propulsion/FGPiston.cpp
src/FDM/JSBSim/models/propulsion/FGPiston.h
src/FDM/JSBSim/models/propulsion/FGPropeller.cpp
src/FDM/JSBSim/models/propulsion/FGPropeller.h
src/FDM/JSBSim/models/propulsion/FGRocket.cpp
src/FDM/JSBSim/models/propulsion/FGRocket.h
src/FDM/JSBSim/models/propulsion/FGRotor.cpp
src/FDM/JSBSim/models/propulsion/FGRotor.h
src/FDM/JSBSim/models/propulsion/FGTank.cpp
src/FDM/JSBSim/models/propulsion/FGTank.h
src/FDM/JSBSim/models/propulsion/FGThruster.cpp
src/FDM/JSBSim/models/propulsion/FGThruster.h
src/FDM/JSBSim/models/propulsion/FGTurbine.cpp
src/FDM/JSBSim/models/propulsion/FGTurbine.h
src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
src/FDM/JSBSim/models/propulsion/FGTurboProp.h

index 6851223810d1208eaca2be7bc291c05f934a3963..820e69daa4dc994bceb3b5a897132b568860287e 100644 (file)
@@ -42,7 +42,6 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGFDMExec.h"
-#include "FGState.h"
 #include "models/FGAtmosphere.h"
 #include "models/atmosphere/FGMSIS.h"
 #include "models/atmosphere/FGMars.h"
@@ -72,7 +71,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGFDMExec.cpp,v 1.78 2010/04/12 12:25:19 jberndt Exp $";
 static const char *IdHdr = ID_FDMEXEC;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -111,7 +110,6 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root)
   Frame           = 0;
   Error           = 0;
   GroundCallback  = 0;
-  State           = 0;
   Atmosphere      = 0;
   FCS             = 0;
   Propulsion      = 0;
@@ -129,11 +127,17 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root)
   Trim            = 0;
   Script          = 0;
 
+  RootDir = "";
+
   modelLoaded = false;
   IsChild = false;
   holding = false;
   Terminate = false;
 
+  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.
+
   IdFDM = FDMctr; // The main (parent) JSBSim instance is always the "zeroth"
   FDMctr++;       // instance. "child" instances are loaded last.
 
@@ -169,6 +173,9 @@ FGFDMExec::FGFDMExec(FGPropertyManager* root) : Root(root)
   instance->Tie("simulation/do_simple_trim", this, (iPMF)0, &FGFDMExec::DoTrim);
   instance->Tie("simulation/reset", this, (iPMF)0, &FGFDMExec::ResetToInitialConditions);
   instance->Tie("simulation/terminate", (int *)&Terminate);
+  instance->Tie("simulation/sim-time-sec", this, &FGFDMExec::GetSimTime);
+  instance->Tie("simulation/jsbsim-debug", this, &FGFDMExec::GetDebugLevel, &FGFDMExec::SetDebugLevel);
+
   Constructing = false;
 }
 
@@ -217,15 +224,11 @@ bool FGFDMExec::Allocate(void)
   Auxiliary       = new FGAuxiliary(this);
   Input           = new FGInput(this);
 
-  State           = new FGState(this); // This must be done here, as the FGState
-                                       // class needs valid pointers to the above
-                                       // model classes
-
   // 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,      30);
+  Schedule(Atmosphere,      1);
   Schedule(FCS,             1);
   Schedule(Propulsion,      1);
   Schedule(MassBalance,     1);
@@ -267,7 +270,6 @@ bool FGFDMExec::DeAllocate(void)
   delete Aircraft;
   delete Propagate;
   delete Auxiliary;
-  delete State;
   delete Script;
 
   for (unsigned i=0; i<Outputs.size(); i++) delete Outputs[i];
@@ -280,7 +282,6 @@ bool FGFDMExec::DeAllocate(void)
 
   Error       = 0;
 
-  State           = 0;
   Input           = 0;
   Atmosphere      = 0;
   FCS             = 0;
@@ -324,13 +325,13 @@ bool FGFDMExec::Run(void)
   }
 
   // returns true if success, false if complete
-  if (Script != 0 && !State->IntegrationSuspended()) success = Script->RunScript();
+  if (Script != 0 && !IntegrationSuspended()) success = Script->RunScript();
 
   vector <FGModel*>::iterator it;
   for (it = Models.begin(); it != Models.end(); ++it) (*it)->Run();
 
   Frame++;
-  if (!Holding()) State->IncrTime();
+  if (!Holding()) IncrTime();
   if (Terminate) success = false;
 
   return (success);
@@ -341,14 +342,49 @@ bool FGFDMExec::Run(void)
 
 bool FGFDMExec::RunIC(void)
 {
-  State->SuspendIntegration();
-  State->Initialize(IC);
+  SuspendIntegration(); // saves the integration rate, dt, then sets it to 0.0.
+  Initialize(IC);
   Run();
-  State->ResumeIntegration();
+  ResumeIntegration(); // Restores the integration rate to what it was.
 
   return true;
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+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);
+
+  Auxiliary->SetMach(Vt/Atmosphere->GetSoundSpeed());
+
+  double qbar = 0.5*Vt*Vt*Atmosphere->GetDensity();
+  Auxiliary->Setqbar(qbar);
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //
 // A private, internal function call for Tie-ing to a property, so it needs an
@@ -388,20 +424,6 @@ void FGFDMExec::SetGroundCallback(FGGroundCallback* p)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-double FGFDMExec::GetSimTime(void)
-{
-  return (State->Getsim_time());
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-double FGFDMExec::GetDeltaT(void)
-{
-  return (State->Getdt());
-}
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
 vector <string> FGFDMExec::EnumerateFDMs(void)
 {
   vector <string> FDMList;
@@ -417,12 +439,12 @@ vector <string> FGFDMExec::EnumerateFDMs(void)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGFDMExec::LoadScript(string script)
+bool FGFDMExec::LoadScript(string script, double deltaT)
 {
   bool result;
 
   Script = new FGScript(this);
-  result = Script->LoadScript(script);
+  result = Script->LoadScript(RootDir + script, deltaT);
 
   return result;
 }
@@ -432,9 +454,9 @@ bool FGFDMExec::LoadScript(string script)
 bool FGFDMExec::LoadModel(string AircraftPath, string EnginePath, string SystemsPath,
                 string model, bool addModelToPath)
 {
-  FGFDMExec::AircraftPath = AircraftPath;
-  FGFDMExec::EnginePath = EnginePath;
-  FGFDMExec::SystemsPath = SystemsPath;
+  FGFDMExec::AircraftPath = RootDir + AircraftPath;
+  FGFDMExec::EnginePath = RootDir + EnginePath;
+  FGFDMExec::SystemsPath = RootDir + SystemsPath;
 
   return LoadModel(model, addModelToPath);
 }
@@ -445,7 +467,6 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
 {
   string token;
   string aircraftCfgFileName;
-  string separator = "/";
   Element* element = 0L;
   bool result = false; // initialize result to false, indicating input file not yet read
 
@@ -458,8 +479,8 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
   }
 
   FullAircraftPath = AircraftPath;
-  if (addModelToPath) FullAircraftPath += separator + model;
-  aircraftCfgFileName = FullAircraftPath + separator + model + ".xml";
+  if (addModelToPath) FullAircraftPath += "/" + model;
+  aircraftCfgFileName = FullAircraftPath + "/" + model + ".xml";
 
   if (modelLoaded) {
     DeAllocate();
@@ -644,6 +665,9 @@ bool FGFDMExec::LoadModel(string model, bool addModelToPath)
 
     modelLoaded = true;
 
+    MassBalance->Run(); // Update all mass properties for the report.
+    MassBalance->GetMassPropertiesReport();
+
     if (debug_lvl > 0) {
       cout << endl << fgblue << highint
            << "End of vehicle configuration loading." << endl
@@ -893,15 +917,17 @@ bool FGFDMExec::SetOutputDirectives(string fname)
   bool result;
 
   FGOutput* Output = new FGOutput(this);
-  Output->SetDirectivesFile(fname);
+  Output->SetDirectivesFile(RootDir + fname);
   Output->InitModel();
-  Schedule(Output,       1);
+  Schedule(Output, 1);
   result = Output->Load(0);
-  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);
+  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);
+  }
 
   return result;
 }
@@ -918,11 +944,11 @@ void FGFDMExec::DoTrim(int mode)
     cerr << endl << "Illegal trimming mode!" << endl << endl;
     return;
   }
-  saved_time = State->Getsim_time();
+  saved_time = sim_time;
   FGTrim trim(this, (JSBSim::TrimMode)mode);
   if ( !trim.DoTrim() ) cerr << endl << "Trim Failed" << endl << endl;
   trim.Report();
-  State->Setsim_time(saved_time);
+  sim_time = saved_time;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -936,7 +962,7 @@ void FGFDMExec::DoTrimAnalysis(int mode)
     cerr << endl << "Illegal trimming mode!" << endl << endl;
     return;
   }
-  saved_time = State->Getsim_time();
+  saved_time = sim_time;
 
   FGTrimAnalysis trimAnalysis(this, (JSBSim::TrimAnalysisMode)mode);
 
@@ -950,7 +976,7 @@ void FGFDMExec::DoTrimAnalysis(int mode)
   if ( !result ) cerr << endl << "Trim Failed" << endl << endl;
 
   trimAnalysis.Report();
-  State->Setsim_time(saved_time);
+  Setsim_time(saved_time);
 
   EnableOutput();
   cout << "\nOutput: " << GetOutputFileName() << endl;
@@ -1025,7 +1051,7 @@ void FGFDMExec::Debug(int from)
   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
     if (from == 2) {
       cout << "================== Frame: " << Frame << "  Time: "
-           << State->Getsim_time() << " dt: " << State->Getdt() << endl;
+           << sim_time << " dt: " << dT << endl;
     }
   }
   if (debug_lvl & 8 ) { // Runtime state variables
index c1fbbb8ef1a17f228582a9d6557223bf01b66d2b..8c91cb2c9ce09430404a0103387788ccd005532b 100644 (file)
@@ -60,7 +60,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FDMEXEC "$Id$"
+#define ID_FDMEXEC "$Id: FGFDMExec.h,v 1.52 2010/07/04 13:50:21 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -169,7 +169,7 @@ CLASS DOCUMENTATION
                                 property actually maps toa function call of DoTrim().
 
     @author Jon S. Berndt
-    @version $Revision$
+    @version $Revision: 1.52 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -270,23 +270,23 @@ public:
   /** Loads a script
       @param Script the full path name and file name for the script to be loaded.
       @return true if successfully loadsd; false otherwise. */
-  bool LoadScript(string Script);
+  bool LoadScript(string Script, double deltaT);
 
   /** Sets the path to the engine config file directories.
       @param path path to the directory under which engine config
       files are kept, for instance "engine"  */
-  bool SetEnginePath(string path)   { EnginePath = path; return true; }
+  bool SetEnginePath(string path)   { EnginePath = RootDir + path; return true; }
 
   /** Sets the path to the aircraft config file directories.
       @param path path to the aircraft directory. For instance:
       "aircraft". Under aircraft, then, would be directories for various
       modeled aircraft such as C172/, x15/, etc.  */
-  bool SetAircraftPath(string path) { AircraftPath = path; return true; }
+  bool SetAircraftPath(string path) { AircraftPath = RootDir + path; return true; }
   
   /** Sets the path to the systems config file directories.
       @param path path to the directory under which systems config
       files are kept, for instance "systems"  */
-  bool SetSystemsPath(string path)   { SystemsPath = path; return true; }
+  bool SetSystemsPath(string path)   { SystemsPath = RootDir + path; return true; }
   
   /// @name Top-level executive State and Model retrieval mechanism
   //@{
@@ -318,8 +318,6 @@ public:
   inline FGInput* GetInput(void)              {return Input;}
   /// Returns the FGGroundCallback pointer.
   inline FGGroundCallback* GetGroundCallback(void) {return GroundCallback;}
-  /// Returns the FGState pointer.
-  inline FGState* GetState(void)              {return State;}
   /// Retrieves the script object
   inline FGScript* GetScript(void) {return Script;}
   // Returns a pointer to the FGInitialCondition object
@@ -351,19 +349,19 @@ public:
 
   /// Returns the model name.
   string GetModelName(void) { return modelName; }
-
+/*
   /// Returns the current time.
   double GetSimTime(void);
 
   /// Returns the current frame time (delta T).
   double GetDeltaT(void);
-  
+*/  
   /// Returns a pointer to the property manager object.
   FGPropertyManager* GetPropertyManager(void);
   /// Returns a vector of strings representing the names of all loaded models (future)
   vector <string> EnumerateFDMs(void);
   /// Gets the number of child FDMs.
-  int GetFDMCount(void) {return ChildFDMList.size();}
+  int GetFDMCount(void) {return (int)ChildFDMList.size();}
   /// Gets a particular child FDM.
   childData* GetChildFDM(int i) {return ChildFDMList[i];}
   /// Marks this instance of the Exec object as a "child" object.
@@ -454,6 +452,8 @@ public:
   // Print the contents of the property catalog for the loaded aircraft.
   void PrintPropertyCatalog(void);
 
+  vector<string>& GetPropertyCatalog(void) {return PropertyCatalog;}
+
   /// Use the MSIS atmosphere model.
   void UseAtmosphereMSIS(void);
 
@@ -465,12 +465,61 @@ public:
   void SetTrimMode(int mode){ ta_mode = mode; }
   int GetTrimMode(void) const { return ta_mode; }
 
+  /// Returns the cumulative simulation time in seconds.
+  double GetSimTime(void) const { return sim_time; }
+
+  /// Returns the simulation delta T.
+  double GetDeltaT(void) {return dT;}
+
+  /// Suspends the simulation and sets the delta T to zero.
+  void SuspendIntegration(void) {saved_dT = dT; dT = 0.0;}
+
+  /// Resumes the simulation by resetting delta T to the correct value.
+  void ResumeIntegration(void)  {dT = saved_dT;}
+
+  /** Returns the simulation suspension state.
+      @return true if suspended, false if executing  */
+  bool IntegrationSuspended(void) {return dT == 0.0;}
+
+  /** Sets the current sim time.
+      @param cur_time the current time
+      @return the current simulation time.      */
+  double Setsim_time(double cur_time) {
+    sim_time = cur_time;
+    return sim_time;
+  }
+
+  /** Sets the integration time step for the simulation executive.
+      @param delta_t the time step in seconds.     */
+  void Setdt(double delta_t) { dT = delta_t; }
+
+  /** Sets the root directory where JSBSim starts looking for its system directories.
+      @param rootDir the string containing the root directory. */
+  void SetRootDir(string rootDir) {RootDir = rootDir;}
+
+  /** Retrieves teh Root Directory.
+      @return the string representing the root (base) JSBSim directory. */
+  string GetRootDir(void) const {return RootDir;}
+
+  /** Increments the simulation time.
+      @return the new simulation time.     */
+  double IncrTime(void) {
+    sim_time += dT;
+    return sim_time;
+  }
+
+  /** Retrieves the current debug level setting. */
+  int GetDebugLevel(void) const {return debug_lvl;};
+
 private:
   static unsigned int FDMctr;
   int Error;
   unsigned int Frame;
   unsigned int IdFDM;
   unsigned short Terminate;
+  double dT;
+  double saved_dT;
+  double sim_time;
   bool holding;
   bool Constructing;
   bool modelLoaded;
@@ -482,6 +531,7 @@ private:
   string SystemsPath;
   string CFGVersion;
   string Release;
+  string RootDir;
 
   bool trim_status;
   int ta_mode;
@@ -489,7 +539,6 @@ private:
   static FGPropertyManager *master;
 
   FGGroundCallback*   GroundCallback;
-  FGState*            State;
   FGAtmosphere*       Atmosphere;
   FGFCS*              FCS;
   FGPropulsion*       Propulsion;
@@ -521,6 +570,7 @@ private:
   void ResetToInitialConditions(int mode);
   bool Allocate(void);
   bool DeAllocate(void);
+  void Initialize(FGInitialCondition *FGIC);
 
   void Debug(int from);
 };
index f07a4f08158fecbd18c6718e3926a2a995bc9be3..a361a37d256732250ebef9803ba2fd9c8e5b23f1 100644 (file)
@@ -44,7 +44,7 @@ INCLUDES
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGJSBBase.cpp,v 1.29 2010/03/18 13:19:21 jberndt Exp $";
 static const char *IdHdr = ID_JSBBASE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -77,8 +77,8 @@ CLASS IMPLEMENTATION
     char FGJSBBase::fgdef[6]    = {'\0' };
 #endif
 
-const double FGJSBBase::radtodeg = 57.29578;
-const double FGJSBBase::degtorad = 1.745329E-2;
+const double FGJSBBase::radtodeg = 57.295779513082320876798154814105;
+const double FGJSBBase::degtorad = 0.017453292519943295769236907684886;
 const double FGJSBBase::hptoftlbssec = 550.0;
 const double FGJSBBase::psftoinhg = 0.014138;
 const double FGJSBBase::psftopa = 47.88;
index d4ceb2c97ad3f59de484d340e28f13ea780031f6..2049a3cadb5ec2af5e8d4e76ae164e4d80bb7bf8 100644 (file)
@@ -63,7 +63,7 @@ namespace std
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_JSBBASE "$Id$"
+#define ID_JSBBASE "$Id: FGJSBBase.h,v 1.30 2010/07/01 23:13:19 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -79,7 +79,7 @@ CLASS DOCUMENTATION
 *   This class provides universal constants, utility functions, messaging
 *   functions, and enumerated constants to JSBSim.
     @author Jon S. Berndt
-    @version $Id$
+    @version $Id: FGJSBBase.h,v 1.30 2010/07/01 23:13:19 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -310,7 +310,7 @@ protected:
 
   static std::queue <Message> Messages;
 
-  void Debug(int from) {};
+  void Debug(int) {};
 
   static unsigned int messageId;
 
index 372d01e79b4fd2f931a63f61a76a255b6e55f0e8..08e38a690cf9639e34511e76d19b0806fdcd1476 100644 (file)
@@ -45,7 +45,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGState.cpp,v 1.15 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_STATE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 9fd627ebae40eb43382247bbf3937639e75f3fc0..220f042fd2b066e07db3dff8ca15d293f8a6281f 100644 (file)
@@ -62,7 +62,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_STATE "$Id$"
+#define ID_STATE "$Id: FGState.h,v 1.15 2009/10/02 10:30:07 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -78,7 +78,7 @@ CLASS DOCUMENTATION
     <h3>Properties</h3>
     @property sim-time-sec (read only) cumulative simulation in seconds.
     @author Jon S. Berndt
-    @version $Revision$
+    @version $Revision: 1.15 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 6409004fcbe193f4ddb3dddc1666d01a9b018a41..a915539cc8025cee7420c88704ec5d17962dfe46 100644 (file)
@@ -5,20 +5,20 @@
 // Copyright (C) 1999  Curtis L. Olson  - curt@flightgear.org
 //
 // This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
+// 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
-// General Public License for more details.
+// Lesser General Public License for more details.
 //
-// You should have received a copy of the GNU General Public License
+// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 //
-// $Id$
+// $Id: JSBSim.cxx,v 1.62 2010/07/14 05:50:40 ehofman Exp $
 
 
 #ifdef HAVE_CONFIG_H
@@ -45,7 +45,6 @@
 #include "JSBSim.hxx"
 #include <FDM/JSBSim/FGFDMExec.h>
 #include <FDM/JSBSim/FGJSBBase.h>
-#include <FDM/JSBSim/FGState.h>
 #include <FDM/JSBSim/initialization/FGInitialCondition.h>
 #include <FDM/JSBSim/initialization/FGTrim.h>
 #include <FDM/JSBSim/models/FGModel.h>
@@ -58,6 +57,8 @@
 #include <FDM/JSBSim/models/FGMassBalance.h>
 #include <FDM/JSBSim/models/FGAerodynamics.h>
 #include <FDM/JSBSim/models/FGLGear.h>
+#include <FDM/JSBSim/models/FGGroundReactions.h>
+#include <FDM/JSBSim/models/FGPropulsion.h>
 #include <FDM/JSBSim/models/propulsion/FGEngine.h>
 #include <FDM/JSBSim/models/propulsion/FGPiston.h>
 #include <FDM/JSBSim/models/propulsion/FGTurbine.h>
@@ -102,7 +103,7 @@ public:
     double contact[3], normal[3], vel[3], agl = 0;
     mInterface->get_agl_ft(t, loc_cart, SG_METER_TO_FEET*2, contact, normal,
                            vel, &agl);
-    n = FGColumnVector3( -normal[0], -normal[1], -normal[2] );
+    n = FGColumnVector3( normal[0], normal[1], normal[2] );
     v = FGColumnVector3( vel[0], vel[1], vel[2] );
     cont = FGColumnVector3( contact[0], contact[1], contact[2] );
     return agl;
@@ -147,7 +148,6 @@ FGJSBsim::FGJSBsim( double dt )
     // Register ground callback.
     fdmex->SetGroundCallback( new FGFSGroundCallback(this) );
 
-    State           = fdmex->GetState();
     Atmosphere      = fdmex->GetAtmosphere();
     FCS             = fdmex->GetFCS();
     MassBalance     = fdmex->GetMassBalance();
@@ -170,7 +170,13 @@ FGJSBsim::FGJSBsim( double dt )
     SGPath systems_path( fgGetString("/sim/aircraft-dir") );
     systems_path.append( "Systems" );
 
-    State->Setdt( dt );
+// deprecate sim-time-sec for simulation/sim-time-sec
+// remove alias with increased configuration file version number (2.1 or later)
+    SGPropertyNode * node = fgGetNode("/fdm/jsbsim/simulation/sim-time-sec");
+    fgGetNode("/fdm/jsbsim/sim-time-sec", true)->alias( node );
+// end of sim-time-sec deprecation patch
+
+    fdmex->Setdt( dt );
 
     result = fdmex->LoadModel( aircraft_path.str(),
                                engine_path.str(),
@@ -257,6 +263,10 @@ FGJSBsim::FGJSBsim( double dt )
     speedbrake_pos_pct->setDoubleValue(0);
     spoilers_pos_pct->setDoubleValue(0);
 
+    ab_brake_engaged = fgGetNode("/autopilot/autobrake/engaged", true);
+    ab_brake_left_pct = fgGetNode("/autopilot/autobrake/brake-left-output", true);
+    ab_brake_right_pct = fgGetNode("/autopilot/autobrake/brake-right-output", true);
+    
     temperature = fgGetNode("/environment/temperature-degc",true);
     pressure = fgGetNode("/environment/pressure-inhg",true);
     density = fgGetNode("/environment/density-slugft3",true);
@@ -296,8 +306,6 @@ FGJSBsim::~FGJSBsim(void)
 
 void FGJSBsim::init()
 {
-    double tmp;
-
     SG_LOG( SG_FLIGHT, SG_INFO, "Starting and initializing JSBsim" );
 
     // Explicitly call the superclass's
@@ -328,6 +336,21 @@ void FGJSBsim::init()
      << ", " << fdmex->GetAtmosphere()->GetPressure()
      << ", " << fdmex->GetAtmosphere()->GetDensity() );
 
+// deprecate egt_degf for egt-degf to have consistent naming
+// TODO: raise log-level to ALERT in summer 2010, 
+// remove alias in fall 2010, 
+// remove this code in winter 2010
+    for (unsigned int i=0; i < Propulsion->GetNumEngines(); i++) {
+      SGPropertyNode * node = fgGetNode("engines/engine", i, true);
+      SGPropertyNode * egtn = node->getNode( "egt_degf" );
+      if( egtn != NULL ) {
+        SG_LOG(SG_FLIGHT,SG_WARN,
+               "Aircraft uses deprecated node egt_degf. Please upgrade to egt-degf");
+        node->getNode("egt-degf", true)->alias( egtn );
+      }
+    }
+// end of egt_degf deprecation patch
+
     if (fgGetBool("/sim/presets/running")) {
           for (unsigned int i=0; i < Propulsion->GetNumEngines(); i++) {
             SGPropertyNode * node = fgGetNode("engines/engine", i, true);
@@ -437,7 +460,7 @@ void FGJSBsim::update( double dt )
       cart = FGLocation(lon, lat, alt+slr);
     }
     double cart_pos[3] = { cart(1), cart(2), cart(3) };
-    double t0 = State->Getsim_time();
+    double t0 = fdmex->GetSimTime();
     bool cache_ok = prepare_ground_cache_ft( t0, t0 + dt, cart_pos,
                                              groundCacheRadius );
     if (!cache_ok) {
@@ -465,7 +488,7 @@ void FGJSBsim::update( double dt )
     if ( needTrim ) {
       if ( startup_trim->getBoolValue() ) {
         double contact[3], d[3], agl;
-        get_agl_ft(State->Getsim_time(), cart_pos, SG_METER_TO_FEET*2, contact,
+        get_agl_ft(fdmex->GetSimTime(), cart_pos, SG_METER_TO_FEET*2, contact,
                    d, d, &agl);
         double terrain_alt = sqrt(contact[0]*contact[0] + contact[1]*contact[1]
              + contact[2]*contact[2]) - fgic->GetSeaLevelRadiusFtIC();
@@ -484,7 +507,7 @@ void FGJSBsim::update( double dt )
 
     for ( i=0; i < multiloop; i++ ) {
       fdmex->Run();
-      update_external_forces(State->Getsim_time() + i * State->Getdt());      
+      update_external_forces(fdmex->GetSimTime() + i * fdmex->GetDeltaT());      
     }
 
     FGJSBBase::Message* msg;
@@ -543,6 +566,12 @@ bool FGJSBsim::copy_to_JSBsim()
     double parking_brake = globals->get_controls()->get_brake_parking();
     double left_brake = globals->get_controls()->get_brake_left();
     double right_brake = globals->get_controls()->get_brake_right();
+    
+    if (ab_brake_engaged->getBoolValue()) {
+      left_brake = ab_brake_left_pct->getDoubleValue();
+      right_brake = ab_brake_right_pct->getDoubleValue(); 
+    }
+    
     FCS->SetLBrake(FMAX(left_brake, parking_brake));
     FCS->SetRBrake(FMAX(right_brake, parking_brake));
     
@@ -773,7 +802,7 @@ bool FGJSBsim::copy_from_JSBsim()
         FGTurbine* eng = (FGTurbine*)Propulsion->GetEngine(i);
         node->setDoubleValue("n1", eng->GetN1());
         node->setDoubleValue("n2", eng->GetN2());
-        node->setDoubleValue("egt_degf", 32 + eng->GetEGT()*9/5);
+        node->setDoubleValue("egt-degf", 32 + eng->GetEGT()*9/5);
         node->setBoolValue("augmentation", eng->GetAugmentation());
         node->setBoolValue("water-injection", eng->GetInjection());
         node->setBoolValue("ignition", eng->GetIgnition());
@@ -817,6 +846,8 @@ bool FGJSBsim::copy_from_JSBsim()
         node->setDoubleValue("rpm", eng->getRPM());
         } // end FGElectric code block
         break;
+      case FGEngine::etUnknown:
+        break;
       }
 
       { // FGEngine code block
@@ -888,7 +919,7 @@ bool FGJSBsim::copy_from_JSBsim()
 
     // force a sim crashed if crashed (altitude AGL < 0)
     if (get_Altitude_AGL() < -100.0) {
-         State->SuspendIntegration();
+         fdmex->SuspendIntegration();
          crashed = true;
     }
 
@@ -1138,9 +1169,6 @@ void FGJSBsim::do_trim(void)
   } else {
     trimmed->setBoolValue(true);
   }
-//  if (FGJSBBase::debug_lvl > 0)
-//      State->ReportState();
-
   delete fgtrim;
 
   pitch_trim->setDoubleValue( FCS->GetPitchTrimCmd() );
@@ -1257,7 +1285,6 @@ void FGJSBsim::update_external_forces(double t_off)
     FGColumnVector3 hook_tip_body = hook_root_body;
     hook_tip_body(1) -= hook_length * cos_fi;
     hook_tip_body(3) += hook_length * sin_fi;    
-    bool hook_tip_valid = true;
     
     double contact[3];
     double ground_normal[3];
index beb33e87b9f115c5ff82d4d2330dc8c0800fad76..38c952bd260fdcd46965aa2a1c61625540706f6b 100644 (file)
@@ -8,16 +8,16 @@
 ------ Copyright (C) 1999 - 2000  Curtis L. Olson (curt@flightgear.org) ------
 
  This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
+ 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
- General Public License for more details.
Lesser General Public License for more details.
 
- You should have received a copy of the GNU General Public License
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 
@@ -86,7 +86,7 @@ CLASS DOCUMENTATION
     documentation for main for direction on running JSBSim apart from FlightGear.
     @author Curtis L. Olson (original)
     @author Tony Peden (Maintained and refined)
-    @version $Id$
+    @version $Id: JSBSim.hxx,v 1.13 2010/07/07 20:46:36 andgi Exp $
     @see main in file JSBSim.cpp (use main() wrapper for standalone usage)
 */
 
@@ -252,6 +252,10 @@ private:
     SGPropertyNode_ptr flap_pos_pct;
     SGPropertyNode_ptr speedbrake_pos_pct;
     SGPropertyNode_ptr spoilers_pos_pct;
+
+    SGPropertyNode_ptr ab_brake_engaged;
+    SGPropertyNode_ptr ab_brake_left_pct;
+    SGPropertyNode_ptr ab_brake_right_pct;
     
     SGPropertyNode_ptr gear_pos_pct;
     SGPropertyNode_ptr wing_fold_pos_pct;
index 7eb3f7f6661b01346b66a01d38c083b415ac1d15..2d8f8a67393192c06d109c72541be98852a91c57 100644 (file)
@@ -56,12 +56,13 @@ INCLUDES
 #include <iostream>
 #include <fstream>
 #include <cstdlib>
+#include "input_output/string_utilities.h"
 
 using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGInitialCondition.cpp,v 1.40 2010/06/02 04:05:13 jberndt Exp $";
 static const char *IdHdr = ID_INITIALCONDITION;
 
 //******************************************************************************
@@ -704,23 +705,22 @@ double FGInitialCondition::calcVcas(double Mach) {
   double psl=fdmex->GetAtmosphere()->GetPressureSL();
   double rhosl=fdmex->GetAtmosphere()->GetDensitySL();
   double pt,A,B,D,vcas;
-  if(Mach < 0) Mach=0;
-  if(Mach < 1)    //calculate total pressure assuming isentropic flow
+
+  if (Mach < 0) Mach=0;
+  if (Mach < 1)    //calculate total pressure assuming isentropic flow
     pt=p*pow((1 + 0.2*Mach*Mach),3.5);
   else {
     // shock in front of pitot tube, we'll assume its normal and use
     // the Rayleigh Pitot Tube Formula, i.e. the ratio of total
-    // pressure behind the shock to the static pressure in front
-
-
-    //the normal shock assumption should not be a bad one -- most supersonic
-    //aircraft place the pitot probe out front so that it is the forward
-    //most point on the aircraft.  The real shock would, of course, take
-    //on something like the shape of a rounded-off cone but, here again,
-    //the assumption should be good since the opening of the pitot probe
-    //is very small and, therefore, the effects of the shock curvature
-    //should be small as well. AFAIK, this approach is fairly well accepted
-    //within the aerospace community
+    // pressure behind the shock to the static pressure in front of
+    // the normal shock assumption should not be a bad one -- most supersonic
+    // aircraft place the pitot probe out front so that it is the forward
+    // most point on the aircraft.  The real shock would, of course, take
+    // on something like the shape of a rounded-off cone but, here again,
+    // the assumption should be good since the opening of the pitot probe
+    // is very small and, therefore, the effects of the shock curvature
+    // should be small as well. AFAIK, this approach is fairly well accepted
+    // within the aerospace community
 
     B = 5.76*Mach*Mach/(5.6*Mach*Mach - 0.8);
 
@@ -842,8 +842,6 @@ double FGInitialCondition::GetWindDirDegIC(void) const {
 
 bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
 {
-  int n;
-
   string sep = "/";
   if( useStoredPath ) {
     init_file_name = fdmex->GetFullAircraftPath() + sep + rstfile + ".xml";
@@ -864,6 +862,26 @@ bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
     exit(-1);
   }
 
+  double version = document->GetAttributeValueAsNumber("version");
+  if (version == HUGE_VAL) {
+    return Load_v1(); // Default to the old version
+  } else if (version >= 3.0) {
+    cerr << "Only initialization file formats 1 and 2 are currently supported" << endl;
+    exit (-1);
+  } else if (version >= 2.0) {
+    return Load_v2();
+  } else if (version >= 1.0) {
+    return Load_v1();
+  } 
+
+}
+
+//******************************************************************************
+
+bool FGInitialCondition::Load_v1(void)
+{
+  int n;
+
   if (document->FindElement("latitude"))
     SetLatitudeDegIC(document->FindElementValueAsNumberConvertTo("latitude", "DEG"));
   if (document->FindElement("longitude"))
@@ -941,6 +959,249 @@ bool FGInitialCondition::Load(string rstfile, bool useStoredPath)
 
 //******************************************************************************
 
+bool FGInitialCondition::Load_v2(void)
+{
+  int n;
+  FGColumnVector3 vLoc, vOrient;
+  bool result = true;
+  FGInertial* Inertial = fdmex->GetInertial();
+  FGPropagate* Propagate = fdmex->GetPropagate();
+
+  if (document->FindElement("earth_position_angle")) {
+    double epa = document->FindElementValueAsNumberConvertTo("earth_position_angle", "RAD");
+    Inertial->SetEarthPositionAngle(epa);
+  }
+
+  // Initialize vehicle position
+  //
+  // Allowable frames:
+  // - ECI (Earth Centered Inertial)
+  // - ECEF (Earth Centered, Earth Fixed)
+
+  Element* position = document->FindElement("position");
+  if (position) {
+    vLoc = position->FindElementTripletConvertTo("FT");
+    string frame = position->GetAttributeValue("frame");
+    frame = to_lower(frame);
+    if (frame == "eci") {
+      // Need to transform vLoc to ECEF for storage and use in FGLocation.
+      vLoc = Propagate->GetTi2ec()*vLoc;
+    } else if (frame == "ecef") {
+      // Move vLoc query until after lat/lon/alt query to eliminate spurious warning msgs.
+      if (vLoc.Magnitude() == 0.0) {
+        Propagate->SetLatitudeDeg(position->FindElementValueAsNumberConvertTo("latitude", "DEG"));
+        Propagate->SetLongitudeDeg(position->FindElementValueAsNumberConvertTo("longitude", "DEG"));
+        if (position->FindElement("radius")) {
+          radius_to_vehicle = position->FindElementValueAsNumberConvertTo("radius", "FT");
+          SetAltitudeASLFtIC(radius_to_vehicle - sea_level_radius);
+        } else if (position->FindElement("altitudeAGL")) {
+          SetAltitudeAGLFtIC(position->FindElementValueAsNumberConvertTo("altitudeAGL", "FT"));
+        } else if (position->FindElement("altitudeMSL")) {
+          SetAltitudeASLFtIC(position->FindElementValueAsNumberConvertTo("altitudeMSL", "FT"));
+        } else {
+          cerr << endl << "  No altitude or radius initial condition is given." << endl;
+          result = false;
+        }
+      }
+    } else {
+      cerr << endl << "  Neither ECI nor ECEF frame is specified for initial position." << endl;
+      result = false;
+    }
+  } else {
+    cerr << endl << "  Initial position not specified in this initialization file." << endl;
+    result = false;
+  }
+
+  // End of position initialization
+
+  // Initialize vehicle orientation
+  // Allowable frames
+  // - ECI (Earth Centered Inertial)
+  // - ECEF (Earth Centered, Earth Fixed)
+  // - Local
+  //
+  // Need to convert the provided orientation to an ECI orientation, using 
+  // the given orientation and knowledge of the Earth position angle.
+  // This could be done using matrices (where in the subscript "b/a",
+  // it is meant "b with respect to a", and where b=body frame, 
+  // i=inertial frame, and e=ecef frame) as:
+  //
+  // C_b/i =  C_b/e * C_e/i
+  //
+  // Using quaternions (note reverse ordering compared to matrix representation):
+  //
+  // Q_b/i = Q_e/i * Q_b/e
+  //
+  // Use the specific matrices as needed. The above example of course is for the whole
+  // body to inertial orientation.
+  // The new orientation angles can be extracted from the matrix or the quaternion.
+  // ToDo: Do we need to deal with normalization of the quaternions here?
+
+  Element* orientation_el = document->FindElement("orientation");
+  if (orientation_el) {
+    string frame = orientation_el->GetAttributeValue("frame");
+    frame = to_lower(frame);
+    vOrient = orientation_el->FindElementTripletConvertTo("RAD");
+    FGQuaternion QuatI2Body;
+    if (frame == "eci") {
+
+      QuatI2Body = FGQuaternion(vOrient);
+
+    } else if (frame == "ecef") {
+
+      // In this case we are given the Euler angles representing the orientation of
+      // the body with respect to the ECEF system, represented by the C_b/e Matrix.
+      // We want the body orientation with respect to the inertial system:
+      //
+      // C_b/i =  C_b/e * C_e/i
+      //
+      // Using quaternions (note reverse ordering compared to matrix representation):
+      //
+      // Q_b/i = Q_e/i * Q_b/e
+
+      FGQuaternion QuatEC2Body(vOrient); // Store relationship of Body frame wrt ECEF frame, Q_b/e
+      FGQuaternion QuatI2EC = Propagate->GetTi2ec(); // Get Q_e/i from matrix
+      QuatI2Body = QuatI2EC * QuatEC2Body; // Q_b/i = Q_e/i * Q_b/e 
+
+    } else if (frame == "local") {
+
+      // In this case, we are supplying the Euler angles for the vehicle with
+      // respect to the local (NED frame), also called the navigation frame.
+      // This is the most common way of initializing the orientation of
+      // aircraft. The matrix representation is:
+      //
+      // C_b/i = C_b/n * C_n/e * C_e/i
+      //
+      // Or, using quaternions (note reverse ordering compared to matrix representation):
+      //
+      // Q_b/i = Q_e/i * Q_n/e * Q_b/n
+
+      FGQuaternion QuatLocal2Body = FGQuaternion(vOrient); // Store relationship of Body frame wrt local (NED) frame, Q_b/n
+      FGQuaternion QuatEC2Local = Propagate->GetTec2l();   // Get Q_n/e from matrix
+      FGQuaternion QuatI2EC = Propagate->GetTi2ec(); // Get Q_e/i from matrix
+      QuatI2Body = QuatI2EC * QuatEC2Local * QuatLocal2Body; // Q_b/i = Q_e/i * Q_n/e * Q_b/n
+
+    } else {
+
+      cerr << endl << fgred << "  Orientation frame type: \"" << frame
+           << "\" is not supported!" << reset << endl << endl;
+      result = false;
+
+    }
+
+    Propagate->SetInertialOrientation(QuatI2Body);
+  }
+
+  // Initialize vehicle velocity
+  // Allowable frames
+  // - ECI (Earth Centered Inertial)
+  // - ECEF (Earth Centered, Earth Fixed)
+  // - Local
+  // - Body
+  // The vehicle will be defaulted to (0,0,0) in the Body frame if nothing is provided.
+  
+  Element* velocity_el = document->FindElement("velocity");
+  FGColumnVector3 vInertialVelocity;
+  FGColumnVector3 vInitVelocity = FGColumnVector3(0.0, 0.0, 0.0);
+  if (velocity_el) {
+
+    string frame = velocity_el->GetAttributeValue("frame");
+    frame = to_lower(frame);
+    FGColumnVector3 vInitVelocity = velocity_el->FindElementTripletConvertTo("FT/SEC");
+    FGColumnVector3 omega_cross_r = Inertial->omega() * Propagate->GetInertialPosition();
+
+    if (frame == "eci") {
+      vInertialVelocity = vInitVelocity;
+    } else if (frame == "ecef") {
+      FGMatrix33 mTec2i = Propagate->GetTec2i(); // Get C_i/e
+      vInertialVelocity = mTec2i * vInitVelocity + omega_cross_r;
+    } else if (frame == "local") {
+      FGMatrix33 mTl2i = Propagate->GetTl2i();
+      vInertialVelocity = mTl2i * vInitVelocity + omega_cross_r;
+    } else if (frame == "body") {
+      FGMatrix33 mTb2i = Propagate->GetTb2i();
+      vInertialVelocity = mTb2i * vInitVelocity + omega_cross_r;
+    } else {
+
+      cerr << endl << fgred << "  Velocity frame type: \"" << frame
+           << "\" is not supported!" << reset << endl << endl;
+      result = false;
+
+    }
+
+  } else {
+
+    FGMatrix33 mTb2i = Propagate->GetTb2i();
+    vInertialVelocity = mTb2i * vInitVelocity + (Inertial->omega() * Propagate->GetInertialPosition());
+
+  }
+
+  Propagate->SetInertialVelocity(vInertialVelocity);
+
+  // Allowable frames
+  // - ECI (Earth Centered Inertial)
+  // - ECEF (Earth Centered, Earth Fixed)
+  // - Body
+  
+  FGColumnVector3 vInertialRate;
+  Element* attrate_el = document->FindElement("attitude_rate");
+  if (attrate_el) {
+
+    string frame = attrate_el->GetAttributeValue("frame");
+    frame = to_lower(frame);
+    FGColumnVector3 vAttRate = attrate_el->FindElementTripletConvertTo("RAD/SEC");
+
+    if (frame == "eci") {
+      vInertialRate = vAttRate;
+    } else if (frame == "ecef") {
+//      vInertialRate = vAttRate + Inertial->omega(); 
+    } else if (frame == "body") {
+    //Todo: determine local frame rate
+      FGMatrix33 mTb2l = Propagate->GetTb2l();
+//      vInertialRate = mTb2l*vAttRate + Inertial->omega();
+    } else if (!frame.empty()) { // misspelling of frame
+      
+      cerr << endl << fgred << "  Attitude rate frame type: \"" << frame
+           << "\" is not supported!" << reset << endl << endl;
+      result = false;
+
+    } else if (frame.empty()) {
+    
+    }
+    
+  } else { // Body frame attitude rate assumed 0 relative to local.
+/*
+    //Todo: determine local frame rate
+
+    FGMatrix33 mTi2l = Propagate->GetTi2l();
+    vVel = mTi2l * vInertialVelocity;
+
+    // Compute the local frame ECEF velocity
+    vVel = Tb2l * VState.vUVW;
+
+    FGColumnVector3 vOmegaLocal = FGColumnVector3(
+       radInv*vVel(eEast),
+      -radInv*vVel(eNorth),
+      -radInv*vVel(eEast)*VState.vLocation.GetTanLatitude() );
+*/  
+  }
+
+  // Check to see if any engines are specified to be initialized in a running state
+  FGPropulsion* propulsion = fdmex->GetPropulsion();
+  Element* running_elements = document->FindElement("running");
+  while (running_elements) {
+    n = int(running_elements->GetDataAsNumber());
+    propulsion->InitRunning(n);
+    running_elements = document->FindNextElement("running");
+  }
+
+  // fdmex->RunIC();
+
+  return result;
+}
+
+//******************************************************************************
+
 void FGInitialCondition::bind(void){
   PropertyManager->Tie("ic/vc-kts", this,
                        &FGInitialCondition::GetVcalibratedKtsIC,
index 898acc3fdf90aef649112ad590523f1c0dadfad6..b5c8c281924e284b5f49af57e62ac7fbcbe9e016 100644 (file)
@@ -56,7 +56,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_INITIALCONDITION "$Id$"
+#define ID_INITIALCONDITION "$Id: FGInitialCondition.h,v 1.20 2010/02/15 03:22:57 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -202,7 +202,7 @@ CLASS DOCUMENTATION
    @property ic/r-rad_sec (read/write) Yaw rate initial condition in radians/second
 
    @author Tony Peden
-   @version "$Id$"
+   @version "$Id: FGInitialCondition.h,v 1.20 2010/02/15 03:22:57 jberndt Exp $"
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -647,6 +647,9 @@ private:
   FGFDMExec *fdmex;
   FGPropertyManager *PropertyManager;
 
+  bool Load_v1(void);
+  bool Load_v2(void);
+
   bool Constructing;
   bool getAlpha(void);
   bool getTheta(void);
index 2f425b769c920f1374cf95f22cec6f59429404a5..6b0cd81c05f665e568067d08ed859a6b7c2682bc 100644 (file)
@@ -51,6 +51,8 @@ INCLUDES
 #include "models/FGGroundReactions.h"
 #include "models/FGInertial.h"
 #include "models/FGAerodynamics.h"
+#include "models/FGPropulsion.h"
+#include "models/propulsion/FGEngine.h"
 #include "math/FGColumnVector3.h"
 
 #if _MSC_VER
@@ -61,7 +63,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGTrim.cpp,v 1.13 2010/04/23 17:23:40 dpculp Exp $";
 static const char *IdHdr = ID_TRIM;
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -239,6 +241,8 @@ bool FGTrim::DoTrim(void) {
 
   fdmex->DisableOutput();
 
+  setEngineTrimMode(true);
+
   fgic->SetPRadpsIC(0.0);
   fgic->SetQRadpsIC(0.0);
   fgic->SetRRadpsIC(0.0);
@@ -354,6 +358,7 @@ bool FGTrim::DoTrim(void) {
   for(i=0;i < fdmex->GetGroundReactions()->GetNumGearUnits();i++){
     fdmex->GetGroundReactions()->GetGearUnit(i)->SetReport(true);
   }
+  setEngineTrimMode(false);
   fdmex->EnableOutput();
   return !trim_failed;
 }
@@ -620,6 +625,15 @@ void FGTrim::setDebug(void) {
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+void FGTrim::setEngineTrimMode(bool mode) {
+  FGPropulsion* prop = fdmex->GetPropulsion();
+  for (unsigned int i=0; i<prop->GetNumEngines(); i++) {
+    prop->GetEngine(i)->SetTrimMode(mode);
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 void FGTrim::SetMode(TrimMode tt) {
     ClearStates();
     mode=tt;
index 420f3fda2be3eca0c99180a4fe85c9e72787b74f..0d6e3092cdd260745df07ada44d3edfa6082bf19 100644 (file)
@@ -60,7 +60,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_TRIM "$Id$"
+#define ID_TRIM "$Id: FGTrim.h,v 1.7 2010/04/23 17:23:40 dpculp Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -120,7 +120,7 @@ CLASS DOCUMENTATION
     @endcode
     
     @author Tony Peden
-    @version "$Id$"
+    @version "$Id: FGTrim.h,v 1.7 2010/04/23 17:23:40 dpculp Exp $"
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -176,7 +176,7 @@ private:
   void setupTurn(void);
 
   void updateRates(void);
-
+  void setEngineTrimMode(bool mode);
   void setDebug(void);
 
 public:
index 186b9b1df354abf8c67fc3472a486f2735f62628..e0378793fb68141b0dd5fd822b2a5db215debb2d 100644 (file)
@@ -55,7 +55,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGTrimAxis.cpp,v 1.10 2010/07/08 11:36:28 jberndt Exp $";
 static const char *IdHdr = ID_TRIMAXIS;
 
 /*****************************************************************************/
@@ -434,6 +434,10 @@ void FGTrimAxis::setThrottlesPct(void) {
 /*****************************************************************************/
 
 void FGTrimAxis::AxisReport(void) {
+  // Save original cout format characteristics
+  std::ios_base::fmtflags originalFormat = cout.flags();
+  std::streamsize originalPrecision = cout.precision();
+  std::streamsize originalWidth = cout.width();
   cout << "  " << setw(20) << GetControlName() << ": ";
   cout << setw(6) << setprecision(2) << GetControl()*control_convert << ' ';
   cout << setw(5) << GetStateName() << ": ";
@@ -444,6 +448,10 @@ void FGTrimAxis::AxisReport(void) {
      cout << "  Passed" << endl;
   else
      cout << "  Failed" << endl;
+  // Restore original cout format characteristics
+  cout.flags(originalFormat);
+  cout.precision(originalPrecision);
+  cout.width(originalWidth);
 }
 
 /*****************************************************************************/
index ac3d45f8f308b947a100c3edd892df3444ff97d9..9fc7cebb9b5dab021c7834db3f13cd2e99ad81ca 100644 (file)
@@ -48,7 +48,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_TRIMAXIS "$Id$"
+#define ID_TRIMAXIS "$Id: FGTrimAxis.h,v 1.4 2006/10/01 22:47:47 jberndt Exp $"
 
 #define DEFAULT_TOLERANCE 0.001
 
index d1484115c034a612afd0154d649461e0d5293e58..bf1cfb1b592c5eaa9fc46b5864774e0ead9dd135 100644 (file)
@@ -71,10 +71,11 @@ double FGGroundCallback::GetAGLevel(double t, const FGLocation& loc,
                                     FGColumnVector3& vel) const
 {
   vel = FGColumnVector3(0.0, 0.0, 0.0);
-  normal = (-1/FGColumnVector3(loc).Magnitude())*FGColumnVector3(loc);
-  double radius = loc.GetRadius();
-  double agl = GetAltitude(loc);
-  contact = ((radius-agl)/radius)*FGColumnVector3(loc);
+  normal = FGColumnVector3(loc).Normalize();
+  double loc_radius = loc.GetRadius();  // Get the radius of the given location
+                                        // (e.g. the CG)
+  double agl = loc_radius - mReferenceRadius;
+  contact = (mReferenceRadius/loc_radius)*FGColumnVector3(loc);
   return agl;
 }
 
index 4def8c1ca35f556104cbc8694452405ebf72b976..63955a4d07674817ad3dc30db01c4cac282264f6 100644 (file)
@@ -45,7 +45,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_GROUNDCALLBACK "$Id$"
+#define ID_GROUNDCALLBACK "$Id: FGGroundCallback.h,v 1.8 2009/10/02 10:30:09 jberndt Exp $"
 
 namespace JSBSim {
 
@@ -59,7 +59,7 @@ CLASS DOCUMENTATION
     ball formed earth.
 
     @author Mathias Froehlich
-    @version $Id$
+    @version $Id: FGGroundCallback.h,v 1.8 2009/10/02 10:30:09 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 991badb909c112bc7c4b48fac8861628bc04eb4b..6e62fef03104a12ea861c28de617b1c4c5e24bfa 100755 (executable)
@@ -152,6 +152,19 @@ string FGPropertyManager::GetFullyQualifiedName(void) {
 
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+string FGPropertyManager::GetRelativeName( const string &path )
+{
+  string temp_string = GetFullyQualifiedName();
+  size_t len = path.length();
+  if ( (len > 0) && (temp_string.substr(0,len) == path) ) {
+    temp_string = temp_string.erase(0,len);
+  }
+  return temp_string;
+}
+
+
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
index 2db5408e33806115cf077c9d6d5336b8ea58d5e1..c29b5a412e55b9a72e786a2d675e4efeb1acd133 100644 (file)
@@ -53,7 +53,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PROPERTYMANAGER "$Id$"
+#define ID_PROPERTYMANAGER "$Id: FGPropertyManager.h,v 1.17 2010/07/08 11:36:28 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -129,6 +129,15 @@ class FGPropertyManager : public SGPropertyNode, public FGJSBBase
      */
     std::string GetFullyQualifiedName(void);
 
+    /**
+     * Get the qualified name of a node relative to given base path,
+     * otherwise the fully qualified name.
+     * This function is very slow, so is probably useful for debugging only.
+     *
+     * @param path The path to strip off, if found.
+     */
+    std::string GetRelativeName( const std::string &path = "/fdm/jsbsim/" );
+
     /**
      * Get a bool value for a property.
      *
index dde76de95828c5e904bf4684ac9d44e2dc9857d6..bd940bb4c4c4264a1bcf25747dea30f2b7cff30e 100755 (executable)
@@ -42,17 +42,19 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGScript.h"
+#include "input_output/FGXMLElement.h"
 #include "input_output/FGXMLParse.h"
 #include "initialization/FGTrim.h"
 
 #include <iostream>
 #include <cstdlib>
+#include <iomanip>
 
 using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGScript.cpp,v 1.41 2010/07/08 11:36:28 jberndt Exp $";
 static const char *IdHdr = ID_FGSCRIPT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -67,8 +69,8 @@ CLASS IMPLEMENTATION
 
 FGScript::FGScript(FGFDMExec* fgex) : FDMExec(fgex)
 {
-  State = FDMExec->GetState();
   PropertyManager=FDMExec->GetPropertyManager();
+
   Debug(0);
 }
 
@@ -89,7 +91,7 @@ FGScript::~FGScript()
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-bool FGScript::LoadScript( string script )
+bool FGScript::LoadScript(string script, double deltaT)
 {
   string aircraft="", initialize="", comparison = "", prop_name="";
   string notifyPropertyName="";
@@ -135,10 +137,18 @@ bool FGScript::LoadScript( string script )
   // Set sim timing
 
   StartTime = run_element->GetAttributeValueAsNumber("start");
-  State->Setsim_time(StartTime);
+  FDMExec->Setsim_time(StartTime);
   EndTime   = run_element->GetAttributeValueAsNumber("end");
-  dt        = run_element->GetAttributeValueAsNumber("dt");
-  State->Setdt(dt);
+
+  if (deltaT == 0.0)
+    dt = run_element->GetAttributeValueAsNumber("dt");
+  else {
+    dt = deltaT;
+    cout << endl << "Overriding simulation step size from the command line. New step size is: "
+         << deltaT << " seconds (" << 1/deltaT << " Hz)" << endl << endl;
+  }
+
+  FDMExec->Setdt(dt);
   
   // read aircraft and initialization files
 
@@ -175,7 +185,7 @@ bool FGScript::LoadScript( string script )
     if (output_file.empty()) {
       cerr << "No logging directives file was specified." << endl;
     } else {
-      FDMExec->SetOutputDirectives(output_file);
+      if (!FDMExec->SetOutputDirectives(output_file)) return false;
     }
   }
 
@@ -226,7 +236,12 @@ bool FGScript::LoadScript( string script )
     // Process the conditions
     condition_element = event_element->FindElement("condition");
     if (condition_element != 0) {
-      newCondition = new FGCondition(condition_element, PropertyManager);
+      try {
+        newCondition = new FGCondition(condition_element, PropertyManager);
+      } catch(string str) {
+        cout << endl << fgred << str << reset << endl << endl;
+        return false;
+      }
       newEvent->Condition = newCondition;
     } else {
       cerr << "No condition specified in script event " << newEvent->Name << endl;
@@ -320,7 +335,7 @@ bool FGScript::RunScript(void)
   unsigned i, j;
   unsigned event_ctr = 0;
 
-  double currentTime = State->Getsim_time();
+  double currentTime = FDMExec->GetSimTime();
   double newSetValue = 0;
 
   if (currentTime > EndTime) return false; //Script done!
@@ -409,7 +424,7 @@ bool FGScript::RunScript(void)
         cout << endl << "  Event " << event_ctr << " (" << Events[ev_ctr].Name << ")"
              << " executed at time: " << currentTime << endl;
         for (j=0; j<Events[ev_ctr].NotifyProperties.size();j++) {
-          cout << "    " << Events[ev_ctr].NotifyProperties[j]->GetName()
+          cout << "    " << Events[ev_ctr].NotifyProperties[j]->GetRelativeName()
                << " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl;
         }
         cout << endl;
@@ -453,7 +468,8 @@ void FGScript::Debug(int from)
       cout << endl;
       cout << "Script: \"" << ScriptName << "\"" << endl;
       cout << "  begins at " << StartTime << " seconds and runs to " << EndTime
-           << " seconds with dt = " << State->Getdt() << endl;
+        << " seconds with dt = " << setprecision(6) << FDMExec->GetDeltaT() << " (" <<
+        ceil(1.0/FDMExec->GetDeltaT()) << " Hz)" << endl;
       cout << endl;
 
       for (unsigned int i=0; i<local_properties.size(); i++) {
@@ -476,7 +492,10 @@ void FGScript::Debug(int from)
 
         Events[i].Condition->PrintCondition();
 
-        cout << endl << "  Actions taken:" << endl << "    {";
+        cout << endl << "  Actions taken";
+        if (Events[i].Delay > 0.0)
+          cout << " (after a delay of " << Events[i].Delay << " secs)";
+        cout << ":" << endl << "    {";
         for (unsigned j=0; j<Events[i].SetValue.size(); j++) {
           if (Events[i].SetValue[j] == 0.0 && Events[i].Functions[j] != 0L) {
             if (Events[i].SetParam[j] == 0) {
@@ -486,7 +505,7 @@ void FGScript::Debug(int from)
                    << reset << endl;
               exit(-1);
             }
-            cout << endl << "      set " << Events[i].SetParam[j]->GetName()
+            cout << endl << "      set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/")
                  << " to function value";
           } else {
             if (Events[i].SetParam[j] == 0) {
@@ -496,7 +515,7 @@ void FGScript::Debug(int from)
                    << reset << endl;
               exit(-1);
             }
-            cout << endl << "      set " << Events[i].SetParam[j]->GetName()
+            cout << endl << "      set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/")
                  << " to " << Events[i].SetValue[j];
           }
 
@@ -529,8 +548,21 @@ void FGScript::Debug(int from)
           if (Events[i].Action[j] == FG_RAMP || Events[i].Action[j] == FG_EXP)
             cout << " with time constant " << Events[i].TC[j] << ")";
         }
-        cout << endl << "    }" << endl << endl;
-
+        cout << endl << "    }" << endl;
+
+        // Print notifications
+        if (Events[i].Notify) {
+          if (Events[i].NotifyProperties.size() > 0) {
+            cout << "  Notifications" << ":" << endl << "    {" << endl;
+            for (unsigned j=0; j<Events[i].NotifyProperties.size();j++) {
+              cout << "      "
+                  << Events[i].NotifyProperties[j]->GetRelativeName("/fdm/jsbsim/")
+                   << endl;
+            }
+            cout << "    }" << endl;
+          }
+        }
+        cout << endl;
       }
     }
   }
index 4dc5c8cf9eddea44611835e96e627762cb5786be..9f8d3ef8e84984bab04bd7857f64fa9ec717ee6d 100644 (file)
@@ -38,7 +38,6 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGJSBBase.h"
-#include "FGState.h"
 #include "FGFDMExec.h"
 #include "math/FGFunction.h"
 #include "math/FGCondition.h"
@@ -49,7 +48,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FGSCRIPT "$Id$"
+#define ID_FGSCRIPT "$Id: FGScript.h,v 1.18 2010/04/11 13:44:42 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -158,7 +157,7 @@ CLASS DOCUMENTATION
     comes the &quot;run&quot; section, where the conditions are
     described in &quot;event&quot; clauses.</p>
     @author Jon S. Berndt
-    @version "$Id$"
+    @version "$Id: FGScript.h,v 1.18 2010/04/11 13:44:42 jberndt Exp $"
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -175,10 +174,13 @@ public:
   ~FGScript();
 
   /** Loads a script to drive JSBSim (usually in standalone mode).
-      The language is the Script Directives for JSBSim.
+      The language is the Script Directives for JSBSim. If a simulation step size
+      has been supplied on the command line, it will be override the script-
+      specified simulation step size.
       @param script the filename (including path name, if any) for the script.
+      @param deltaT a simulation step size from the command line
       @return true if successful */
-  bool LoadScript( string script );
+  bool LoadScript(string script, double deltaT);
 
   /** This function is called each pass through the executive Run() method IF
       scripting is enabled.
@@ -259,7 +261,6 @@ private:
   vector <LocalProps*> local_properties;
 
   FGFDMExec* FDMExec;
-  FGState* State;
   FGPropertyManager* PropertyManager;
   void Debug(int from);
 };
index df541fa3aaee1b8af04d9adc0b2c464d3a32d24e..0c3e91063d96e7f3dabfde3cc92ded234a9a57f1 100755 (executable)
@@ -42,7 +42,7 @@ FORWARD DECLARATIONS
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.29 2010/03/18 13:18:31 jberndt Exp $";
 static const char *IdHdr = ID_XMLELEMENT;
 
 bool Element::converterIsInitialized = false;
@@ -114,7 +114,10 @@ Element::Element(const string& nm)
     convert["KTS"]["FT/SEC"] = 1.68781;
     convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"];
     convert["M/S"]["FT/S"] = 3.2808399;
+    convert["M/SEC"]["FT/SEC"] = 3.2808399;
     convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"];
+    convert["M/SEC"]["FT/SEC"] = 3.2808399;
+    convert["FT/SEC"]["M/SEC"] = 1.0/convert["M/SEC"]["FT/SEC"];
     // Torque
     convert["FT*LBS"]["N*M"] = 1.35581795;
     convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
@@ -185,6 +188,7 @@ Element::Element(const string& nm)
     convert["FT/SEC"]["FT/SEC"] = 1.00;
     convert["KTS"]["KTS"] = 1.00;
     convert["M/S"]["M/S"] = 1.0;
+    convert["M/SEC"]["M/SEC"] = 1.0;
     // Torque
     convert["FT*LBS"]["FT*LBS"] = 1.00;
     convert["N*M"]["N*M"] = 1.00;
index 75add86b77d83ab441d31d25b2d50931a278c06d..21af97275d2251a8af575465723b0ab2e57ddcd5 100755 (executable)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_XMLELEMENT "$Id$"
+#define ID_XMLELEMENT "$Id: FGXMLElement.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -136,7 +136,7 @@ CLASS DOCUMENTATION
     - GAL = gallon (U.S. liquid) 
 
     @author Jon S. Berndt
-    @version $Id$
+    @version $Id: FGXMLElement.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 204c4013851ba52cd56130e2bc9fd79513918152..d7366db7c996745e7eb34ab728564e50b908f6e9 100755 (executable)
@@ -43,7 +43,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_XMLFILEREAD "$Id$"
+#define ID_XMLFILEREAD "$Id: FGXMLFileRead.h,v 1.5 2009/11/28 20:12:47 andgi Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index 7eefba94f8f5e3b93fa5e41e3bf348145e266d51..90fe0e7b90d7b7b5882cb4b384ea66139de0c332 100755 (executable)
@@ -40,7 +40,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGXMLParse.cpp,v 1.10 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_XMLPARSE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 5fdd92b06dd8a15b50e1b1b2cf56fb19699bbcfd..350e3e6a7894c01918f59e132dbc422bdba834cc 100755 (executable)
@@ -40,7 +40,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_XMLPARSE "$Id$"
+#define ID_XMLPARSE "$Id: FGXMLParse.h,v 1.7 2009/10/24 22:59:30 jberndt Exp $"
 #define VALID_CHARS """`!@#$%^&*()_+`1234567890-={}[];':,.<>/?abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -57,7 +57,7 @@ CLASS DOCUMENTATION
 
 /** Encapsulates an XML parser based on the EasyXML parser from the SimGear library.
     @author Jon S. Berndt
-    @version $Id$
+    @version $Id: FGXMLParse.h,v 1.7 2009/10/24 22:59:30 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 85cb88c4f9c25c70e7695afb2b9f458e8ca8ec96..d1edb67394876a630d64a7fd39311f8437d78143 100644 (file)
@@ -52,7 +52,7 @@ using std::string;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGfdmSocket.cpp,v 1.27 2010/05/13 03:07:59 jberndt Exp $";
 static const char *IdHdr = ID_FDMSOCKET;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -77,7 +77,9 @@ FGfdmSocket::FGfdmSocket(const string& address, int port, int protocol)
       cout << "Could not get host net address by name..." << endl;
     }
   } else {
-    if ((host = gethostbyaddr(address.c_str(), address.size(), PF_INET)) == NULL) {
+    unsigned int ip;
+    ip = inet_addr(address.c_str());
+    if ((host = gethostbyaddr((char*)&ip, address.size(), PF_INET)) == NULL) {
       cout << "Could not get host net address by number..." << endl;
     }
   }
index 46b41ad56f5f8c93f91df468e1ee6cbaeac895c1..4c9e34b3ca77a07bd46701fb8b5fc11bcff02b80 100644 (file)
@@ -51,6 +51,7 @@ INCLUDES
   #include <unistd.h>
   #include <sys/socket.h>
   #include <netinet/in.h>
+  #include <arpa/inet.h>
   #include <netdb.h>
   #include <errno.h>
   #include <sys/ioctl.h>
@@ -64,7 +65,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FDMSOCKET "$Id$"
+#define ID_FDMSOCKET "$Id: FGfdmSocket.h,v 1.19 2010/05/13 03:07:59 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index bc3a152a9e105df37b06c890254c61862156cab8..f2dc22090272ddb1480cc4a8edde9a398ab3f76b 100644 (file)
@@ -45,7 +45,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_STRINGUTILS "$Id$"
+#define ID_STRINGUTILS "$Id: string_utilities.h,v 1.13 2010/07/07 11:59:48 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -64,18 +64,19 @@ CLASS DECLARATION
   extern std::string& trim_left(std::string& str);
   extern std::string& trim_right(std::string& str);
   extern std::string& trim(std::string& str);
+  extern std::string& trim_all_space(std::string& str);
   extern std::string& to_upper(std::string& str);
   extern std::string& to_lower(std::string& str);
   extern bool is_number(const std::string& str);
   std::vector <std::string> split(std::string str, char d);
 #else
-  #include <ctype.h>
+  #include <cctype>
 
   using namespace std;
 
   string& trim_left(string& str)
   {
-    while (str.size() && !isgraph(str[0])) {
+    while (str.size() && isspace((unsigned char)str[0])) {
       str = str.erase(0,1);
     }
     return str;
@@ -83,7 +84,7 @@ CLASS DECLARATION
 
   string& trim_right(string& str)
   {
-    while (str.size() && !isgraph(str[str.size()-1])) {
+    while (str.size() && isspace((unsigned char)str[str.size()-1])) {
       str = str.erase(str.size()-1,1);
     }
     return str;
@@ -96,6 +97,17 @@ CLASS DECLARATION
     return str = trim_left(temp_str);
   }
 
+  string& trim_all_space(string& str)
+  {
+    for (size_t i=0; i<str.size(); i++) {
+      if (isspace((unsigned char)str[i])) {
+        str = str.erase(i,1);
+        --i;
+      }
+    }
+    return str;
+  }
+
   string& to_upper(string& str)
   {
     for (size_t i=0; i<str.size(); i++) str[i] = toupper(str[i]);
index 8a85454e2ce5bb322500905e268f799cd75f3d05..1e41cd193a936d5646be60a71e4291d674136e83 100644 (file)
@@ -47,7 +47,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGColumnVector3.cpp,v 1.12 2010/06/30 03:13:40 jberndt Exp $";
 static const char *IdHdr = ID_COLUMNVECTOR3;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -65,9 +65,9 @@ FGColumnVector3::FGColumnVector3(void)
 string FGColumnVector3::Dump(const string& delimiter) const
 {
   ostringstream buffer;
-  buffer << std::setw(18) << std::setprecision(16) << Entry(1) << delimiter;
-  buffer << std::setw(18) << std::setprecision(16) << Entry(2) << delimiter;
-  buffer << std::setw(18) << std::setprecision(16) << Entry(3);
+  buffer << std::setw(18) << std::setprecision(16) << data[0] << delimiter;
+  buffer << std::setw(18) << std::setprecision(16) << data[1] << delimiter;
+  buffer << std::setw(18) << std::setprecision(16) << data[2];
   return buffer.str();
 }
 
@@ -110,10 +110,10 @@ FGColumnVector3& FGColumnVector3::operator/=(const double scalar)
 
 double FGColumnVector3::Magnitude(void) const
 {
-  if (Entry(1) == 0.0 && Entry(2) == 0.0 && Entry(3) == 0.0)
+  if (data[0] == 0.0 && data[1] == 0.0 && data[2] == 0.0)
     return 0.0;
   else
-    return sqrt( Entry(1)*Entry(1) +  Entry(2)*Entry(2) +  Entry(3)*Entry(3) );
+    return sqrt( data[0]*data[0] +  data[1]*data[1] +  data[2]*data[2] );
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 2817f9571fd880a11fb910107a62225279a1c2e2..e1564dc3cb06d1dc3ac44306caeae612b56e3d73 100644 (file)
@@ -47,7 +47,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_COLUMNVECTOR3 "$Id$"
+#define ID_COLUMNVECTOR3 "$Id: FGColumnVector3.h,v 1.12 2010/06/30 03:13:40 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -61,7 +61,7 @@ CLASS DOCUMENTATION
 
 /** This class implements a 3 element column vector.
     @author Jon S. Berndt, Tony Peden, et. al.
-    @version $Id$
+    @version $Id: FGColumnVector3.h,v 1.12 2010/06/30 03:13:40 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -84,7 +84,7 @@ public:
     data[0] = X;
     data[1] = Y;
     data[2] = Z;
-    Debug(0);
+//    Debug(0);
   }
 
   /** Copy constructor.
@@ -94,25 +94,25 @@ public:
     data[0] = v.data[0];
     data[1] = v.data[1];
     data[2] = v.data[2];
-    Debug(0);
+//    Debug(0);
   }
 
   /// Destructor.
-  ~FGColumnVector3(void) { Debug(1); }
+  ~FGColumnVector3(void) { /* Debug(1); */ }
 
   /** Read access the entries of the vector.
       @param idx the component index.
       Return the value of the matrix entry at the given index.
       Indices are counted starting with 1.
       Note that the index given in the argument is unchecked.   */
-  double operator()(unsigned int idx) const { return Entry(idx); }
+  double operator()(unsigned int idx) const { return data[idx-1]; }
 
   /** Write access the entries of the vector.
       @param idx the component index.
       Return a reference to the vector entry at the given index.
       Indices are counted starting with 1.
       Note that the index given in the argument is unchecked.   */
-  double& operator()(unsigned int idx) { return Entry(idx); }
+  double& operator()(unsigned int idx) { return data[idx-1]; }
 
   /** Read access the entries of the vector.
       @param idx the component index.
@@ -166,7 +166,7 @@ public:
       @return The resulting vector from the multiplication with that scalar.
       Multiply the vector with the scalar given in the argument.   */
   FGColumnVector3 operator*(const double scalar) const {
-    return FGColumnVector3(scalar*Entry(1), scalar*Entry(2), scalar*Entry(3));
+    return FGColumnVector3(scalar*data[0], scalar*data[1], scalar*data[2]);
   }
 
   /** Multiply by 1/scalar.
@@ -181,42 +181,42 @@ public:
       Compute and return the cross product of the current vector with
       the given argument.   */
   FGColumnVector3 operator*(const FGColumnVector3& V) const {
-    return FGColumnVector3( Entry(2) * V(3) - Entry(3) * V(2),
-                            Entry(3) * V(1) - Entry(1) * V(3),
-                            Entry(1) * V(2) - Entry(2) * V(1) );
+    return FGColumnVector3( data[1] * V(3) - data[2] * V(2),
+                            data[2] * V(1) - data[0] * V(3),
+                            data[0] * V(2) - data[1] * V(1) );
   }
 
   /// Addition operator.
   FGColumnVector3 operator+(const FGColumnVector3& B) const {
-    return FGColumnVector3( Entry(1) + B(1), Entry(2) + B(2), Entry(3) + B(3) );
+    return FGColumnVector3( data[0] + B(1), data[1] + B(2), data[2] + B(3) );
   }
 
   /// Subtraction operator.
   FGColumnVector3 operator-(const FGColumnVector3& B) const {
-    return FGColumnVector3( Entry(1) - B(1), Entry(2) - B(2), Entry(3) - B(3) );
+    return FGColumnVector3( data[0] - B(1), data[1] - B(2), data[2] - B(3) );
   }
 
   /// Subtract an other vector.
   FGColumnVector3& operator-=(const FGColumnVector3 &B) {
-    Entry(1) -= B(1);
-    Entry(2) -= B(2);
-    Entry(3) -= B(3);
+    data[0] -= B(1);
+    data[1] -= B(2);
+    data[2] -= B(3);
     return *this;
   }
 
   /// Add an other vector.
   FGColumnVector3& operator+=(const FGColumnVector3 &B) {
-    Entry(1) += B(1);
-    Entry(2) += B(2);
-    Entry(3) += B(3);
+    data[0] += B(1);
+    data[1] += B(2);
+    data[2] += B(3);
     return *this;
   }
 
   /// Scale by a scalar.
   FGColumnVector3& operator*=(const double scalar) {
-    Entry(1) *= scalar;
-    Entry(2) *= scalar;
-    Entry(3) *= scalar;
+    data[0] *= scalar;
+    data[1] *= scalar;
+    data[2] *= scalar;
     return *this;
   }
 
@@ -237,7 +237,7 @@ public:
       Compute and return the euclidean norm of this vector projected into
       the coordinate axis plane idx1-idx2.   */
   double Magnitude(int idx1, int idx2) const {
-    return sqrt( Entry(idx1)*Entry(idx1) +  Entry(idx2)*Entry(idx2) );
+    return sqrt( data[idx1-1]*data[idx1-1] +  data[idx2-1]*data[idx2-1] );
   }
 
   /** Normalize.
@@ -245,21 +245,6 @@ public:
       is equal to zero it is left untouched.   */
   FGColumnVector3& Normalize(void);
 
-  // little trick here.
-  struct AssignRef {
-    AssignRef(FGColumnVector3& r, int i) : Ref(r), idx(i) {}
-    AssignRef operator<<(const double ff) {
-      Ref.Entry(idx) = ff;
-      return AssignRef(Ref, idx+1);
-    }
-    FGColumnVector3& Ref;
-    int idx;
-  };
-  AssignRef operator<<(const double ff) {
-    Entry(1) = ff;
-    return AssignRef(*this, 2);
-  }
-
 private:
   double data[3];
 
index ff2f77543b89f92a9b3dc917a0519942efafda5f..2a1ffd47f2415b2e574451ba985e3a94fbd921ac 100644 (file)
@@ -44,7 +44,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGCondition.cpp,v 1.13 2010/07/14 05:50:40 ehofman Exp $";
 static const char *IdHdr = ID_CONDITION;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -122,12 +122,27 @@ FGCondition::FGCondition(const string& test, FGPropertyManager* PropertyManager)
     exit(-1);
   }
 
-  TestParam1 = PropertyManager->GetNode(property1, true);
+  TestParam1 = PropertyManager->GetNode(property1, false);
+  if (!TestParam1) {
+      cerr << fgred << "  In condition: " << test << ". Unknown property "
+           << property1 << " referenced." << endl
+           << "Creating property.  Check usage." << reset << endl;
+      TestParam1 = PropertyManager->GetNode(property1, true);
+  }
   Comparison = mComparison[conditional];
+  if (Comparison == ecUndef) {
+       throw("Comparison operator: \""+conditional+"\" does not exist.  Please check the conditional.");
+  }
   if (is_number(property2)) {
     TestValue = atof(property2.c_str());
   } else {
-    TestParam2 = PropertyManager->GetNode(property2, true);
+    TestParam2 = PropertyManager->GetNode(property2, false);
+    if (!TestParam2) {
+        cerr << fgred << "  In condition: " << test << ". Unknown property "
+             << property2 << " referenced." << endl
+             << "Creating property.  Check usage." << reset << endl;
+        TestParam2 = PropertyManager->GetNode(property2, true);
+    }
   }
 }
 
@@ -252,9 +267,12 @@ void FGCondition::PrintCondition(void )
 
   } else {
     if (TestParam2 != 0L)
-      cout << "    " << TestParam1->GetName() << " " << conditional << " " << TestParam2->GetName();
+      cout << "    " << TestParam1->GetRelativeName() << " "
+                        << conditional << " "
+                        << TestParam2->GetRelativeName();
     else
-      cout << "    " << TestParam1->GetName() << " " << conditional << " " << TestValue;
+      cout << "    " << TestParam1->GetRelativeName() << " "
+                     << conditional << " " << TestValue;
   }
 }
 
index 6272a8371cfa98add3f50e167d59bb0a8b9e4f97..2cd75bdfbf2a9761547e42c5a1aefc0c17a07dc8 100644 (file)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_CONDITION "$Id$"
+#define ID_CONDITION "$Id: FGCondition.h,v 1.5 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index e45e6d9aa23c1a14181e4a9371fb2f2f9ad9e44b..183654e2e54b0217aef2598a7b791947db0f199d 100755 (executable)
@@ -43,7 +43,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGFunction.cpp,v 1.32 2010/03/18 13:21:24 jberndt Exp $";
 static const char *IdHdr = ID_FUNCTION;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -265,7 +265,10 @@ double FGFunction::GetValue(void) const
     }
     break;
   case eQuotient:
-    temp /= Parameters[1]->GetValue();
+    if (Parameters[1]->GetValue() != 0.0)
+      temp /= Parameters[1]->GetValue();
+    else
+      temp = HUGE_VAL;
     break;
   case ePow:
     temp = pow(temp,Parameters[1]->GetValue());
index d122ffe20755952aa66a38b2704cbf067e51bde4..91a811f9acacf7972e4fe1d04b2965bd2e6465af 100755 (executable)
@@ -42,7 +42,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FUNCTION "$Id$"
+#define ID_FUNCTION "$Id: FGFunction.h,v 1.21 2009/11/18 04:49:02 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index 42619b93fbac45f03566f36174389a78578b551f..f3c4d88bc91e15bfad0b04eb90569c3ebcff295b 100644 (file)
@@ -45,7 +45,7 @@ INCLUDES
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGLocation.cpp,v 1.21 2010/07/02 01:48:12 jberndt Exp $";
 static const char *IdHdr = ID_LOCATION;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -64,6 +64,19 @@ FGLocation::FGLocation(void)
   e = 1.0;
   eps2 = -1.0;
   f = 1.0;
+  epa = 0.0;
+
+  mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0;
+  
+//  initial_longitude = 0.0;
+
+  mTl2ec.InitMatrix();
+  mTec2l.InitMatrix();
+  mTi2ec.InitMatrix();
+  mTec2i.InitMatrix();
+  mTi2l.InitMatrix();
+  mTl2i.InitMatrix();
+  mECLoc.InitMatrix();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -76,7 +89,7 @@ FGLocation::FGLocation(double lon, double lat, double radius)
   double cosLat = cos(lat);
   double sinLon = sin(lon);
   double cosLon = cos(lon);
-  initial_longitude = lon;
+
   a = 0.0;
   b = 0.0;
   a2 = 0.0;
@@ -85,9 +98,15 @@ FGLocation::FGLocation(double lon, double lat, double radius)
   e = 1.0;
   eps2 = -1.0;
   f = 1.0;
+  epa = 0.0;
   mECLoc = FGColumnVector3( radius*cosLat*cosLon,
                             radius*cosLat*sinLon,
                             radius*sinLat );
+  mLon = mLat = mRadius = mGeodLat = GeodeticAltitude = 0.0;
+  
+//  initial_longitude = 0.0
+
+  ComputeDerived();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -159,7 +178,7 @@ void FGLocation::SetPosition(double lon, double lat, double radius)
   double cosLat = cos(lat);
   double sinLon = sin(lon);
   double cosLon = cos(lon);
-  initial_longitude = lon;
+//  initial_longitude = lon;
   mECLoc = FGColumnVector3( radius*cosLat*cosLon,
                             radius*cosLat*sinLon,
                             radius*sinLat );
@@ -176,7 +195,7 @@ void FGLocation::SetPositionGeodetic(double lon, double lat, double height)
   mLon = lon;
   GeodeticAltitude = height;
 
-  initial_longitude = mLon;
+//  initial_longitude = mLon;
 
   double RN = a / sqrt(1.0 - e2*sin(mGeodLat)*sin(mGeodLat));
 
@@ -204,25 +223,23 @@ void FGLocation::SetEllipse(double semimajor, double semiminor)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 // Compute the ECEF to ECI transformation matrix using Stevens and Lewis "Aircraft
-// Control and Simulation", second edition, eqn. 1.4-12, pg. 39
+// Control and Simulation", second edition, eqn. 1.4-12, pg. 39. In Stevens and Lewis
+// notation, this is C_i/e, a transformation from ECEF to ECI.
 
-const FGMatrix33& FGLocation::GetTec2i(double epa)
+const FGMatrix33& FGLocation::GetTec2i(void)
 {
-  double mu = epa - initial_longitude;
-  mTec2i = FGMatrix33( cos(mu), -sin(mu), 0.0,
-                       sin(mu),  cos(mu), 0.0,
-                            0.0,     0.0, 1.0 );
   return mTec2i;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// This is given in Stevens and Lewis "Aircraft
+// Control and Simulation", second edition, eqn. 1.4-12, pg. 39
+// The notation in Stevens and Lewis is: C_e/i. This represents a transformation
+// from ECI to ECEF - and the orientation of the ECEF frame relative to the ECI
+// frame.
 
-const FGMatrix33& FGLocation::GetTi2ec(double epa)
+const FGMatrix33& FGLocation::GetTi2ec(void)
 {
-  double mu = epa - initial_longitude;
-  mTi2ec = FGMatrix33( cos(mu), sin(mu), 0.0,
-                      -sin(mu), cos(mu), 0.0,
-                           0.0,      0.0, 1.0 );
   return mTi2ec;
 }
 
@@ -235,7 +252,8 @@ void FGLocation::ComputeDerivedUnconditional(void) const
 
   // The distance of the location to the Z-axis, which is the axis
   // through the poles.
-  double rxy = sqrt(mECLoc(eX)*mECLoc(eX) + mECLoc(eY)*mECLoc(eY));
+  double r02 = mECLoc(eX)*mECLoc(eX) + mECLoc(eY)*mECLoc(eY);
+  double rxy = sqrt(r02);
 
   // Compute the sin/cos values of the longitude
   double sinLon, cosLon;
@@ -270,23 +288,42 @@ void FGLocation::ComputeDerivedUnconditional(void) const
 
   // Compute the transform matrices from and to the earth centered frame.
   // See Stevens and Lewis, "Aircraft Control and Simulation", Second Edition,
-  // Eqn. 1.4-13, page 40. 
+  // Eqn. 1.4-13, page 40. In Stevens and Lewis notation, this is C_n/e - the 
+  // orientation of the navigation (local) frame relative to the ECEF frame,
+  // and a transformation from ECEF to nav (local) frame.
+
   mTec2l = FGMatrix33( -cosLon*sinLat, -sinLon*sinLat,  cosLat,
                            -sinLon   ,     cosLon    ,    0.0 ,
                        -cosLon*cosLat, -sinLon*cosLat, -sinLat  );
 
+  // In Stevens and Lewis notation, this is C_e/n - the 
+  // orientation of the ECEF frame relative to the nav (local) frame,
+  // and a transformation from nav (local) to ECEF frame.
+
   mTl2ec = mTec2l.Transposed();
-  
+
+  // Calculate the inertial to ECEF and transpose matrices
+  double cos_epa = cos(epa);
+  double sin_epa = sin(epa);
+  mTi2ec = FGMatrix33( cos_epa, sin_epa, 0.0,
+                      -sin_epa, cos_epa, 0.0,
+                           0.0,      0.0, 1.0 );
+  mTec2i = mTi2ec.Transposed();
+
+  // Now calculate the local (or nav, or ned) frame to inertial transform matrix,
+  // and the inverse.
+  mTl2i = mTec2i * mTl2ec;
+  mTi2l = mTl2i.Transposed();
+
   // Calculate the geodetic latitude base on AIAA Journal of Guidance and Control paper,
   // "Improved Method for Calculating Exact Geodetic Latitude and Altitude", and
   // "Improved Method for Calculating Exact Geodetic Latitude and Altitude, Revisited",
   // author: I. Sofair
 
   if (a != 0.0 && b != 0.0) {
-    double c, p, q, s, t, u, v, w, z, p2, u2, r02, r0;
+    double c, p, q, s, t, u, v, w, z, p2, u2, r0;
     double Ne, P, Q0, Q, signz0, sqrt_q; 
     p  = fabs(mECLoc(eZ))/eps2;
-    r02 = mECLoc(eX)*mECLoc(eX) + mECLoc(eY)*mECLoc(eY);
     s  = r02/(e2*eps2);
     p2 = p*p;
     q  = p2 - b2 + s;
@@ -306,7 +343,7 @@ void FGLocation::ComputeDerivedUnconditional(void) const
       z  = signz0*sqrt_q*(w+sqrt(sqrt(t*t+v)-u*w-0.5*t-0.25));
       Ne = a*sqrt(1+eps2*z*z/b2);
       mGeodLat = asin((eps2+1.0)*(z/Ne));
-      r0 = sqrt(r02);
+      r0 = rxy;
       GeodeticAltitude = r0*cos(mGeodLat) + mECLoc(eZ)*sin(mGeodLat) - a2/Ne;
     }
   }
index b61ffa966cbbc287553edf15dd8523732ce09776..2785932d5ba554eb2d06130862063ca4d13e2418 100644 (file)
@@ -48,7 +48,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_LOCATION "$Id$"
+#define ID_LOCATION "$Id: FGLocation.h,v 1.21 2010/07/09 04:11:45 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -60,79 +60,89 @@ namespace JSBSim {
 CLASS DOCUMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-/** Holds an arbitrary location in the earth centered reference frame.
-    This coordinate frame has its center in the middle of the earth.
-    Its x-axis points from the center of the earth towards a location
-    with zero latitude and longitude on the earths surface. The y-axis
-    points from the center of the earth towards a location with zero
-    latitude and 90deg longitude on the earths surface. The z-axis
-    points from the earths center to the geographic north pole.
-
-    This class provides access functions to set and get the location as
-    either the simple x, y and z values in ft or longitude/latitude and
-    the radial distance of the location from the earth center.
-
-    It is common to associate a parent frame with a location. This
-    frame is usually called the local horizontal frame or simply the local
-    frame. This frame has its x/y plane parallel to the surface of the earth
-    (with the assumption of a spherical earth). The x-axis points
-    towards north, the y-axis points towards east and the z-axis
-    points to the center of the earth.
-
-    Since this frame is determined by the location, this class also
-    provides the rotation matrices required to transform from the
-    earth centered frame to the local horizontal frame and back. There
-    are also conversion functions for conversion of position vectors
-    given in the one frame to positions in the other frame.
-
-    The earth centered reference frame is *NOT* an inertial frame
-    since it rotates with the earth.
-
-    The coordinates in the earth centered frame are the master values.
-    All other values are computed from these master values and are
-    cached as long as the location is changed by access through a
-    non-const member function. Values are cached to improve performance.
-    It is best practice to work with a natural set of master values.
-    Other parameters that are derived from these master values are calculated
-    only when needed, and IF they are needed and calculated, then they are
-    cached (stored and remembered) so they do not need to be re-calculated
-    until the master values they are derived from are themselves changed
-    (and become stale).
-
-    Accuracy and round off:
-
-    Given that we model a vehicle near the earth, the earths surface
-    radius is about 2*10^7, ft and that we use double values for the
-    representation of the location, we have an accuracy of about
-    1e-16*2e7ft/1=2e-9ft left. This should be sufficient for our needs.
-    Note that this is the same relative accuracy we would have when we
-    compute directly with lon/lat/radius. For the radius value this
-    is clear. For the lon/lat pair this is easy to see. Take for
-    example KSFO located at about 37.61deg north 122.35deg west, which
-    corresponds to 0.65642rad north and 2.13541rad west. Both values
-    are of magnitude of about 1. But 1ft corresponds to about
-    1/(2e7*2*pi)=7.9577e-09rad. So the left accuracy with this
-    representation is also about 1*1e-16/7.9577e-09=1.2566e-08 which
-    is of the same magnitude as the representation chosen here.
-
-    The advantage of this representation is that it is a linear space
-    without singularities. The singularities are the north and south
-    pole and most notably the non-steady jump at -pi to pi. It is
-    harder to track this jump correctly especially when we need to
-    work with error norms and derivatives of the equations of motion
-    within the time-stepping code. Also, the rate of change is of the
-    same magnitude for all components in this representation which is
-    an advantage for numerical stability in implicit time-stepping too.
-
-    Note: The latitude is a GEOCENTRIC value. FlightGear
-    converts latitude to a geodetic value and uses that. In order to get best
-    matching relative to a map, geocentric latitude must be converted to geodetic.
+/** FGLocation holds an arbitrary location in the Earth centered Earth fixed
+    reference frame (ECEF). This coordinate frame has its center in the middle
+    of the earth. The X-axis points from the center of the Earth towards a
+    location with zero latitude and longitude on the Earth surface. The Y-axis
+    points from the center of the Earth towards a location with zero latitude
+    and 90 deg East longitude on the Earth surface. The Z-axis points from the
+    Earth center to the geographic north pole.
+
+    This class provides access functions to set and get the location as either
+    the simple X, Y and Z values in ft or longitude/latitude and the radial
+    distance of the location from the Earth center.
+
+    It is common to associate a parent frame with a location. This frame is
+    usually called the local horizontal frame or simply the local frame. It is
+    also called the NED frame (North, East, Down), as well as the Navigation
+    frame. This frame has its X/Y plane parallel to the surface of the Earth
+    (with the assumption of a spherical Earth). The X-axis points towards north,
+    the Y-axis points east and the Z-axis points to the center of the Earth.
+
+    Since the local frame is determined by the location (and NOT by the
+    orientation of the  vehicle IN any frame), this class also provides the
+    rotation matrices required to transform from the Earth centered (ECEF) frame
+    to the local horizontal frame and back. This class also "owns" the
+    transformations that go from the inertial frame (Earth-centered Inertial, or
+    ECI) to and from the ECEF frame, as well as to and from the local frame.
+    Again, this is because the ECI, ECEF, and local frames do not involve the
+    actual orientation of the vehicle - only the location on the Earth surface,
+    and the angular difference between the ECI and ECEF frames. There are
+    conversion functions for conversion of position vectors given in the one
+    frame to positions in the other frame.
+
+    The Earth centered reference frame is NOT an inertial frame since it rotates
+    with the Earth.
+
+    The coordinates in the Earth centered frame are the master values. All other
+    values are computed from these master values and are cached as long as the
+    location is changed by access through a non-const member function. Values
+    are cached to improve performance. It is best practice to work with a
+    natural set of master values. Other parameters that are derived from these
+    master values are calculated only when needed, and IF they are needed and
+    calculated, then they are cached (stored and remembered) so they do not need
+    to be re-calculated until the master values they are derived from are
+    themselves changed (and become stale).
+
+    Accuracy and round off
+
+    Given,
+
+    -that we model a vehicle near the Earth
+    -that the Earth surface radius is about 2*10^7, ft
+    -that we use double values for the representation of the location
+    
+    we have an accuracy of about
+    
+    1e-16*2e7ft/1 = 2e-9 ft
+    
+    left. This should be sufficient for our needs. Note that this is the same
+    relative accuracy we would have when we compute directly with
+    lon/lat/radius. For the radius value this is clear. For the lon/lat pair
+    this is easy to see. Take for example KSFO located at about 37.61 deg north
+    122.35 deg west, which corresponds to 0.65642 rad north and 2.13541 rad
+    west. Both values are of magnitude of about 1. But 1 ft corresponds to about
+    1/(2e7*2*pi) = 7.9577e-09 rad. So the left accuracy with this representation
+    is also about 1*1e-16/7.9577e-09 = 1.2566e-08 which is of the same magnitude
+    as the representation chosen here.
+
+    The advantage of this representation is that it is a linear space without
+    singularities. The singularities are the north and south pole and most
+    notably the non-steady jump at -pi to pi. It is harder to track this jump
+    correctly especially when we need to work with error norms and derivatives
+    of the equations of motion within the time-stepping code. Also, the rate of
+    change is of the same magnitude for all components in this representation
+    which is an advantage for numerical stability in implicit time-stepping.
+
+    Note: The latitude is a GEOCENTRIC value. FlightGear converts latitude to a
+    geodetic value and uses that. In order to get best matching relative to a
+    map, geocentric latitude must be converted to geodetic.
 
     @see Stevens and Lewis, "Aircraft Control and Simulation", Second edition
     @see W. C. Durham "Aircraft Dynamics & Control", section 2.2
 
     @author Mathias Froehlich
-    @version $Id$
+    @version $Id: FGLocation.h,v 1.21 2010/07/09 04:11:45 jberndt Exp $
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -244,6 +254,13 @@ public:
       and semiminor axis lengths */
   void SetEllipse(double semimajor, double semiminor);
 
+  /** Sets the Earth position angle.
+      This is the relative orientation of the ECEF frame with respect to the
+      Inertial frame.
+      @param EPA Earth fixed frame (ECEF) rotation offset about the axis with
+                 respect to the Inertial (ECI) frame in radians. */
+  void SetEarthPositionAngle(double EPA) {epa = EPA; /*mCacheValid = false;*/ ComputeDerived();}
+
   /** Get the longitude.
       @return the longitude in rad of the location represented with this
       class instance. The returned values are in the range between
@@ -309,7 +326,7 @@ public:
       @return the distance of the location represented with this class
       instance to the center of the earth in ft. The radius value is
       always positive. */
-  double GetRadius() const { ComputeDerived(); return mRadius; }
+  double GetRadius() const { return mECLoc.Magnitude(); }
 
   /** Transform matrix from local horizontal to earth centered frame.
       Returns a const reference to the rotation matrix of the transform from
@@ -324,12 +341,16 @@ public:
   /** Transform matrix from inertial to earth centered frame.
       Returns a const reference to the rotation matrix of the transform from
       the inertial frame to the earth centered frame (ECI to ECEF). */
-  const FGMatrix33& GetTi2ec(double epa);
+  const FGMatrix33& GetTi2ec(void);
 
   /** Transform matrix from the earth centered to inertial frame.
       Returns a const reference to the rotation matrix of the transform from
       the earth centered frame to the inertial frame (ECEF to ECI). */
-  const FGMatrix33& GetTec2i(double epa);
+  const FGMatrix33& GetTec2i(void);
+
+  const FGMatrix33& GetTi2l(void) const {return mTi2l;}
+
+  const FGMatrix33& GetTl2i(void) const {return mTl2i;}
 
   /** Conversion from Local frame coordinates to a location in the
       earth centered and fixed frame.
@@ -354,14 +375,14 @@ public:
       Return the value of the matrix entry at the given index.
       Indices are counted starting with 1.
       Note that the index given in the argument is unchecked. */
-  double operator()(unsigned int idx) const { return Entry(idx); }
+  double operator()(unsigned int idx) const { return mECLoc.Entry(idx); }
 
   /** Write access the entries of the vector.
       @param idx the component index.
       @return a reference to the vector entry at the given index.
       Indices are counted starting with 1.
       Note that the index given in the argument is unchecked. */
-  double& operator()(unsigned int idx) { return Entry(idx); }
+  double& operator()(unsigned int idx) { mCacheValid = false; return mECLoc.Entry(idx); }
 
   /** Read access the entries of the vector.
       @param idx the component index.
@@ -385,6 +406,12 @@ public:
     mCacheValid = false; return mECLoc.Entry(idx);
   }
 
+  /** Sets this location via the supplied vector.
+      The location can be set by an Earth-centered, Earth-fixed (ECEF) frame
+      position vector. The cache is marked as invalid, so any future requests
+      for selected important data will cause the parameters to be calculated.
+      @param v the ECEF column vector in feet. 
+      @return a reference to the FGLocation object. */
   const FGLocation& operator=(const FGColumnVector3& v)
   {
     mECLoc(eX) = v(eX);
@@ -395,6 +422,9 @@ public:
     return *this;
   }
 
+  /** Sets this location via the supplied location object.
+      @param v A location object reference. 
+      @return a reference to the FGLocation object. */
   const FGLocation& operator=(const FGLocation& l)
   {
     mECLoc = l.mECLoc;
@@ -422,31 +452,47 @@ public:
 
     return *this;
   }
+
+  /** This operator returns true if the ECEF location vectors for the two
+      location objects are equal. */
   bool operator==(const FGLocation& l) const {
     return mECLoc == l.mECLoc;
   }
+
+  /** This operator returns true if the ECEF location vectors for the two
+      location objects are not equal. */
   bool operator!=(const FGLocation& l) const { return ! operator==(l); }
+
+  /** This operator adds the ECEF position vectors.
+      The supplied vector (right side) is added to the ECEF position vector
+      on the left side of the equality, and a pointer to this object is
+      returned. */
   const FGLocation& operator+=(const FGLocation &l) {
     mCacheValid = false;
     mECLoc += l.mECLoc;
     return *this;
   }
+
   const FGLocation& operator-=(const FGLocation &l) {
     mCacheValid = false;
     mECLoc -= l.mECLoc;
     return *this;
   }
+
   const FGLocation& operator*=(double scalar) {
     mCacheValid = false;
     mECLoc *= scalar;
     return *this;
   }
+
   const FGLocation& operator/=(double scalar) {
     return operator*=(1.0/scalar);
   }
+
   FGLocation operator+(const FGLocation& l) const {
     return FGLocation(mECLoc + l.mECLoc);
   }
+
   FGLocation operator-(const FGLocation& l) const {
     return FGLocation(mECLoc - l.mECLoc);
   }
@@ -500,7 +546,11 @@ private:
   mutable FGMatrix33 mTec2l;
   mutable FGMatrix33 mTi2ec;
   mutable FGMatrix33 mTec2i;
-  
+  mutable FGMatrix33 mTi2l;
+  mutable FGMatrix33 mTl2i;
+
+  double epa;
+
   /* Terms for geodetic latitude calculation. Values are from WGS84 model */
   double a;    // Earth semimajor axis in feet (6,378,137.0 meters)
   double b;    // Earth semiminor axis in feet (6,356,752.3142 meters)
index 5eccfdfce13576107bd707316b10c1c8bbc12393..379b370048469bdf569c156b4a2f29a6fed7c345 100644 (file)
@@ -48,7 +48,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGMatrix33.cpp,v 1.10 2010/07/01 23:13:19 jberndt Exp $";
 static const char *IdHdr = ID_MATRIX33;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -70,20 +70,94 @@ FGMatrix33::FGMatrix33(void)
 string FGMatrix33::Dump(const string& delimiter) const
 {
   ostringstream buffer;
-  buffer << std::setw(18) << std::setprecision(16) << Entry(1,1) << delimiter;
-  buffer << std::setw(18) << std::setprecision(16) << Entry(1,2) << delimiter;
-  buffer << std::setw(18) << std::setprecision(16) << Entry(1,3) << delimiter;
-  buffer << std::setw(18) << std::setprecision(16) << Entry(2,1) << delimiter;
-  buffer << std::setw(18) << std::setprecision(16) << Entry(2,2) << delimiter;
-  buffer << std::setw(18) << std::setprecision(16) << Entry(2,3) << delimiter;
-  buffer << std::setw(18) << std::setprecision(16) << Entry(3,1) << delimiter;
-  buffer << std::setw(18) << std::setprecision(16) << Entry(3,2) << delimiter;
-  buffer << std::setw(18) << std::setprecision(16) << Entry(3,3);
+  buffer << setw(12) << setprecision(10) << data[0] << delimiter;
+  buffer << setw(12) << setprecision(10) << data[3] << delimiter;
+  buffer << setw(12) << setprecision(10) << data[6] << delimiter;
+  buffer << setw(12) << setprecision(10) << data[1] << delimiter;
+  buffer << setw(12) << setprecision(10) << data[4] << delimiter;
+  buffer << setw(12) << setprecision(10) << data[7] << delimiter;
+  buffer << setw(12) << setprecision(10) << data[2] << delimiter;
+  buffer << setw(12) << setprecision(10) << data[5] << delimiter;
+  buffer << setw(12) << setprecision(10) << data[8];
   return buffer.str();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+string FGMatrix33::Dump(const string& delimiter, const string& prefix) const
+{
+  ostringstream buffer;
+
+  buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[0] << delimiter;
+  buffer << right << fixed << setw(9) << setprecision(6) << data[3] << delimiter;
+  buffer << right << fixed << setw(9) << setprecision(6) << data[6] << endl;
+
+  buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[1] << delimiter;
+  buffer << right << fixed << setw(9) << setprecision(6) << data[4] << delimiter;
+  buffer << right << fixed << setw(9) << setprecision(6) << data[7] << endl;
+
+  buffer << prefix << right << fixed << setw(9) << setprecision(6) << data[2] << delimiter;
+  buffer << right << fixed << setw(9) << setprecision(6) << data[5] << delimiter;
+  buffer << right << fixed << setw(9) << setprecision(6) << data[8];
+
+  buffer << setw(0) << left;
+
+  return buffer.str();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGQuaternion FGMatrix33::GetQuaternion(void)
+{
+  FGQuaternion Q;
+
+  double tempQ[4];
+  int idx;
+
+  tempQ[0] = 1.0 + data[0] + data[4] + data[8];
+  tempQ[1] = 1.0 + data[0] - data[4] - data[8];
+  tempQ[2] = 1.0 - data[0] + data[4] - data[8];
+  tempQ[3] = 1.0 - data[0] - data[4] + data[8];
+
+  // Find largest of the above
+  idx = 0;
+  for (int i=1; i<4; i++) if (tempQ[i] > tempQ[idx]) idx = i; 
+
+  switch(idx) {
+    case 0:
+      Q(1) = 0.50*sqrt(tempQ[0]);
+      Q(2) = 0.25*(data[7] - data[5])/Q(1);
+      Q(3) = 0.25*(data[2] - data[6])/Q(1);
+      Q(4) = 0.25*(data[3] - data[1])/Q(1);
+      break;
+    case 1:
+      Q(2) = 0.50*sqrt(tempQ[1]);
+      Q(1) = 0.25*(data[7] - data[5])/Q(2);
+      Q(3) = 0.25*(data[3] + data[1])/Q(2);
+      Q(4) = 0.25*(data[2] + data[6])/Q(2);
+      break;
+    case 2:
+      Q(3) = 0.50*sqrt(tempQ[2]);
+      Q(1) = 0.25*(data[2] - data[6])/Q(3);
+      Q(2) = 0.25*(data[3] + data[1])/Q(3);
+      Q(4) = 0.25*(data[7] + data[5])/Q(3);
+      break;
+    case 3:
+      Q(4) = 0.50*sqrt(tempQ[3]);
+      Q(1) = 0.25*(data[3] - data[1])/Q(4);
+      Q(2) = 0.25*(data[6] + data[2])/Q(4);
+      Q(3) = 0.25*(data[7] + data[5])/Q(4);
+      break;
+    default:
+      //error
+      break;
+  }
+
+  return (Q);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 ostream& operator<<(ostream& os, const FGMatrix33& M)
 {
   for (unsigned int i=1; i<=M.Rows(); i++) {
@@ -112,9 +186,9 @@ istream& operator>>(istream& is, FGMatrix33& M)
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 double FGMatrix33::Determinant(void) const {
-  return Entry(1,1)*Entry(2,2)*Entry(3,3) + Entry(1,2)*Entry(2,3)*Entry(3,1)
-    + Entry(1,3)*Entry(2,1)*Entry(3,2) - Entry(1,3)*Entry(2,2)*Entry(3,1)
-    - Entry(1,2)*Entry(2,1)*Entry(3,3) - Entry(2,3)*Entry(3,2)*Entry(1,1);
+  return data[0]*data[4]*data[8] + data[3]*data[7]*data[2]
+       + data[6]*data[1]*data[5] - data[6]*data[4]*data[2]
+       - data[3]*data[1]*data[8] - data[7]*data[5]*data[0];
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -123,21 +197,28 @@ FGMatrix33 FGMatrix33::Inverse(void) const {
   // Compute the inverse of a general matrix using Cramers rule.
   // I guess googling for cramers rule gives tons of references
   // for this. :)
-  double rdet = 1.0/Determinant();
-
-  double i11 = rdet*(Entry(2,2)*Entry(3,3)-Entry(2,3)*Entry(3,2));
-  double i21 = rdet*(Entry(2,3)*Entry(3,1)-Entry(2,1)*Entry(3,3));
-  double i31 = rdet*(Entry(2,1)*Entry(3,2)-Entry(2,2)*Entry(3,1));
-  double i12 = rdet*(Entry(1,3)*Entry(3,2)-Entry(1,2)*Entry(3,3));
-  double i22 = rdet*(Entry(1,1)*Entry(3,3)-Entry(1,3)*Entry(3,1));
-  double i32 = rdet*(Entry(1,2)*Entry(3,1)-Entry(1,1)*Entry(3,2));
-  double i13 = rdet*(Entry(1,2)*Entry(2,3)-Entry(1,3)*Entry(2,2));
-  double i23 = rdet*(Entry(1,3)*Entry(2,1)-Entry(1,1)*Entry(2,3));
-  double i33 = rdet*(Entry(1,1)*Entry(2,2)-Entry(1,2)*Entry(2,1));
-
-  return FGMatrix33( i11, i12, i13,
-                     i21, i22, i23,
-                     i31, i32, i33 );
+
+  if (Determinant() != 0.0) {
+    double rdet = 1.0/Determinant();
+
+    double i11 = rdet*(data[4]*data[8]-data[7]*data[5]);
+    double i21 = rdet*(data[7]*data[2]-data[1]*data[8]);
+    double i31 = rdet*(data[1]*data[5]-data[4]*data[2]);
+    double i12 = rdet*(data[6]*data[5]-data[3]*data[8]);
+    double i22 = rdet*(data[0]*data[8]-data[6]*data[2]);
+    double i32 = rdet*(data[3]*data[2]-data[0]*data[5]);
+    double i13 = rdet*(data[3]*data[7]-data[6]*data[4]);
+    double i23 = rdet*(data[6]*data[1]-data[0]*data[7]);
+    double i33 = rdet*(data[0]*data[4]-data[3]*data[1]);
+
+    return FGMatrix33( i11, i12, i13,
+                       i21, i22, i23,
+                       i31, i32, i33 );
+  } else {
+    return FGMatrix33( 0, 0, 0,
+                       0, 0, 0,
+                       0, 0, 0 );
+  }
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -154,15 +235,15 @@ void FGMatrix33::InitMatrix(void)
 
 FGMatrix33 FGMatrix33::operator-(const FGMatrix33& M) const
 {
-  return FGMatrix33( Entry(1,1) - M(1,1),
-                     Entry(1,2) - M(1,2),
-                     Entry(1,3) - M(1,3),
-                     Entry(2,1) - M(2,1),
-                     Entry(2,2) - M(2,2),
-                     Entry(2,3) - M(2,3),
-                     Entry(3,1) - M(3,1),
-                     Entry(3,2) - M(3,2),
-                     Entry(3,3) - M(3,3) );
+  return FGMatrix33( data[0] - M.data[0],
+                     data[3] - M.data[3],
+                     data[6] - M.data[6],
+                     data[1] - M.data[1],
+                     data[4] - M.data[4],
+                     data[7] - M.data[7],
+                     data[2] - M.data[2],
+                     data[5] - M.data[5],
+                     data[8] - M.data[8] );
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -186,30 +267,30 @@ FGMatrix33& FGMatrix33::operator-=(const FGMatrix33 &M)
 
 FGMatrix33 FGMatrix33::operator+(const FGMatrix33& M) const
 {
-  return FGMatrix33( Entry(1,1) + M(1,1),
-                     Entry(1,2) + M(1,2),
-                     Entry(1,3) + M(1,3),
-                     Entry(2,1) + M(2,1),
-                     Entry(2,2) + M(2,2),
-                     Entry(2,3) + M(2,3),
-                     Entry(3,1) + M(3,1),
-                     Entry(3,2) + M(3,2),
-                     Entry(3,3) + M(3,3) );
+  return FGMatrix33( data[0] + M.data[0],
+                     data[3] + M.data[3],
+                     data[6] + M.data[6],
+                     data[1] + M.data[1],
+                     data[4] + M.data[4],
+                     data[7] + M.data[7],
+                     data[2] + M.data[2],
+                     data[5] + M.data[5],
+                     data[8] + M.data[8] );
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 FGMatrix33& FGMatrix33::operator+=(const FGMatrix33 &M)
 {
-  Entry(1,1) += M(1,1);
-  Entry(1,2) += M(1,2);
-  Entry(1,3) += M(1,3);
-  Entry(2,1) += M(2,1);
-  Entry(2,2) += M(2,2);
-  Entry(2,3) += M(2,3);
-  Entry(3,1) += M(3,1);
-  Entry(3,2) += M(3,2);
-  Entry(3,3) += M(3,3);
+  data[0] += M.data[0];
+  data[3] += M.data[3];
+  data[6] += M.data[6];
+  data[1] += M.data[1];
+  data[4] += M.data[4];
+  data[7] += M.data[7];
+  data[2] += M.data[2];
+  data[5] += M.data[5];
+  data[8] += M.data[8];
 
   return *this;
 }
@@ -218,19 +299,19 @@ FGMatrix33& FGMatrix33::operator+=(const FGMatrix33 &M)
 
 FGMatrix33 FGMatrix33::operator*(const double scalar) const
 {
-  return FGMatrix33( scalar * Entry(1,1),
-                     scalar * Entry(1,2),
-                     scalar * Entry(1,3),
-                     scalar * Entry(2,1),
-                     scalar * Entry(2,2),
-                     scalar * Entry(2,3),
-                     scalar * Entry(3,1),
-                     scalar * Entry(3,2),
-                     scalar * Entry(3,3) );
+  return FGMatrix33( scalar * data[0],
+                     scalar * data[3],
+                     scalar * data[6],
+                     scalar * data[1],
+                     scalar * data[4],
+                     scalar * data[7],
+                     scalar * data[2],
+                     scalar * data[5],
+                     scalar * data[8] );
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
+/*
 FGMatrix33 operator*(double scalar, FGMatrix33 &M)
 {
   return FGMatrix33( scalar * M(1,1),
@@ -243,20 +324,20 @@ FGMatrix33 operator*(double scalar, FGMatrix33 &M)
                      scalar * M(3,2),
                      scalar * M(3,3) );
 }
-
+*/
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 FGMatrix33& FGMatrix33::operator*=(const double scalar)
 {
-  Entry(1,1) *= scalar;
-  Entry(1,2) *= scalar;
-  Entry(1,3) *= scalar;
-  Entry(2,1) *= scalar;
-  Entry(2,2) *= scalar;
-  Entry(2,3) *= scalar;
-  Entry(3,1) *= scalar;
-  Entry(3,2) *= scalar;
-  Entry(3,3) *= scalar;
+  data[0] *= scalar;
+  data[3] *= scalar;
+  data[6] *= scalar;
+  data[1] *= scalar;
+  data[4] *= scalar;
+  data[7] *= scalar;
+  data[2] *= scalar;
+  data[5] *= scalar;
+  data[8] *= scalar;
 
   return *this;
 }
@@ -265,18 +346,17 @@ FGMatrix33& FGMatrix33::operator*=(const double scalar)
 
 FGMatrix33 FGMatrix33::operator*(const FGMatrix33& M) const
 {
-  // FIXME: Make compiler friendlier
   FGMatrix33 Product;
 
-  Product(1,1) = Entry(1,1)*M(1,1) + Entry(1,2)*M(2,1) + Entry(1,3)*M(3,1);
-  Product(1,2) = Entry(1,1)*M(1,2) + Entry(1,2)*M(2,2) + Entry(1,3)*M(3,2);
-  Product(1,3) = Entry(1,1)*M(1,3) + Entry(1,2)*M(2,3) + Entry(1,3)*M(3,3);
-  Product(2,1) = Entry(2,1)*M(1,1) + Entry(2,2)*M(2,1) + Entry(2,3)*M(3,1);
-  Product(2,2) = Entry(2,1)*M(1,2) + Entry(2,2)*M(2,2) + Entry(2,3)*M(3,2);
-  Product(2,3) = Entry(2,1)*M(1,3) + Entry(2,2)*M(2,3) + Entry(2,3)*M(3,3);
-  Product(3,1) = Entry(3,1)*M(1,1) + Entry(3,2)*M(2,1) + Entry(3,3)*M(3,1);
-  Product(3,2) = Entry(3,1)*M(1,2) + Entry(3,2)*M(2,2) + Entry(3,3)*M(3,2);
-  Product(3,3) = Entry(3,1)*M(1,3) + Entry(3,2)*M(2,3) + Entry(3,3)*M(3,3);
+  Product.data[0] = data[0]*M.data[0] + data[3]*M.data[1] + data[6]*M.data[2];
+  Product.data[3] = data[0]*M.data[3] + data[3]*M.data[4] + data[6]*M.data[5];
+  Product.data[6] = data[0]*M.data[6] + data[3]*M.data[7] + data[6]*M.data[8];
+  Product.data[1] = data[1]*M.data[0] + data[4]*M.data[1] + data[7]*M.data[2];
+  Product.data[4] = data[1]*M.data[3] + data[4]*M.data[4] + data[7]*M.data[5];
+  Product.data[7] = data[1]*M.data[6] + data[4]*M.data[7] + data[7]*M.data[8];
+  Product.data[2] = data[2]*M.data[0] + data[5]*M.data[1] + data[8]*M.data[2];
+  Product.data[5] = data[2]*M.data[3] + data[5]*M.data[4] + data[8]*M.data[5];
+  Product.data[8] = data[2]*M.data[6] + data[5]*M.data[7] + data[8]*M.data[8];
 
   return Product;
 }
@@ -288,20 +368,20 @@ FGMatrix33& FGMatrix33::operator*=(const FGMatrix33& M)
   // FIXME: Make compiler friendlier
   double a,b,c;
 
-  a = Entry(1,1); b=Entry(1,2); c=Entry(1,3);
-  Entry(1,1) = a*M(1,1) + b*M(2,1) + c*M(3,1);
-  Entry(1,2) = a*M(1,2) + b*M(2,2) + c*M(3,2);
-  Entry(1,3) = a*M(1,3) + b*M(2,3) + c*M(3,3);
+  a = data[0]; b=data[3]; c=data[6];
+  data[0] = a*M.data[0] + b*M.data[1] + c*M.data[2];
+  data[3] = a*M.data[3] + b*M.data[4] + c*M.data[5];
+  data[6] = a*M.data[6] + b*M.data[7] + c*M.data[8];
 
-  a = Entry(2,1); b=Entry(2,2); c=Entry(2,3);
-  Entry(2,1) = a*M(1,1) + b*M(2,1) + c*M(3,1);
-  Entry(2,2) = a*M(1,2) + b*M(2,2) + c*M(3,2);
-  Entry(2,3) = a*M(1,3) + b*M(2,3) + c*M(3,3);
+  a = data[1]; b=data[4]; c=data[7];
+  data[1] = a*M.data[0] + b*M.data[1] + c*M.data[2];
+  data[4] = a*M.data[3] + b*M.data[4] + c*M.data[5];
+  data[7] = a*M.data[6] + b*M.data[7] + c*M.data[8];
 
-  a = Entry(3,1); b=Entry(3,2); c=Entry(3,3);
-  Entry(3,1) = a*M(1,1) + b*M(2,1) + c*M(3,1);
-  Entry(3,2) = a*M(1,2) + b*M(2,2) + c*M(3,2);
-  Entry(3,3) = a*M(1,3) + b*M(2,3) + c*M(3,3);
+  a = data[2]; b=data[5]; c=data[8];
+  data[2] = a*M.data[0] + b*M.data[1] + c*M.data[2];
+  data[5] = a*M.data[3] + b*M.data[4] + c*M.data[5];
+  data[8] = a*M.data[6] + b*M.data[7] + c*M.data[8];
 
   return *this;
 }
@@ -314,15 +394,15 @@ FGMatrix33 FGMatrix33::operator/(const double scalar) const
 
   if ( scalar != 0 ) {
     double tmp = 1.0/scalar;
-    Quot(1,1) = Entry(1,1) * tmp;
-    Quot(1,2) = Entry(1,2) * tmp;
-    Quot(1,3) = Entry(1,3) * tmp;
-    Quot(2,1) = Entry(2,1) * tmp;
-    Quot(2,2) = Entry(2,2) * tmp;
-    Quot(2,3) = Entry(2,3) * tmp;
-    Quot(3,1) = Entry(3,1) * tmp;
-    Quot(3,2) = Entry(3,2) * tmp;
-    Quot(3,3) = Entry(3,3) * tmp;
+    Quot.data[0] = data[0] * tmp;
+    Quot.data[3] = data[3] * tmp;
+    Quot.data[6] = data[6] * tmp;
+    Quot.data[1] = data[1] * tmp;
+    Quot.data[4] = data[4] * tmp;
+    Quot.data[7] = data[7] * tmp;
+    Quot.data[2] = data[2] * tmp;
+    Quot.data[5] = data[5] * tmp;
+    Quot.data[8] = data[8] * tmp;
   } else {
     MatrixException mE;
     mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/(const double scalar)";
@@ -337,15 +417,15 @@ FGMatrix33& FGMatrix33::operator/=(const double scalar)
 {
   if ( scalar != 0 ) {
     double tmp = 1.0/scalar;
-    Entry(1,1) *= tmp;
-    Entry(1,2) *= tmp;
-    Entry(1,3) *= tmp;
-    Entry(2,1) *= tmp;
-    Entry(2,2) *= tmp;
-    Entry(2,3) *= tmp;
-    Entry(3,1) *= tmp;
-    Entry(3,2) *= tmp;
-    Entry(3,3) *= tmp;
+    data[0] *= tmp;
+    data[3] *= tmp;
+    data[6] *= tmp;
+    data[1] *= tmp;
+    data[4] *= tmp;
+    data[7] *= tmp;
+    data[2] *= tmp;
+    data[5] *= tmp;
+    data[8] *= tmp;
   } else {
     MatrixException mE;
     mE.Message = "Attempt to divide by zero in method FGMatrix33::operator/=(const double scalar)";
@@ -358,29 +438,40 @@ FGMatrix33& FGMatrix33::operator/=(const double scalar)
 
 void FGMatrix33::T(void)
 {
-  for (unsigned int i=1; i<=3; i++) {
-    for (unsigned int j=i+1; j<=3; j++) {
-      double tmp = Entry(i,j);
-      Entry(i,j) = Entry(j,i);
-      Entry(j,i) = tmp;
-    }
-  }
+  double tmp;
+
+  tmp = data[3];
+  data[3] = data[1];
+  data[1] = tmp;
+
+  tmp = data[6];
+  data[6] = data[2];
+  data[2] = tmp;
+
+  tmp = data[7];
+  data[7] = data[5];
+  data[5] = tmp;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-FGColumnVector3 FGMatrix33::operator*(const FGColumnVector3& v) const {
-  double tmp1 = v(1)*Entry(1,1);
-  double tmp2 = v(1)*Entry(2,1);
-  double tmp3 = v(1)*Entry(3,1);
+FGColumnVector3 FGMatrix33::operator*(const FGColumnVector3& v) const
+{
+  double v1 = v(1);
+  double v2 = v(2);
+  double v3 = v(3);
+
+  double tmp1 = v1*data[0];  //[(col-1)*eRows+row-1]
+  double tmp2 = v1*data[1];
+  double tmp3 = v1*data[2];
 
-  tmp1 += v(2)*Entry(1,2);
-  tmp2 += v(2)*Entry(2,2);
-  tmp3 += v(2)*Entry(3,2);
+  tmp1 += v2*data[3];
+  tmp2 += v2*data[4];
+  tmp3 += v2*data[5];
 
-  tmp1 += v(3)*Entry(1,3);
-  tmp2 += v(3)*Entry(2,3);
-  tmp3 += v(3)*Entry(3,3);
+  tmp1 += v3*data[6];
+  tmp2 += v3*data[7];
+  tmp3 += v3*data[8];
 
   return FGColumnVector3( tmp1, tmp2, tmp3 );
 }
index d07687ea9808de43b31aaa2c5ef00e4a9d3570d0..7af43031b26d7e52776e15788f9a460b090fd39e 100644 (file)
@@ -50,7 +50,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_MATRIX33 "$Id$"
+#define ID_MATRIX33 "$Id: FGMatrix33.h,v 1.11 2010/06/30 03:13:40 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -59,6 +59,7 @@ FORWARD DECLARATIONS
 namespace JSBSim {
 
 class FGColumnVector3;
+class FGQuaternion;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS DOCUMENTATION
@@ -111,17 +112,17 @@ public:
       Create copy of the matrix given in the argument.
    */
   FGMatrix33(const FGMatrix33& M) {
-    Entry(1,1) = M.Entry(1,1);
-    Entry(2,1) = M.Entry(2,1);
-    Entry(3,1) = M.Entry(3,1);
-    Entry(1,2) = M.Entry(1,2);
-    Entry(2,2) = M.Entry(2,2);
-    Entry(3,2) = M.Entry(3,2);
-    Entry(1,3) = M.Entry(1,3);
-    Entry(2,3) = M.Entry(2,3);
-    Entry(3,3) = M.Entry(3,3);
-
-    Debug(0);
+    data[0] = M.data[0];
+    data[1] = M.data[1];
+    data[2] = M.data[2];
+    data[3] = M.data[3];
+    data[4] = M.data[4];
+    data[5] = M.data[5];
+    data[6] = M.data[6];
+    data[7] = M.data[7];
+    data[8] = M.data[8];
+
+//    Debug(0);
   }
 
   /** Initialization by given values.
@@ -141,28 +142,34 @@ public:
   FGMatrix33(double m11, double m12, double m13,
              double m21, double m22, double m23,
              double m31, double m32, double m33) {
-    Entry(1,1) = m11;
-    Entry(2,1) = m21;
-    Entry(3,1) = m31;
-    Entry(1,2) = m12;
-    Entry(2,2) = m22;
-    Entry(3,2) = m32;
-    Entry(1,3) = m13;
-    Entry(2,3) = m23;
-    Entry(3,3) = m33;
-
-    Debug(0);
+    data[0] = m11;
+    data[1] = m21;
+    data[2] = m31;
+    data[3] = m12;
+    data[4] = m22;
+    data[5] = m32;
+    data[6] = m13;
+    data[7] = m23;
+    data[8] = m33;
+
+    // Debug(0);
   }
 
   /** Destructor.
    */
-  ~FGMatrix33(void) { Debug(1); }
+  ~FGMatrix33(void) { /* Debug(1); */ }
 
   /** Prints the contents of the matrix.
       @param delimeter the item separator (tab or comma)
       @return a string with the delimeter-separated contents of the matrix  */
   std::string Dump(const std::string& delimeter) const;
 
+  /** Prints the contents of the matrix.
+      @param delimeter the item separator (tab or comma, etc.)
+      @param prefix an additional prefix that is used to indent the 3X3 matrix printout
+      @return a string with the delimeter-separated contents of the matrix  */
+  std::string Dump(const std::string& delimiter, const std::string& prefix) const;
+
   /** Read access the entries of the matrix.
       @param row Row index.
       @param col Column index.
@@ -171,7 +178,7 @@ public:
       column indices. Indices are counted starting with 1.
    */
   double operator()(unsigned int row, unsigned int col) const {
-    return Entry(row, col);
+    return data[(col-1)*eRows+row-1];
   }
 
   /** Write access the entries of the matrix.
@@ -184,7 +191,7 @@ public:
       column indices. Indices are counted starting with 1.
    */
   double& operator()(unsigned int row, unsigned int col) {
-    return Entry(row, col);
+    return data[(col-1)*eRows+row-1];
   }
 
   /** Read access the entries of the matrix.
@@ -237,9 +244,9 @@ public:
       @return the transposed matrix.
    */
   FGMatrix33 Transposed(void) const {
-    return FGMatrix33( Entry(1,1), Entry(2,1), Entry(3,1),
-                       Entry(1,2), Entry(2,2), Entry(3,2),
-                       Entry(1,3), Entry(2,3), Entry(3,3) );
+    return FGMatrix33( data[0], data[1], data[2],
+                       data[3], data[4], data[5],
+                       data[6], data[7], data[8] );
   }
 
   /** Transposes this matrix.
@@ -258,17 +265,21 @@ public:
   void InitMatrix(double m11, double m12, double m13,
                   double m21, double m22, double m23,
                   double m31, double m32, double m33) {
-    Entry(1,1) = m11;
-    Entry(2,1) = m21;
-    Entry(3,1) = m31;
-    Entry(1,2) = m12;
-    Entry(2,2) = m22;
-    Entry(3,2) = m32;
-    Entry(1,3) = m13;
-    Entry(2,3) = m23;
-    Entry(3,3) = m33;
+    data[0] = m11;
+    data[1] = m21;
+    data[2] = m31;
+    data[3] = m12;
+    data[4] = m22;
+    data[5] = m32;
+    data[6] = m13;
+    data[7] = m23;
+    data[8] = m33;
   }
 
+  /** Returns the quaternion associated with this direction cosine (rotation) matrix.
+  */
+  FGQuaternion GetQuaternion(void);
+  
   /** Determinant of the matrix.
       @return the determinant of the matrix.
    */
@@ -458,4 +469,6 @@ std::istream& operator>>(std::istream& is, FGMatrix33& M);
 
 } // namespace JSBSim
 
+#include "FGQuaternion.h"
+
 #endif
index f1f42a8ed961859ae9db82135b17e9ae59c9aa62..85b43b1af2abb8929f5fd73a2d238f76c78c3a44 100755 (executable)
@@ -40,7 +40,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PARAMETER "$Id$"
+#define ID_PARAMETER "$Id: FGParameter.h,v 1.5 2009/08/30 03:51:28 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index 111b078c8de475d3bd2ff3109dccb7d3c67aef63..66f89b89a6d9bde03658758e37f728ab7106ee52 100755 (executable)
@@ -32,7 +32,7 @@ INCLUDES
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGPropertyValue.cpp,v 1.4 2009/08/30 03:51:28 jberndt Exp $";
 static const char *IdHdr = ID_PROPERTYVALUE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 82803f55818e6cd2f1600829ef9e75eb50f5dec5..3466c66ba4e7cd52cad76c6b3daba56258784a62 100755 (executable)
@@ -41,7 +41,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PROPERTYVALUE "$Id$"
+#define ID_PROPERTYVALUE "$Id: FGPropertyValue.h,v 1.6 2009/10/02 10:30:09 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index 74b63d8884848826f8e671e8b68dd6ed849bd19e..07868cfa0b0b58905efbdb807f79fe4079b8bcf0 100644 (file)
@@ -40,6 +40,7 @@ SENTRY
 
 #include <string>
 #include <iostream>
+#include <iomanip>
 #include <cmath>
 using std::cerr;
 using std::cout;
@@ -56,18 +57,18 @@ using std::endl;
 
 namespace JSBSim {
   
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGQuaternion.cpp,v 1.16 2010/06/30 03:13:40 jberndt Exp $";
 static const char *IdHdr = ID_QUATERNION;
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 // Initialize from q
-FGQuaternion::FGQuaternion(const FGQuaternion& q)
-  : mCacheValid(q.mCacheValid) {
-  Entry(1) = q(1);
-  Entry(2) = q(2);
-  Entry(3) = q(3);
-  Entry(4) = q(4);
+FGQuaternion::FGQuaternion(const FGQuaternion& q) : mCacheValid(q.mCacheValid)
+{
+  data[0] = q(1);
+  data[1] = q(2);
+  data[2] = q(3);
+  data[3] = q(4);
   if (mCacheValid) {
     mT = q.mT;
     mTInv = q.mTInv;
@@ -80,8 +81,36 @@ FGQuaternion::FGQuaternion(const FGQuaternion& q)
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 // Initialize with the three euler angles
-FGQuaternion::FGQuaternion(double phi, double tht, double psi)
-  : mCacheValid(false) {
+FGQuaternion::FGQuaternion(double phi, double tht, double psi): mCacheValid(false)
+{
+  InitializeFromEulerAngles(phi, tht, psi);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGQuaternion::FGQuaternion(FGColumnVector3 vOrient): mCacheValid(false)
+{
+  double phi = vOrient(ePhi);
+  double tht = vOrient(eTht);
+  double psi = vOrient(ePsi);
+
+  InitializeFromEulerAngles(phi, tht, psi);
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//
+// This function computes the quaternion that describes the relationship of the
+// body frame with respect to another frame, such as the ECI or ECEF frames. The
+// Euler angles used represent a 3-2-1 (psi, theta, phi) rotation sequence from
+// the reference frame to the body frame. See "Quaternions and Rotation
+// Sequences", Jack B. Kuipers, sections 9.2 and 7.6. 
+
+void FGQuaternion::InitializeFromEulerAngles(double phi, double tht, double psi)
+{
+  mEulerAngles(ePhi) = phi;
+  mEulerAngles(eTht) = tht;
+  mEulerAngles(ePsi) = psi;
+
   double thtd2 = 0.5*tht;
   double psid2 = 0.5*psi;
   double phid2 = 0.5*phi;
@@ -99,10 +128,27 @@ FGQuaternion::FGQuaternion(double phi, double tht, double psi)
   double Sphid2Sthtd2 = Sphid2*Sthtd2;
   double Sphid2Cthtd2 = Sphid2*Cthtd2;
   
-  Entry(1) = Cphid2Cthtd2*Cpsid2 + Sphid2Sthtd2*Spsid2;
-  Entry(2) = Sphid2Cthtd2*Cpsid2 - Cphid2Sthtd2*Spsid2;
-  Entry(3) = Cphid2Sthtd2*Cpsid2 + Sphid2Cthtd2*Spsid2;
-  Entry(4) = Cphid2Cthtd2*Spsid2 - Sphid2Sthtd2*Cpsid2;
+  data[0] = Cphid2Cthtd2*Cpsid2 + Sphid2Sthtd2*Spsid2;
+  data[1] = Sphid2Cthtd2*Cpsid2 - Cphid2Sthtd2*Spsid2;
+  data[2] = Cphid2Sthtd2*Cpsid2 + Sphid2Cthtd2*Spsid2;
+  data[3] = Cphid2Cthtd2*Spsid2 - Sphid2Sthtd2*Cpsid2;
+
+  Normalize();
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+// Initialize with a direction cosine (rotation) matrix
+
+FGQuaternion::FGQuaternion(const FGMatrix33& m) : mCacheValid(false)
+{
+  data[0] = 0.50*sqrt(1.0 + m(1,1) + m(2,2) + m(3,3));
+  double t = 0.25/data[0];
+  data[1] = t*(m(2,3) - m(3,2));
+  data[2] = t*(m(3,1) - m(1,3));
+  data[3] = t*(m(1,2) - m(2,1));
+
+  ComputeDerivedUnconditional();
+
+  Normalize();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -111,37 +157,32 @@ FGQuaternion::FGQuaternion(double phi, double tht, double psi)
     angular velocities PQR.
     See Stevens and Lewis, "Aircraft Control and Simulation", Second Edition,
     Equation 1.3-36. 
+    Also see Jack Kuipers, "Quaternions and Rotation Sequences", Equation 11.12.
 */
-FGQuaternion FGQuaternion::GetQDot(const FGColumnVector3& PQR) const {
-  double norm = Magnitude();
-  if (norm == 0.0)
-    return FGQuaternion::zero();
-  double rnorm = 1.0/norm;
-
-  FGQuaternion QDot;
-  QDot(1) = -0.5*(Entry(2)*PQR(eP) + Entry(3)*PQR(eQ) + Entry(4)*PQR(eR));
-  QDot(2) =  0.5*(Entry(1)*PQR(eP) + Entry(3)*PQR(eR) - Entry(4)*PQR(eQ));
-  QDot(3) =  0.5*(Entry(1)*PQR(eQ) + Entry(4)*PQR(eP) - Entry(2)*PQR(eR));
-  QDot(4) =  0.5*(Entry(1)*PQR(eR) + Entry(2)*PQR(eQ) - Entry(3)*PQR(eP));
-  return rnorm*QDot;
+FGQuaternion FGQuaternion::GetQDot(const FGColumnVector3& PQR)
+{
+  return FGQuaternion(
+    -0.5*( data[1]*PQR(eP) + data[2]*PQR(eQ) + data[3]*PQR(eR)),
+     0.5*( data[0]*PQR(eP) - data[3]*PQR(eQ) + data[2]*PQR(eR)),
+     0.5*( data[3]*PQR(eP) + data[0]*PQR(eQ) - data[1]*PQR(eR)),
+     0.5*(-data[2]*PQR(eP) + data[1]*PQR(eQ) + data[0]*PQR(eR))
+  );
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 void FGQuaternion::Normalize()
 {
-  // Note: this does not touch the cache
-  // since it does not change the orientation ...
-  
+  // Note: this does not touch the cache since it does not change the orientation
   double norm = Magnitude();
-  if (norm == 0.0)
-    return;
-  
+  if (norm == 0.0 || fabs(norm - 1.000) < 1e-10) return;
+
   double rnorm = 1.0/norm;
-  Entry(1) *= rnorm;
-  Entry(2) *= rnorm;
-  Entry(3) *= rnorm;
-  Entry(4) *= rnorm;
+
+  data[0] *= rnorm;
+  data[1] *= rnorm;
+  data[2] *= rnorm;
+  data[3] *= rnorm;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -150,45 +191,42 @@ void FGQuaternion::Normalize()
 void FGQuaternion::ComputeDerivedUnconditional(void) const
 {
   mCacheValid = true;
-  
-  // First normalize the 4-vector
-  double norm = Magnitude();
-  if (norm == 0.0)
-    return;
 
-  double rnorm = 1.0/norm;
-  double q1 = rnorm*Entry(1);
-  double q2 = rnorm*Entry(2);
-  double q3 = rnorm*Entry(3);
-  double q4 = rnorm*Entry(4);
+  double q0 = data[0]; // use some aliases/shorthand for the quat elements.
+  double q1 = data[1];
+  double q2 = data[2];
+  double q3 = data[3];
 
   // Now compute the transformation matrix.
+  double q0q0 = q0*q0;
   double q1q1 = q1*q1;
   double q2q2 = q2*q2;
   double q3q3 = q3*q3;
-  double q4q4 = q4*q4;
+  double q0q1 = q0*q1;
+  double q0q2 = q0*q2;
+  double q0q3 = q0*q3;
   double q1q2 = q1*q2;
   double q1q3 = q1*q3;
-  double q1q4 = q1*q4;
   double q2q3 = q2*q3;
-  double q2q4 = q2*q4;
-  double q3q4 = q3*q4;
   
-  mT(1,1) = q1q1 + q2q2 - q3q3 - q4q4;
-  mT(1,2) = 2.0*(q2q3 + q1q4);
-  mT(1,3) = 2.0*(q2q4 - q1q3);
-  mT(2,1) = 2.0*(q2q3 - q1q4);
-  mT(2,2) = q1q1 - q2q2 + q3q3 - q4q4;
-  mT(2,3) = 2.0*(q3q4 + q1q2);
-  mT(3,1) = 2.0*(q2q4 + q1q3);
-  mT(3,2) = 2.0*(q3q4 - q1q2);
-  mT(3,3) = q1q1 - q2q2 - q3q3 + q4q4;
-  // Since this is an orthogonal matrix, the inverse is simply
-  // the transpose.
+  mT(1,1) = q0q0 + q1q1 - q2q2 - q3q3; // This is found from Eqn. 1.3-32 in
+  mT(1,2) = 2.0*(q1q2 + q0q3);         // Stevens and Lewis
+  mT(1,3) = 2.0*(q1q3 - q0q2);
+  mT(2,1) = 2.0*(q1q2 - q0q3);
+  mT(2,2) = q0q0 - q1q1 + q2q2 - q3q3;
+  mT(2,3) = 2.0*(q2q3 + q0q1);
+  mT(3,1) = 2.0*(q1q3 + q0q2);
+  mT(3,2) = 2.0*(q2q3 - q0q1);
+  mT(3,3) = q0q0 - q1q1 - q2q2 + q3q3;
+
+  // Since this is an orthogonal matrix, the inverse is simply the transpose.
+
   mTInv = mT;
   mTInv.T();
   
   // Compute the Euler-angles
+  // Also see Jack Kuipers, "Quaternions and Rotation Sequences", section 7.8..
+
   if (mT(3,3) == 0.0)
     mEulerAngles(ePhi) = 0.5*M_PI;
   else
@@ -218,6 +256,55 @@ void FGQuaternion::ComputeDerivedUnconditional(void) const
   mEulerCosines(ePhi) = cos(mEulerAngles(ePhi));
   mEulerCosines(eTht) = cos(mEulerAngles(eTht));
   mEulerCosines(ePsi) = cos(mEulerAngles(ePsi));
+
+//  Debug(2);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGQuaternion::Debug(int from) const
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGQuaternion" << endl;
+    if (from == 1) cout << "Destroyed:    FGQuaternion" << 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 (!EqualToRoundoff(Magnitude(), 1.0)) {
+      cout << "Quaternion magnitude differs from 1.0 !" << endl;
+      cout << "\tdelta from 1.0: " << std::scientific << Magnitude()-1.0 << endl;
+    }
+  }
+  if (debug_lvl & 64) {
+    if (from == 0) { // Constructor
+      cout << IdSrc << endl;
+      cout << IdHdr << endl;
+    }
+  }
 }
 
 } // namespace JSBSim
index 73c0e009a0833807242b1d1efb87e284caee9c62..104a52f39a5301ef9ba71bfc0d13d337e5aa5616 100644 (file)
@@ -41,18 +41,18 @@ SENTRY
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGJSBBase.h"
-#include "FGMatrix33.h"
 #include "FGColumnVector3.h"
-#include "input_output/FGPropertyManager.h"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   DEFINITIONS
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_QUATERNION "$Id$"
+#define ID_QUATERNION "$Id: FGQuaternion.h,v 1.17 2010/06/30 03:13:40 jberndt Exp $"
 
 namespace JSBSim {
 
+class FGMatrix33;
+
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   CLASS DOCUMENTATION
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
@@ -88,14 +88,13 @@ namespace JSBSim {
   CLASS DECLARATION
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-class FGQuaternion
-  : virtual FGJSBBase {
+class FGQuaternion : virtual FGJSBBase {
 public:
   /** Default initializer.
       Default initializer, initializes the class with the identity rotation.  */
   FGQuaternion() : mCacheValid(false) {
-    Entry(1) = 1.0;
-    Entry(2) = Entry(3) = Entry(4) = 0.0;
+    data[0] = 1.0;
+    data[1] = data[2] = data[3] = 0.0;
   }
 
   /** Copy constructor.
@@ -110,6 +109,11 @@ public:
       @param psi The euler Z axis (heading) angle in radians  */
   FGQuaternion(double phi, double tht, double psi);
 
+  /** Initializer by euler angle vector.
+      Initialize the quaternion with the euler angle vector.
+      @param vOrient The euler axis angle vector in radians (phi, tht, psi) */
+  FGQuaternion(FGColumnVector3 vOrient);
+
   /** Initializer by one euler angle.
       Initialize the quaternion with the single euler angle where its index
       is given in the first argument.
@@ -117,43 +121,50 @@ public:
       @param angle The euler angle in radians  */
   FGQuaternion(int idx, double angle)
     : mCacheValid(false) {
+
     double angle2 = 0.5*angle;
 
     double Sangle2 = sin(angle2);
     double Cangle2 = cos(angle2);
 
     if (idx == ePhi) {
-      Entry(1) = Cangle2;
-      Entry(2) = Sangle2;
-      Entry(3) = 0.0;
-      Entry(4) = 0.0;
+      data[0] = Cangle2;
+      data[1] = Sangle2;
+      data[2] = 0.0;
+      data[3] = 0.0;
 
     } else if (idx == eTht) {
-      Entry(1) = Cangle2;
-      Entry(2) = 0.0;
-      Entry(3) = Sangle2;
-      Entry(4) = 0.0;
+      data[0] = Cangle2;
+      data[1] = 0.0;
+      data[2] = Sangle2;
+      data[3] = 0.0;
 
     } else {
-      Entry(1) = Cangle2;
-      Entry(2) = 0.0;
-      Entry(3) = 0.0;
-      Entry(4) = Sangle2;
+      data[0] = Cangle2;
+      data[1] = 0.0;
+      data[2] = 0.0;
+      data[3] = Sangle2;
 
     }
   }
 
+  /** Initializer by matrix.
+      Initialize the quaternion with the matrix representing a transform from one frame
+      to another using the standard aerospace sequence, Yaw-Pitch-Roll (3-2-1).
+      @param m the rotation matrix */
+  FGQuaternion(const FGMatrix33& m);
+
   /// Destructor.
   ~FGQuaternion() {}
 
   /** Quaternion derivative for given angular rates.
       Computes the quaternion derivative which results from the given
       angular velocities
-      @param PQR a constant reference to the body rate vector
+      @param PQR a constant reference to a rotation rate vector
       @return the quaternion derivative
       @see Stevens and Lewis, "Aircraft Control and Simulation", Second Edition,
            Equation 1.3-36. */
-  FGQuaternion GetQDot(const FGColumnVector3& PQR) const;
+  FGQuaternion GetQDot(const FGColumnVector3& PQR);
 
   /** Transformation matrix.
       @return a reference to the transformation/rotation matrix
@@ -220,7 +231,7 @@ public:
 
       Note that the index given in the argument is unchecked.
    */
-  double operator()(unsigned int idx) const { return Entry(idx); }
+  double operator()(unsigned int idx) const { return data[idx-1]; }
 
   /** Write access the entries of the vector.
 
@@ -231,7 +242,7 @@ public:
 
       Note that the index given in the argument is unchecked.
    */
-  double& operator()(unsigned int idx) { return Entry(idx); }
+  double& operator()(unsigned int idx) { mCacheValid = false; return data[idx-1]; }
 
   /** Read access the entries of the vector.
 
@@ -246,7 +257,7 @@ public:
 
       Note that the index given in the argument is unchecked.
   */
-  double Entry(unsigned int idx) const { return mData[idx-1]; }
+  double Entry(unsigned int idx) const { return data[idx-1]; }
 
   /** Write access the entries of the vector.
 
@@ -261,7 +272,10 @@ public:
 
       Note that the index given in the argument is unchecked.
   */
-  double& Entry(unsigned int idx) { mCacheValid = false; return mData[idx-1]; }
+  double& Entry(unsigned int idx) {
+    mCacheValid = false;
+   return data[idx-1];
+  }
 
   /** Assignment operator "=".
       Assign the value of q to the current object. Cached values are
@@ -270,10 +284,11 @@ public:
       @return reference to a quaternion object  */
   const FGQuaternion& operator=(const FGQuaternion& q) {
     // Copy the master values ...
-    Entry(1) = q(1);
-    Entry(2) = q(2);
-    Entry(3) = q(3);
-    Entry(4) = q(4);
+    data[0] = q(1);
+    data[1] = q(2);
+    data[2] = q(3);
+    data[3] = q(4);
+    ComputeDerived();
     // .. and copy the derived values if they are valid
     mCacheValid = q.mCacheValid;
     if (mCacheValid) {
@@ -286,12 +301,15 @@ public:
     return *this;
   }
 
+  /// Conversion from Quat to Matrix
+  operator FGMatrix33() const { return GetT(); }
+
   /** Comparison operator "==".
       @param q a quaternion reference
       @return true if both quaternions represent the same rotation.  */
   bool operator==(const FGQuaternion& q) const {
-    return Entry(1) == q(1) && Entry(2) == q(2)
-      && Entry(3) == q(3) && Entry(4) == q(4);
+    return data[0] == q(1) && data[1] == q(2)
+      && data[2] == q(3) && data[3] == q(4);
   }
 
   /** Comparison operator "!=".
@@ -300,10 +318,10 @@ public:
   bool operator!=(const FGQuaternion& q) const { return ! operator==(q); }
   const FGQuaternion& operator+=(const FGQuaternion& q) {
     // Copy the master values ...
-    Entry(1) += q(1);
-    Entry(2) += q(2);
-    Entry(3) += q(3);
-    Entry(4) += q(4);
+    data[0] += q(1);
+    data[1] += q(2);
+    data[2] += q(3);
+    data[3] += q(4);
     mCacheValid = false;
     return *this;
   }
@@ -313,10 +331,10 @@ public:
       @return a quaternion reference representing Q, where Q = Q - q. */
   const FGQuaternion& operator-=(const FGQuaternion& q) {
     // Copy the master values ...
-    Entry(1) -= q(1);
-    Entry(2) -= q(2);
-    Entry(3) -= q(3);
-    Entry(4) -= q(4);
+    data[0] -= q(1);
+    data[1] -= q(2);
+    data[2] -= q(3);
+    data[3] -= q(4);
     mCacheValid = false;
     return *this;
   }
@@ -325,10 +343,10 @@ public:
       @param scalar a multiplicative value.
       @return a quaternion reference representing Q, where Q = Q * scalar. */
   const FGQuaternion& operator*=(double scalar) {
-    Entry(1) *= scalar;
-    Entry(2) *= scalar;
-    Entry(3) *= scalar;
-    Entry(4) *= scalar;
+    data[0] *= scalar;
+    data[1] *= scalar;
+    data[2] *= scalar;
+    data[3] *= scalar;
     mCacheValid = false;
     return *this;
   }
@@ -344,16 +362,16 @@ public:
       @param q a quaternion to be summed.
       @return a quaternion representing Q, where Q = Q + q. */
   FGQuaternion operator+(const FGQuaternion& q) const {
-    return FGQuaternion(Entry(1)+q(1), Entry(2)+q(2),
-                        Entry(3)+q(3), Entry(4)+q(4));
+    return FGQuaternion(data[0]+q(1), data[1]+q(2),
+                        data[2]+q(3), data[3]+q(4));
   }
 
   /** Arithmetic operator "-".
       @param q a quaternion to be subtracted.
       @return a quaternion representing Q, where Q = Q - q. */
   FGQuaternion operator-(const FGQuaternion& q) const {
-    return FGQuaternion(Entry(1)-q(1), Entry(2)-q(2),
-                        Entry(3)-q(3), Entry(4)-q(4));
+    return FGQuaternion(data[0]-q(1), data[1]-q(2),
+                        data[2]-q(3), data[3]-q(4));
   }
 
   /** Arithmetic operator "*".
@@ -361,10 +379,10 @@ public:
       @param q a quaternion to be multiplied.
       @return a quaternion representing Q, where Q = Q * q. */
   FGQuaternion operator*(const FGQuaternion& q) const {
-    return FGQuaternion(Entry(1)*q(1)-Entry(2)*q(2)-Entry(3)*q(3)-Entry(4)*q(4),
-                        Entry(1)*q(2)+Entry(2)*q(1)+Entry(3)*q(4)-Entry(4)*q(3),
-                        Entry(1)*q(3)-Entry(2)*q(4)+Entry(3)*q(1)+Entry(4)*q(2),
-                        Entry(1)*q(4)+Entry(2)*q(3)-Entry(3)*q(2)+Entry(4)*q(1));
+    return FGQuaternion(data[0]*q(1)-data[1]*q(2)-data[2]*q(3)-data[3]*q(4),
+                        data[0]*q(2)+data[1]*q(1)+data[2]*q(4)-data[3]*q(3),
+                        data[0]*q(3)-data[1]*q(4)+data[2]*q(1)+data[3]*q(2),
+                        data[0]*q(4)+data[1]*q(3)-data[2]*q(2)+data[3]*q(1));
   }
 
   /** Arithmetic operator "*=".
@@ -372,14 +390,14 @@ public:
       @param q a quaternion to be multiplied.
       @return a quaternion reference representing Q, where Q = Q * q. */
   const FGQuaternion& operator*=(const FGQuaternion& q) {
-    double q0 = Entry(1)*q(1)-Entry(2)*q(2)-Entry(3)*q(3)-Entry(4)*q(4);
-    double q1 = Entry(1)*q(2)+Entry(2)*q(1)+Entry(3)*q(4)-Entry(4)*q(3);
-    double q2 = Entry(1)*q(3)-Entry(2)*q(4)+Entry(3)*q(1)+Entry(4)*q(2);
-    double q3 = Entry(1)*q(4)+Entry(2)*q(3)-Entry(3)*q(2)+Entry(4)*q(1);
-    Entry(1) = q0;
-    Entry(2) = q1;
-    Entry(3) = q2;
-    Entry(4) = q3;
+    double q0 = data[0]*q(1)-data[1]*q(2)-data[2]*q(3)-data[3]*q(4);
+    double q1 = data[0]*q(2)+data[1]*q(1)+data[2]*q(4)-data[3]*q(3);
+    double q2 = data[0]*q(3)-data[1]*q(4)+data[2]*q(1)+data[3]*q(2);
+    double q3 = data[0]*q(4)+data[1]*q(3)-data[2]*q(2)+data[3]*q(1);
+    data[0] = q0;
+    data[1] = q1;
+    data[2] = q2;
+    data[3] = q3;
     mCacheValid = false;
     return *this;
   }
@@ -391,12 +409,12 @@ public:
       the identity orientation.
   */
   FGQuaternion Inverse(void) const {
-    double norm = Magnitude();
+    double norm = SqrMagnitude();
     if (norm == 0.0)
       return *this;
     double rNorm = 1.0/norm;
-    return FGQuaternion( Entry(1)*rNorm, -Entry(2)*rNorm,
-                         -Entry(3)*rNorm, -Entry(4)*rNorm );
+    return FGQuaternion( data[0]*rNorm, -data[1]*rNorm,
+                         -data[2]*rNorm, -data[3]*rNorm );
   }
 
   /** Conjugate of the quaternion.
@@ -405,7 +423,7 @@ public:
       to the inverse iff the quaternion is normalized.
   */
   FGQuaternion Conjugate(void) const {
-    return FGQuaternion( Entry(1), -Entry(2), -Entry(3), -Entry(4) );
+    return FGQuaternion( data[0], -data[1], -data[2], -data[3] );
   }
 
   friend FGQuaternion operator*(double, const FGQuaternion&);
@@ -421,11 +439,11 @@ public:
       Compute and return the square of the euclidean norm of this vector.
   */
   double SqrMagnitude(void) const {
-    return Entry(1)*Entry(1)+Entry(2)*Entry(2)
-      +Entry(3)*Entry(3)+Entry(4)*Entry(4);
+    return  data[0]*data[0] + data[1]*data[1]
+          + data[2]*data[2] + data[3]*data[3];
   }
 
-  /** Normialze.
+  /** Normalize.
 
       Normalize the vector to have the Magnitude() == 1.0. If the vector
       is equal to zero it is left untouched.
@@ -439,7 +457,7 @@ public:
 private:
   /** Copying by assigning the vector valued components.  */
   FGQuaternion(double q1, double q2, double q3, double q4) : mCacheValid(false)
-    { Entry(1) = q1; Entry(2) = q2; Entry(3) = q3; Entry(4) = q4; }
+    { data[0] = q1; data[1] = q2; data[2] = q3; data[3] = q4; }
 
   /** Computation of derived values.
       This function recomputes the derived values like euler angles and
@@ -450,16 +468,15 @@ private:
       This function checks if the derived values like euler angles and
       transformation matrices are already computed. If so, it
       returns. If they need to be computed the real worker routine
-      \ref FGQuaternion::ComputeDerivedUnconditional(void) const
-      is called.
-      This function is inlined to avoid function calls in the fast path. */
+      FGQuaternion::ComputeDerivedUnconditional(void) const
+      is called. */
   void ComputeDerived(void) const {
     if (!mCacheValid)
       ComputeDerivedUnconditional();
   }
 
   /** The quaternion values itself. This is the master copy. */
-  double mData[4];
+  double data[4];
 
   /** A data validity flag.
       This class implements caching of the derived values like the
@@ -479,6 +496,10 @@ private:
   /** The cached sines and cosines of the euler angles.  */
   mutable FGColumnVector3 mEulerSines;
   mutable FGColumnVector3 mEulerCosines;
+
+  void Debug(int from) const;
+
+  void InitializeFromEulerAngles(double phi, double tht, double psi);
 };
 
 /** Scalar multiplication.
@@ -494,4 +515,6 @@ inline FGQuaternion operator*(double scalar, const FGQuaternion& q) {
 
 } // namespace JSBSim
 
+#include "FGMatrix33.h"
+
 #endif
index 9d3deec3b4c60fac4ed1ab82f9685d391cc0757a..a30f9fccee4d4a21d464f86713b958cddcaae0e9 100755 (executable)
@@ -32,7 +32,7 @@ INCLUDES
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGRealValue.cpp,v 1.4 2009/08/30 03:51:28 jberndt Exp $";
 static const char *IdHdr = ID_REALVALUE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 626770c2616838ca117c28a5016564a7312c03eb..277c595c1b2f0a4aa8e0a3794b23c6a1a576d16b 100755 (executable)
@@ -40,7 +40,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_REALVALUE "$Id$"
+#define ID_REALVALUE "$Id: FGRealValue.h,v 1.4 2009/08/30 03:51:28 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index f19669191c00f8d8fe725fa0317106d218886d7e..2d604dca21aff37c0b315fa9b91dbbce2af94096 100644 (file)
@@ -47,7 +47,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGTable.cpp,v 1.21 2010/04/07 03:08:37 jberndt Exp $";
 static const char *IdHdr = ID_TABLE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -165,9 +165,7 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(prop
       node = PropertyManager->GetNode(property_string);
 
       if (node == 0) {
-        cerr << "IndependenVar property, " << property_string
-             << " in Table definition is not defined." << endl;
-        abort();
+        throw("IndependenVar property, " + property_string + " in Table definition is not defined.");
       }
 
       lookup_axis = axisElement->GetAttributeValue("lookup");
@@ -177,6 +175,8 @@ FGTable::FGTable(FGPropertyManager* propMan, Element* el) : PropertyManager(prop
         lookupProperty[eColumn] = node;
       } else if (lookup_axis == string("table")) {
         lookupProperty[eTable] = node;
+      } else if (!lookup_axis.empty()) {
+        throw("Lookup table axis specification not understood: " + lookup_axis);
       } else { // assumed single dimension table; row lookup
         lookupProperty[eRow] = node;
       }
index 1b0d22e16e5f4ca8cbb3c9d5ae48aadbbfc292f5..e96cf07fea67495d95fb4a47ece653055156ce6b 100644 (file)
@@ -47,7 +47,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_TABLE "$Id$"
+#define ID_TABLE "$Id: FGTable.h,v 1.11 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -233,7 +233,7 @@ combustion_efficiency = Lookup_Combustion_Efficiency->GetValue(equivalence_ratio
 @endcode
 
 @author Jon S. Berndt
-@version $Id$
+@version $Id: FGTable.h,v 1.11 2009/10/24 22:59:30 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index a793cce2f443df453b2cbc586688f02814c6b14c..d8c66df201305a18858220a6d5e635b3168ec251 100644 (file)
@@ -52,7 +52,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.31 2009/11/28 14:30:11 andgi Exp $";
 static const char *IdHdr = ID_AERODYNAMICS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 8c26e527729d5d35e10668e05b6abe992f58a361..0f966d8459b236f37d4abc46eb57ffca57f65de6 100644 (file)
@@ -52,7 +52,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_AERODYNAMICS "$Id$"
+#define ID_AERODYNAMICS "$Id: FGAerodynamics.h,v 1.20 2009/11/12 13:08:11 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -109,7 +109,7 @@ CLASS DOCUMENTATION
     Systems may NOT be combined, or a load error will occur.
 
     @author Jon S. Berndt, Tony Peden
-    @version $Revision$
+    @version $Revision: 1.20 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -214,7 +214,6 @@ private:
   typedef std::map<std::string,int> AxisIndex;
   AxisIndex AxisIdx;
   FGFunction* AeroRPShift;
-  std::vector <FGFunction*> variables;
   typedef vector <FGFunction*> CoeffArray;
   CoeffArray* Coeff;
   FGColumnVector3 vFnative;
index 75f9fba590b680eeb7b79a6273d8228e26fd2145..c71a787eb495eb1401ccf1ff5966196528acbe4d 100644 (file)
@@ -68,7 +68,7 @@ DEFINITIONS
 GLOBAL DATA
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGAircraft.cpp,v 1.26 2010/02/15 03:28:24 jberndt Exp $";
 static const char *IdHdr = ID_AIRCRAFT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -123,6 +123,9 @@ bool FGAircraft::Run(void)
     vForces += GroundReactions->GetForces();
     vForces += ExternalReactions->GetForces();
     vForces += BuoyantForces->GetForces();
+  } else {
+    const FGMatrix33& mTl2b = Propagate->GetTl2b();
+    vForces = mTl2b * FGColumnVector3(0,0,-MassBalance->GetWeight());
   }
 
   vMoments.InitMatrix();
index a66665c061c7df63305609752f7f9921dd983f7d..a03656895c1db137e2e88b2f8eabf10bd3b1d4b9 100644 (file)
@@ -49,7 +49,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_AIRCRAFT "$Id$"
+#define ID_AIRCRAFT "$Id: FGAircraft.h,v 1.15 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -90,7 +90,7 @@ CLASS DOCUMENTATION
 @endcode
 
     @author Jon S. Berndt
-    @version $Id$
+    @version $Id: FGAircraft.h,v 1.15 2009/10/24 22:59:30 jberndt Exp $
     @see Cooke, Zyda, Pratt, and McGhee, "NPSNET: Flight Simulation Dynamic Modeling
           Using Quaternions", Presence, Vol. 1, No. 4, pp. 404-420  Naval Postgraduate
           School, January 1994
index 8acb17c1b42056c7c112169b7023c5294727a8f8..60165892257ad41e0f4178c89c70501121e218f9 100644 (file)
@@ -48,11 +48,11 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGAtmosphere.h"
-#include "FGState.h"
-#include "FGFDMExec.h"
 #include "FGAircraft.h"
 #include "FGPropagate.h"
 #include "FGInertial.h"
+#include "FGAuxiliary.h"
+#include "FGFDMExec.h"
 #include "input_output/FGPropertyManager.h"
 #include <iostream>
 #include <cstdlib>
@@ -61,7 +61,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGAtmosphere.cpp,v 1.33 2010/02/25 05:21:36 jberndt Exp $";
 static const char *IdHdr = ID_ATMOSPHERE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -383,7 +383,7 @@ void FGAtmosphere::SetWindPsi(double dir)
 
 void FGAtmosphere::Turbulence(void)
 {
-  double DeltaT = rate*State->Getdt();
+  double DeltaT = rate*FDMExec->GetDeltaT();
 
   switch (turbType) {
   case ttStandard: {
index 2a7443e5d02c8557e3b9a142beffc9901a76f01b..84d3f072a33857c063152dc63f0315eddad232b9 100644 (file)
@@ -49,7 +49,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ATMOSPHERE "$Id$"
+#define ID_ATMOSPHERE "$Id: FGAtmosphere.h,v 1.22 2009/10/02 10:30:09 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -63,7 +63,7 @@ CLASS DOCUMENTATION
 
 /** Models the 1976 Standard Atmosphere.
     @author Tony Peden, Jon Berndt
-    @version $Id$
+    @version $Id: FGAtmosphere.h,v 1.22 2009/10/02 10:30:09 jberndt Exp $
     @see Anderson, John D. "Introduction to Flight, Third Edition", McGraw-Hill,
          1989, ISBN 0-07-001641-0
 */
index 815a1b400d09e0e0790f2ffc83b687c62743f2e8..13a8e67e760fa466ee47c0e351d7eeaccd06c3e2 100755 (executable)
@@ -59,7 +59,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.39 2010/07/09 12:06:11 jberndt Exp $";
 static const char *IdHdr = ID_AUXILIARY;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -249,11 +249,12 @@ bool FGAuxiliary::Run()
 
   vPilotAccel.InitMatrix();
   if ( Vt > 1.0 ) {
-     vAircraftAccel = Aerodynamics->GetForces()
-                    + Propulsion->GetForces()
-                    + GroundReactions->GetForces()
-                    + ExternalReactions->GetForces()
-                    + BuoyantForces->GetForces();
+     // Use the "+=" operator to avoid the creation of temporary objects.
+     vAircraftAccel = Aerodynamics->GetForces();
+     vAircraftAccel += Propulsion->GetForces();
+     vAircraftAccel += GroundReactions->GetForces();
+     vAircraftAccel += ExternalReactions->GetForces();
+     vAircraftAccel += BuoyantForces->GetForces();
 
      vAircraftAccel /= MassBalance->GetMass();
      // Nz is Acceleration in "g's", along normal axis (-Z body axis)
@@ -276,7 +277,7 @@ bool FGAuxiliary::Run()
 
   // VRP computation
   const FGLocation& vLocation = Propagate->GetLocation();
-  FGColumnVector3 vrpStructural = Aircraft->GetXYZvrp();
+  FGColumnVector3& vrpStructural = Aircraft->GetXYZvrp();
   FGColumnVector3 vrpBody = MassBalance->StructuralToBody( vrpStructural );
   FGColumnVector3 vrpLocal = Propagate->GetTb2l() * vrpBody;
   vLocationVRP = vLocation.LocalToLocation( vrpLocal );
index e3baa49117a8d1e64fe9741302d6b56009a1d370..d86cc5f11a05cc26e76e9cd145f0762654989109 100644 (file)
@@ -48,7 +48,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_AUXILIARY "$Id$"
+#define ID_AUXILIARY "$Id: FGAuxiliary.h,v 1.17 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -100,7 +100,7 @@ CLASS DOCUMENTATION
     The radius R is calculated below in the vector vToEyePt.
 
     @author Tony Peden, Jon Berndt
-    @version $Id$
+    @version $Id: FGAuxiliary.h,v 1.17 2009/10/24 22:59:30 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 49d9cb2e5069402f35c9db616e99debf5bd6a17f..64c97ebfb6f520f5cbc418e21f66bebda0601567 100644 (file)
@@ -5,7 +5,7 @@
  Date started: 01/21/08
  Purpose:      Encapsulates the buoyant forces
 
- ------------- Copyright (C) 2008 - 2009  Anders Gidenstam        -------------
+ ------------- Copyright (C) 2008 - 2010  Anders Gidenstam        -------------
  ------------- Copyright (C) 2008  Jon S. Berndt (jon@jsbsim.org) -------------
 
  This program is free software; you can redistribute it and/or modify it under
@@ -38,14 +38,14 @@ INCLUDES
 
 #include "FGBuoyantForces.h"
 #include "FGMassBalance.h"
-#include "input_output/FGPropertyManager.h"  // Need?
+#include "input_output/FGPropertyManager.h"
 #include <iostream>
 
 using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGBuoyantForces.cpp,v 1.12 2010/05/07 18:59:55 andgi Exp $";
 static const char *IdHdr = ID_BUOYANTFORCES;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -63,8 +63,6 @@ FGBuoyantForces::FGBuoyantForces(FGFDMExec* FDMExec) : FGModel(FDMExec)
 
   gasCellJ.InitMatrix();
 
-  bind();
-
   Debug(0);
 }
 
@@ -141,6 +139,10 @@ bool FGBuoyantForces::Load(Element *element)
   
   FGModel::PostLoad(element);
 
+  if (!NoneDefined) {
+    bind();
+  }
+
   return true;
 }
 
@@ -258,6 +260,19 @@ string FGBuoyantForces::GetBuoyancyValues(string delimeter)
 
 void FGBuoyantForces::bind(void)
 {
+  typedef double (FGBuoyantForces::*PMF)(int) const;
+  PropertyManager->Tie("moments/l-buoyancy-lbsft", this, eL,
+                       (PMF)&FGBuoyantForces::GetMoments);
+  PropertyManager->Tie("moments/m-buoyancy-lbsft", this, eM,
+                       (PMF)&FGBuoyantForces::GetMoments);
+  PropertyManager->Tie("moments/n-buoyancy-lbsft", this, eN,
+                       (PMF)&FGBuoyantForces::GetMoments);
+  PropertyManager->Tie("forces/fbx-buoyancy-lbs", this, eX,
+                       (PMF)&FGBuoyantForces::GetForces);
+  PropertyManager->Tie("forces/fby-buoyancy-lbs", this, eY,
+                       (PMF)&FGBuoyantForces::GetForces);
+  PropertyManager->Tie("forces/fbz-buoyancy-lbs", this, eZ,
+                       (PMF)&FGBuoyantForces::GetForces);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index ec664b3abde02c096869c8751da1a83b082129ed..c27566d3788546219e5761dfd28504e51415bc2c 100644 (file)
@@ -4,7 +4,7 @@
  Author:       Anders Gidenstam, Jon S. Berndt
  Date started: 01/21/08
 
- ------------- Copyright (C) 2008  Anders Gidenstam               -------------
+ ------------- Copyright (C) 2008 - 2010  Anders Gidenstam        -------------
  ------------- Copyright (C) 2008  Jon S. Berndt (jon@jsbsim.org) -------------
 
  This program is free software; you can redistribute it and/or modify it under
@@ -51,7 +51,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_BUOYANTFORCES "$Id$"
+#define ID_BUOYANTFORCES "$Id: FGBuoyantForces.h,v 1.11 2010/05/07 20:38:34 andgi Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -96,7 +96,7 @@ CLASS DOCUMENTATION
     See FGGasCell for the full configuration file format for gas cells.
 
     @author Anders Gidenstam, Jon S. Berndt
-    @version $Id$
+    @version $Id: FGBuoyantForces.h,v 1.11 2010/05/07 20:38:34 andgi Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -130,10 +130,18 @@ public:
       @return a force vector. */
   const FGColumnVector3& GetForces(void) const {return vTotalForces;}
 
+  /** Gets a component of the total Buoyant force vector.
+      @return a component of the force vector. */
+  double GetForces(int idx) const {return vTotalForces(idx);}
+
   /** Gets the total Buoyancy moment vector.
       @return a moment vector. */
   const FGColumnVector3& GetMoments(void) const {return vTotalMoments;}
 
+  /** Gets a component of the total Buoyancy moment vector.
+      @return a component of the moment vector. */
+  double GetMoments(int idx) const {return vTotalMoments(idx);}
+
   /** Gets the total gas mass. The gas mass is part of the aircraft's
       inertia.
       @return mass in slugs. */
index fa1d35d22fe90fc2dc07e9b7e08ee93ab0845195..12ade79e70ec8c9743780c6e875db758318612d1 100755 (executable)
@@ -60,7 +60,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGExternalForce.cpp,v 1.10 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_EXTERNALFORCE;
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index d4a90db83b2b1437f6ef57c3aed35b6774f8510f..f1a6a41ac73e40bd03543b59f366375e13df1453 100755 (executable)
@@ -51,7 +51,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_EXTERNALFORCE "$Id$"
+#define ID_EXTERNALFORCE "$Id: FGExternalForce.h,v 1.8 2009/10/02 10:30:09 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index a9b6ee2753b33f4c45331656e6c5ad2aad078d5a..7df087c1e3c576ac95f87bd2488ae592d45b3605 100755 (executable)
@@ -53,7 +53,7 @@ DEFINITIONS
 GLOBAL DATA
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGExternalReactions.cpp,v 1.8 2009/11/12 13:08:11 jberndt Exp $";
 static const char *IdHdr = ID_EXTERNALREACTIONS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index c6f65fe1048bcb6bb5423a38e563cadb8974070c..10ad35d07c62367462adc1c830a79c0350cb149e 100755 (executable)
@@ -46,7 +46,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_EXTERNALREACTIONS "$Id$"
+#define ID_EXTERNALREACTIONS "$Id: FGExternalReactions.h,v 1.9 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index 477890295478671424b026873c20664dfeb362fb..f5bbba07d885103ff29cb796df7993f3df08bd34 100644 (file)
@@ -63,7 +63,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGFCS.cpp,v 1.68 2010/03/18 13:21:24 jberndt Exp $";
 static const char *IdHdr = ID_FCS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -533,19 +533,17 @@ bool FGFCS::Load(Element* el, SystemType systype)
 
   Components=0;
 
-  string separator = "/";
-
 // ToDo: The handling of name and file attributes could be improved, here,
 //       considering that a name can be in the external file, as well.
 
   name = el->GetAttributeValue("name");
 
-  if (name.empty()) {
+  if (name.empty() || !el->GetAttributeValue("file").empty()) {
     fname = el->GetAttributeValue("file");
     if (systype == stSystem) {
       file = FindSystemFullPathname(fname);
     } else { 
-      file = FDMExec->GetFullAircraftPath() + separator + fname + ".xml";
+      file = FDMExec->GetFullAircraftPath() + "/" + fname + ".xml";
     }
     if (fname.empty()) {
       cerr << "FCS, Autopilot, or system does not appear to be defined inline nor in a file" << endl;
@@ -692,49 +690,55 @@ double FGFCS::GetBrake(FGLGear::BrakeGroup bg)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-string FGFCS::FindSystemFullPathname(const string& system_filename)
+string FGFCS::FindSystemFullPathname(const string& sysfilename)
 {
   string fullpath, localpath;
+  string system_filename = sysfilename;
   string systemPath = FDMExec->GetSystemsPath();
   string aircraftPath = FDMExec->GetFullAircraftPath();
   ifstream system_file;
 
-  string separator = "/";
+  fullpath = systemPath + "/";
+  localpath = aircraftPath + "/Systems/";
 
-  fullpath = systemPath + separator;
-  localpath = aircraftPath + separator + "Systems" + separator;
+  if (system_filename.length() <=4 || system_filename.substr(system_filename.length()-4, 4) != ".xml") {
+    system_filename.append(".xml");
+  }
 
-  system_file.open(string(fullpath + system_filename + ".xml").c_str());
+  system_file.open(string(fullpath + system_filename).c_str());
   if ( !system_file.is_open()) {
-    system_file.open(string(localpath + system_filename + ".xml").c_str());
+    system_file.open(string(localpath + system_filename).c_str());
       if ( !system_file.is_open()) {
         cerr << " Could not open system file: " << system_filename << " in path "
              << fullpath << " or " << localpath << endl;
         return string("");
       } else {
-        return string(localpath + system_filename + ".xml");
+        return string(localpath + system_filename);
       }
   }
-  return string(fullpath + system_filename + ".xml");
+  return string(fullpath + system_filename);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-ifstream* FGFCS::FindSystemFile(const string& system_filename)
+ifstream* FGFCS::FindSystemFile(const string& sysfilename)
 {
   string fullpath, localpath;
+  string system_filename = sysfilename;
   string systemPath = FDMExec->GetSystemsPath();
   string aircraftPath = FDMExec->GetFullAircraftPath();
   ifstream* system_file = new ifstream();
 
-  string separator = "/";
+  fullpath = systemPath + "/";
+  localpath = aircraftPath + "/Systems/";
 
-  fullpath = systemPath + separator;
-  localpath = aircraftPath + separator + "Systems" + separator;
+  if (system_filename.substr(system_filename.length()-4, 4) != ".xml") {
+    system_filename.append(".xml");
+  }
 
-  system_file->open(string(fullpath + system_filename + ".xml").c_str());
+  system_file->open(string(fullpath + system_filename).c_str());
   if ( !system_file->is_open()) {
-    system_file->open(string(localpath + system_filename + ".xml").c_str());
+    system_file->open(string(localpath + system_filename).c_str());
       if ( !system_file->is_open()) {
         cerr << " Could not open system file: " << system_filename << " in path "
              << fullpath << " or " << localpath << endl;
index b00c037a9ef447dc464406c084504b55a63d5c31..6e10de9c4340d27a28abe93386a8889542f2e4ad 100644 (file)
@@ -51,7 +51,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FCS "$Id$"
+#define ID_FCS "$Id: FGFCS.h,v 1.28 2010/01/18 13:12:25 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -168,7 +168,7 @@ CLASS DOCUMENTATION
     @property gear/tailhook-pos-norm
 
     @author Jon S. Berndt
-    @version $Revision$
+    @version $Revision: 1.28 $
     @see FGActuator
     @see FGDeadBand
     @see FGFCSFunction
@@ -407,12 +407,12 @@ public:
 
   /** Sets the throttle command for the specified engine
       @param engine engine ID number
-      @param cmd throttle command in percent (0 - 100)*/
+      @param cmd normalized throttle command (0.0 - 1.0)*/
   void SetThrottleCmd(int engine, double cmd);
 
   /** Sets the mixture command for the specified engine
       @param engine engine ID number
-      @param cmd mixture command in percent (0 - 100)*/
+      @param cmd normalized mixture command (0.0 - 1.0)*/
   void SetMixtureCmd(int engine, double cmd);
 
   /** Set the gear extend/retract command, defaults to down
@@ -462,12 +462,12 @@ public:
 
   /** Sets the actual throttle setting for the specified engine
       @param engine engine ID number
-      @param cmd throttle setting in percent (0 - 100)*/
+      @param cmd normalized throttle setting (0.0 - 1.0)*/
   void SetThrottlePos(int engine, double cmd);
 
   /** Sets the actual mixture setting for the specified engine
       @param engine engine ID number
-      @param cmd mixture setting in percent (0 - 100)*/
+      @param cmd normalized mixture setting (0.0 - 1.0)*/
   void SetMixturePos(int engine, double cmd);
 
   /** Sets the steering position
index 73c5091dd0659aeac38e140d005678291042206e..8edabcd9afe9935b4b2b005d209c07cdd1557881 100644 (file)
@@ -53,7 +53,7 @@ using std::max;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGGasCell.cpp,v 1.12 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_GASCELL;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 0aae911b1076033d7bd620f17c622dd20d3558b1..de34fb670aef7013f0baa4fa6481ce03b304a591 100644 (file)
@@ -50,7 +50,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_GASCELL "$Id$"
+#define ID_GASCELL "$Id: FGGasCell.h,v 1.10 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index c8afc723b711578848d01d2dd4b6cad3f31977d9..338e79f3868d2889d1a664fd47853348ab1777f8 100644 (file)
@@ -46,7 +46,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGGroundReactions.cpp,v 1.26 2009/11/12 13:08:11 jberndt Exp $";
 static const char *IdHdr = ID_GROUNDREACTIONS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index a5785d6ca72139060cf1daf39966e87169b8bb02..118815625bc3e96df1fed61fc75a145160a6cfdb 100644 (file)
@@ -45,7 +45,7 @@ INCLUDES
 #include "math/FGColumnVector3.h"
 #include "input_output/FGXMLElement.h"
 
-#define ID_GROUNDREACTIONS "$Id$"
+#define ID_GROUNDREACTIONS "$Id: FGGroundReactions.h,v 1.15 2009/10/02 10:30:09 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index 4ff657a51e8774471cab7986cd67374a10d56371..ab2670eb97700868ada2dc29b2ef43ad121e1157 100644 (file)
@@ -38,7 +38,6 @@ INCLUDES
 #include "FGInertial.h"
 #include "FGFDMExec.h"
 #include "FGPropagate.h"
-#include "FGState.h"
 #include "FGMassBalance.h"
 #include <iostream>
 
@@ -46,7 +45,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGInertial.cpp,v 1.18 2010/03/28 05:57:00 jberndt Exp $";
 static const char *IdHdr = ID_INERTIAL;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -119,7 +118,7 @@ bool FGInertial::Run(void)
   // Gravitation accel
   double r = Propagate->GetRadius();
   gAccel = GetGAccel(r);
-  earthPosAngle += State->Getdt()*RotationRate;
+  earthPosAngle += FDMExec->GetDeltaT()*RotationRate;
 
   RunPostFunctions();
 
@@ -133,6 +132,34 @@ double FGInertial::GetGAccel(double r) const
   return GM/(r*r);
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//
+// Calculate the WGS84 gravitation value in ECEF frame. Pass in the ECEF position
+// via the position parameter. The J2Gravity value returned is in ECEF frame,
+// and therefore may need to be expressed (transformed) in another frame,
+// depending on how it is used. See Stevens and Lewis eqn. 1.4-16.
+
+FGColumnVector3 FGInertial::GetGravityJ2(FGColumnVector3 position) const
+{
+  FGColumnVector3 J2Gravity;
+
+  // Gravitation accel
+  double r = position.Magnitude();
+  double lat = Propagate->GetLatitude();
+  double sinLat = sin(lat);
+
+  double preCommon = 1.5*J2*(a/r)*(a/r);
+  double xy = 1.0 - 5.0*(sinLat*sinLat);
+  double z = 3.0 - 5.0*(sinLat*sinLat);
+  double GMOverr2 = GM/(r*r);
+
+  J2Gravity(1) = -GMOverr2 * ((1.0 + (preCommon * xy)) * position(eX)/r);
+  J2Gravity(2) = -GMOverr2 * ((1.0 + (preCommon * xy)) * position(eY)/r);
+  J2Gravity(3) = -GMOverr2 * ((1.0 + (preCommon *  z)) * position(eZ)/r);
+
+  return J2Gravity;
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 void FGInertial::bind(void)
index cf457923636242ad26510d8eb416bcae13dfcc89..f4db378a2dc24da6060f7a18a416450a2ba3032e 100644 (file)
@@ -47,7 +47,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_INERTIAL "$Id$"
+#define ID_INERTIAL "$Id: FGInertial.h,v 1.15 2010/01/27 04:01:09 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -82,10 +82,13 @@ public:
   double GetEarthPositionAngle(void) const { return earthPosAngle; }
   double GetEarthPositionAngleDeg(void) const { return earthPosAngle*radtodeg;}
   double GetGAccel(double r) const;
+  FGColumnVector3 GetGravityJ2(FGColumnVector3 position) const;
   double GetRefRadius(void) const {return RadiusReference;}
   double GetSemimajor(void) const {return a;}
   double GetSemiminor(void) const {return b;}
 
+  void SetEarthPositionAngle(double epa) {earthPosAngle = epa;}
+
 private:
   double gAccel;
   double gAccelReference;
index dd124efa0937f74ddda21a65e130bfe87788a58e..c8cc13b83c3514e39f38489c71515d398ad114f3 100755 (executable)
@@ -39,7 +39,7 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGInput.h"
-#include "FGState.h"
+#include "FGAircraft.h"
 #include "FGFDMExec.h"
 
 #include "input_output/FGfdmSocket.h"
@@ -53,7 +53,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGInput.cpp,v 1.19 2010/02/25 05:21:36 jberndt Exp $";
 static const char *IdHdr = ID_INPUT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -192,7 +192,7 @@ bool FGInput::Run(void)
         info << "JSBSim version: " << JSBSim_version << endl;
         info << "Config File version: " << needed_cfg_version << endl;
         info << "Aircraft simulated: " << Aircraft->GetAircraftName() << endl;
-        info << "Simulation time: " << setw(8) << setprecision(3) << State->Getsim_time() << endl;
+        info << "Simulation time: " << setw(8) << setprecision(3) << FDMExec->GetSimTime() << endl;
         socket->Reply(info.str());
 
       } else if (command == "help") {                   // HELP
index 58aa9ebdbd4070fec76852900f1c93560c463abf..b86a428c6097d20c189cf8a585dbe840eb3b0f33 100755 (executable)
@@ -46,7 +46,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_INPUT "$Id$"
+#define ID_INPUT "$Id: FGInput.h,v 1.8 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index b0c448b41777baf98a5ff7375f6017505f067c27..18ece98d554ae940cf9045b2fbfe7caa20a3b37f 100644 (file)
@@ -41,7 +41,6 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGLGear.h"
-#include "FGState.h"
 #include "FGGroundReactions.h"
 #include "FGFCS.h"
 #include "FGAuxiliary.h"
@@ -62,7 +61,7 @@ DEFINITIONS
 GLOBAL DATA
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGLGear.cpp,v 1.74 2010/05/18 10:54:14 jberndt Exp $";
 static const char *IdHdr = ID_LGEAR;
 
 // Body To Structural (body frame is rotated 180 deg about Y and lengths are given in
@@ -76,7 +75,8 @@ CLASS IMPLEMENTATION
 FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) :
   FGForce(fdmex),
   GearNumber(number),
-  SteerAngle(0.0)
+  SteerAngle(0.0),
+  Castered(false)
 {
   Element *force_table=0;
   Element *dampCoeff=0;
@@ -202,7 +202,7 @@ FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) :
 
   if      (sSteerType == "STEERABLE") eSteerType = stSteer;
   else if (sSteerType == "FIXED"    ) eSteerType = stFixed;
-  else if (sSteerType == "CASTERED" ) eSteerType = stCaster;
+  else if (sSteerType == "CASTERED" ) {eSteerType = stCaster; Castered = true;}
   else if (sSteerType.empty()       ) {eSteerType = stFixed;
                                        sSteerType = "FIXED (defaulted)";}
   else {
@@ -223,15 +223,14 @@ FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) :
     }
   }
 
-  State       = fdmex->GetState();
   Aircraft    = fdmex->GetAircraft();
   Propagate   = fdmex->GetPropagate();
   Auxiliary   = fdmex->GetAuxiliary();
   FCS         = fdmex->GetFCS();
   MassBalance = fdmex->GetMassBalance();
 
-  LongForceLagFilterCoeff = 1/State->Getdt(); // default longitudinal force filter coefficient
-  LatForceLagFilterCoeff  = 1/State->Getdt(); // default lateral force filter coefficient
+  LongForceLagFilterCoeff = 1/fdmex->GetDeltaT(); // default longitudinal force filter coefficient
+  LatForceLagFilterCoeff  = 1/fdmex->GetDeltaT(); // default lateral force filter coefficient
 
   Element* force_lag_filter_elem = el->FindElement("force_lag_filter");
   if (force_lag_filter_elem) {
@@ -243,17 +242,17 @@ FGLGear::FGLGear(Element* el, FGFDMExec* fdmex, int number) :
     }
   }
 
-  LongForceFilter = Filter(LongForceLagFilterCoeff, State->Getdt());
-  LatForceFilter = Filter(LatForceLagFilterCoeff, State->Getdt());
+  LongForceFilter = Filter(LongForceLagFilterCoeff, fdmex->GetDeltaT());
+  LatForceFilter = Filter(LatForceLagFilterCoeff, fdmex->GetDeltaT());
 
-  WheelSlipLagFilterCoeff = 1/State->Getdt();
+  WheelSlipLagFilterCoeff = 1/fdmex->GetDeltaT();
 
   Element *wheel_slip_angle_lag_elem = el->FindElement("wheel_slip_filter");
   if (wheel_slip_angle_lag_elem) {
     WheelSlipLagFilterCoeff = wheel_slip_angle_lag_elem->GetDataAsNumber();
   }
   
-  WheelSlipFilter = Filter(WheelSlipLagFilterCoeff, State->Getdt());
+  WheelSlipFilter = Filter(WheelSlipLagFilterCoeff, fdmex->GetDeltaT());
 
   GearUp = false;
   GearDown = true;
@@ -307,8 +306,8 @@ FGLGear::~FGLGear()
 
 FGColumnVector3& FGLGear::GetBodyForces(void)
 {
-  double t = fdmex->GetState()->Getsim_time();
-  dT = State->Getdt()*fdmex->GetGroundReactions()->GetRate();
+  double t = fdmex->GetSimTime();
+  dT = fdmex->GetDeltaT()*fdmex->GetGroundReactions()->GetRate();
 
   vFn.InitMatrix();
 
@@ -324,7 +323,7 @@ FGColumnVector3& FGLGear::GetBodyForces(void)
     // Compute the height of the theoretical location of the wheel (if strut is not compressed) with
     // respect to the ground level
     double height = fdmex->GetGroundCallback()->GetAGLevel(t, gearLoc, contact, normal, cvel);
-    vGroundNormal = -1. * Propagate->GetTec2b() * normal;
+    vGroundNormal = Propagate->GetTec2b() * normal;
 
     // The height returned above is the AGL and is expressed in the Z direction of the local
     // coordinate frame. We now need to transform this height in actual compression of the strut (BOGEY)
@@ -335,7 +334,7 @@ FGColumnVector3& FGLGear::GetBodyForces(void)
       compressLength = verticalZProj > 0.0 ? -height / verticalZProj : 0.0;
       break;
     case ctSTRUCTURE:
-      verticalZProj = (Propagate->GetTec2l()*normal)(eZ);
+      verticalZProj = -(Propagate->GetTec2l()*normal)(eZ);
       compressLength = fabs(verticalZProj) > 0.0 ? -height / verticalZProj : 0.0;
       break;
     }
@@ -516,7 +515,13 @@ void FGLGear::ComputeSteeringAngle(void)
     SteerAngle = 0.0;
     break;
   case stCaster:
-    SteerAngle = atan2(vWhlVelVec(eY), fabs(vWhlVelVec(eX)));
+    if (!Castered)
+      SteerAngle = degtorad * FCS->GetSteerPosDeg(GearNumber);
+    else {
+      // Check that the speed is non-null otherwise use the current angle
+      if (vWhlVelVec.Magnitude(eX,eY) > 1E-3)
+        SteerAngle = atan2(vWhlVelVec(eY), fabs(vWhlVelVec(eX)));
+    }
     break;
   default:
     cerr << "Improper steering type membership detected for this gear." << endl;
@@ -571,7 +576,7 @@ void FGLGear::InitializeReporting(void)
 
 void FGLGear::ReportTakeoffOrLanding(void)
 {
-  double deltaT = State->Getdt()*fdmex->GetGroundReactions()->GetRate();
+  double deltaT = fdmex->GetDeltaT()*fdmex->GetGroundReactions()->GetRate();
 
   if (FirstContact)
     LandingDistanceTraveled += Auxiliary->GetVground()*deltaT;
@@ -608,10 +613,10 @@ void FGLGear::CrashDetect(void)
   if ( (compressLength > 500.0 ||
       vFn.Magnitude() > 100000000.0 ||
       GetMoments().Magnitude() > 5000000000.0 ||
-      SinkRate > 1.4666*30 ) && !State->IntegrationSuspended())
+      SinkRate > 1.4666*30 ) && !fdmex->IntegrationSuspended())
   {
     PutMessage("Crash Detected: Simulation FREEZE.");
-    State->SuspendIntegration();
+    fdmex->SuspendIntegration();
   }
 }
 
@@ -760,8 +765,10 @@ void FGLGear::bind(void)
     fdmex->GetPropertyManager()->Tie( property_name.c_str(), &staticFCoeff );
 
     if (eSteerType == stCaster) {
-      property_name = base_property_name + "/steering-angle-rad";
-      fdmex->GetPropertyManager()->Tie( property_name.c_str(), &SteerAngle );
+      property_name = base_property_name + "/steering-angle-deg";
+      fdmex->GetPropertyManager()->Tie( property_name.c_str(), this, &FGLGear::GetSteerAngleDeg );
+      property_name = base_property_name + "/castered";
+      fdmex->GetPropertyManager()->Tie( property_name.c_str(), &Castered);
     }
   }
 
@@ -780,7 +787,7 @@ void FGLGear::Report(ReportType repType)
   switch(repType) {
   case erLand:
     cout << endl << "Touchdown report for " << name << " (WOW at time: "
-         << fdmex->GetState()->Getsim_time() << " seconds)" << endl;
+         << fdmex->GetSimTime() << " seconds)" << endl;
     cout << "  Sink rate at contact:  " << SinkRate                << " fps,    "
                                 << SinkRate*0.3048          << " mps"     << endl;
     cout << "  Contact ground speed:  " << GroundSpeed*.5925       << " knots,  "
@@ -795,7 +802,7 @@ void FGLGear::Report(ReportType repType)
     break;
   case erTakeoff:
     cout << endl << "Takeoff report for " << name << " (Liftoff at time: "
-         << fdmex->GetState()->Getsim_time() << " seconds)" << endl;
+        << fdmex->GetSimTime() << " seconds)" << endl;
     cout << "  Distance traveled:                " << TakeoffDistanceTraveled
          << " ft,     " << TakeoffDistanceTraveled*0.3048  << " meters"  << endl;
     cout << "  Distance traveled (over 50'):     " << TakeoffDistanceTraveled50ft
index 9b86b68794d174fb5565ca324d979b4caaf85d7a..c3734f914ea06a5e3a57af3aae019ba3307f8eb3 100644 (file)
@@ -46,7 +46,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_LGEAR "$Id$"
+#define ID_LGEAR "$Id: FGLGear.h,v 1.38 2010/03/23 22:44:36 andgi Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -84,7 +84,6 @@ CLASS DOCUMENTATION
     <h3>Operational Properties</h3>
     <ol>
     <li>Name</li>
-    <li>Steerability attribute {one of STEERABLE | FIXED | CASTERED}</li>
     <li>Brake Group Membership {one of LEFT | CENTER | RIGHT | NOSE | TAIL | NONE}</li>
     <li>Max Steer Angle, in degrees</li>
     </ol></p>
@@ -190,7 +189,7 @@ CLASS DOCUMENTATION
         </contact>
 @endcode
     @author Jon S. Berndt
-    @version $Id$
+    @version $Id: FGLGear.h,v 1.38 2010/03/23 22:44:36 andgi Exp $
     @see Richard E. McFarland, "A Standard Kinematic Model for Flight Simulation at
      NASA-Ames", NASA CR-2497, January 1975
     @see Barnes W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics",
@@ -289,6 +288,7 @@ public:
   double GetWheelVel(int axis) const   { return vWhlVelVec(axis);}
   bool IsBogey(void) const             { return (eContactType == ctBOGEY);}
   double GetGearUnitPos(void);
+  double GetSteerAngleDeg(void) const { return radtodeg*SteerAngle; }
 
   void bind(void);
 
@@ -337,6 +337,7 @@ private:
   bool isRetractable;
   bool GearUp, GearDown;
   bool Servicable;
+  bool Castered;
   std::string name;
   std::string sSteerType;
   std::string sBrakeGroup;
index 7b6752a3ea7e00e4a58bed237f28d3cbe419187b..24727547c322775d0e2b469e2d0cec7f51ae6761 100644 (file)
@@ -40,16 +40,18 @@ INCLUDES
 
 #include "FGMassBalance.h"
 #include "FGPropulsion.h"
+#include "propulsion/FGTank.h"
 #include "FGBuoyantForces.h"
 #include "input_output/FGPropertyManager.h"
 #include <iostream>
+#include <iomanip>
 #include <cstdlib>
 
 using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGMassBalance.cpp,v 1.31 2010/02/19 00:30:00 jberndt Exp $";
 static const char *IdHdr = ID_MASSBALANCE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -124,7 +126,9 @@ bool FGMassBalance::Load(Element* el)
   SetAircraftBaseInertias(FGMatrix33(  bixx,  -bixy,  bixz,
                                       -bixy,  biyy,  -biyz,
                                        bixz,  -biyz,  bizz ));
-  EmptyWeight = el->FindElementValueAsNumberConvertTo("emptywt", "LBS");
+  if (el->FindElement("emptywt")) {
+    EmptyWeight = el->FindElementValueAsNumberConvertTo("emptywt", "LBS");
+  }
 
   element = el->FindElement("location");
   while (element) {
@@ -241,6 +245,7 @@ bool FGMassBalance::Run(void)
 
 void FGMassBalance::AddPointMass(Element* el)
 {
+  double radius=0, length=0;
   Element* loc_element = el->FindElement("location");
   string pointmass_name = el->GetAttributeValue("name");
   if (!loc_element) {
@@ -251,8 +256,36 @@ void FGMassBalance::AddPointMass(Element* el)
   double w = el->FindElementValueAsNumberConvertTo("weight", "LBS");
   FGColumnVector3 vXYZ = loc_element->FindElementTripletConvertTo("IN");
 
-  PointMasses.push_back(new PointMass(w, vXYZ));
-  PointMasses.back()->bind(PropertyManager, PointMasses.size()-1);
+  PointMass *pm = new PointMass(w, vXYZ);
+  pm->SetName(pointmass_name);
+
+  Element* form_element = el->FindElement("form");
+  if (form_element) {
+    string shape = form_element->GetAttributeValue("shape");
+    Element* radius_element = form_element->FindElement("radius");
+    Element* length_element = form_element->FindElement("length");
+    if (radius_element) radius = form_element->FindElementValueAsNumberConvertTo("radius", "FT");
+    if (length_element) length = form_element->FindElementValueAsNumberConvertTo("length", "FT");
+    if (shape == "tube") {
+      pm->SetPointMassShapeType(PointMass::esTube);
+      pm->SetRadius(radius);
+      pm->SetLength(length);
+      pm->CalculateShapeInertia();
+    } else if (shape == "cylinder") {
+      pm->SetPointMassShapeType(PointMass::esCylinder);
+      pm->SetRadius(radius);
+      pm->SetLength(length);
+      pm->CalculateShapeInertia();
+    } else if (shape == "sphere") {
+      pm->SetPointMassShapeType(PointMass::esSphere);
+      pm->SetRadius(radius);
+      pm->CalculateShapeInertia();
+    } else {
+    }
+  }
+
+  pm->bind(PropertyManager, PointMasses.size());
+  PointMasses.push_back(pm);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -290,8 +323,10 @@ FGMatrix33& FGMassBalance::CalculatePMInertias(void)
 
   pmJ = FGMatrix33();
 
-  for (unsigned int i=0; i<size; i++)
+  for (unsigned int i=0; i<size; i++) {
     pmJ += GetPointmassInertia( lbtoslug * PointMasses[i]->Weight, PointMasses[i]->Location );
+    pmJ += PointMasses[i]->GetPointMassInertia();
+  }
 
   return pmJ;
 }
@@ -339,7 +374,7 @@ void FGMassBalance::bind(void)
   PropertyManager->Tie("inertia/weight-lbs", this,
                        &FGMassBalance::GetWeight);
   PropertyManager->Tie("inertia/empty-weight-lbs", this,
-    &FGMassBalance::GetWeight, &FGMassBalance::SetEmptyWeight);
+                       &FGMassBalance::GetEmptyWeight);
   PropertyManager->Tie("inertia/cg-x-in", this,1,
                        (PMF)&FGMassBalance::GetXYZcg);
   PropertyManager->Tie("inertia/cg-y-in", this,2,
@@ -349,7 +384,9 @@ void FGMassBalance::bind(void)
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
+//
+// This function binds properties for each pointmass object created.
+//
 void FGMassBalance::PointMass::bind(FGPropertyManager* PropertyManager, int num) {
   string tmp = CreateIndexedPropertyName("inertia/pointmass-weight-lbs", num);
   PropertyManager->Tie( tmp.c_str(), this, &PointMass::GetPointMassWeight,
@@ -366,6 +403,63 @@ void FGMassBalance::PointMass::bind(FGPropertyManager* PropertyManager, int num)
                                            &PointMass::SetPointMassLocation);
 }
 
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGMassBalance::GetMassPropertiesReport(void) const
+{
+  cout << endl << fgblue << highint 
+       << "  Mass Properties Report (English units: lbf, in, slug-ft^2)"
+       << reset << endl;
+  cout << "                                  " << underon << "    Weight    CG-X    CG-Y"
+       << "    CG-Z         Ixx         Iyy         Izz" << underoff << endl;
+  cout.precision(1);
+  cout << highint << setw(34) << left << "    Base Vehicle " << normint
+       << right << setw(10) << EmptyWeight << setw(8) << vbaseXYZcg(eX) << setw(8)
+       << vbaseXYZcg(eY) << setw(8) << vbaseXYZcg(eZ) << setw(12) << baseJ(1,1)
+       << setw(12) << baseJ(2,2) << setw(12) << baseJ(3,3) << endl;
+
+  for (unsigned int i=0;i<PointMasses.size();i++) {
+    PointMass* pm = PointMasses[i];
+    double pmweight = pm->GetPointMassWeight();
+    cout << highint << left << setw(4) << i << setw(30) << pm->GetName() << normint
+         << right << setw(10) << pmweight << setw(8) << pm->GetLocation()(eX)
+         << setw(8) << pm->GetLocation()(eY) << setw(8) << pm->GetLocation()(eZ)
+         << setw(12) << pm->GetPointMassMoI(1,1) << setw(12) << pm->GetPointMassMoI(2,2)
+         << setw(12) << pm->GetPointMassMoI(3,3) << endl;
+  }
+
+  for (unsigned int i=0;i<Propulsion->GetNumTanks() ;i++) {
+    FGTank* tank = Propulsion->GetTank(i);
+    string tankname="";
+    if (tank->GetType() == FGTank::ttFUEL && tank->GetGrainType() != FGTank::gtUNKNOWN) {
+      tankname = "Solid Fuel";
+    } else if (tank->GetType() == FGTank::ttFUEL) {
+      tankname = "Fuel";
+    } else if (tank->GetType() == FGTank::ttOXIDIZER) {
+      tankname = "Oxidizer";
+    } else {
+      tankname = "(Unknown tank type)";
+    }
+    cout << highint << left << setw(4) << i << setw(30) << tankname << normint
+      << right << setw(10) << tank->GetContents() << setw(8) << tank->GetXYZ(eX)
+         << setw(8) << tank->GetXYZ(eY) << setw(8) << tank->GetXYZ(eZ)
+         << setw(12) << "*" << setw(12) << "*"
+         << setw(12) << "*" << endl;
+  }
+
+  cout << underon << setw(104) << " " << underoff << endl;
+  cout << highint << left << setw(30) << "    Total: " << right << setw(14) << Weight 
+       << setw(8) << vXYZcg(eX)
+       << setw(8) << vXYZcg(eY)
+       << setw(8) << vXYZcg(eZ)
+       << setw(12) << mJ(1,1)
+       << setw(12) << mJ(2,2)
+       << setw(12) << mJ(3,3)
+       << normint << endl;
+
+  cout.setf(ios_base::fixed);
+}
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 //    The bitmasked value choices are as follows:
 //    unset: In this case (the default) JSBSim would only print
@@ -398,7 +492,7 @@ void FGMassBalance::Debug(int from)
       cout << "    baseIxy: " << baseJ(1,2) << " slug-ft2" << endl;
       cout << "    baseIxz: " << baseJ(1,3) << " slug-ft2" << endl;
       cout << "    baseIyz: " << baseJ(2,3) << " slug-ft2" << endl;
-      cout << "    EmptyWeight: " << EmptyWeight << " lbm" << endl;
+      cout << "    Empty Weight: " << EmptyWeight << " lbm" << endl;
       cout << "    CG (x, y, z): " << vbaseXYZcg << endl;
       // ToDo: Need to add point mass outputs here
       for (unsigned int i=0; i<PointMasses.size(); i++) {
index 686b27b74de18571702f571dee6ba07d81ff489d..c49fe2904ec0e4dfa338aca4e9f20763b98fb99f 100644 (file)
@@ -43,17 +43,20 @@ INCLUDES
 #include "math/FGMatrix33.h"
 #include "input_output/FGXMLElement.h"
 #include <vector>
+#include <string>
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_MASSBALANCE "$Id$"
+#define ID_MASSBALANCE "$Id: FGMassBalance.h,v 1.20 2010/02/04 13:09:26 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONSS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
+using std::string;
+
 namespace JSBSim {
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -109,9 +112,10 @@ public:
 
   double GetMass(void) const {return Mass;}
   double GetWeight(void) const {return Weight;}
-  FGColumnVector3& GetXYZcg(void) {return vXYZcg;}
+  double GetEmptyWeight(void) const {return EmptyWeight;}
+  const FGColumnVector3& GetXYZcg(void) const {return vXYZcg;}
   double GetXYZcg(int axis) const  {return vXYZcg(axis);}
-  FGColumnVector3& GetDeltaXYZcg(void) {return vDeltaXYZcg;}
+  const FGColumnVector3& GetDeltaXYZcg(void) const {return vDeltaXYZcg;}
   double GetDeltaXYZcg(int axis) const  {return vDeltaXYZcg(axis);}
 
   /** Computes the inertia contribution of a pointmass.
@@ -158,6 +162,7 @@ public:
   FGMatrix33& GetJ(void) {return mJ;}
   FGMatrix33& GetJinv(void) {return mJinv;}
   void SetAircraftBaseInertias(FGMatrix33 BaseJ) {baseJ = BaseJ;}
+  void GetMassPropertiesReport(void) const;
   
 private:
   double Weight;
@@ -177,17 +182,57 @@ private:
   FGColumnVector3 PointMassCG;
   FGMatrix33& CalculatePMInertias(void);
 
+
+  /** The PointMass structure encapsulates a point mass object, moments of inertia
+     mass, location, etc. */
   struct PointMass {
     PointMass(double w, FGColumnVector3& vXYZ) {
       Weight = w;
       Location = vXYZ;
+      mPMInertia.InitMatrix();
+      Radius = 0.0;
+      Length = 0.0;
     }
+
+    void CalculateShapeInertia(void) {
+      switch(eShapeType) {
+        case esTube:
+          mPMInertia(1,1) = (Weight/(32.16))*Radius*Radius; // mr^2
+          mPMInertia(2,2) = (Weight/(32.16*12))*(6*Radius*Radius + Length*Length);
+          mPMInertia(3,3) = mPMInertia(2,2);
+          break;
+        case esCylinder:
+          mPMInertia(1,1) = (Weight/(32.16*2))*Radius*Radius; // 0.5*mr^2
+          mPMInertia(2,2) = (Weight/(32.16*12))*(3*Radius*Radius + Length*Length);
+          mPMInertia(3,3) = mPMInertia(2,2);
+          break;
+        default:
+          break;
+      }
+    }
+
+    enum esShape {esUnspecified, esTube, esCylinder, esSphere} eShapeType;
     FGColumnVector3 Location;
-    double Weight;
+    double Weight; /// Weight in pounds.
+    double Radius; /// Radius in feet.
+    double Length; /// Length in feet.
+    string Name;
+    FGMatrix33 mPMInertia;
+
     double GetPointMassLocation(int axis) const {return Location(axis);}
+    double GetPointMassWeight(void) const {return Weight;}
+    esShape GetShapeType(void) {return eShapeType;}
+    FGColumnVector3 GetLocation(void) {return Location;}
+    FGMatrix33 GetPointMassInertia(void) {return mPMInertia;}
+    string GetName(void) {return Name;}
+
     void SetPointMassLocation(int axis, double value) {Location(axis) = value;}
     void SetPointMassWeight(double wt) {Weight = wt;}
-    double GetPointMassWeight(void) const {return Weight;}
+    void SetPointMassShapeType(esShape st) {eShapeType = st;}
+    void SetRadius(double r) {Radius = r;}
+    void SetLength(double l) {Length = l;}
+    void SetName(string name) {Name = name;}
+    double GetPointMassMoI(int r, int c) {return mPMInertia(r,c);}
 
     void bind(FGPropertyManager* PropertyManager, int num);
   };
index 2e2b8357e5bf70efe6a5e32039a675f22f3414f7..cd9a7eabbdb31f9268a9db0290e42c78d5861a43 100644 (file)
@@ -39,7 +39,6 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGModel.h"
-#include "FGState.h"
 #include "FGFDMExec.h"
 #include "FGAtmosphere.h"
 #include "FGFCS.h"
@@ -58,7 +57,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGModel.cpp,v 1.14 2010/02/25 05:21:36 jberndt Exp $";
 static const char *IdHdr = ID_MODEL;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -74,7 +73,6 @@ FGModel::FGModel(FGFDMExec* fdmex)
   FDMExec     = fdmex;
   NextModel   = 0L;
 
-  State           = 0;
   Atmosphere      = 0;
   FCS             = 0;
   Propulsion      = 0;
@@ -115,7 +113,6 @@ FGModel::~FGModel()
 
 bool FGModel::InitModel(void)
 {
-  State           = FDMExec->GetState();
   Atmosphere      = FDMExec->GetAtmosphere();
   FCS             = FDMExec->GetFCS();
   Propulsion      = FDMExec->GetPropulsion();
@@ -129,8 +126,7 @@ bool FGModel::InitModel(void)
   Propagate       = FDMExec->GetPropagate();
   Auxiliary       = FDMExec->GetAuxiliary();
 
-  if (!State ||
-      !Atmosphere ||
+  if (!Atmosphere ||
       !FCS ||
       !Propulsion ||
       !MassBalance ||
index 5907328f9e0514249f512ca8619ec8f65866be0c..5f3ac94897d95eac1f738d1f65b5e44820b49ea2 100644 (file)
@@ -48,7 +48,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_MODEL "$Id$"
+#define ID_MODEL "$Id: FGModel.h,v 1.14 2009/11/12 13:08:11 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index e358ce0285a9340136f19142254bda24606a80f5..a974915f4cfd72106cdd10f8810ae7dca7810d07 100644 (file)
@@ -40,7 +40,6 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGOutput.h"
-#include "FGState.h"
 #include "FGFDMExec.h"
 #include "FGAtmosphere.h"
 #include "FGFCS.h"
@@ -53,6 +52,7 @@ INCLUDES
 #include "FGPropagate.h"
 #include "FGAuxiliary.h"
 #include "FGInertial.h"
+#include "FGPropulsion.h"
 #include "models/propulsion/FGEngine.h"
 #include "models/propulsion/FGTank.h"
 #include "models/propulsion/FGPiston.h"
@@ -77,7 +77,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGOutput.cpp,v 1.48 2010/04/12 12:25:19 jberndt Exp $";
 static const char *IdHdr = ID_OUTPUT;
 
 // (stolen from FGFS native_fdm.cxx)
@@ -187,7 +187,7 @@ bool FGOutput::Run(void)
 {
   if (FGModel::Run()) return true;
 
-  if (enabled && !State->IntegrationSuspended()&& !FDMExec->Holding()) {
+  if (enabled && !FDMExec->IntegrationSuspended()&& !FDMExec->Holding()) {
     RunPreFunctions();
     if (Type == otSocket) {
       SocketOutput();
@@ -267,7 +267,8 @@ void FGOutput::DelimitedOutput(const string& fname)
     if (SubSystems & ssRates) {
       outstream << delimeter;
       outstream << "P (deg/s)" + delimeter + "Q (deg/s)" + delimeter + "R (deg/s)" + delimeter;
-      outstream << "P dot (deg/s^2)" + delimeter + "Q dot (deg/s^2)" + delimeter + "R dot (deg/s^2)";
+      outstream << "P dot (deg/s^2)" + delimeter + "Q dot (deg/s^2)" + delimeter + "R dot (deg/s^2)" + delimeter;
+      outstream << "P_{inertial} (deg/s)" + delimeter + "Q_{inertial} (deg/s)" + delimeter + "R_{inertial} (deg/s)";
     }
     if (SubSystems & ssVelocities) {
       outstream << delimeter;
@@ -277,6 +278,7 @@ void FGOutput::DelimitedOutput(const string& fname)
       outstream << "V_{Inertial} (ft/s)" + delimeter;
       outstream << "UBody" + delimeter + "VBody" + delimeter + "WBody" + delimeter;
       outstream << "Aero V_{X Body} (ft/s)" + delimeter + "Aero V_{Y Body} (ft/s)" + delimeter + "Aero V_{Z Body} (ft/s)" + delimeter;
+      outstream << "V_{X_{inertial}} (ft/s)" + delimeter + "V_{Y_{inertial}} (ft/s)" + delimeter + "V_{Z_{inertial}} (ft/s)" + delimeter;
       outstream << "V_{North} (ft/s)" + delimeter + "V_{East} (ft/s)" + delimeter + "V_{Down} (ft/s)";
     }
     if (SubSystems & ssForces) {
@@ -334,8 +336,9 @@ void FGOutput::DelimitedOutput(const string& fname)
       outstream << "Beta (deg)" + delimeter;
       outstream << "Latitude (deg)" + delimeter;
       outstream << "Longitude (deg)" + delimeter;
-      outstream << "ECEF X (ft)" + delimeter + "ECEF Y (ft)" + delimeter + "ECEF Z (ft)" + delimeter;
-      outstream << "EPA (deg)" + delimeter;
+      outstream << "X_{ECI} (ft)" + delimeter + "Y_{ECI} (ft)" + delimeter + "Z_{ECI} (ft)" + delimeter;
+      outstream << "X_{ECEF} (ft)" + delimeter + "Y_{ECEF} (ft)" + delimeter + "Z_{ECEF} (ft)" + delimeter;
+      outstream << "Earth Position Angle (deg)" + delimeter;
       outstream << "Distance AGL (ft)" + delimeter;
       outstream << "Terrain Elevation (ft)";
     }
@@ -365,7 +368,7 @@ void FGOutput::DelimitedOutput(const string& fname)
     dFirstPass = false;
   }
 
-  outstream << State->Getsim_time();
+  outstream << FDMExec->GetSimTime();
   if (SubSystems & ssSimulation) {
   }
   if (SubSystems & ssAerosurfaces) {
@@ -383,7 +386,8 @@ void FGOutput::DelimitedOutput(const string& fname)
   if (SubSystems & ssRates) {
     outstream << delimeter;
     outstream << (radtodeg*Propagate->GetPQR()).Dump(delimeter) << delimeter;
-    outstream << (radtodeg*Propagate->GetPQRdot()).Dump(delimeter);
+    outstream << (radtodeg*Propagate->GetPQRdot()).Dump(delimeter) << delimeter;
+    outstream << (radtodeg*Propagate->GetPQRi()).Dump(delimeter);
   }
   if (SubSystems & ssVelocities) {
     outstream << delimeter;
@@ -393,6 +397,7 @@ void FGOutput::DelimitedOutput(const string& fname)
     outstream << Propagate->GetInertialVelocityMagnitude() << delimeter;
     outstream << setprecision(12) << Propagate->GetUVW().Dump(delimeter) << delimeter;
     outstream << Auxiliary->GetAeroUVW().Dump(delimeter) << delimeter;
+    outstream << Propagate->GetInertialVelocity().Dump(delimeter) << delimeter;
     outstream << Propagate->GetVel().Dump(delimeter);
     outstream.precision(10);
   }
@@ -445,6 +450,7 @@ void FGOutput::DelimitedOutput(const string& fname)
     outstream << Propagate->GetLocation().GetLatitudeDeg() << delimeter;
     outstream << Propagate->GetLocation().GetLongitudeDeg() << delimeter;
     outstream.precision(18);
+    outstream << ((FGColumnVector3)Propagate->GetInertialPosition()).Dump(delimeter) << delimeter;
     outstream << ((FGColumnVector3)Propagate->GetLocation()).Dump(delimeter) << delimeter;
     outstream.precision(14);
     outstream << Inertial->GetEarthPositionAngleDeg() << delimeter;
@@ -817,7 +823,7 @@ void FGOutput::SocketOutput(void)
   }
 
   socket->Clear();
-  socket->Append(State->Getsim_time());
+  socket->Append(FDMExec->GetSimTime());
 
   if (SubSystems & ssAerosurfaces) {
     socket->Append(FCS->GetDaCmd());
@@ -952,13 +958,15 @@ bool FGOutput::Load(Element* element)
     output_file_name = DirectivesFile;      // one found in the config file.
     document = LoadXMLDocument(output_file_name);
   } else if (!element->GetAttributeValue("file").empty()) {
-    output_file_name = element->GetAttributeValue("file");
+    output_file_name = FDMExec->GetRootDir() + element->GetAttributeValue("file");
     document = LoadXMLDocument(output_file_name);
   } else {
     document = element;
   }
 
-  name = document->GetAttributeValue("name");
+  if (!document) return false;
+
+  name = FDMExec->GetRootDir() + document->GetAttributeValue("name");
   type = document->GetAttributeValue("type");
   SetType(type);
   if (!document->GetAttributeValue("port").empty() && type == string("SOCKET")) {
@@ -1035,7 +1043,7 @@ void FGOutput::SetRate(int rtHz)
 {
   rtHz = rtHz>1000?1000:(rtHz<0?0:rtHz);
   if (rtHz > 0) {
-    rate = (int)(0.5 + 1.0/(State->Getdt()*rtHz));
+    rate = (int)(0.5 + 1.0/(FDMExec->GetDeltaT()*rtHz));
     Enable();
   } else {
     rate = 1;
@@ -1085,7 +1093,7 @@ void FGOutput::Debug(int from)
       }
       switch (Type) {
       case otCSV:
-        cout << scratch << " in CSV format output at rate " << 1/(State->Getdt()*rate) << " Hz" << endl;
+        cout << scratch << " in CSV format output at rate " << 1/(FDMExec->GetDeltaT()*rate) << " Hz" << endl;
         break;
       case otNone:
       default:
index cd1ca6e30881c39587eb101bd983a772e0b547f6..f1cfef7d0e5c2d125208b8a8e410898ecef6bae4 100644 (file)
@@ -50,7 +50,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_OUTPUT "$Id$"
+#define ID_OUTPUT "$Id: FGOutput.h,v 1.17 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -123,7 +123,7 @@ CLASS DOCUMENTATION
     propulsion       ON|OFF
 </pre>
     NOTE that Time is always output with the data.
-    @version $Id$
+    @version $Id: FGOutput.h,v 1.17 2009/10/24 22:59:30 jberndt Exp $
  */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 9bd50289882d378cae31575ecb69f13b59e308a2..a698b542cd78e4361d5e1c9ae3dacce30e4eddf7 100644 (file)
@@ -56,10 +56,11 @@ INCLUDES
 #include <cmath>
 #include <cstdlib>
 #include <iostream>
+#include <iomanip>
 
 #include "FGPropagate.h"
+#include "FGGroundReactions.h"
 #include "FGFDMExec.h"
-#include "FGState.h"
 #include "FGAircraft.h"
 #include "FGMassBalance.h"
 #include "FGInertial.h"
@@ -69,7 +70,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.55 2010/07/09 04:11:45 jberndt Exp $";
 static const char *IdHdr = ID_PROPAGATE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -80,30 +81,23 @@ FGPropagate::FGPropagate(FGFDMExec* fdmex) : FGModel(fdmex)
 {
   Debug(0);
   Name = "FGPropagate";
-
-  last2_vPQRdot.InitMatrix();
-  last_vPQRdot.InitMatrix();
+  gravType = gtWGS84;
   vPQRdot.InitMatrix();
-  
-  last2_vQtrndot = FGQuaternion(0,0,0);
-  last_vQtrndot = FGQuaternion(0,0,0);
   vQtrndot = FGQuaternion(0,0,0);
-
-  last2_vUVWdot.InitMatrix();
-  last_vUVWdot.InitMatrix();
   vUVWdot.InitMatrix();
-  
-  last2_vLocationDot.InitMatrix();
-  last_vLocationDot.InitMatrix();
-  vLocationDot.InitMatrix();
-
-  vOmegaLocal.InitMatrix();
+  vInertialVelocity.InitMatrix();
 
   integrator_rotational_rate = eAdamsBashforth2;
   integrator_translational_rate = eTrapezoidal;
   integrator_rotational_position = eAdamsBashforth2;
   integrator_translational_position = eTrapezoidal;
 
+  VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
+  VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
+  VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
+  VState.dqQtrndot.resize(4, FGQuaternion(0.0,0.0,0.0));
+
   bind();
   Debug(0);
 }
@@ -126,25 +120,17 @@ bool FGPropagate::InitModel(void)
 
   VState.vLocation.SetRadius( LocalTerrainRadius + 4.0 );
   VState.vLocation.SetEllipse(Inertial->GetSemimajor(), Inertial->GetSemiminor());
-  vOmega = FGColumnVector3( 0.0, 0.0, Inertial->omega() ); // Earth rotation vector
+  vOmegaEarth = FGColumnVector3( 0.0, 0.0, Inertial->omega() ); // Earth rotation vector
 
-  last2_vPQRdot.InitMatrix();
-  last_vPQRdot.InitMatrix();
   vPQRdot.InitMatrix();
-  
-  last2_vQtrndot = FGQuaternion(0,0,0);
-  last_vQtrndot = FGQuaternion(0,0,0);
   vQtrndot = FGQuaternion(0,0,0);
-
-  last2_vUVWdot.InitMatrix();
-  last_vUVWdot.InitMatrix();
   vUVWdot.InitMatrix();
-  
-  last2_vLocationDot.InitMatrix();
-  last_vLocationDot.InitMatrix();
-  vLocationDot.InitMatrix();
+  vInertialVelocity.InitMatrix();
 
-  vOmegaLocal.InitMatrix();
+  VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
+  VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
+  VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
+  VState.dqQtrndot.resize(4, FGColumnVector3(0.0,0.0,0.0));
 
   integrator_rotational_rate = eAdamsBashforth2;
   integrator_translational_rate = eTrapezoidal;
@@ -161,51 +147,92 @@ void FGPropagate::SetInitialState(const FGInitialCondition *FGIC)
   SetSeaLevelRadius(FGIC->GetSeaLevelRadiusFtIC());
   SetTerrainElevation(FGIC->GetTerrainElevationFtIC());
 
+  VehicleRadius = GetRadius();
+  radInv = 1.0/VehicleRadius;
+
+  // Initialize the State Vector elements and the transformation matrices
+
   // Set the position lat/lon/radius
   VState.vLocation.SetPosition( FGIC->GetLongitudeRadIC(),
-                          FGIC->GetLatitudeRadIC(),
-                          FGIC->GetAltitudeASLFtIC() + FGIC->GetSeaLevelRadiusFtIC() );
+                                FGIC->GetLatitudeRadIC(),
+                                FGIC->GetAltitudeASLFtIC() + FGIC->GetSeaLevelRadiusFtIC() );
 
-  VehicleRadius = GetRadius();
-  radInv = 1.0/VehicleRadius;
+  VState.vLocation.SetEarthPositionAngle(Inertial->GetEarthPositionAngle());
 
-  // Set the Orientation from the euler angles
-  VState.vQtrn = FGQuaternion( FGIC->GetPhiRadIC(),
-                        FGIC->GetThetaRadIC(),
-                        FGIC->GetPsiRadIC() );
+  Ti2ec = GetTi2ec();         // ECI to ECEF transform
+  Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform
+  
+  Tl2ec = GetTl2ec();         // local to ECEF transform
+  Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform
+
+  Ti2l  = GetTi2l();
+  Tl2i  = Ti2l.Transposed();
+
+  // Set the orientation from the euler angles (is normalized within the
+  // constructor). The Euler angles represent the orientation of the body
+  // frame relative to the local frame.
+  VState.qAttitudeLocal = FGQuaternion( FGIC->GetPhiRadIC(),
+                                        FGIC->GetThetaRadIC(),
+                                        FGIC->GetPsiRadIC() );
+
+  VState.qAttitudeECI = Ti2l.GetQuaternion()*VState.qAttitudeLocal;
+
+  Ti2b  = GetTi2b();           // ECI to body frame transform
+  Tb2i  = Ti2b.Transposed();   // body to ECI frame transform
+
+  Tl2b  = VState.qAttitudeLocal; // local to body frame transform
+  Tb2l  = Tl2b.Transposed();     // body to local frame transform
+
+  Tec2b = Tl2b * Tec2l;        // ECEF to body frame transform
+  Tb2ec = Tec2b.Transposed();  // body to ECEF frame tranform
 
   // Set the velocities in the instantaneus body frame
   VState.vUVW = FGColumnVector3( FGIC->GetUBodyFpsIC(),
-                          FGIC->GetVBodyFpsIC(),
-                          FGIC->GetWBodyFpsIC() );
+                                 FGIC->GetVBodyFpsIC(),
+                                 FGIC->GetWBodyFpsIC() );
 
-  // Set the angular velocities in the instantaneus body frame.
-  VState.vPQR = FGColumnVector3( FGIC->GetPRadpsIC(),
-                          FGIC->GetQRadpsIC(),
-                          FGIC->GetRRadpsIC() );
+  VState.vInertialPosition = Tec2i * VState.vLocation;
 
   // Compute the local frame ECEF velocity
-  vVel = GetTb2l()*VState.vUVW;
+  vVel = Tb2l * VState.vUVW;
 
-  // Finally, make sure that the quaternion stays normalized.
-  VState.vQtrn.Normalize();
+  // Refer to Stevens and Lewis, 1.5-14a, pg. 49.
+  // This is the rotation rate of the "Local" frame, expressed in the local frame.
 
-  // Recompute the LocalTerrainRadius.
-  RecomputeLocalTerrainRadius();
+  FGColumnVector3 vOmegaLocal = FGColumnVector3(
+     radInv*vVel(eEast),
+    -radInv*vVel(eNorth),
+    -radInv*vVel(eEast)*VState.vLocation.GetTanLatitude() );
 
-  // These local copies of the transformation matrices are for use for
-  // initial conditions only.
+  // Set the angular velocities of the body frame relative to the ECEF frame,
+  // expressed in the body frame. Effectively, this is:
+  //   w_b/e = w_b/l + w_l/e
+  VState.vPQR = FGColumnVector3( FGIC->GetPRadpsIC(),
+                                 FGIC->GetQRadpsIC(),
+                                 FGIC->GetRRadpsIC() ) + Tl2b*vOmegaLocal;
+
+  VState.vPQRi = VState.vPQR + Ti2b * vOmegaEarth;
+
+  // Make an initial run and set past values
+  CalculatePQRdot();           // Angular rate derivative
+  CalculateUVWdot();           // Translational rate derivative
+  CalculateQuatdot();          // Angular orientation derivative
+  CalculateInertialVelocity(); // Translational position derivative
+
+  // Initialize past values deques
+  VState.dqPQRdot.clear();
+  VState.dqUVWdot.clear();
+  VState.dqInertialVelocity.clear();
+  VState.dqQtrndot.clear();
+  for (int i=0; i<4; i++) {
+    VState.dqPQRdot.push_front(vPQRdot);
+    VState.dqUVWdot.push_front(vUVWdot);
+    VState.dqInertialVelocity.push_front(VState.vInertialVelocity);
+    VState.dqQtrndot.push_front(vQtrndot);
+  }
 
-  Tl2b = GetTl2b();           // local to body frame transform
-  Tb2l = Tl2b.Transposed();   // body to local frame transform
-  Tl2ec = GetTl2ec();         // local to ECEF transform
-  Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform
-  Tec2b = Tl2b * Tec2l;       // ECEF to body frame transform
-  Tb2ec = Tec2b.Transposed(); // body to ECEF frame tranform
-  Ti2ec = GetTi2ec();         // ECI to ECEF transform
-  Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform
-  Ti2b  = Tec2b*Ti2ec;        // ECI to body frame transform
-  Tb2i  = Ti2b.Transposed();  // body to ECI frame transform
+  // Recompute the LocalTerrainRadius.
+  RecomputeLocalTerrainRadius();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -230,123 +257,65 @@ Inertial.
 
 bool FGPropagate::Run(void)
 {
+static int ctr;
+
   if (FGModel::Run()) return true;  // Fast return if we have nothing to do ...
   if (FDMExec->Holding()) return false;
 
-  RunPreFunctions();
-
-  RecomputeLocalTerrainRadius();
-
-  // Calculate current aircraft radius from center of planet
-
-  VehicleRadius = GetRadius();
-  radInv = 1.0/VehicleRadius;
+  double dt = FDMExec->GetDeltaT()*rate;  // The 'stepsize'
 
-  // These local copies of the transformation matrices are for use this
-  // pass through Run() only.
-
-  Tl2b = GetTl2b();           // local to body frame transform
-  Tb2l = Tl2b.Transposed();   // body to local frame transform
-  Tl2ec = GetTl2ec();         // local to ECEF transform
-  Tec2l = Tl2ec.Transposed(); // ECEF to local frame transform
-  Tec2b = Tl2b * Tec2l;       // ECEF to body frame transform
-  Tb2ec = Tec2b.Transposed(); // body to ECEF frame tranform
-  Ti2ec = GetTi2ec();         // ECI to ECEF transform
-  Tec2i = Ti2ec.Transposed(); // ECEF to ECI frame transform
-  Ti2b  = Tec2b*Ti2ec;        // ECI to body frame transform
-  Tb2i  = Ti2b.Transposed();  // body to ECI frame transform
+  RunPreFunctions();
 
-  // Compute vehicle velocity wrt ECEF frame, expressed in Local horizontal frame.
-  vVel = Tb2l * VState.vUVW;
+  // Calculate state derivatives
+  CalculatePQRdot();           // Angular rate derivative
+  CalculateUVWdot();           // Translational rate derivative
+  CalculateQuatdot();          // Angular orientation derivative
+  CalculateInertialVelocity(); // Translational position derivative
 
-  // Inertial angular velocity measured in the body frame.
-  vPQRi = VState.vPQR + Tec2b*vOmega;
+  // Propagate rotational / translational velocity, angular /translational position, respectively.
+  Integrate(VState.vPQRi,             vPQRdot,           VState.dqPQRdot,           dt, integrator_rotational_rate);
+  Integrate(VState.vUVW,              vUVWdot,           VState.dqUVWdot,           dt, integrator_translational_rate);
+  Integrate(VState.qAttitudeECI,      vQtrndot,          VState.dqQtrndot,          dt, integrator_rotational_position);
+  Integrate(VState.vInertialPosition, VState.vInertialVelocity, VState.dqInertialVelocity, dt, integrator_translational_position);
 
-  // Calculate state derivatives
-  CalculatePQRdot();      // Angular rate derivative
-  CalculateUVWdot();      // Translational rate derivative
-  CalculateQuatdot();     // Angular orientation derivative
-  CalculateLocationdot(); // Translational position derivative
+  VState.qAttitudeECI.Normalize(); // Normalize the ECI Attitude quaternion
 
-  // Integrate to propagate the state
+  VState.vLocation.SetEarthPositionAngle(Inertial->GetEarthPositionAngle()); // Update the Earth position angle (EPA)
 
-  double dt = State->Getdt()*rate;  // The 'stepsize'
+  // Update the "Location-based" transformation matrices from the vLocation vector.
 
-  // Propagate rotational velocity
+  Ti2ec = GetTi2ec();          // ECI to ECEF transform
+  Tec2i = Ti2ec.Transposed();  // ECEF to ECI frame transform
+  Tl2ec = GetTl2ec();          // local to ECEF transform
+  Tec2l = Tl2ec.Transposed();  // ECEF to local frame transform
+  Ti2l  = GetTi2l();
+  Tl2i  = Ti2l.Transposed();
 
-  switch(integrator_rotational_rate) {
-  case eRectEuler:       VState.vPQR += dt*vPQRdot;
-    break;
-  case eTrapezoidal:     VState.vPQR += 0.5*dt*(vPQRdot + last_vPQRdot);
-    break;
-  case eAdamsBashforth2: VState.vPQR += dt*(1.5*vPQRdot - 0.5*last_vPQRdot);
-    break;
-  case eAdamsBashforth3: VState.vPQR += (1/12.0)*dt*(23.0*vPQRdot - 16.0*last_vPQRdot + 5.0*last2_vPQRdot);
-    break;
-  case eNone: // do nothing, freeze angular rate
-    break;
-  }
-  
-  // Propagate translational velocity
+  // Update the "Orientation-based" transformation matrices from the orientation quaternion
 
-  switch(integrator_translational_rate) {
-  case eRectEuler:       VState.vUVW += dt*vUVWdot;
-    break;
-  case eTrapezoidal:     VState.vUVW += 0.5*dt*(vUVWdot + last_vUVWdot);
-    break;
-  case eAdamsBashforth2: VState.vUVW += dt*(1.5*vUVWdot - 0.5*last_vUVWdot);
-    break;
-  case eAdamsBashforth3: VState.vUVW += (1/12.0)*dt*(23.0*vUVWdot - 16.0*last_vUVWdot + 5.0*last2_vUVWdot);
-    break;
-  case eNone: // do nothing, freeze translational rate
-    break;
-  }
+  Ti2b  = GetTi2b();           // ECI to body frame transform
+  Tb2i  = Ti2b.Transposed();   // body to ECI frame transform
+  Tl2b  = Ti2b*Tl2i;           // local to body frame transform
+  Tb2l  = Tl2b.Transposed();   // body to local frame transform
+  Tec2b = Tl2b * Tec2l;        // ECEF to body frame transform
+  Tb2ec = Tec2b.Transposed();  // body to ECEF frame tranform
 
-  // Propagate angular position
+  // Set auxililary state variables
+  VState.vLocation = Ti2ec*VState.vInertialPosition;
+  RecomputeLocalTerrainRadius();
 
-  switch(integrator_rotational_position) {
-  case eRectEuler:       VState.vQtrn += dt*vQtrndot;
-    break;
-  case eTrapezoidal:     VState.vQtrn += 0.5*dt*(vQtrndot + last_vQtrndot);
-    break;
-  case eAdamsBashforth2: VState.vQtrn += dt*(1.5*vQtrndot - 0.5*last_vQtrndot);
-    break;
-  case eAdamsBashforth3: VState.vQtrn += (1/12.0)*dt*(23.0*vQtrndot - 16.0*last_vQtrndot + 5.0*last2_vQtrndot);
-    break;
-  case eNone: // do nothing, freeze angular position
-    break;
-  }
+  // Calculate current aircraft radius from center of planet
+  VehicleRadius = VState.vInertialPosition.Magnitude();
+  radInv = 1.0/VehicleRadius;
 
-  // Propagate translational position
+  VState.vPQR = VState.vPQRi - Ti2b * vOmegaEarth;
 
-  switch(integrator_translational_position) {
-  case eRectEuler:       VState.vLocation += dt*vLocationDot;
-    break;
-  case eTrapezoidal:     VState.vLocation += 0.5*dt*(vLocationDot + last_vLocationDot);
-    break;
-  case eAdamsBashforth2: VState.vLocation += dt*(1.5*vLocationDot - 0.5*last_vLocationDot);
-    break;
-  case eAdamsBashforth3: VState.vLocation += (1/12.0)*dt*(23.0*vLocationDot - 16.0*last_vLocationDot + 5.0*last2_vLocationDot);
-    break;
-  case eNone: // do nothing, freeze translational position
-    break;
-  }
-  
-  // Set past values
-  
-  last2_vPQRdot = last_vPQRdot;
-  last_vPQRdot = vPQRdot;
-  
-  last2_vUVWdot = last_vUVWdot;
-  last_vUVWdot = vUVWdot;
-  
-  last2_vQtrndot = last_vQtrndot;
-  last_vQtrndot = vQtrndot;
+  VState.qAttitudeLocal = Tl2b.GetQuaternion();
 
-  last2_vLocationDot = last_vLocationDot;
-  last_vLocationDot = vLocationDot;
+  // Compute vehicle velocity wrt ECEF frame, expressed in Local horizontal frame.
+  vVel = Tb2l * VState.vUVW;
 
-  RunPreFunctions();
+  RunPostFunctions();
 
   Debug(2);
   return false;
@@ -361,7 +330,7 @@ bool FGPropagate::Run(void)
 // J is the inertia matrix
 // Jinv is the inverse inertia matrix
 // vMoments is the moment vector in the body frame
-// vPQRi is the total inertial angular velocity of the vehicle
+// VState.vPQRi is the total inertial angular velocity of the vehicle
 // expressed in the body frame.
 // Reference: See Stevens and Lewis, "Aircraft Control and Simulation", 
 //            Second edition (2004), eqn 1.5-16e (page 50)
@@ -376,7 +345,7 @@ void FGPropagate::CalculatePQRdot(void)
   // moments and the total inertial angular velocity expressed in the body
   // frame.
 
-  vPQRdot = Jinv*(vMoments - vPQRi*(J*vPQRi));
+  vPQRdot = Jinv*(vMoments - VState.vPQRi*(J*VState.vPQRi));
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -388,72 +357,140 @@ void FGPropagate::CalculatePQRdot(void)
 
 void FGPropagate::CalculateQuatdot(void)
 {
-  vOmegaLocal.InitMatrix( radInv*vVel(eEast),
-                         -radInv*vVel(eNorth),
-                         -radInv*vVel(eEast)*VState.vLocation.GetTanLatitude() );
-
   // Compute quaternion orientation derivative on current body rates
-  vQtrndot = VState.vQtrn.GetQDot( VState.vPQR - Tl2b*vOmegaLocal);
+  vQtrndot = VState.qAttitudeECI.GetQDot( VState.vPQRi);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 // This set of calculations results in the body frame accelerations being
 // computed.
+// Compute body frame accelerations based on the current body forces.
+// Include centripetal and coriolis accelerations.
+// vOmegaEarth is the Earth angular rate - expressed in the inertial frame -
+//   so it has to be transformed to the body frame. More completely,
+//   vOmegaEarth is the rate of the ECEF frame relative to the Inertial
+//   frame (ECI), expressed in the Inertial frame.
+// vForces is the total force on the vehicle in the body frame.
+// VState.vPQR is the vehicle body rate relative to the ECEF frame, expressed
+//   in the body frame.
+// VState.vUVW is the vehicle velocity relative to the ECEF frame, expressed
+//   in the body frame.
 // Reference: See Stevens and Lewis, "Aircraft Control and Simulation", 
-//            Second edition (2004), eqn 1.5-16d (page 50)
+//            Second edition (2004), eqns 1.5-13 (pg 48) and 1.5-16d (page 50)
 
 void FGPropagate::CalculateUVWdot(void)
 {
   double mass = MassBalance->GetMass();                      // mass
   const FGColumnVector3& vForces = Aircraft->GetForces();    // current forces
 
-  const FGColumnVector3 vGravAccel( 0.0, 0.0, Inertial->GetGAccel(VehicleRadius) );
-
-  // Begin to compute body frame accelerations based on the current body forces
-  vUVWdot = vForces/mass - VState.vPQR * VState.vUVW;
+  vUVWdot = vForces/mass - (VState.vPQR + 2.0*(Ti2b *vOmegaEarth)) * VState.vUVW;
 
-  // Include Coriolis acceleration.
-  vUVWdot -= 2.0 * (Ti2b *vOmega) * VState.vUVW;
-
-  // Include Centrifugal acceleration.
-  if (!GroundReactions->GetWOW()) {
-    vUVWdot -= Ti2b*(vOmega*(vOmega*(Tec2i*VState.vLocation)));
+  // Include Centripetal acceleration.
+  if (!GroundReactions->GetWOW() && Aircraft->GetHoldDown() == 0) {
+    vUVWdot -= Ti2b * (vOmegaEarth*(vOmegaEarth*VState.vInertialPosition));
   }
 
   // Include Gravitation accel
-  FGColumnVector3 gravAccel = Tl2b*vGravAccel;
-  vUVWdot += gravAccel;
+  switch (gravType) {
+    case gtStandard:
+      vGravAccel = Tl2b * FGColumnVector3( 0.0, 0.0, Inertial->GetGAccel(VehicleRadius) );
+      break;
+    case gtWGS84:
+      vGravAccel = Tec2b * Inertial->GetGravityJ2(VState.vLocation);
+      break;
+  }
+
+  vUVWdot += vGravAccel;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-void FGPropagate::CalculateLocationdot(void)
-{
-  // Transform the vehicle velocity relative to the ECEF frame, expressed
-  // in the body frame, to be expressed in the ECEF frame.
-  vLocationDot = Tb2ec * VState.vUVW;
-
-  // Now, transform the velocity vector of the body relative to the origin (Earth
+  // Transform the velocity vector of the body relative to the origin (Earth
   // center) to be expressed in the inertial frame, and add the vehicle velocity
-  // contribution due to the rotation of the planet. The above velocity is only
-  // relative to the rotating ECEF frame.
+  // contribution due to the rotation of the planet.
   // Reference: See Stevens and Lewis, "Aircraft Control and Simulation", 
   //            Second edition (2004), eqn 1.5-16c (page 50)
 
-  vInertialVelocity = Tec2i * vLocationDot + (vOmega * (Tec2i * VState.vLocation));
+void FGPropagate::CalculateInertialVelocity(void)
+{
+  VState.vInertialVelocity = Tb2i * VState.vUVW + (vOmegaEarth * VState.vInertialPosition);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropagate::Integrate( FGColumnVector3& Integrand,
+                             FGColumnVector3& Val,
+                             deque <FGColumnVector3>& ValDot,
+                             double dt,
+                             eIntegrateType integration_type)
+{
+  ValDot.push_front(Val);
+  ValDot.pop_back();
+
+  switch(integration_type) {
+  case eRectEuler:       Integrand += dt*ValDot[0];
+    break;
+  case eTrapezoidal:     Integrand += 0.5*dt*(ValDot[0] + ValDot[1]);
+    break;
+  case eAdamsBashforth2: Integrand += dt*(1.5*ValDot[0] - 0.5*ValDot[1]);
+    break;
+  case eAdamsBashforth3: Integrand += (1/12.0)*dt*(23.0*ValDot[0] - 16.0*ValDot[1] + 5.0*ValDot[2]);
+    break;
+  case eAdamsBashforth4: Integrand += (1/24.0)*dt*(55.0*ValDot[0] - 59.0*ValDot[1] + 37.0*ValDot[2] - 9.0*ValDot[3]);
+    break;
+  case eNone: // do nothing, freeze translational rate
+    break;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropagate::Integrate( FGQuaternion& Integrand,
+                             FGQuaternion& Val,
+                             deque <FGQuaternion>& ValDot,
+                             double dt,
+                             eIntegrateType integration_type)
+{
+  ValDot.push_front(Val);
+  ValDot.pop_back();
+
+  switch(integration_type) {
+  case eRectEuler:       Integrand += dt*ValDot[0];
+    break;
+  case eTrapezoidal:     Integrand += 0.5*dt*(ValDot[0] + ValDot[1]);
+    break;
+  case eAdamsBashforth2: Integrand += dt*(1.5*ValDot[0] - 0.5*ValDot[1]);
+    break;
+  case eAdamsBashforth3: Integrand += (1/12.0)*dt*(23.0*ValDot[0] - 16.0*ValDot[1] + 5.0*ValDot[2]);
+    break;
+  case eAdamsBashforth4: Integrand += (1/24.0)*dt*(55.0*ValDot[0] - 59.0*ValDot[1] + 37.0*ValDot[2] - 9.0*ValDot[3]);
+    break;
+  case eNone: // do nothing, freeze translational rate
+    break;
+  }
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropagate::SetInertialOrientation(FGQuaternion Qi) {
+  VState.qAttitudeECI = Qi;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void FGPropagate::SetInertialVelocity(FGColumnVector3 Vi) {
+  VState.vInertialVelocity = Vi;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 void FGPropagate::RecomputeLocalTerrainRadius(void)
 {
-  double t = State->Getsim_time();
+  double t = FDMExec->GetSimTime();
 
   // Get the LocalTerrain radius.
-  FGLocation contactloc;
-  FGColumnVector3 dv;
-  FDMExec->GetGroundCallback()->GetAGLevel(t, VState.vLocation, contactloc, dv, dv);
-  LocalTerrainRadius = contactloc.GetRadius();
+//  FDMExec->GetGroundCallback()->GetAGLevel(t, VState.vLocation, contactloc, dv, dv);
+//  LocalTerrainRadius = contactloc.GetRadius();
+  LocalTerrainRadius = FDMExec->GetGroundCallback()->GetTerrainGeoCentRadius();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -472,17 +509,19 @@ double FGPropagate::GetTerrainElevation(void) const
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
+//Todo: when should this be called - when should the new EPA be used to
+// calculate the transformation matrix, so that the matrix is not a step
+// ahead of the sim and the associated calculations?
 const FGMatrix33& FGPropagate::GetTi2ec(void)
 {
-  return VState.vLocation.GetTi2ec(Inertial->GetEarthPositionAngle());
+  return VState.vLocation.GetTi2ec();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 const FGMatrix33& FGPropagate::GetTec2i(void)
 {
-  return VState.vLocation.GetTec2i(Inertial->GetEarthPositionAngle());
+  return VState.vLocation.GetTec2i();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -518,7 +557,7 @@ void FGPropagate::SetDistanceAGL(double tt)
 void FGPropagate::bind(void)
 {
   typedef double (FGPropagate::*PMF)(int) const;
-//  typedef double (FGPropagate::*dPMF)() const;
+
   PropertyManager->Tie("velocities/h-dot-fps", this, &FGPropagate::Gethdot);
 
   PropertyManager->Tie("velocities/v-north-fps", this, eNorth, (PMF)&FGPropagate::GetVel);
@@ -572,10 +611,11 @@ void FGPropagate::bind(void)
   PropertyManager->Tie("attitude/pitch-rad", this, (int)eTht, (PMF)&FGPropagate::GetEuler);
   PropertyManager->Tie("attitude/heading-true-rad", this, (int)ePsi, (PMF)&FGPropagate::GetEuler);
   
-  PropertyManager->Tie("simulation/integrator/rate/rotational", &integrator_rotational_rate);
-  PropertyManager->Tie("simulation/integrator/rate/translational", &integrator_translational_rate);
-  PropertyManager->Tie("simulation/integrator/position/rotational", &integrator_rotational_position);
-  PropertyManager->Tie("simulation/integrator/position/translational", &integrator_translational_position);
+  PropertyManager->Tie("simulation/integrator/rate/rotational", (int*)&integrator_rotational_rate);
+  PropertyManager->Tie("simulation/integrator/rate/translational", (int*)&integrator_translational_rate);
+  PropertyManager->Tie("simulation/integrator/position/rotational", (int*)&integrator_rotational_position);
+  PropertyManager->Tie("simulation/integrator/position/translational", (int*)&integrator_translational_position);
+  PropertyManager->Tie("simulation/gravity-model", &gravType);
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -612,7 +652,96 @@ void FGPropagate::Debug(int from)
   }
   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
   }
-  if (debug_lvl & 8 ) { // Runtime state variables
+  if (debug_lvl & 8 && from == 2) { // Runtime state variables
+    cout << endl << fgblue << highint << left 
+         << "  Propagation Report (English units: ft, degrees) at simulation time " << FDMExec->GetSimTime() << " seconds"
+         << reset << endl;
+    cout << endl;
+    cout << highint << "  Earth Position Angle (deg): " << setw(8) << setprecision(3) << reset
+                    << Inertial->GetEarthPositionAngleDeg() << endl;
+    cout << endl;
+    cout << highint << "  Body velocity (ft/sec): " << setw(8) << setprecision(3) << reset << VState.vUVW << endl;
+    cout << highint << "  Local velocity (ft/sec): " << setw(8) << setprecision(3) << reset << vVel << endl;
+    cout << highint << "  Inertial velocity (ft/sec): " << setw(8) << setprecision(3) << reset << VState.vInertialVelocity << endl;
+    cout << highint << "  Inertial Position (ft): " << setw(10) << setprecision(3) << reset << VState.vInertialPosition << endl;
+    cout << highint << "  Latitude (deg): " << setw(8) << setprecision(3) << reset << VState.vLocation.GetLatitudeDeg() << endl;
+    cout << highint << "  Longitude (deg): " << setw(8) << setprecision(3) << reset << VState.vLocation.GetLongitudeDeg() << endl;
+    cout << highint << "  Altitude ASL (ft): " << setw(8) << setprecision(3) << reset << GetAltitudeASL() << endl;
+    cout << highint << "  Acceleration (NED, ft/sec^2): " << setw(8) << setprecision(3) << reset << Tb2l*GetUVWdot() << endl;
+    cout << endl;
+    cout << highint << "  Matrix ECEF to Body (Orientation of Body with respect to ECEF): "
+                    << reset << endl << Tec2b.Dump("\t", "    ") << endl;
+    cout << highint << "    Associated Euler angles (deg): " << setw(8)
+                    << setprecision(3) << reset << (Tec2b.GetQuaternion().GetEuler()*radtodeg)
+                    << endl << endl;
+
+    cout << highint << "  Matrix Body to ECEF (Orientation of ECEF with respect to Body):"
+                    << reset << endl << Tb2ec.Dump("\t", "    ") << endl;
+    cout << highint << "    Associated Euler angles (deg): " << setw(8)
+                    << setprecision(3) << reset << (Tb2ec.GetQuaternion().GetEuler()*radtodeg)
+                    << endl << endl;
+
+    cout << highint << "  Matrix Local to Body (Orientation of Body with respect to Local):"
+                    << reset << endl << Tl2b.Dump("\t", "    ") << endl;
+    cout << highint << "    Associated Euler angles (deg): " << setw(8)
+                    << setprecision(3) << reset << (Tl2b.GetQuaternion().GetEuler()*radtodeg)
+                    << endl << endl;
+
+    cout << highint << "  Matrix Body to Local (Orientation of Local with respect to Body):"
+                    << reset << endl << Tb2l.Dump("\t", "    ") << endl;
+    cout << highint << "    Associated Euler angles (deg): " << setw(8)
+                    << setprecision(3) << reset << (Tb2l.GetQuaternion().GetEuler()*radtodeg)
+                    << endl << endl;
+
+    cout << highint << "  Matrix Local to ECEF (Orientation of ECEF with respect to Local):"
+                    << reset << endl << Tl2ec.Dump("\t", "    ") << endl;
+    cout << highint << "    Associated Euler angles (deg): " << setw(8)
+                    << setprecision(3) << reset << (Tl2ec.GetQuaternion().GetEuler()*radtodeg)
+                    << endl << endl;
+
+    cout << highint << "  Matrix ECEF to Local (Orientation of Local with respect to ECEF):"
+                    << reset << endl << Tec2l.Dump("\t", "    ") << endl;
+    cout << highint << "    Associated Euler angles (deg): " << setw(8)
+                    << setprecision(3) << reset << (Tec2l.GetQuaternion().GetEuler()*radtodeg)
+                    << endl << endl;
+
+    cout << highint << "  Matrix ECEF to Inertial (Orientation of Inertial with respect to ECEF):"
+                    << reset << endl << Tec2i.Dump("\t", "    ") << endl;
+    cout << highint << "    Associated Euler angles (deg): " << setw(8)
+                    << setprecision(3) << reset << (Tec2i.GetQuaternion().GetEuler()*radtodeg)
+                    << endl << endl;
+
+    cout << highint << "  Matrix Inertial to ECEF (Orientation of ECEF with respect to Inertial):"
+                    << reset << endl << Ti2ec.Dump("\t", "    ") << endl;
+    cout << highint << "    Associated Euler angles (deg): " << setw(8)
+                    << setprecision(3) << reset << (Ti2ec.GetQuaternion().GetEuler()*radtodeg)
+                    << endl << endl;
+
+    cout << highint << "  Matrix Inertial to Body (Orientation of Body with respect to Inertial):"
+                    << reset << endl << Ti2b.Dump("\t", "    ") << endl;
+    cout << highint << "    Associated Euler angles (deg): " << setw(8)
+                    << setprecision(3) << reset << (Ti2b.GetQuaternion().GetEuler()*radtodeg)
+                    << endl << endl;
+
+    cout << highint << "  Matrix Body to Inertial (Orientation of Inertial with respect to Body):"
+                    << reset << endl << Tb2i.Dump("\t", "    ") << endl;
+    cout << highint << "    Associated Euler angles (deg): " << setw(8)
+                    << setprecision(3) << reset << (Tb2i.GetQuaternion().GetEuler()*radtodeg)
+                    << endl << endl;
+
+    cout << highint << "  Matrix Inertial to Local (Orientation of Local with respect to Inertial):"
+                    << reset << endl << Ti2l.Dump("\t", "    ") << endl;
+    cout << highint << "    Associated Euler angles (deg): " << setw(8)
+                    << setprecision(3) << reset << (Ti2l.GetQuaternion().GetEuler()*radtodeg)
+                    << endl << endl;
+
+    cout << highint << "  Matrix Local to Inertial (Orientation of Inertial with respect to Local):"
+                    << reset << endl << Tl2i.Dump("\t", "    ") << endl;
+    cout << highint << "    Associated Euler angles (deg): " << setw(8)
+                    << setprecision(3) << reset << (Tl2i.GetQuaternion().GetEuler()*radtodeg)
+                    << endl << endl;
+
+    cout << setprecision(6); // reset the output stream
   }
   if (debug_lvl & 16) { // Sanity checking
     if (from == 2) { // State sanity checking
index c8400531870c6c46568cc272f83a01a5516605fd..a98a87e2089e49ceba749debb8fe7647431b0bd4 100644 (file)
@@ -43,12 +43,13 @@ INCLUDES
 #include "math/FGLocation.h"
 #include "math/FGQuaternion.h"
 #include "math/FGMatrix33.h"
+#include <deque>
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PROPAGATE "$Id$"
+#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.41 2010/07/09 04:11:45 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -56,6 +57,7 @@ FORWARD DECLARATIONS
 
 namespace JSBSim {
 
+using std::deque;
 class FGInitialCondition;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -66,6 +68,16 @@ CLASS DOCUMENTATION
     The Equations of Motion (EOM) for JSBSim are integrated to propagate the
     state of the vehicle given the forces and moments that act on it. The
     integration accounts for a rotating Earth.
+
+    The general execution of this model follows this process:
+
+    -Calculate the angular accelerations
+    -Calculate the translational accelerations
+    -Calculate the angular rate
+    -Calculate the translational velocity
+
+    -Integrate accelerations and rates
+
     Integration of rotational and translation position and rate can be 
     customized as needed or frozen by the selection of no integrator. The
     selection of which integrator to use is done through the setting of 
@@ -86,10 +98,11 @@ CLASS DOCUMENTATION
     2: Trapezoidal
     3: Adams Bashforth 2
     4: Adams Bashforth 3
+    5: Adams Bashforth 4
     @endcode
 
     @author Jon S. Berndt, Mathias Froehlich
-    @version $Id$
+    @version $Id: FGPropagate.h,v 1.41 2010/07/09 04:11:45 jberndt Exp $
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -106,17 +119,38 @@ public:
         fixed (ECEF) frame.
         units ft */
     FGLocation vLocation;
+
     /** The velocity vector of the vehicle with respect to the ECEF frame,
         expressed in the body system.
         units ft/sec */
     FGColumnVector3 vUVW;
+
     /** The angular velocity vector for the vehicle relative to the ECEF frame,
         expressed in the body frame.
         units rad/sec */
     FGColumnVector3 vPQR;
+
+    /** The angular velocity vector for the vehicle body frame relative to the
+        ECI frame, expressed in the body frame.
+        units rad/sec */
+    FGColumnVector3 vPQRi;
+
     /** The current orientation of the vehicle, that is, the orientation of the
-        body frame relative to the local, vehilce-carried, NED frame. */
-    FGQuaternion vQtrn;
+        body frame relative to the local, NED frame. */
+    FGQuaternion qAttitudeLocal;
+
+    /** The current orientation of the vehicle, that is, the orientation of the
+        body frame relative to the inertial (ECI) frame. */
+    FGQuaternion qAttitudeECI;
+
+    FGColumnVector3 vInertialVelocity;
+
+    FGColumnVector3 vInertialPosition;
+
+    deque <FGColumnVector3> dqPQRdot;
+    deque <FGColumnVector3> dqUVWdot;
+    deque <FGColumnVector3> dqInertialVelocity;
+    deque <FGQuaternion> dqQtrndot;
   };
 
   /** Constructor.
@@ -133,7 +167,10 @@ public:
   ~FGPropagate();
   
   /// These define the indices use to select the various integrators.
-  enum eIntegrateType {eNone = 0, eRectEuler, eTrapezoidal, eAdamsBashforth2, eAdamsBashforth3};
+  enum eIntegrateType {eNone = 0, eRectEuler, eTrapezoidal, eAdamsBashforth2, eAdamsBashforth3, eAdamsBashforth4};
+
+  /// These define the indices use to select the gravitation models.
+  enum eGravType {gtStandard, gtWGS84}; 
 
   /** Initializes the FGPropagate class after instantiation and prior to first execution.
       The base class FGModel::InitModel is called first, initializing pointers to the 
@@ -144,6 +181,12 @@ public:
       @return false if no error */
   bool Run(void);
 
+  void CalculatePQRdot(void);
+  void CalculateQuatdot(void);
+  void CalculateInertialVelocity(void);
+  void CalculateUVWdot(void);
+  const FGQuaternion& GetQuaterniondot(void) const {return vQtrndot;}
+
   /** Retrieves the velocity vector.
       The vector returned is represented by an FGColumnVector reference. The vector
       for the velocity in Local frame is organized (Vnorth, Veast, Vdown). The vector
@@ -207,9 +250,9 @@ public:
       in FGJSBBase. The relevant enumerators for the vector returned by this call are,
       eP=1, eQ=2, eR=3.
       units rad/sec
-      @return The body frame angular rates in rad/sec.
+      @return The body frame inertial angular rates in rad/sec.
   */
-  const FGColumnVector3& GetPQRi(void) const {return vPQRi;}
+  const FGColumnVector3& GetPQRi(void) const {return VState.vPQRi;}
 
   /** Retrieves the body axis angular acceleration vector.
       Retrieves the body axis angular acceleration vector in rad/sec^2. The
@@ -241,7 +284,7 @@ public:
               angle about the Y axis, and the third item is the angle
               about the Z axis (Phi, Theta, Psi).
   */
-  const FGColumnVector3& GetEuler(void) const { return VState.vQtrn.GetEuler(); }
+  const FGColumnVector3& GetEuler(void) const { return VState.qAttitudeLocal.GetEuler(); }
 
   /** Retrieves a body frame velocity component.
       Retrieves a body frame velocity component. The velocity returned is
@@ -284,7 +327,15 @@ public:
 
   /** Retrieves the total inertial velocity in ft/sec.
   */
-  double GetInertialVelocityMagnitude(void) const { return vInertialVelocity.Magnitude(); }
+  double GetInertialVelocityMagnitude(void) const { return VState.vInertialVelocity.Magnitude(); }
+
+  /** Retrieves the inertial velocity vector in ft/sec.
+  */
+  const FGColumnVector3& GetInertialVelocity(void) const { return VState.vInertialVelocity; }
+
+  /** Retrieves the inertial position vector.
+  */
+  const FGColumnVector3& GetInertialPosition(void) const { return VState.vInertialPosition; }
 
   /** Returns the current altitude above sea level.
       This function returns the altitude above sea level.
@@ -324,7 +375,7 @@ public:
       @param axis the index of the angular velocity component desired (1-based).
       @return The body frame angular velocity component.
   */
-  double GetPQRi(int axis) const {return vPQRi(axis);}
+  double GetPQRi(int axis) const {return VState.vPQRi(axis);}
 
   /** Retrieves a body frame angular acceleration component.
       Retrieves a body frame angular acceleration component. The angular
@@ -350,7 +401,7 @@ public:
       units radians
       @return An Euler angle.
   */
-  double GetEuler(int axis) const { return VState.vQtrn.GetEuler(axis); }
+  double GetEuler(int axis) const { return VState.qAttitudeLocal.GetEuler(axis); }
 
   /** Retrieves the cosine of a vehicle Euler angle component.
       Retrieves the cosine of an Euler angle (Phi, Theta, or Psi) from the
@@ -362,7 +413,7 @@ public:
       units none
       @return The cosine of an Euler angle.
   */
-  double GetCosEuler(int idx) const { return VState.vQtrn.GetCosEuler(idx); }
+  double GetCosEuler(int idx) const { return VState.qAttitudeLocal.GetCosEuler(idx); }
 
   /** Retrieves the sine of a vehicle Euler angle component.
       Retrieves the sine of an Euler angle (Phi, Theta, or Psi) from the
@@ -374,7 +425,7 @@ public:
       units none
       @return The sine of an Euler angle.
   */
-  double GetSinEuler(int idx) const { return VState.vQtrn.GetSinEuler(idx); }
+  double GetSinEuler(int idx) const { return VState.qAttitudeLocal.GetSinEuler(idx); }
 
   /** Returns the current altitude rate.
       Returns the current altitude rate (rate of climb).
@@ -414,13 +465,13 @@ public:
       The quaternion class, being the means by which the orientation of the
       vehicle is stored, manages the local-to-body transformation matrix.
       @return a reference to the local-to-body transformation matrix.  */
-  const FGMatrix33& GetTl2b(void) const { return VState.vQtrn.GetT(); }
+  const FGMatrix33& GetTl2b(void) const { return VState.qAttitudeLocal.GetT(); }
 
   /** Retrieves the body-to-local transformation matrix.
       The quaternion class, being the means by which the orientation of the
       vehicle is stored, manages the body-to-local transformation matrix.
       @return a reference to the body-to-local matrix.  */
-  const FGMatrix33& GetTb2l(void) const { return VState.vQtrn.GetTInv(); }
+  const FGMatrix33& GetTb2l(void) const { return VState.qAttitudeLocal.GetTInv(); }
 
   /** Retrieves the ECEF-to-body transformation matrix.
       @return a reference to the ECEF-to-body transformation matrix.  */
@@ -430,6 +481,14 @@ public:
       @return a reference to the body-to-ECEF matrix.  */
   const FGMatrix33& GetTb2ec(void) const { return Tb2ec; }
 
+  /** Retrieves the ECI-to-body transformation matrix.
+      @return a reference to the ECI-to-body transformation matrix.  */
+  const FGMatrix33& GetTi2b(void) const { return VState.qAttitudeECI.GetT(); }
+
+  /** Retrieves the body-to-ECI transformation matrix.
+      @return a reference to the body-to-ECI matrix.  */
+  const FGMatrix33& GetTb2i(void) const { return VState.qAttitudeECI.GetTInv(); }
+
   /** Retrieves the ECEF-to-ECI transformation matrix.
       @return a reference to the ECEF-to-ECI transformation matrix.  */
   const FGMatrix33& GetTec2i(void);
@@ -450,16 +509,33 @@ public:
       @return a reference to the local-to-ECEF matrix.  */
   const FGMatrix33& GetTl2ec(void) const { return VState.vLocation.GetTl2ec(); }
 
+  /** Retrieves the local-to-inertial transformation matrix.
+      @return a reference to the local-to-inertial transformation matrix.  */
+  const FGMatrix33& GetTl2i(void)  { return VState.vLocation.GetTl2i(); }
+
+  /** Retrieves the inertial-to-local transformation matrix.
+      @return a reference to the inertial-to-local matrix.  */
+  const FGMatrix33& GetTi2l(void)  { return VState.vLocation.GetTi2l(); }
+
   VehicleState* GetVState(void) { return &VState; }
 
   void SetVState(VehicleState* vstate) {
       VState.vLocation = vstate->vLocation;
       VState.vUVW = vstate->vUVW;
       VState.vPQR = vstate->vPQR;
-      VState.vQtrn = vstate->vQtrn; // ... mmh
+      VState.qAttitudeLocal = vstate->qAttitudeLocal;
+      VState.qAttitudeECI = vstate->qAttitudeECI;
+
+      VState.dqPQRdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
+      VState.dqUVWdot.resize(4, FGColumnVector3(0.0,0.0,0.0));
+      VState.dqInertialVelocity.resize(4, FGColumnVector3(0.0,0.0,0.0));
+      VState.dqQtrndot.resize(4, FGColumnVector3(0.0,0.0,0.0));
   }
 
-  const FGQuaternion GetQuaternion(void) const { return VState.vQtrn; }
+  void SetInertialOrientation(FGQuaternion Qi);
+  void SetInertialVelocity(FGColumnVector3 Vi);
+
+  const FGQuaternion GetQuaternion(void) const { return VState.qAttitudeLocal; }
 
   void SetPQR(unsigned int i, double val) {
       if ((i>=1) && (i<=3) )
@@ -492,11 +568,6 @@ public:
     VState.vLocation -= vDeltaXYZEC;
   }
 
-  void CalculatePQRdot(void);
-  void CalculateQuatdot(void);
-  void CalculateLocationdot(void);
-  void CalculateUVWdot(void);
-
 private:
 
 // state vector
@@ -504,16 +575,14 @@ private:
   struct VehicleState VState;
 
   FGColumnVector3 vVel;
+  FGColumnVector3 vPQRdot;
+  FGColumnVector3 vUVWdot;
   FGColumnVector3 vInertialVelocity;
-  FGColumnVector3 vPQRdot, last_vPQRdot, last2_vPQRdot;
-  FGColumnVector3 vUVWdot, last_vUVWdot, last2_vUVWdot;
-  FGColumnVector3 vLocationDot, last_vLocationDot, last2_vLocationDot;
   FGColumnVector3 vLocation;
   FGColumnVector3 vDeltaXYZEC;
-  FGColumnVector3 vPQRi;   // Inertial frame angular velocity
-  FGColumnVector3 vOmega;  // The Earth angular velocity vector
-  FGColumnVector3 vOmegaLocal;  // The local frame angular velocity vector
-  FGQuaternion vQtrndot, last_vQtrndot, last2_vQtrndot;
+  FGColumnVector3 vGravAccel;
+  FGColumnVector3 vOmegaEarth;  // The Earth angular velocity vector
+  FGQuaternion vQtrndot;
   FGMatrix33 Tec2b;
   FGMatrix33 Tb2ec;
   FGMatrix33 Tl2b;   // local to body frame matrix copy for immediate local use
@@ -524,13 +593,30 @@ private:
   FGMatrix33 Ti2ec;  // ECI to ECEF frame matrix copy for immediate local use
   FGMatrix33 Ti2b;   // ECI to body frame rotation matrix
   FGMatrix33 Tb2i;   // body to ECI frame rotation matrix
+  FGMatrix33 Ti2l;
+  FGMatrix33 Tl2i;
+  FGLocation contactloc;
+  FGColumnVector3 dv;
   
   double LocalTerrainRadius, SeaLevelRadius, VehicleRadius;
   double radInv;
-  int integrator_rotational_rate;
-  int integrator_translational_rate;
-  int integrator_rotational_position;
-  int integrator_translational_position;
+  eIntegrateType integrator_rotational_rate;
+  eIntegrateType integrator_translational_rate;
+  eIntegrateType integrator_rotational_position;
+  eIntegrateType integrator_translational_position;
+  int gravType;
+
+  void Integrate( FGColumnVector3& Integrand,
+                  FGColumnVector3& Val,
+                  deque <FGColumnVector3>& ValDot,
+                  double dt,
+                  eIntegrateType integration_type);
+
+  void Integrate( FGQuaternion& Integrand,
+                  FGQuaternion& Val,
+                  deque <FGQuaternion>& ValDot,
+                  double dt,
+                  eIntegrateType integration_type);
 
   void bind(void);
   void Debug(int from);
index e71dfeaf03d11cc9dcb0fb8e017801a3a6b075a1..bd3b09f0a2868906ec1bac6eb66ef2bb594e20b0 100644 (file)
@@ -45,7 +45,6 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGPropulsion.h"
-#include "FGState.h"
 #include "models/FGFCS.h"
 #include "models/FGMassBalance.h"
 #include "models/propulsion/FGThruster.h"
@@ -66,7 +65,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.39 2010/02/25 05:21:36 jberndt Exp $";
 static const char *IdHdr = ID_PROPULSION;
 
 extern short debug_lvl;
@@ -149,7 +148,7 @@ bool FGPropulsion::Run(void)
 
   RunPreFunctions();
 
-  double dt = State->Getdt();
+  double dt = FDMExec->GetDeltaT();
 
   vForces.InitMatrix();
   vMoments.InitMatrix();
index ce62a60ea0f4d6719fca5bcb4c4e1546e2294ab4..ff3502c95eb3b08226122d68d5b256b73e1b6de8 100644 (file)
@@ -49,7 +49,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PROPULSION "$Id$"
+#define ID_PROPULSION "$Id: FGPropulsion.h,v 1.25 2010/01/02 17:58:01 andgi Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -91,7 +91,7 @@ CLASS DOCUMENTATION
   @endcode
 
     @author Jon S. Berndt
-    @version $Id$
+    @version $Id: FGPropulsion.h,v 1.25 2010/01/02 17:58:01 andgi Exp $
     @see
     FGEngine
     FGTank
@@ -132,8 +132,8 @@ public:
       @return the address of the specific engine, or zero if no such engine is
               available */
   inline FGEngine* GetEngine(unsigned int index) {
-                      if (index <= Engines.size()-1) return Engines[index];
-                      else                           return 0L;      }
+                      if (index < Engines.size()) return Engines[index];
+                      else                        return 0L;      }
 
   /// Retrieves the number of tanks defined for the aircraft.
   inline unsigned int GetNumTanks(void) const {return (unsigned int)Tanks.size();}
@@ -143,8 +143,8 @@ public:
       @return the address of the specific tank, or zero if no such tank is
               available */
   inline FGTank* GetTank(unsigned int index) {
-                      if (index <= Tanks.size()-1) return Tanks[index];
-                      else                         return 0L;        }
+                      if (index < Tanks.size()) return Tanks[index];
+                      else                      return 0L;        }
 
   /** Returns the number of fuel tanks currently actively supplying fuel */
   inline int GetnumSelectedFuelTanks(void) const {return numSelectedFuelTanks;}
index bd2a0abb86872db53b43457af7b300b217f2cefd..390a11449709a7ee2502aeda5a5a1d56beb86cbe 100755 (executable)
@@ -58,7 +58,7 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGMSIS.h"
-#include "FGState.h"
+#include "models/FGAuxiliary.h"
 #include <cmath>          /* maths functions */
 #include <iostream>        // for cout, endl
 
@@ -66,7 +66,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGMSIS.cpp,v 1.13 2010/02/25 05:21:36 jberndt Exp $";
 static const char *IdHdr = ID_MSIS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 1765388a7e9a75bb97965b817ddc401e34c6241f..5761b1921965cfd421778bec430d7bb45b42d16c 100755 (executable)
@@ -41,12 +41,13 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "models/FGAtmosphere.h"
+#include "FGFDMExec.h"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_MSIS "$Id$"
+#define ID_MSIS "$Id: FGMSIS.h,v 1.7 2010/02/25 05:21:36 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -74,7 +75,7 @@ CLASS DOCUMENTATION
     and check http://www.brodo.de/english/pub/nrlmsise/index.html for
     updated releases of this package.
     @author David Culp
-    @version $Id$
+    @version $Id: FGMSIS.h,v 1.7 2010/02/25 05:21:36 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 7bebc7d3400dabf4221a5f1ca56bdeacf2b597a2..93c388f5f60f2b6dddae881660c2a24376d301f5 100755 (executable)
@@ -42,14 +42,13 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGMars.h"
-#include "FGState.h"
 #include <iostream>
 
 using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGMars.cpp,v 1.10 2010/02/25 05:21:36 jberndt Exp $";
 static const char *IdHdr = ID_MARS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 5f4bba35083f89c1ce51bcc7e7211232338c5a6f..e98634ecfb7661f707e9067dc689faaa62460d46 100755 (executable)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_MARS "$Id$"
+#define ID_MARS "$Id: FGMars.h,v 1.8 2009/10/02 10:30:09 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -58,7 +58,7 @@ CLASS DOCUMENTATION
 
 /** Models the Martian atmosphere.
     @author Jon Berndt
-    @version $Id$
+    @version $Id: FGMars.h,v 1.8 2009/10/02 10:30:09 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 1148c81b6fe64fff7e88647b79d222f48a590cc9..30c2f2244f0dafd45dbce930af012b4c4f65f42d 100755 (executable)
@@ -45,7 +45,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGAccelerometer.cpp,v 1.8 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_ACCELEROMETER;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index d552fe434de6846fbcadf270ec7e643ab817ff1f..5616ed55b0cb7029849663a2e31d7708fa453fea 100755 (executable)
@@ -50,7 +50,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ACCELEROMETER "$Id$"
+#define ID_ACCELEROMETER "$Id: FGAccelerometer.h,v 1.4 2009/10/02 10:30:09 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -110,7 +110,7 @@ even varying all the way from 0.95 to 1.05 in adjacent frames - whatever the del
 time.
 
 @author Jon S. Berndt
-@version $Revision$
+@version $Revision: 1.4 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
old mode 100755 (executable)
new mode 100644 (file)
index ae2aa38..4c58beb
@@ -43,7 +43,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGActuator.cpp,v 1.14 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_ACTUATOR;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
old mode 100755 (executable)
new mode 100644 (file)
index ecfb3bf..7a7866e
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ACTUATOR "$Id$"
+#define ID_ACTUATOR "$Id: FGActuator.h,v 1.11 2009/10/02 10:30:09 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -111,7 +111,7 @@ Example:
 @endcode
 
 @author Jon S. Berndt
-@version $Revision$
+@version $Revision: 1.11 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 3d0689d382e0a364a2800cc23b66ccfce9155827..0158b63560a36b867b7b6349a7a5501332287278 100644 (file)
@@ -46,7 +46,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGDeadBand.cpp,v 1.9 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_DEADBAND;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 9dd4a39a354cb819ae5dabc2126378c4feab9a9d..80464769f6ef2618a92fa9a724fffde3ad73dad7 100644 (file)
@@ -43,7 +43,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_DEADBAND "$Id$"
+#define ID_DEADBAND "$Id: FGDeadBand.h,v 1.9 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -80,7 +80,7 @@ CLASS DOCUMENTATION
     produce no output. For example, say that the width value is 2.0. If the
     input is between -1.0 and +1.0, the output will be zero.
     @author Jon S. Berndt
-    @version $Id$
+    @version $Id: FGDeadBand.h,v 1.9 2009/10/24 22:59:30 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index d1f454555f5e73f931e75d187ba34a93579a2c0b..8e713589f2f73712d5971f0b26b6cfc6d724cd11 100644 (file)
@@ -47,7 +47,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.27 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_FCSCOMPONENT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index b1fc2c6c5d7057742bf9ba6640f152d5330fea2d..27186fb6de80a6cd50ab389708e4d7610ef40f83 100644 (file)
@@ -45,7 +45,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FCSCOMPONENT "$Id$"
+#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -80,7 +80,7 @@ CLASS DOCUMENTATION
     - FGActuator
 
     @author Jon S. Berndt
-    @version $Id$
+    @version $Id: FGFCSComponent.h,v 1.16 2009/10/24 22:59:30 jberndt Exp $
     @see Documentation for the FGFCS class, and for the configuration file class
 */
 
index d8a91572e3879e7492c24fdc1de9bcca6002c73e..c6a352f3b7d01ed7c35dcb9bc014fbf4dd5588d9 100755 (executable)
@@ -45,7 +45,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGFCSFunction.cpp,v 1.9 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_FCSFUNCTION;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index fe731e8c3f25a8db1ee566ae5b8c9625a2f52ec6..d6524edf248c195808c555b7aab6be905d869650 100755 (executable)
@@ -45,7 +45,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FCSFUNCTION "$Id$"
+#define ID_FCSFUNCTION "$Id: FGFCSFunction.h,v 1.7 2009/10/02 10:30:09 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -105,7 +105,7 @@ a function (from an aero specification):
 </function>
 @endcode
 
-    @version $Id$
+    @version $Id: FGFCSFunction.h,v 1.7 2009/10/02 10:30:09 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index f0ca4906406cf6b2f04ade940e8da0538c5ff0be..2aab6e2b80d06844fc11f420d939a914c98db86c 100644 (file)
@@ -48,7 +48,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGFilter.cpp,v 1.15 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_FILTER;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 7aeafc202c293eea8432d4a2c0bb1dcadb5bf253..efb03541cef6cd4f63575456105a6a01ec68aa73 100644 (file)
@@ -43,7 +43,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FILTER "$Id$"
+#define ID_FILTER "$Id: FGFilter.h,v 1.12 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -228,7 +228,7 @@ is so that the last component in a "string" can copy its value to the appropriat
 output, such as the elevator, or speedbrake, etc.
 
 @author Jon S. Berndt
-@version $Revision$
+@version $Revision: 1.12 $
 
 */
 
index 0ecb8c6459fe0f60dcc6a184f1c66c2767899bce..e52cd37e6dd830b3974c5f63c728337fb32e3e4d 100644 (file)
@@ -47,7 +47,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGGain.cpp,v 1.20 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_GAIN;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 525c4e449cbcd0de44882ef5e0d1b21bcb6daf8b..5383cab20908080e5a540a9e7725bbf34ecdd666 100644 (file)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_GAIN "$Id$"
+#define ID_GAIN "$Id: FGGain.h,v 1.14 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -208,7 +208,7 @@ CLASS DOCUMENTATION
     @endcode
 
     @author Jon S. Berndt
-    @version $Revision$
+    @version $Revision: 1.14 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 2325dec1e25135a9afaf9b87e65f8ea797ed6389..9046e4975b00ea1f4a9143990a803f71084d75b9 100644 (file)
@@ -44,7 +44,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGGradient.cpp,v 1.4 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_GRADIENT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index ce7dac4f8042ddf48c0a53089a281dcf2d24fe74..06d3e843f936a57abb471b151280d260a0a1233d 100644 (file)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_GRADIENT "$Id$"
+#define ID_GRADIENT "$Id: FGGradient.h,v 1.5 2009/10/02 10:30:09 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index 740c01e3a554bf1166ffad03211370e3d433a26d..dffb3c9da3d017a531a80f24c695fdeb8971b69f 100755 (executable)
@@ -44,7 +44,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGGyro.cpp,v 1.5 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_GYRO;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index af10851bfa463f8e091d96538bf36e4102d21511..2dcc9fb215930ee2ec57e9b991846e92eedb3509 100755 (executable)
@@ -50,7 +50,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_GYRO "$Id$"
+#define ID_GYRO "$Id: FGGyro.h,v 1.5 2009/12/11 06:03:06 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -70,7 +70,6 @@ Syntax:
 
 @code
 <gyro name="name">
-  <input> property </input>
   <lag> number </lag>
   <noise variation="PERCENT|ABSOLUTE"> number </noise>
   <quantization name="name">
@@ -86,8 +85,8 @@ Syntax:
 Example:
 
 @code
-<gyro name="aero/gyro/qbar">
-  <input> aero/qbar </input>
+<gyro name="aero/gyro/roll">
+  <axis> X </axis>
   <lag> 0.5 </lag>
   <noise variation="PERCENT"> 2 </noise>
   <quantization name="aero/gyro/quantized/qbar">
@@ -99,9 +98,6 @@ Example:
 </gyro>
 @endcode
 
-The only required element in the gyro definition is the input element. In that
-case, no degradation would be modeled, and the output would simply be the input.
-
 For noise, if the type is PERCENT, then the value supplied is understood to be a
 percentage variance. That is, if the number given is 0.05, the the variance is
 understood to be +/-0.05 percent maximum variance. So, the actual value for the gyro
@@ -110,7 +106,7 @@ even varying all the way from 0.95 to 1.05 in adjacent frames - whatever the del
 time.
 
 @author Jon S. Berndt
-@version $Revision$
+@version $Revision: 1.5 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 931c1740caf2612803218b03dfd273edec153c26..525fcee377cdbf9a6a2ef124f7ecf0c47ead5a51 100644 (file)
@@ -46,7 +46,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGKinemat.cpp,v 1.10 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_FLAPS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 8dcc73bb876cc9c1478ef4e4fc0ca16dc00e11f1..93ae1ce762c9abafe22c2466042a196e3c0a9206 100644 (file)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FLAPS "$Id$"
+#define ID_FLAPS "$Id: FGKinemat.h,v 1.10 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
index 368d3524e9daf28b114336d7a5012c40f9ce90bc..3c04e68fa508203cdca2c4980ae2246736b0c619 100755 (executable)
@@ -47,7 +47,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGMagnetometer.cpp,v 1.5 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_MAGNETOMETER;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index e806fb62280a8b614203f30d24d3cd1649651020..c7a850ab31b5a3e1e404f88fa4f594f907d06e68 100755 (executable)
@@ -50,7 +50,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_MAGNETOMETER "$Id$"
+#define ID_MAGNETOMETER "$Id: FGMagnetometer.h,v 1.4 2009/12/11 06:03:06 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -70,8 +70,13 @@ Syntax:
 
 @code
 <magnetometer name="name">
-  <input> property </input>
+  <axis> {X|Y|Z} </axis>
   <lag> number </lag>
+  <orientation unit=DEG">
+    <x> number </x>
+    <y> number </y>
+    <z> number </z>
+  </orientation>
   <noise variation="PERCENT|ABSOLUTE"> number </noise>
   <quantization name="name">
     <bits> number </bits>
@@ -87,8 +92,8 @@ Syntax:
 Example:
 
 @code
-<magnetometer name="aero/magnetometer/qbar">
-  <input> aero/qbar </input>
+<magnetometer name="aero/magnetometer/X">
+  <axis> X </axis>
   <lag> 0.5 </lag>
   <noise variation="PERCENT"> 2 </noise>
   <quantization name="aero/magnetometer/quantized/qbar">
@@ -101,8 +106,9 @@ Example:
 </magnetometer>
 @endcode
 
-The only required element in the magnetometer definition is the input element. In that
-case, no degradation would be modeled, and the output would simply be the input.
+The only required element in the magnetometer definition is the axis element. In
+the default case, no degradation would be modeled, and the output would simply be
+the input.
 
 For noise, if the type is PERCENT, then the value supplied is understood to be a
 percentage variance. That is, if the number given is 0.05, the the variance is
@@ -112,7 +118,7 @@ even varying all the way from 0.95 to 1.05 in adjacent frames - whatever the del
 time.
 
 @author Jon S. Berndt
-@version $Revision$
+@version $Revision: 1.4 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 3dda266f208c4ddc37037d13061cbad4a3ae254a..ac265b8ff991275b7cff7e2561a3dc5ce99b44dc 100755 (executable)
@@ -44,7 +44,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGPID.cpp,v 1.16 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_PID;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index adad3606c571874af027162d560863bfecc74285..a573dc3214a28c165b473daa9dbed00e4c22eba0 100755 (executable)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PID "$Id$"
+#define ID_PID "$Id: FGPID.h,v 1.12 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -83,7 +83,7 @@ CLASS DOCUMENTATION
 </pre>
 
     @author Jon S. Berndt
-    @version $Revision$
+    @version $Revision: 1.12 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 1ca89b6ba7eb66a3f9db8c035880e6d5628ef7ee..1f46dc9540a9679da8acb35a3c1b3c072ffde525 100755 (executable)
@@ -46,7 +46,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGSensor.cpp,v 1.20 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_SENSOR;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 136099536e51d8b93cff0c7800d9e49c60cbefad..bcc18dbe51f88534bdac7b6e5d3c8ea26135aef4 100755 (executable)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_SENSOR "$Id$"
+#define ID_SENSOR "$Id: FGSensor.h,v 1.19 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -107,7 +107,7 @@ time. The delay element can specify a frame delay. The integer number provided i
 the number of frames to delay the output signal.
 
 @author Jon S. Berndt
-@version $Revision$
+@version $Revision: 1.19 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 4f6d52f3eaed93fdbf4003407bb6c269a9dfead1..4defe4f7a76451d2fa454e8b79572a125b515dab 100755 (executable)
@@ -48,7 +48,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_SensorOrientation "$Id$"
+#define ID_SensorOrientation "$Id: FGSensorOrientation.h,v 1.3 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -65,7 +65,7 @@ CLASS DOCUMENTATION
 Syntax:
 
 @author Jon S. Berndt
-@version $Revision$
+@version $Revision: 1.3 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index e77ee72082ea1b503bbc1365a6fe5623c06edf7e..40e6753510a627fccf5ea868404e89b205aebf00 100644 (file)
@@ -45,7 +45,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGSummer.cpp,v 1.7 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_SUMMER;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index e37642855b6f5ed0f35c1e2f78c24a87ba594a89..12a198d01bd47bc4f7f0599132111f7e9e70e5b9 100644 (file)
@@ -43,7 +43,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_SUMMER "$Id$"
+#define ID_SUMMER "$Id: FGSummer.h,v 1.9 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -99,7 +99,7 @@ CLASS DOCUMENTATION
 </pre>
 
     @author Jon S. Berndt
-    @version $Id$
+    @version $Id: FGSummer.h,v 1.9 2009/10/24 22:59:30 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index c29c7227752ccfe485453afd30ec96512cf23e6f..4e68ea7ffc2a5cefe08df67ca1cc5a6ef8b9e7bf 100644 (file)
@@ -69,7 +69,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGSwitch.cpp,v 1.19 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_SWITCH;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index a68c2c4a55829a24dd992a83e61885c70f36b52a..a230aef7e5a2fadc1e5bd7ef35cb823e6c0ba4dc 100644 (file)
@@ -45,7 +45,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_SWITCH "$Id$"
+#define ID_SWITCH "$Id: FGSwitch.h,v 1.13 2009/10/02 10:30:09 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -124,7 +124,7 @@ ap/attitude_hold takes the value 1), the value of the switch component will be
 whatever value fcs/roll-ap-error-summer is.
 
 @author Jon S. Berndt
-@version $Id$
+@version $Id: FGSwitch.h,v 1.13 2009/10/02 10:30:09 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 1ab17c7b60c0a9529908f553d04d41f042c110f4..b1459ebaddea16260d37bb8ef805415df9545062 100644 (file)
@@ -40,7 +40,6 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGElectric.h"
-#include "FGState.h"
 #include "models/FGPropulsion.h"
 #include "models/propulsion/FGThruster.h"
 
@@ -51,7 +50,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGElectric.cpp,v 1.8 2010/02/25 05:21:36 jberndt Exp $";
 static const char *IdHdr = ID_ELECTRIC;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -67,7 +66,7 @@ FGElectric::FGElectric(FGFDMExec* exec, Element *el, int engine_number)
   PowerWatts = 745.7;
   hptowatts = 745.7;
 
-  dt = State->Getdt();
+  dt = FDMExec->GetDeltaT();
 
   if (el->FindElement("power"))
     PowerWatts = el->FindElementValueAsNumberConvertTo("power","WATTS");
index da4a575bb0349f869f137276da85dad762584d9d..7bcdb406ff45c24131bf472d5a18f543265c6d10 100644 (file)
@@ -45,7 +45,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ELECTRIC "$Id$";
+#define ID_ELECTRIC "$Id: FGElectric.h,v 1.8 2009/10/24 22:59:30 jberndt Exp $";
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -65,7 +65,7 @@ CLASS DOCUMENTATION
     there is no battery model available, so this motor does not consume any
     energy.  There is no internal friction.
     @author David Culp
-    @version "$Id$"
+    @version "$Id: FGElectric.h,v 1.8 2009/10/24 22:59:30 jberndt Exp $"
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index b95837b041a2d1140be051992091d9aa97654255..abaf368e2538b3e82a5b1ff2ee4d3599a342dab0 100644 (file)
@@ -41,7 +41,7 @@ INCLUDES
 #include "FGTank.h"
 #include "FGPropeller.h"
 #include "FGNozzle.h"
-#include "FGState.h"
+#include "FGRotor.h"
 #include "models/FGPropulsion.h"
 #include "input_output/FGXMLParse.h"
 #include "math/FGColumnVector3.h"
@@ -54,7 +54,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGEngine.cpp,v 1.38 2010/06/02 04:05:13 jberndt Exp $";
 static const char *IdHdr = ID_ENGINE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -80,7 +80,6 @@ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
   ResetToIC(); // initialize dynamic terms
 
   FDMExec = exec;
-  State = FDMExec->GetState();
   Atmosphere = FDMExec->GetAtmosphere();
   FCS = FDMExec->GetFCS();
   Propulsion = FDMExec->GetPropulsion();
@@ -124,8 +123,13 @@ FGEngine::FGEngine(FGFDMExec* exec, Element* engine_element, int engine_number)
     while (local_element) {
       int tankID = (int)local_element->GetDataAsNumber();
       FGTank* tank = Propulsion->GetTank(tankID); 
-      AddFeedTank( tankID , tank->GetPriority());
-      FuelDensity = tank->GetDensity();
+      if (tank) {
+        AddFeedTank(tankID, tank->GetPriority());
+        FuelDensity = tank->GetDensity();
+      } else {
+        cerr << "Feed tank " << tankID <<
+          " specified in engine definition does not exist." << endl;
+      }
       local_element = engine_element->GetParent()->FindNextElement("feed");
     }
   } else {
@@ -168,6 +172,7 @@ void FGEngine::ResetToIC(void)
   TrimMode = false;
   FuelFlow_gph = 0.0;
   FuelFlow_pph = 0.0;
+  FuelFlowRate = 0.0;
   FuelFreeze = false;
 }
 
@@ -234,7 +239,7 @@ void FGEngine::ConsumeFuel(void)
 
 double FGEngine::CalcFuelNeed(void)
 {
-  double dT = State->Getdt()*Propulsion->GetRate();
+  double dT = FDMExec->GetDeltaT()*Propulsion->GetRate();
   FuelFlowRate = SLFuelFlowMax*PctPower;
   FuelExpended = FuelFlowRate*dT;
   return FuelExpended;
@@ -317,11 +322,13 @@ bool FGEngine::LoadThruster(Element *thruster_element)
     Thruster = new FGPropeller(FDMExec, document, EngineNumber);
   } else if (thrType == "nozzle") {
     Thruster = new FGNozzle(FDMExec, document, EngineNumber);
+  } else if (thrType == "rotor") {
+    Thruster = new FGRotor(FDMExec, document, EngineNumber);
   } else if (thrType == "direct") {
     Thruster = new FGThruster( FDMExec, document, EngineNumber);
   }
 
-  Thruster->SetdeltaT(State->Getdt() * Propulsion->GetRate());
+  Thruster->SetdeltaT(FDMExec->GetDeltaT() * Propulsion->GetRate());
 
   Debug(2);
   return true;
index c758d3bc7620a7701a0f65c08b6efcf39802971e..8a3f51a8e47c87da7e255706db99f7901a80db23 100644 (file)
@@ -45,6 +45,8 @@ INCLUDES
 
 #include "FGJSBBase.h"
 #include "input_output/FGXMLFileRead.h"
+#include "input_output/FGXMLElement.h"
+#include "models/FGFCS.h"
 #include "math/FGColumnVector3.h"
 #include <vector>
 #include <string>
@@ -53,7 +55,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ENGINE "$Id$"
+#define ID_ENGINE "$Id: FGEngine.h,v 1.20 2010/02/25 05:21:36 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -62,9 +64,7 @@ FORWARD DECLARATIONS
 namespace JSBSim {
 
 class FGFDMExec;
-class FGState;
 class FGAtmosphere;
-class FGFCS;
 class FGAircraft;
 class FGPropagate;
 class FGPropulsion;
@@ -118,7 +118,7 @@ CLASS DOCUMENTATION
        documentation for engine and thruster classes.
 </pre>     
     @author Jon S. Berndt
-    @version $Id$
+    @version $Id: FGEngine.h,v 1.20 2010/02/25 05:21:36 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -228,7 +228,6 @@ protected:
   double FuelDensity;
 
   FGFDMExec*      FDMExec;
-  FGState*        State;
   FGAtmosphere*   Atmosphere;
   FGFCS*          FCS;
   FGPropulsion*   Propulsion;
index ff7532916325914025583df537d86be4388e5979..0180d18e404b15f73aec103a04550d1822ce50c2 100644 (file)
@@ -53,7 +53,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGForce.cpp,v 1.14 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_FORCE;
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index eb2f59506290ca98fc3f537fb81eea7262e335fd..9ec0d30649ab725e0904bdadaceee545e9e7ea85 100644 (file)
@@ -66,7 +66,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FORCE "$Id$"
+#define ID_FORCE "$Id: FGForce.h,v 1.13 2009/10/05 04:48:03 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -215,7 +215,7 @@ and vMn, the moments, can be made directly. Otherwise, the usage is similar.<br>
 <br><br></p>
 
     @author Tony Peden
-    @version $Id$
+    @version $Id: FGForce.h,v 1.13 2009/10/05 04:48:03 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index fdbd1533fe8cf9f6b020595eb4970b522a6740e0..f1d0fb12e1911e07bc223f71fbe70d41656c6bf2 100644 (file)
@@ -47,7 +47,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGNozzle.cpp,v 1.13 2009/10/26 03:49:58 jberndt Exp $";
 static const char *IdHdr = ID_NOZZLE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 4b5dc40a559afa2cf25e1ef348b1ef58263e1ce1..d2945ba7b677bf4020d3b9d90fd33850995221c7 100644 (file)
@@ -44,7 +44,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_NOZZLE "$Id$";
+#define ID_NOZZLE "$Id: FGNozzle.h,v 1.8 2009/10/26 03:49:58 jberndt Exp $";
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -75,7 +75,7 @@ CLASS DOCUMENTATION
 
     All parameters MUST be specified.  
     @author Jon S. Berndt
-    @version $Id$
+    @version $Id: FGNozzle.h,v 1.8 2009/10/26 03:49:58 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 7f484e6b9e97ae5594abef65ca45e505f3b29084..77dcf245a64858c28b456f373d1f31e24f64f444 100644 (file)
@@ -43,8 +43,8 @@ INCLUDES
 #include <sstream>
 
 #include "FGPiston.h"
-#include "FGState.h"
 #include "models/FGAtmosphere.h"
+#include "models/FGAuxiliary.h"
 #include "models/FGPropulsion.h"
 #include "FGPropeller.h"
 #include <iostream>
@@ -53,7 +53,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGPiston.cpp,v 1.52 2010/06/05 12:12:34 jberndt Exp $";
 static const char *IdHdr = ID_PISTON;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -74,7 +74,7 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
   // Defaults and initializations
 
   Type = etPiston;
-  dt = State->Getdt();
+  dt = FDMExec->GetDeltaT();
 
   // These items are read from the configuration file
   // Defaults are from a Lycoming O-360, more or less
@@ -96,6 +96,9 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
   Z_airbox = -999;
   Ram_Air_Factor = 1;
   PeakMeanPistonSpeed_fps = 100;
+  FMEPDynamic= 18400;
+  FMEPStatic = 46500;
+
 
   // These are internal program variables
 
@@ -201,6 +204,10 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
     Z_airbox = el->FindElementValueAsNumber("air-intake-impedance-factor");
   if (el->FindElement("ram-air-factor"))
     Ram_Air_Factor  = el->FindElementValueAsNumber("ram-air-factor");
+  if (el->FindElement("dynamic-fmep"))
+    FMEPDynamic= el->FindElementValueAsNumberConvertTo("dynamic-fmep","PA");
+  if (el->FindElement("static-fmep"))
+    FMEPStatic = el->FindElementValueAsNumberConvertTo("static-fmep","PA");
   if (el->FindElement("peak-piston-speed"))
     PeakMeanPistonSpeed_fps  = el->FindElementValueAsNumber("peak-piston-speed");
   if (el->FindElement("numboostspeeds")) { // Turbo- and super-charging parameters
@@ -244,8 +251,8 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
   // Create IFSC to match the engine if not provided
   if (ISFC < 0) {
       double pmep = 29.92 - MaxManifoldPressure_inHg;
-      pmep *= inhgtopa;
-      double fmep = (18400 * RatedMeanPistonSpeed_fps * fttom + 46500);
+      pmep *= inhgtopa  * volumetric_efficiency;
+      double fmep = (FMEPDynamic * RatedMeanPistonSpeed_fps * fttom + FMEPStatic);
       double hp_loss = ((pmep + fmep) * displacement_SI * MaxRPM)/(Cycles*22371);
       ISFC = ( 1.1*Displacement * MaxRPM * volumetric_efficiency *(MaxManifoldPressure_inHg / 29.92) ) / (9411 * (MaxHP+hp_loss));
 // cout <<"FMEP: "<< fmep <<" PMEP: "<< pmep << " hp_loss: " <<hp_loss <<endl;
@@ -262,13 +269,13 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
  * Where:
  * Pm = Manifold Pressure
  * Pa = Ambient Pressre
- * Ze = engine impedance, Ze is effectively 1 / Mean Piston Speed  
+ * Ze = engine impedance, Ze is effectively 1 / Mean Piston Speed
  * Zi = airbox impedance
  * Zt = throttle impedance
- * 
+ *
  * For the calculation below throttle is fully open or Zt = 0
  *
- * 
+ *
  *
  */
 
@@ -276,7 +283,9 @@ FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number)
     double Ze=PeakMeanPistonSpeed_fps/RatedMeanPistonSpeed_fps; // engine impedence
     Z_airbox = (standard_pressure *Ze / maxMAP) - Ze; // impedence of airbox
   }
-  Z_throttle=(((MaxRPM * Stroke) / 360)/((IdleRPM * Stroke) / 360))*(standard_pressure/minMAP - 1) - Z_airbox; // Constant for Throttle impedence
+  // Constant for Throttle impedence
+  Z_throttle=(PeakMeanPistonSpeed_fps/((IdleRPM * Stroke) / 360))*(standard_pressure/minMAP - 1) - Z_airbox; 
+  //  Z_throttle=(MaxRPM/IdleRPM )*(standard_pressure/minMAP+2); // Constant for Throttle impedence
 
   string property_name, base_property_name;
   base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
@@ -376,14 +385,11 @@ void FGPiston::ResetToIC(void)
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
 double FGPiston::Calculate(void)
 {
   if (FuelFlow_gph > 0.0) ConsumeFuel();
 
   Throttle = FCS->GetThrottlePos(EngineNumber);
-  // calculate the throttle plate angle.  1 unit is approx pi/2 radians.
-  ThrottleAngle = MinThrottle+((MaxThrottle-MinThrottle)*Throttle );
   Mixture = FCS->GetMixturePos(EngineNumber);
 
   //
@@ -435,7 +441,7 @@ double FGPiston::Calculate(void)
 
 double FGPiston::CalcFuelNeed(void)
 {
-  double dT = State->Getdt() * Propulsion->GetRate();
+  double dT = FDMExec->GetDeltaT() * Propulsion->GetRate();
   FuelExpended = FuelFlowRate * dT;
   return FuelExpended;
 }
@@ -444,9 +450,13 @@ double FGPiston::CalcFuelNeed(void)
 
 int FGPiston::InitRunning(void) {
   Magnetos=3;
-  //Thruster->SetRPM( 1.1*IdleRPM/Thruster->GetGearRatio() );
-  Thruster->SetRPM( 1000 );
+  p_amb = Atmosphere->GetPressure() * psftopa;
+  double mix= p_amb / (101325.0*1.3);
+  FCS->SetMixturePos(EngineNumber, mix);
+  Thruster->SetRPM( 2.*IdleRPM/Thruster->GetGearRatio() );
+  //Thruster->SetRPM( 1000 );
   Running=true;
+// cout <<"Set Running in FGPiston. RPM:" << Thruster->GetRPM()*Thruster->GetGearRatio() <<" Pressure:"<<p_amb<<" Mixture:"<< mix <<endl;
   return 1;
 }
 
@@ -461,7 +471,6 @@ void FGPiston::doEngineStartup(void)
   // (spark, fuel, starter motor etc)
   bool spark;
   bool fuel;
-
   // Check for spark
   Magneto_Left = false;
   Magneto_Right = false;
@@ -541,7 +550,7 @@ void FGPiston::doBoostControl(void)
       if(p_amb < BoostSwitchPressure[BoostSpeed] - BoostSwitchHysteresis) {
         BoostSpeed++;
       }
-    } else if(BoostSpeed > 0) {
+    } if(BoostSpeed > 0) {
       // Check if we need to change to a lower boost speed
       if(p_amb > BoostSwitchPressure[BoostSpeed - 1] + BoostSwitchHysteresis) {
         BoostSpeed--;
@@ -559,7 +568,7 @@ void FGPiston::doBoostControl(void)
  * from the throttle position, turbo/supercharger boost control
  * system, engine speed and local ambient air density.
  *
- * Inputs: p_amb, Throttle, ThrottleAngle,
+ * Inputs: p_amb, Throttle,
  *         MeanPistonSpeed_fps, dt
  *
  * Outputs: MAP, ManifoldPressure_inHg, TMAP
@@ -567,7 +576,7 @@ void FGPiston::doBoostControl(void)
 
 void FGPiston::doMAP(void)
 {
-  double Zt =(1-Throttle)*(1-Throttle)*Z_throttle; // throttle impedence
+  double Zt = (1-Throttle)*(1-Throttle)*Z_throttle; // throttle impedence
   double Ze= MeanPistonSpeed_fps > 0 ? PeakMeanPistonSpeed_fps/MeanPistonSpeed_fps : 999999; // engine impedence
 
   double map_coefficient = Ze/(Ze+Z_airbox+Zt);
@@ -579,7 +588,7 @@ void FGPiston::doMAP(void)
   // Find the mean effective pressure required to achieve this manifold pressure
   // Fixme: determine the HP consumed by the supercharger
 
-  PMEP = TMAP - p_amb; // Fixme: p_amb should be exhaust manifold pressure
+  PMEP = (TMAP - p_amb) * volumetric_efficiency; // Fixme: p_amb should be exhaust manifold pressure
 
   if (Boosted) {
     // If takeoff boost is fitted, we currently assume the following throttle map:
@@ -618,7 +627,7 @@ void FGPiston::doMAP(void)
  * (used in CHT calculation for air-cooled engines).
  *
  * Inputs: p_amb, R_air, T_amb, MAP, Displacement,
- *   RPM, volumetric_efficiency, ThrottleAngle
+ *   RPM, volumetric_efficiency,
  *
  * TODO: Model inlet manifold air temperature.
  *
@@ -627,9 +636,10 @@ void FGPiston::doMAP(void)
 
 void FGPiston::doAirFlow(void)
 {
-  double gamma = 1.1; // specific heat constants
+  double gamma = 1.3; // specific heat constants
 // loss of volumentric efficiency due to difference between MAP and exhaust pressure
-  double ve =((gamma-1)/gamma)+( CompressionRatio -(p_amb/MAP))/(gamma*( CompressionRatio - 1));
+// Eq 6-10 from The Internal Combustion Engine - Charles Taylor Vol 1
+  double ve =((gamma-1)/gamma) +( CompressionRatio -(p_amb/MAP))/(gamma*( CompressionRatio - 1));
 
   rho_air = p_amb / (R_air * T_amb);
   double swept_volume = (displacement_SI * (RPM/60)) / 2;
@@ -665,15 +675,11 @@ void FGPiston::doFuelFlow(void)
 /**
  * Calculate the power produced by the engine.
  *
- * Currently, the JSBSim propellor model does not allow the
- * engine to produce enough RPMs to get up to a high horsepower.
- * When tested with sufficient RPM, it has no trouble reaching
- * 200HP.
- *
- * Inputs: ManifoldPressure_inHg, p_amb, RPM, T_amb,
+ * Inputs: ManifoldPressure_inHg, p_amb, RPM, T_amb, ISFC,
  *   Mixture_Efficiency_Correlation, Cycles, MaxHP, PMEP,
+ *   MeanPistonSpeed_fps
  *
- * Outputs: PctPower, HP
+ * Outputs: PctPower, HP, FMEP, IndicatedHorsePower
  */
 
 void FGPiston::doEnginePower(void)
@@ -686,9 +692,8 @@ void FGPiston::doEnginePower(void)
     ME = Mixture_Efficiency_Correlation->GetValue(m_dot_fuel/m_dot_air);
 
     percent_RPM = RPM/MaxRPM;
-// Guestimate engine friction as a percentage of rated HP + a percentage of rpm + a percentage of Indicted HP
-//    friction = 1 - (percent_RPM * percent_RPM * percent_RPM/10);
-    FMEP = (-18400 * MeanPistonSpeed_fps * fttom - 46500);
+// Guestimate engine friction losses from Figure 4.4 of "Engines: An Introduction", John Lumley
+    FMEP = (-FMEPDynamic * MeanPistonSpeed_fps * fttom - FMEPStatic);
 
     power = 1;
 
@@ -770,7 +775,7 @@ void FGPiston::doCHT(void)
   double h2 = -3.95;
   double h3 = -140.0; // -0.05 * 2800 (default maxrpm)
 
-  double arbitary_area = 1.0;
+  double arbitary_area = Displacement/360.0;
   double CpCylinderHead = 800.0;
   double MassCylinderHead = 8.0;
 
@@ -813,8 +818,8 @@ void FGPiston::doOilTemperature(void)
   if (OilPressure_psi > 5.0 ) {
     time_constant = 5000 / OilPressure_psi; // Guess at a time constant for circulated oil.
                                             // The higher the pressure the faster it reaches
-                                           // target temperature.  Oil pressure should be about
-                                           // 60 PSI yielding a TC of about 80.
+                                            // target temperature.  Oil pressure should be about
+                                            // 60 PSI yielding a TC of about 80.
   } else {
     time_constant = 1000;  // Time constant for engine-off; reflects the fact
                            // that oil is no longer getting circulated
@@ -919,12 +924,13 @@ void FGPiston::Debug(int from)
       cout << "      Cycles: "              << Cycles                   << endl;
       cout << "      IdleRPM: "             << IdleRPM                  << endl;
       cout << "      MaxRPM: "              << MaxRPM                   << endl;
-      cout << "      MaxThrottle: "         << MaxThrottle              << endl;
-      cout << "      MinThrottle: "         << MinThrottle              << endl;
+      cout << "      Throttle Constant: "   << Z_throttle               << endl;
       cout << "      ISFC: "                << ISFC                     << endl;
       cout << "      Volumetric Efficiency: " << volumetric_efficiency    << endl;
       cout << "      PeakMeanPistonSpeed_fps: " << PeakMeanPistonSpeed_fps << endl;
       cout << "      Intake Impedance Factor: " << Z_airbox << endl;
+      cout << "      Dynamic FMEP Factor: " << FMEPDynamic << endl;
+      cout << "      Static FMEP Factor: " << FMEPStatic << endl;
 
       cout << endl;
       cout << "      Combustion Efficiency table:" << endl;
index 2bfb1971a8ec7c3ce129c5c57c10be1f2c042a21..a008e6a7327f526d27b1f96772a0d586e1430ddf 100644 (file)
@@ -41,13 +41,12 @@ INCLUDES
 
 #include "FGEngine.h"
 #include "math/FGTable.h"
-#include "input_output/FGXMLElement.h"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PISTON "$Id$";
+#define ID_PISTON "$Id: FGPiston.h,v 1.23 2010/02/25 05:21:36 jberndt Exp $";
 #define FG_MAX_BOOST_SPEEDS 3
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -66,7 +65,7 @@ CLASS DOCUMENTATION
 
 @code
 <piston_engine name="{string}">
-  <minmp unit="{INHG | PA | ATM}"> {number} </minmp> <!-- Depricated -->
+  <minmp unit="{INHG | PA | ATM}"> {number} </minmp>
   <maxmp unit="{INHG | PA | ATM}"> {number} </maxmp>
   <displacement unit="{IN3 | LTR | CC}"> {number} </displacement>
   <bore unit="{IN | M}"> {number} </bore>
@@ -82,6 +81,8 @@ CLASS DOCUMENTATION
   <minthrottle> {number} </minthrottle>
   <bsfc unit="{LBS/HP*HR | "KG/KW*HR"}"> {number} </bsfc>
   <volumetric-efficiency> {number} </volumetric-efficiency>
+  <dynamic-fmep unit="{INHG | PA | ATM}"> {number} </dynamic-fmep>
+  <static-fmep unit="{INHG | PA | ATM}"> {number} </static-fmep>
   <numboostspeeds> {number} </numboostspeeds>
   <boostoverride> {0 | 1} </boostoverride>
   <boostmanual> {0 | 1} </boostmanual>
@@ -180,7 +181,7 @@ CLASS DOCUMENTATION
     @author Dave Luff (engine operational code)
     @author David Megginson (initial porting and additional code)
     @author Ron Jensen (additional engine code)
-    @version $Id$
+    @version $Id: FGPiston.h,v 1.23 2010/02/25 05:21:36 jberndt Exp $
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -216,7 +217,6 @@ public:
   double getRPM(void) {return RPM;}
 
 protected:
-  double ThrottleAngle;
 
 private:
   int crank_counter;
@@ -224,9 +224,8 @@ private:
   double IndicatedHorsePower;
   double PMEP;
   double FMEP;
-  double SpeedSlope;
-  double SpeedIntercept;
-  double AltitudeSlope;
+  double FMEPDynamic;
+  double FMEPStatic;
   double PowerAvailable;
 
   // timestep
index fb1be8ac125de1d236b4014a6dfbf1c9c97c7c97..8204bb9d21cd88bd127071fee4da1e5eb43a419b 100644 (file)
@@ -48,7 +48,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGPropeller.cpp,v 1.30 2010/05/02 15:10:07 jberndt Exp $";
 static const char *IdHdr = ID_PROPELLER;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -76,6 +76,9 @@ FGPropeller::FGPropeller(FGFDMExec* exec, Element* prop_element, int num)
   Reverse_coef = 0.0;
   GearRatio = 1.0;
   CtFactor = CpFactor = 1.0;
+  ConstantSpeed = 0;
+  cThrust = cPower = CtMach = CpMach = 0;
+  Vinduced = 0.0;
 
   if (prop_element->FindElement("ixx"))
     Ixx = prop_element->FindElementValueAsNumberConvertTo("ixx", "SLUG*FT2");
@@ -91,8 +94,12 @@ FGPropeller::FGPropeller(FGFDMExec* exec, Element* prop_element, int num)
     MaxPitch = prop_element->FindElementValueAsNumber("maxpitch");
   if (prop_element->FindElement("minrpm"))
     MinRPM = prop_element->FindElementValueAsNumber("minrpm");
-  if (prop_element->FindElement("maxrpm"))
+  if (prop_element->FindElement("maxrpm")) {
     MaxRPM = prop_element->FindElementValueAsNumber("maxrpm");
+    ConstantSpeed = 1;
+    }
+  if (prop_element->FindElement("constspeed"))
+    ConstantSpeed = (int)prop_element->FindElementValueAsNumber("constspeed");
   if (prop_element->FindElement("reversepitch"))
     ReversePitch = prop_element->FindElementValueAsNumber("reversepitch");
   for (int i=0; i<2; i++) {
@@ -102,6 +109,10 @@ FGPropeller::FGPropeller(FGFDMExec* exec, Element* prop_element, int num)
       cThrust = new FGTable(PropertyManager, table_element);
     } else if (name == "C_POWER") {
       cPower = new FGTable(PropertyManager, table_element);
+    } else if (name == "CT_MACH") {
+      CtMach = new FGTable(PropertyManager, table_element);
+    } else if (name == "CP_MACH") {
+      CpMach = new FGTable(PropertyManager, table_element);
     } else {
       cerr << "Unknown table type: " << name << " in propeller definition." << endl;
     }
@@ -129,6 +140,7 @@ FGPropeller::FGPropeller(FGFDMExec* exec, Element* prop_element, int num)
   vTorque.InitMatrix();
   D4 = Diameter*Diameter*Diameter*Diameter;
   D5 = D4*Diameter;
+  Pitch = MinPitch;
 
   string property_name, base_property_name;
   base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum);
@@ -140,6 +152,14 @@ FGPropeller::FGPropeller(FGFDMExec* exec, Element* prop_element, int num)
   PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetThrustCoefficient );
   property_name = base_property_name + "/propeller-rpm";
   PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetRPM );
+  property_name = base_property_name + "/helical-tip-Mach";
+  PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetHelicalTipMach );
+  property_name = base_property_name + "/constant-speed-mode";
+  PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetConstantSpeed,
+                      &FGPropeller::SetConstantSpeed );
+  property_name = base_property_name + "/prop-induced-velocity_fps";
+  PropertyManager->Tie( property_name.c_str(), this, &FGPropeller::GetInducedVelocity,
+                      &FGPropeller::SetInducedVelocity );
 
   Debug(0);
 }
@@ -150,6 +170,8 @@ FGPropeller::~FGPropeller()
 {
   delete cThrust;
   delete cPower;
+  delete CtMach;
+  delete CpMach;
 
   Debug(1);
 }
@@ -176,13 +198,27 @@ double FGPropeller::Calculate(double PowerAvailable)
   double rho = fdmex->GetAtmosphere()->GetDensity();
   double RPS = RPM/60.0;
 
-  if (RPS > 0.00) J = Vel / (Diameter * RPS); // Calculate J normally
-  else            J = 1000.0;                 // Set J to a high number
+  // Calculate helical tip Mach
+  double Area = 0.25*Diameter*Diameter*M_PI;
+  double Vtip = RPS * Diameter * M_PI;
+  HelicalTipMach = sqrt(Vtip*Vtip + Vel*Vel) / 
+                   fdmex->GetAtmosphere()->GetSoundSpeed(); 
+
+  if (RPS > 0.0) J = Vel / (Diameter * RPS); // Calculate J normally
+  else           J = Vel / Diameter;      
 
-  if (MaxPitch == MinPitch)  ThrustCoeff = cThrust->GetValue(J);
-  else                       ThrustCoeff = cThrust->GetValue(J, Pitch);
+  if (MaxPitch == MinPitch) {    // Fixed pitch prop
+         ThrustCoeff = cThrust->GetValue(J);
+  } else {                       // Variable pitch prop
+         ThrustCoeff = cThrust->GetValue(J, Pitch);
+  }
+  // Apply optional scaling factor to Ct (default value = 1)
   ThrustCoeff *= CtFactor;
 
+  // Apply optional Mach effects from CT_MACH table
+  if (CtMach) ThrustCoeff *= CtMach->GetValue(HelicalTipMach);
+
   if (P_Factor > 0.0001) {
     alpha = fdmex->GetAuxiliary()->Getalpha();
     beta  = fdmex->GetAuxiliary()->Getbeta();
@@ -191,6 +227,11 @@ double FGPropeller::Calculate(double PowerAvailable)
   }
 
   Thrust = ThrustCoeff*RPS*RPS*D4*rho;
+
+  // From B. W. McCormick, "Aerodynamics, Aeronautics, and Flight Mechanics"
+  // first edition, eqn. 6.15 (propeller analysis chapter).
+  Vinduced = 0.5 * (-Vel + sqrt(Vel*Vel + 2.0*Thrust/(rho*Area)));
+
   omega = RPS*2.0*M_PI;
 
   vFn(1) = Thrust;
@@ -203,12 +244,12 @@ double FGPropeller::Calculate(double PowerAvailable)
   vH(eY) = 0.0;
   vH(eZ) = 0.0;
 
-  if (omega > 0.0) ExcessTorque = GearRatio * PowerAvailable / omega;
-  else             ExcessTorque = GearRatio * PowerAvailable / 1.0;
+  if (omega > 0.0) ExcessTorque = PowerAvailable / omega;
+  else             ExcessTorque = PowerAvailable / 1.0;
 
   RPM = (RPS + ((ExcessTorque / Ixx) / (2.0 * M_PI)) * deltaT) * 60.0;
 
-  if (RPM < 1.0) RPM = 0; // Engine friction stops rotation arbitrarily at 1 RPM.
+  if (RPM < 0.0) RPM = 0.0; // Engine won't turn backwards
 
   // Transform Torque and momentum first, as PQR is used in this
   // equation and cannot be transformed itself.
@@ -223,19 +264,23 @@ double FGPropeller::GetPowerRequired(void)
 {
   double cPReq, J;
   double rho = fdmex->GetAtmosphere()->GetDensity();
+  double Vel = fdmex->GetAuxiliary()->GetAeroUVW(eU);
   double RPS = RPM / 60.0;
 
-  if (RPS != 0) J = fdmex->GetAuxiliary()->GetAeroUVW(eU) / (Diameter * RPS);
-  else          J = 1000.0; // Set J to a high number
+  if (RPS != 0.0) J = Vel / (Diameter * RPS);
+  else            J = Vel / Diameter; 
 
-  if (MaxPitch == MinPitch) { // Fixed pitch prop
-    Pitch = MinPitch;
+  if (MaxPitch == MinPitch) {   // Fixed pitch prop
     cPReq = cPower->GetValue(J);
+
   } else {                      // Variable pitch prop
 
-    if (MaxRPM != MinRPM) {   // fixed-speed prop
+    if (ConstantSpeed != 0) {   // Constant Speed Mode
 
       // do normal calculation when propeller is neither feathered nor reversed
+      // Note:  This method of feathering and reversing was added to support the
+      //        turboprop model.  It's left here for backward compatablity, but
+      //        now feathering and reversing should be done in Manual Pitch Mode.
       if (!Feathered) {
         if (!Reversed) {
 
@@ -267,19 +312,29 @@ double FGPropeller::GetPowerRequired(void)
         Pitch += (MaxPitch - Pitch) / 300; // just a guess (about 5 sec to fully feathered)
       }
 
-    } else { // Variable Speed Prop
-      Pitch = MinPitch + (MaxPitch - MinPitch) * Advance;
+    } else { // Manual Pitch Mode, pitch is controlled externally
+
     }
+  
     cPReq = cPower->GetValue(J, Pitch);
   }
+
+  // Apply optional scaling factor to Cp (default value = 1)
   cPReq *= CpFactor;
 
-  if (RPS > 0) {
+  // Apply optional Mach effects from CP_MACH table
+  if (CpMach) cPReq *= CpMach->GetValue(HelicalTipMach);
+
+  if (RPS > 0.1) {
     PowerRequired = cPReq*RPS*RPS*RPS*D5*rho;
     vTorque(eX) = -Sense*PowerRequired / (RPS*2.0*M_PI);
   } else {
-    PowerRequired = 0.0;
-    vTorque(eX) = 0.0;
+     // For a stationary prop we have to estimate torque first.
+     double CL = (90.0 - Pitch) / 20.0;
+     if (CL > 1.5) CL = 1.5;
+     double BladeArea = Diameter * Diameter / 32.0 * numBlades;
+     vTorque(eX) = -Sense*BladeArea*Diameter*Vel*Vel*rho*0.19*CL;
+     PowerRequired = vTorque(eX)*0.2*M_PI;
   }
 
   return PowerRequired;
index 500e6798599bf2372f7eedd2f052887525a26f0f..ea7953e1eabc8eba4c422104b02b3b63e7d3b932 100644 (file)
@@ -45,7 +45,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PROPELLER "$Id$"
+#define ID_PROPELLER "$Id: FGPropeller.h,v 1.16 2010/04/09 12:44:06 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -71,6 +71,7 @@ CLASS DOCUMENTATION
   <maxpitch> {number} </maxpitch>
   <minrpm> {number} </minrpm>
   <maxrpm> {number} </maxrpm>
+  <constspeed> {number} </constspeed>
   <reversepitch> {number} </reversepitch>
   <sense> {1 | -1} </sense>
   <p_factor> {number} </p_factor>
@@ -89,6 +90,19 @@ CLASS DOCUMENTATION
     </tableData>
   </table>
 
+  <table name="CT_MACH" type="internal">
+    <tableData>
+      {numbers}
+    </tableData>
+  </table>
+
+  <table name="CP_MACH" type="internal">
+    <tableData>
+      {numbers}
+    </tableData>
+  </table>
+
+
 </propeller>
 @endcode
 
@@ -102,6 +116,7 @@ CLASS DOCUMENTATION
     \<maxpitch>      - Maximum blade pitch angle.
     \<minrpm>        - Minimum rpm target for constant speed propeller.
     \<maxrpm>        - Maximum rpm target for constant speed propeller.
+    \<constspeed>    - 1 = constant speed mode, 0 = manual pitch mode. 
     \<reversepitch>  - Blade pitch angle for reverse.
     \<sense>         - Direction of rotation (1=clockwise as viewed from cockpit,
                         -1=anti-clockwise as viewed from cockpit).
@@ -111,7 +126,10 @@ CLASS DOCUMENTATION
 </pre>
 
     Two tables are needed. One for coefficient of thrust (Ct) and one for
-    coefficient of power (Cp).  
+    coefficient of power (Cp).
+
+    Two tables are optional. They apply a factor to Ct and Cp based on the
+    helical tip Mach.  
     <br>
 
     Several references were helpful, here:<ul>
@@ -123,7 +141,7 @@ CLASS DOCUMENTATION
     <li>Various NACA Technical Notes and Reports</li>
     </ul>
     @author Jon S. Berndt
-    @version $Id$
+    @version $Id: FGPropeller.h,v 1.16 2010/04/09 12:44:06 jberndt Exp $
     @see FGEngine
     @see FGThruster
 */
@@ -169,6 +187,9 @@ public:
   /// Sets the P-Factor constant
   void SetPFactor(double pf) {P_Factor = pf;}
 
+  /// Sets propeller into constant speed mode, or manual pitch mode
+  void SetConstantSpeed(int mode) {ConstantSpeed = mode;} 
+
   /// Sets coefficient of thrust multiplier
   void SetCtFactor(double ctf) {CtFactor = ctf;}
 
@@ -204,6 +225,11 @@ public:
   /// Retrieves propeller power table
   FGTable* GetCPowerTable(void)  const { return cPower; }
 
+  /// Retrieves propeller thrust Mach effects factor
+  FGTable* GetCtMachTable(void) const { return CtMach; }
+  /// Retrieves propeller power Mach effects factor
+  FGTable* GetCpMachTable(void) const { return CpMach; }
+
   /// Retrieves the Torque in foot-pounds (Don't you love the English system?)
   double GetTorque(void)        { return vTorque(eX);    }
 
@@ -233,6 +259,10 @@ public:
   void   SetFeather (bool f) { Feathered = f; }
   bool   GetFeather (void) { return Feathered; }
   double GetThrustCoefficient(void) const {return ThrustCoeff;}
+  double GetHelicalTipMach(void) const {return HelicalTipMach;}
+  int    GetConstantSpeed(void) const {return ConstantSpeed;}
+  void   SetInducedVelocity(double Vi) {Vinduced = Vi;}
+  double GetInducedVelocity(void) const {return Vinduced;}
 
 private:
   int   numBlades;
@@ -251,14 +281,19 @@ private:
   double ExcessTorque;
   double D4;
   double D5;
+  double HelicalTipMach;
+  double Vinduced;
   FGColumnVector3 vTorque;
   FGTable *cThrust;
   FGTable *cPower;
+  FGTable *CtMach;
+  FGTable *CpMach;
   double CtFactor;
   double CpFactor;
+  int    ConstantSpeed;
   void Debug(int from);
   double ReversePitch; // Pitch, when fully reversed
-  bool   Reversed;              // true, when propeller is reversed
+  bool   Reversed;     // true, when propeller is reversed
   double Reverse_coef; // 0 - 1 defines AdvancePitch (0=MIN_PITCH 1=REVERSE_PITCH)
   bool   Feathered;    // true, if feather command
 };
index 85b0fd57f63324291181f0aa1ae13c65b3d3eeda..52ab88cb25827b533738d2476323786a924e624b 100644 (file)
@@ -41,7 +41,6 @@ INCLUDES
 #include <iostream>
 #include <sstream>
 #include "FGRocket.h"
-#include "FGState.h"
 #include "models/FGPropulsion.h"
 #include "FGThruster.h"
 #include "FGTank.h"
@@ -50,7 +49,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGRocket.cpp,v 1.19 2010/02/25 05:21:36 jberndt Exp $";
 static const char *IdHdr = ID_ROCKET;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -66,9 +65,9 @@ FGRocket::FGRocket(FGFDMExec* exec, Element *el, int engine_number)
   previousFuelNeedPerTank = 0.0;
   previousOxiNeedPerTank = 0.0;
   PropellantFlowRate = 0.0;
-  FuelFlowRate = 0.0;
-  OxidizerFlowRate = 0.0;
-  SLOxiFlowMax = 0.0;
+  FuelFlowRate = FuelExpended = 0.0;
+  OxidizerFlowRate = OxidizerExpended = 0.0;
+  SLOxiFlowMax = SLFuelFlowMax = 0.0;
   BuildupTime = 0.0;
   It = 0.0;
   ThrustVariation = 0.0;
@@ -127,7 +126,7 @@ FGRocket::~FGRocket(void)
 
 double FGRocket::Calculate(void)
 {
-  double dT = State->Getdt()*Propulsion->GetRate();
+  double dT = FDMExec->GetDeltaT()*Propulsion->GetRate();
   double thrust;
 
   if (!Flameout && !Starved) ConsumeFuel();
@@ -157,7 +156,7 @@ double FGRocket::Calculate(void)
         VacThrust *= sin((BurnTime/BuildupTime)*M_PI/2.0);
         // VacThrust *= (1-cos((BurnTime/BuildupTime)*M_PI))/2.0; // 1 - cos approach
       }
-      BurnTime += State->Getdt(); // Increment burn time
+      BurnTime += FDMExec->GetDeltaT(); // Increment burn time
     } else {
       VacThrust = 0.0;
     }
@@ -210,14 +209,16 @@ void FGRocket::ConsumeFuel(void)
   // a solid rocket is being modeled.
 
   for (i=0; i<SourceTanks.size(); i++) {
-    Tank = Propulsion->GetTank(SourceTanks[i]);
+    Tank = Propulsion->GetTank(i);
     switch(Tank->GetType()) {
       case FGTank::ttFUEL:
-        if (Tank->GetContents() > 0.0 && Tank->GetSelected()) ++TanksWithFuel;
+        if (Tank->GetContents() > 0.0 && Tank->GetSelected() && SourceTanks[i] > 0) ++TanksWithFuel;
         break;
       case FGTank::ttOXIDIZER:
-        haveOxTanks = true;
-        if (Tank->GetContents() > 0.0 && Tank->GetSelected()) ++TanksWithOxidizer;
+        if (Tank->GetContents() > 0.0 && Tank->GetSelected() && SourceTanks[i] > 0) {
+          haveOxTanks = true;
+          ++TanksWithOxidizer;
+        }
         break;
     }
   }
@@ -232,12 +233,15 @@ void FGRocket::ConsumeFuel(void)
   // Expend fuel from the engine's tanks if the tank is selected as a source
   // for this engine.
 
-  double fuelNeedPerTank = CalcFuelNeed()/TanksWithFuel;
-  double oxiNeedPerTank = CalcOxidizerNeed()/TanksWithOxidizer;
+  double fuelNeedPerTank = 0;
+  double oxiNeedPerTank = 0;
+
+  if (TanksWithFuel > 0) fuelNeedPerTank = CalcFuelNeed()/TanksWithFuel;
+  if (TanksWithOxidizer > 0) oxiNeedPerTank = CalcOxidizerNeed()/TanksWithOxidizer;
 
   for (i=0; i<SourceTanks.size(); i++) {
-    Tank = Propulsion->GetTank(SourceTanks[i]);
-    if ( ! Tank->GetSelected()) continue; // If this tank is not selected as a source, skip it.
+    Tank = Propulsion->GetTank(i);
+    if ( ! Tank->GetSelected() || SourceTanks[i] == 0) continue; // If this tank is not selected as a source, skip it.
     switch(Tank->GetType()) {
       case FGTank::ttFUEL:
         Fshortage += Tank->Drain(2.0*fuelNeedPerTank - previousFuelNeedPerTank);
@@ -263,7 +267,7 @@ void FGRocket::ConsumeFuel(void)
 
 double FGRocket::CalcFuelNeed(void)
 {
-  double dT = State->Getdt()*Propulsion->GetRate();
+  double dT = FDMExec->GetDeltaT()*Propulsion->GetRate();
 
   if (ThrustTable != 0L) {          // Thrust table given - infers solid fuel
     FuelFlowRate = VacThrust/Isp;   // This calculates wdot (weight flow rate in lbs/sec)
@@ -280,7 +284,7 @@ double FGRocket::CalcFuelNeed(void)
 
 double FGRocket::CalcOxidizerNeed(void)
 {
-  double dT = State->Getdt()*Propulsion->GetRate();
+  double dT = FDMExec->GetDeltaT()*Propulsion->GetRate();
   OxidizerFlowRate = SLOxiFlowMax*PctPower;
   OxidizerExpended = OxidizerFlowRate*dT;
   return OxidizerExpended;
@@ -367,7 +371,8 @@ void FGRocket::Debug(int from)
       cout << "      Minimum Throttle = " << MinThrottle << endl;
       cout << "      Fuel Flow (max) = " << SLFuelFlowMax << endl;
       cout << "      Oxidizer Flow (max) = " << SLOxiFlowMax << endl;
-      cout << "      Mixture ratio = " << SLOxiFlowMax/SLFuelFlowMax << endl;
+      if (SLFuelFlowMax > 0)
+        cout << "      Mixture ratio = " << SLOxiFlowMax/SLFuelFlowMax << endl;
     }
   }
   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
index 4ff539572ff97cc6863a5c2a0009e3a777dd1a35..8692a5c1a8ba8ca853946e2d99fedf405870d124 100644 (file)
@@ -46,7 +46,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ROCKET "$Id$"
+#define ID_ROCKET "$Id: FGRocket.h,v 1.12 2009/11/08 02:24:17 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -118,7 +118,7 @@ for the rocket engine to be throttle up to 1. At that time, the solid rocket
 fuel begins burning and thrust is provided.
 
     @author Jon S. Berndt
-    $Id$
+    $Id: FGRocket.h,v 1.12 2009/11/08 02:24:17 jberndt Exp $
     @see FGNozzle,
     FGThruster,
     FGForce,
index 6ef33e7c03feb540ce5a8c517126b73c30f82abd..b1c1661d034710fa386b04e1fa1ac537ef65340a 100644 (file)
@@ -5,7 +5,7 @@
  Date started: 08/24/00
  Purpose:      Encapsulates the rotor object
 
- ------------- Copyright (C) 2000  Jon S. Berndt (jon@jsbsim.org) -------------
+ ------------- Copyright (C) 2000  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
@@ -30,32 +30,733 @@ FUNCTIONAL DESCRIPTION
 HISTORY
 --------------------------------------------------------------------------------
 08/24/00  JSB  Created
+01/01/10  T.Kreitler test implementation
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#include "FGRotor.h"
 #include <iostream>
+#include <sstream>
+
+#include "FGRotor.h"
+
+#include "models/FGPropagate.h"
+#include "models/FGAtmosphere.h"
+#include "models/FGAuxiliary.h"
+#include "models/FGMassBalance.h"
+
+#include "input_output/FGXMLElement.h"
+
+#include "math/FGRungeKutta.h"
 
 using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGRotor.cpp,v 1.9 2010/06/05 12:12:34 jberndt Exp $";
 static const char *IdHdr = ID_ROTOR;
 
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+MISC
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+static int dump_req; // debug schwafel flag
+
+static inline double sqr(double x) { return x*x; }
+
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 CLASS IMPLEMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
+// starting with 'inner' rotor, FGRotor constructor is further down
+
+FGRotor::rotor::~rotor() { }
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// hmm, not a real alternative to a pretty long initializer list
+
+void FGRotor::rotor::zero() {
+  FGColumnVector3 zero_vec(0.0, 0.0, 0.0);
+
+  flags               = 0;
+  parent              = NULL  ;
+
+  reports             = 0;
+
+  // configuration
+  Radius              = 0.0 ;
+  BladeNum            = 0   ;
+  RelDistance_xhub    = 0.0 ;
+  RelShift_yhub       = 0.0 ;
+  RelHeight_zhub      = 0.0 ;
+  NominalRPM          = 0.0 ;
+  MinRPM              = 0.0 ;
+  BladeChord          = 0.0 ;
+  LiftCurveSlope      = 0.0 ;
+  BladeFlappingMoment = 0.0 ;
+  BladeTwist          = 0.0 ;
+  BladeMassMoment     = 0.0 ;
+  TipLossB            = 0.0 ;
+  PolarMoment         = 0.0 ;
+  InflowLag           = 0.0 ;
+  ShaftTilt           = 0.0 ;
+  HingeOffset         = 0.0 ;
+  HingeOffset_hover   = 0.0 ;
+  CantAngleD3         = 0.0 ;
+
+  theta_shaft         = 0.0 ;
+  phi_shaft           = 0.0 ;
+
+  // derived parameters
+  LockNumberByRho     = 0.0 ;
+  solidity            = 0.0 ;
+  RpmRatio            = 0.0 ;
 
-FGRotor::FGRotor(FGFDMExec *FDMExec, Element* rotor_element, int num)
-                    : FGThruster(FDMExec, rotor_element, num)
+  for (int i=0; i<5; i++) R[i] = 0.0;
+  for (int i=0; i<6; i++) B[i] = 0.0;
+
+  BodyToShaft.InitMatrix();
+  ShaftToBody.InitMatrix();
+
+  // dynamic values
+  ActualRPM           = 0.0 ;
+  Omega               = 0.0 ;
+  beta_orient         = 0.0 ;
+  a0                  = 0.0 ;
+  a_1 = b_1 = a_dw    = 0.0 ;
+  a1s = b1s           = 0.0 ;
+  H_drag = J_side     = 0.0 ;
+
+  Torque              = 0.0 ;
+  Thrust              = 0.0 ;
+  Ct                  = 0.0 ;
+  lambda              = 0.0 ;
+  mu                  = 0.0 ;
+  nu                  = 0.0 ;
+  v_induced           = 0.0 ;
+
+  force      = zero_vec ;
+  moment     = zero_vec ;
+
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// 5in1: value-fetch-convert-default-return function 
+
+double FGRotor::rotor::cnf_elem(  const string& ename, double default_val, 
+                                  const string& unit, bool tell)
 {
-  Debug(0);
+
+  Element *e = NULL;
+  double val=default_val;
+
+  std::string pname = "*No parent element*";
+
+  if (parent) {
+    e = parent->FindElement(ename);
+    pname = parent->GetName();
+  }
+
+  if (e) {
+    if (unit.empty()) {
+      // val = e->FindElementValueAsNumber(ename); 
+      // yields to: Attempting to get single data value from multiple lines
+      val = parent->FindElementValueAsNumber(ename);
+    } else {
+      // val = e->FindElementValueAsNumberConvertTo(ename,unit); 
+      // yields to: Attempting to get non-existent element diameter + crash, why ?
+      val = parent->FindElementValueAsNumberConvertTo(ename,unit);
+    }
+  } else {
+    if (tell) {
+      cerr << pname << ": missing element '" << ename <<"' using estimated value: " << default_val << endl;
+    }
+  }
+
+  return val;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+double FGRotor::rotor::cnf_elem(const string& ename, double default_val, bool tell)
+{
+  return cnf_elem(ename, default_val, "", tell);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// 1. read configuration and try to fill holes, ymmv
+// 2. calculate derived parameters and transforms
+void FGRotor::rotor::configure(int f, const rotor *xmain)
+{
+
+  double estimate;
+  const bool yell   = true;
+  const bool silent = false;
+
+  flags = f;
+
+  estimate = (xmain) ? 2.0 * xmain->Radius * 0.2 : 42.0;
+  Radius = 0.5 * cnf_elem("diameter", estimate, "FT", yell);
+
+  estimate = (xmain) ? xmain->BladeNum  : 2.0;
+  estimate = Constrain(1.0,estimate,4.0);
+  BladeNum = (int) cnf_elem("numblades", estimate, yell);
+
+  estimate = (xmain) ? - xmain->Radius * 1.05 - Radius : - 0.025 * Radius ; 
+  RelDistance_xhub = cnf_elem("xhub", estimate, "FT", yell);
+
+  RelShift_yhub = cnf_elem("yhub", 0.0, "FT", silent);
+  
+  estimate = - 0.1 * Radius - 4.0;
+  RelHeight_zhub = cnf_elem("zhub", estimate, "FT", yell);
+  
+  // make sure that v_tip (omega*r) is below 0.7mach ~ 750ft/s
+  estimate = (750.0/Radius)/(2.0*M_PI) * 60.0;  // 7160/Radius
+  NominalRPM = cnf_elem("nominalrpm", estimate, yell);
+
+  MinRPM = cnf_elem("minrpm", 1.0, silent);
+  MinRPM = Constrain(1.0, MinRPM, NominalRPM-1.0);
+
+  estimate = (xmain) ? 0.12 : 0.07;  // guess solidity
+  estimate = estimate * M_PI*Radius/BladeNum;
+  BladeChord = cnf_elem("chord", estimate, "FT", yell);
+
+  LiftCurveSlope = cnf_elem("liftcurveslope", 6.0, yell); // "1/RAD"
+
+  estimate = sqr(BladeChord) * sqr(Radius) * 0.57;
+  BladeFlappingMoment = cnf_elem("flappingmoment", estimate, "SLUG*FT2", yell);   
+  BladeFlappingMoment = Constrain(0.1, BladeFlappingMoment, 1e9);
+
+  BladeTwist = cnf_elem("twist", -0.17, "RAD", yell);
+
+  estimate = sqr(BladeChord) * BladeChord * 15.66; // might be really wrong!
+  BladeMassMoment = cnf_elem("massmoment", estimate, yell); // slug-ft
+  BladeMassMoment = Constrain(0.1, BladeMassMoment, 1e9);
+
+  TipLossB = cnf_elem("tiplossfactor", 0.98, silent);
+
+  estimate = 1.1 * BladeFlappingMoment * BladeNum;
+  PolarMoment = cnf_elem("polarmoment", estimate, "SLUG*FT2", silent);
+  PolarMoment = Constrain(0.1, PolarMoment, 1e9);
+
+  InflowLag = cnf_elem("inflowlag", 0.2, silent); // fixme, depends on size
+
+  estimate = (xmain) ? 0.0 : -0.06;  
+  ShaftTilt = cnf_elem("shafttilt", estimate, "RAD", silent);
+
+  // ignore differences between teeter/hingeless/fully-articulated constructions
+  estimate = 0.05 * Radius;
+  HingeOffset = cnf_elem("hingeoffset", estimate, "FT", (xmain) ? silent : yell);
+
+  CantAngleD3 = cnf_elem("cantangle", 0.0, "RAD", silent);  
+
+  // derived parameters
+
+  // precalc often used powers
+  R[0]=1.0; R[1]=Radius;   R[2]=R[1]*R[1]; R[3]=R[2]*R[1]; R[4]=R[3]*R[1];
+  B[0]=1.0; B[1]=TipLossB; B[2]=B[1]*B[1]; B[3]=B[2]*B[1]; B[4]=B[3]*B[1]; B[5]=B[4]*B[1];
+
+  LockNumberByRho = LiftCurveSlope * BladeChord * R[4] / BladeFlappingMoment;
+  solidity = BladeNum * BladeChord / (M_PI * Radius);
+
+  // use simple orientations at the moment
+  if (flags & eTail) { // axis parallel to Y_body
+    theta_shaft = 0.0; // no tilt
+    phi_shaft = 0.5*M_PI;
+
+    // opposite direction if main rotor is spinning CW
+    if (xmain && (xmain->flags & eRotCW) ) { 
+      phi_shaft = -phi_shaft; 
+    }
+  } else {  // more or less upright
+    theta_shaft = ShaftTilt;
+    phi_shaft = 0.0; 
+  }
+
+  // setup Shaft-Body transforms, see /SH79/ eqn(17,18)
+  double st = sin(theta_shaft);
+  double ct = cos(theta_shaft);
+  double sp = sin(phi_shaft);
+  double cp = cos(phi_shaft);
+
+  ShaftToBody.InitMatrix(    ct, st*sp, st*cp,
+                            0.0,    cp,   -sp,
+                            -st, ct*sp, ct*cp  );
+
+  BodyToShaft  =  ShaftToBody.Inverse();
+
+  // misc defaults
+  nu = 0.001; // help the flow solver by providing some moving molecules
+  
+  return;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// calculate control-axes components of total airspeed at the hub.
+// sets rotor orientation angle (beta) as side effect. /SH79/ eqn(19-22)
+
+FGColumnVector3 FGRotor::rotor::hub_vel_body2ca( const FGColumnVector3 &uvw, 
+                                                 const FGColumnVector3 &pqr,
+                                                 double a_ic, double b_ic)
+{
+
+  FGColumnVector3  v_r, v_shaft, v_w;
+  FGColumnVector3  pos(RelDistance_xhub,0.0,RelHeight_zhub);
+
+  v_r = uvw + pqr*pos;
+  v_shaft = BodyToShaft * v_r;
+
+  beta_orient = atan2(v_shaft(eV),v_shaft(eU));
+
+  v_w(eU) = v_shaft(eU)*cos(beta_orient) + v_shaft(eV)*sin(beta_orient);
+  v_w(eV) = 0.0;
+  v_w(eW) = v_shaft(eW) - b_ic*v_shaft(eU) - a_ic*v_shaft(eV);
+
+  return v_w;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// express fuselage angular velocity in control axes /SH79/ eqn(30,31)
+
+FGColumnVector3 FGRotor::rotor::fus_angvel_body2ca( const FGColumnVector3 &pqr)
+{
+  FGColumnVector3 av_s_fus, av_w_fus;    
+
+  av_s_fus = BodyToShaft * pqr;
+
+  av_w_fus(eP)=   av_s_fus(eP)*cos(beta_orient) + av_s_fus(eQ)*sin(beta_orient);
+  av_w_fus(eQ)= - av_s_fus(eP)*sin(beta_orient) + av_s_fus(eQ)*cos(beta_orient);
+  av_w_fus(eR)=   av_s_fus(eR);
+         
+  return av_w_fus;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// problem function passed to rk solver
+
+  double FGRotor::rotor::dnuFunction::pFunc(double x, double nu) {
+    double d_nu;
+    d_nu =  k_sat * (ct_lambda * (k_wor - nu) + k_theta) / 
+                     (2.0 * sqrt( mu2 + sqr(k_wor - nu)) ); 
+    d_nu = d_nu * k_flowscale - nu;
+    return  d_nu; 
+  }; 
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+  // merge params to keep the equation short
+  void FGRotor::rotor::dnuFunction::update_params(rotor *r, double ct_t01, double fs, double w) {
+    k_sat       = 0.5* r->solidity * r->LiftCurveSlope;
+    ct_lambda   = 1.0/2.0*r->B[2] + 1.0/4.0 * r->mu*r->mu;
+    k_wor       = w/(r->Omega*r->Radius);
+    k_theta     = ct_t01;
+    mu2         = r->mu * r->mu;
+    k_flowscale = fs;
+  };
+
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// Calculate rotor thrust and inflow-ratio (lambda), this is achieved by
+// approximating a solution for the differential equation:
+// 
+//  dnu/dt = 1/tau ( Ct / (2*sqrt(mu^2+lambda^2))  -  nu )  , /SH79/ eqn(26).
+// 
+// Propper calculation of the inflow-ratio (lambda) is vital for the
+// following calculations. Simple implementations (i.e. Newton-Raphson w/o
+// checking) tend to oscillate or overshoot in the low speed region,
+// therefore a more expensive solver is used.
+//
+// The flow_scale parameter is used to approximate a reduction of inflow
+// if the helicopter is close to the ground, yielding to higher thrust,
+// see /TA77/ eqn(10a). Doing the ground effect calculation here seems
+// more favorable then to code it in the fdm_config.
+
+void FGRotor::rotor::calc_flow_and_thrust(    
+                           double dt, double rho, double theta_0,
+                           double Uw, double Ww, double flow_scale)
+{
+
+  double ct_over_sigma = 0.0;
+  double ct_l, ct_t0, ct_t1;
+  double nu_ret = 0.0;
+
+  mu = Uw/(Omega*Radius); // /SH79/ eqn(24)
+
+  ct_t0 = (1.0/3.0*B[3] + 1.0/2.0 * TipLossB*mu*mu - 4.0/(9.0*M_PI) * mu*mu*mu )*theta_0;
+  ct_t1 = (1.0/4.0*B[4] + 1.0/4.0 * B[2]*mu*mu)*BladeTwist;
+
+  // merge params together
+  flowEquation.update_params(this, ct_t0+ct_t1, flow_scale, Ww);
+  
+  nu_ret = rk.evolve(nu, &flowEquation);
+
+  if (rk.getStatus() != FGRungeKutta::eNoError) { // never observed so far
+    cerr << "# IEHHHH [" << flags << "]: Solver Error - resetting!" << endl;
+    rk.clearStatus();
+    nu_ret = nu; // use old value and keep fingers crossed.
+  }
+
+  // keep an eye on the solver, but be quiet after a hundred messages
+  if (reports < 100 && rk.getIterations()>6) {
+    cerr << "# LOOK [" << flags << "]: Solver took " 
+         << rk.getIterations() << " rounds." << endl;
+    reports++;
+    if (reports==100) {
+      cerr << "# stopped babbling after 100 notifications." << endl;
+    }
+  }
+
+  // now from nu to lambda, Ct, and Thrust
+
+  nu = nu_ret;
+  lambda = Ww/(Omega*Radius) - nu; // /SH79/ eqn(25)
+
+  ct_l  = (1.0/2.0*B[2] + 1.0/4.0 * mu*mu)*lambda;  
+  ct_over_sigma = (LiftCurveSlope/2.0)*(ct_l + ct_t0 + ct_t1); // /SH79/ eqn(27)
+
+  Thrust = BladeNum*BladeChord*Radius*rho*sqr(Omega*Radius) * ct_over_sigma;
+
+  Ct = ct_over_sigma * solidity;
+  v_induced = nu * (Omega*Radius);
+
+  if (dump_req && (flags & eMain) ) {
+    printf("# mu %f : nu %f lambda %f vi %f\n", mu, nu, lambda, v_induced);
+  }
+
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// this is the most arcane part in the calculation chain the
+// constants used should be reverted to more general parameters.
+// otoh: it works also for smaller rotors, sigh!
+// See /SH79/ eqn(36), and /BA41/ for a richer set of equations.
+
+void FGRotor::rotor::calc_torque(double rho, double theta_0)
+{
+  double Qa0;
+  double cq_s_m[5], cq_over_sigma;
+  double l,m,t075; // shortcuts
+
+  t075 = theta_0 + 0.75 * BladeTwist;
+
+  m = mu;
+  l = lambda;
+
+  cq_s_m[0] = 0.00109 - 0.0036*l - 0.0027*t075 - 1.10*sqr(l) - 0.545*l*t075 + 0.122*sqr(t075);
+  cq_s_m[2] = ( 0.00109 - 0.0027*t075 - 3.13*sqr(l) - 6.35*l*t075 - 1.93*sqr(t075) ) * sqr(m);
+  cq_s_m[3] = - 0.133*l*t075 * sqr(m)*m;
+  cq_s_m[4] = ( - 0.976*sqr(l) - 6.38*l*t075 - 5.26*sqr(t075) ) * sqr(m)*sqr(m);
+
+  cq_over_sigma = cq_s_m[0] + cq_s_m[2] + cq_s_m[3] + cq_s_m[4];
+  // guess an a (LiftCurveSlope) is included in eqn above, so check if there is a large
+  // influence when  a_'other-model'/ a_'ch54' diverts from 1.0.
+
+  Qa0 = BladeNum * BladeChord * R[2] * rho * sqr(Omega*Radius);
+
+// TODO: figure out how to handle negative cq_over_sigma/torque
+
+  Torque =  Qa0 *  cq_over_sigma;
+
+  return;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// The coning angle doesn't apply for teetering rotors, but calculating
+// doesn't hurt. /SH79/ eqn(29)
+
+void FGRotor::rotor::calc_coning_angle(double rho, double theta_0)
+{
+  double lock_gamma = LockNumberByRho * rho;
+
+  double a0_l  = (1.0/6.0  * B[3] + 0.04 * mu*mu*mu) * lambda;
+  double a0_t0 = (1.0/8.0  * B[4] + 1.0/8.0  * B[2]*mu*mu) * theta_0;
+  double a0_t1 = (1.0/10.0 * B[5] + 1.0/12.0 * B[3]*mu*mu) * BladeTwist;
+  a0 = lock_gamma * ( a0_l + a0_t0 + a0_t1);
+  return;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// Flapping angles relative to control axes /SH79/ eqn(32)
+
+void FGRotor::rotor::calc_flapping_angles(  double rho, double theta_0, 
+                                            const FGColumnVector3 &pqr_fus_w)
+{
+  double lock_gamma = LockNumberByRho * rho;
+
+  double mu2_2B2 = sqr(mu)/(2.0*B[2]);
+  double t075 = theta_0 + 0.75 * BladeTwist;  // common approximation for rectangular blades
+  
+  a_1 = 1.0/(1.0 - mu2_2B2) * (
+                                 (2.0*lambda + (8.0/3.0)*t075)*mu
+                               + pqr_fus_w(eP)/Omega
+                               - 16.0 * pqr_fus_w(eQ)/(B[4]*lock_gamma*Omega)
+                             );
+  
+  b_1 = 1.0/(1.0 + mu2_2B2) * (
+                                 (4.0/3.0)*mu*a0
+                               - pqr_fus_w(eQ)/Omega
+                               - 16.0 * pqr_fus_w(eP)/(B[4]*lock_gamma*Omega)
+                             );
+  
+  // used in  force calc
+  a_dw = 1.0/(1.0 - mu2_2B2) * (
+                                 (2.0*lambda + (8.0/3.0)*t075)*mu
+                               - 24.0 * pqr_fus_w(eQ)/(B[4]*lock_gamma*Omega)
+                                 * ( 1.0 - ( 0.29 * t075 / (Ct/solidity) ) )
+                             );
+  
+  return;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// /SH79/ eqn(38,39)
+
+void FGRotor::rotor::calc_drag_and_side_forces(double rho, double theta_0)
+{
+  double cy_over_sigma  ;
+  double t075 = theta_0 + 0.75 * BladeTwist;
+
+  H_drag = Thrust * a_dw;
+  
+  cy_over_sigma = (
+                      0.75*b_1*lambda - 1.5*a0*mu*lambda + 0.25*a_1*b_1*mu
+                    - a0*a_1*sqr(mu) + (1.0/6.0)*a0*a_1
+                    - (0.75*mu*a0 - (1.0/3.0)*b_1 - 0.5*sqr(mu)*b_1)*t075
+                  );
+  cy_over_sigma *= LiftCurveSlope/2.0;
+  
+  J_side = BladeNum * BladeChord * Radius * rho * sqr(Omega*Radius) * cy_over_sigma;
+
+  return;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// transform rotor forces from control axes to shaft axes, and express
+// in body axes /SH79/ eqn(40,41)
+
+FGColumnVector3 FGRotor::rotor::body_forces(double a_ic, double b_ic)
+{
+    FGColumnVector3 F_s(
+          - H_drag*cos(beta_orient) - J_side*sin(beta_orient) + Thrust*b_ic,
+          - H_drag*sin(beta_orient) + J_side*cos(beta_orient) + Thrust*a_ic,
+          - Thrust);    
+
+    if (dump_req && (flags & eMain) ) {
+      printf("# abß:  % f % f % f\n", a_ic, b_ic, beta_orient );
+      printf("# HJT:  % .2f % .2f % .2f\n", H_drag, J_side, Thrust );
+      printf("# F_s:  % .2f % .2f % .2f\n", F_s(1), F_s(2), F_s(3) );
+      FGColumnVector3 F_h;   
+      F_h = ShaftToBody * F_s;
+      printf("# F_h:  % .2f % .2f % .2f\n", F_h(1), F_h(2), F_h(3) );
+    }
+
+    return ShaftToBody * F_s;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// rotational sense is handled here
+// still a todo: how to get propper values for 'BladeMassMoment'
+// here might be a good place to tweak hovering stability, check /AM50/.
+
+FGColumnVector3 FGRotor::rotor::body_moments(FGColumnVector3 F_h, double a_ic, double b_ic)
+{
+  FGColumnVector3 M_s, M_hub, M_h;
+  
+  FGColumnVector3 h_pos(RelDistance_xhub, 0.0, RelHeight_zhub);
+
+  // vermutlich ein biege moment, bzw.widerstands moment ~ d^3
+  double M_w_tilde = 0.0 ;
+  double mf = 0.0 ;
+  M_w_tilde = BladeMassMoment;
+
+  // cyclic flapping relative to shaft axes /SH79/ eqn(43)
+  a1s = a_1*cos(beta_orient) + b_1*sin(beta_orient) - b_ic;
+  b1s = b_1*cos(beta_orient) - a_1*sin(beta_orient) + a_ic;
+
+  // mind this: no HingeOffset, no additional pitch/roll moments
+  mf = 0.5 * (HingeOffset+HingeOffset_hover) * BladeNum * Omega*Omega * M_w_tilde;
+  M_s(eL) = mf*b1s;
+  M_s(eM) = mf*a1s;
+  M_s(eN) = Torque;
+
+  if (flags & eRotCW) {
+    M_s(eN) = -M_s(eN);
+  }
+
+  if (flags & eCoaxial) {
+    M_s(eN) = 0.0;
+  }
+
+  M_hub = ShaftToBody * M_s;
+
+  M_h = M_hub + (h_pos * F_h);
+
+  return M_h;
 }
 
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// Constructor
+
+FGRotor::FGRotor(FGFDMExec *exec, Element* rotor_element, int num)
+                    : FGThruster(exec, rotor_element, num)
+{
+
+  FGColumnVector3 location, orientation;
+  Element *thruster_element;
+
+  PropertyManager = fdmex->GetPropertyManager();
+  dt = fdmex->GetDeltaT();
+
+  /* apply defaults */
+
+  rho = 0.002356; // just a sane value
+  
+  RPM = 0.0;
+  Sense = 1.0;
+  tailRotorPresent = false;
+  
+  effective_tail_col = 0.001; // just a sane value 
+
+  prop_inflow_ratio_lambda =  0.0;
+  prop_advance_ratio_mu = 0.0; 
+  prop_inflow_ratio_induced_nu = 0.0;
+  prop_mr_torque = 0.0;
+  prop_thrust_coefficient = 0.0;
+  prop_coning_angle = 0.0;
+
+  prop_theta_downwash = prop_phi_downwash = 0.0;
+
+  hover_threshold = 0.0;
+  hover_scale = 0.0;
+
+  mr.zero();
+  tr.zero();
+
+  // debug stuff
+  prop_DumpFlag = 0;
+
+  /* configure */
+
+  Type = ttRotor;
+  SetTransformType(FGForce::tCustom);
+
+  // get data from parent and 'mount' the rotor system
+
+  thruster_element = rotor_element->GetParent()->FindElement("sense");
+  if (thruster_element) {
+    Sense = thruster_element->GetDataAsNumber() >= 0.0 ? 1.0: -1.0;
+  }
+
+  thruster_element = rotor_element->GetParent()->FindElement("location");
+  if (thruster_element)  location = thruster_element->FindElementTripletConvertTo("IN");
+  else          cerr << "No thruster location found." << endl;
+
+  thruster_element = rotor_element->GetParent()->FindElement("orient");
+  if (thruster_element)  orientation = thruster_element->FindElementTripletConvertTo("RAD");
+  else          cerr << "No thruster orientation found." << endl;
+
+  SetLocation(location);
+  SetAnglesToBody(orientation);
+
+  // get main rotor parameters 
+  mr.parent = rotor_element;
+
+  int flags = eMain;
+
+  string a_val="";
+  a_val = rotor_element->GetAttributeValue("variant");
+  if ( a_val == "coaxial" ) {
+    flags += eCoaxial;
+    cerr << "# found 'coaxial' variant" << endl;
+  }  
+
+  if (Sense<0.0) {
+    flags += eRotCW;
+  }
+    
+  mr.configure(flags);
+
+  mr.rk.init(0,dt,6);
+
+  // get tail rotor parameters
+  tr.parent=rotor_element->FindElement("tailrotor");
+  if (tr.parent) {
+    tailRotorPresent = true;
+  } else {
+    tailRotorPresent = false;
+    cerr << "# No tailrotor found, assuming a single rotor." << endl;
+  }
+
+  if (tailRotorPresent) {
+    int flags = eTail;
+    if (Sense<0.0) {
+      flags += eRotCW;
+    }
+    tr.configure(flags, &mr);
+    tr.rk.init(0,dt,6);
+    tr.RpmRatio = tr.NominalRPM/mr.NominalRPM; // 'connect'
+  }
+
+  /* remaining parameters */
+
+  // ground effect  
+  double c_ground_effect = 0.0;  // uh1 ~ 0.28 , larger values increase the effect
+  ground_effect_exp = 0.0;  
+  ground_effect_shift = 0.0;
+
+  if (rotor_element->FindElement("cgroundeffect"))
+    c_ground_effect = rotor_element->FindElementValueAsNumber("cgroundeffect");
+
+  if (rotor_element->FindElement("groundeffectshift"))
+    ground_effect_shift = rotor_element->FindElementValueAsNumberConvertTo("groundeffectshift","FT");
+
+  // prepare calculations, see /TA77/
+  if (c_ground_effect > 1e-5) {
+    ground_effect_exp = 1.0 / ( 2.0*mr.Radius * c_ground_effect );
+  } else {
+    ground_effect_exp = 0.0; // disable
+  }
+
+  // smooth out jumps in hagl reported, otherwise the ground effect
+  // calculation would cause jumps too. 1Hz seems sufficient.
+  damp_hagl = Filter(1.0,dt);
+
+
+  // misc, experimental
+  if (rotor_element->FindElement("hoverthreshold"))
+    hover_threshold = rotor_element->FindElementValueAsNumberConvertTo("hoverthreshold", "FT/SEC");
+
+  if (rotor_element->FindElement("hoverscale"))
+    hover_scale = rotor_element->FindElementValueAsNumber("hoverscale");
+
+  // enable import-export
+  bind();
+
+  // unused right now
+  prop_rotorbrake->setDoubleValue(0.0);
+  prop_freewheel_factor->setDoubleValue(1.0);  
+
+  Debug(0);
+
+}  // Constructor
+
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 FGRotor::~FGRotor()
@@ -65,23 +766,295 @@ FGRotor::~FGRotor()
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+// mea-culpa - the connection to the engine might be wrong, but the calling
+// convention appears to be 'variable' too.
+//   piston call:  
+//        return Thruster->Calculate((Eng_HP * hptoftlbssec)-Thruster->GetPowerRequired());
+//   turbine call: 
+//        Thrust = Thruster->Calculate(Thrust); // allow thruster to modify thrust (i.e. reversing)
+//
+// Here 'Calculate' takes thrust and estimates the power provided.
+
 double FGRotor::Calculate(double PowerAvailable)
 {
-  return 0.0;
+  // controls
+  double A_IC;       // lateral (roll) control in radians
+  double B_IC;       // longitudinal (pitch) control in radians
+  double theta_col;  // main rotor collective pitch in radians
+  double tail_col;   // tail rotor collective in radians
+
+  // state
+  double h_agl_ft = 0.0;
+  double Vt ;
+
+  FGColumnVector3 UVW_h;
+  FGColumnVector3 PQR_h;
+
+  /* total vehicle velocity including wind effects in feet per second. */
+  Vt = fdmex->GetAuxiliary()->GetVt();
+
+  dt = fdmex->GetDeltaT(); // might be variable ?
+
+  dump_req = prop_DumpFlag;
+  prop_DumpFlag = 0;
+
+  // fetch often used values
+  rho = fdmex->GetAtmosphere()->GetDensity(); // slugs/ft^3.
+
+  UVW_h = fdmex->GetAuxiliary()->GetAeroUVW();
+  PQR_h = fdmex->GetAuxiliary()->GetAeroPQR();
+
+  // handle present RPM now, calc omega values.
+
+  if (RPM < mr.MinRPM) { // kludge, otherwise calculations go bananas 
+    RPM = mr.MinRPM;
+  }
+
+  mr.ActualRPM = RPM;
+  mr.Omega = (RPM/60.0)*2.0*M_PI;
+
+  if (tailRotorPresent) {
+    tr.ActualRPM = RPM*tr.RpmRatio;
+    tr.Omega = (RPM*tr.RpmRatio/60.0)*2.0*M_PI;
+  }
+
+  // read control inputs
+
+  A_IC      = prop_lateral_ctrl->getDoubleValue();
+  B_IC      = prop_longitudinal_ctrl->getDoubleValue();
+  theta_col = prop_collective_ctrl->getDoubleValue();
+  tail_col  = 0.0;
+  if (tailRotorPresent) {
+    tail_col  = prop_antitorque_ctrl->getDoubleValue();
+  }
+
+
+  FGColumnVector3  vHub_ca = mr.hub_vel_body2ca(UVW_h,PQR_h,A_IC,B_IC);
+  FGColumnVector3 avFus_ca = mr.fus_angvel_body2ca(PQR_h);
+
+
+  h_agl_ft = fdmex->GetPropagate()->GetDistanceAGL();
+
+  double filtered_hagl;
+  filtered_hagl = damp_hagl.execute( h_agl_ft + ground_effect_shift );
+
+  // gnuplot> plot [-1:50] 1 - exp((-x/44)/.28)
+  double ge_factor = 1.0;  
+  if (ground_effect_exp > 1e-5) {
+    ge_factor -= exp(-filtered_hagl*ground_effect_exp);
+  }
+  // clamp
+  if (ge_factor<0.5) ge_factor=0.5;
+
+  if (dump_req) {
+    printf("# GE h: %.3f  (%.3f) f: %f\n", filtered_hagl, h_agl_ft + ground_effect_shift, ge_factor);
+  }
+
+
+  // EXPERIMENTAL: modify rotor for hover, see rotor::body_moments for the consequences
+  if (hover_threshold > 1e-5 && Vt < hover_threshold) {
+    double scale = 1.0 - Vt/hover_threshold;
+    mr.HingeOffset_hover = scale*hover_scale*mr.Radius;
+  } else {
+    mr.HingeOffset_hover = 0.0;
+  }
+
+  // all set, start calculations
+
+  /* MAIN ROTOR */
+
+  mr.calc_flow_and_thrust(dt, rho, theta_col, vHub_ca(eU), vHub_ca(eW), ge_factor);
+
+  prop_inflow_ratio_lambda = mr.lambda;
+  prop_advance_ratio_mu = mr.mu;
+  prop_inflow_ratio_induced_nu = mr.nu;
+  prop_thrust_coefficient = mr.Ct;
+
+  mr.calc_coning_angle(rho, theta_col);
+  prop_coning_angle = mr.a0;
+
+  mr.calc_torque(rho, theta_col);
+  prop_mr_torque = mr.Torque;
+
+  mr.calc_flapping_angles(rho, theta_col, avFus_ca);
+  mr.calc_drag_and_side_forces(rho, theta_col);
+
+  FGColumnVector3 F_h_mr = mr.body_forces(A_IC,B_IC);
+  FGColumnVector3 M_h_mr = mr.body_moments(F_h_mr, A_IC, B_IC); 
+
+  // export downwash angles
+  // theta: positive for downwash moving from +z_h towards +x_h
+  // phi:   positive for downwash moving from +z_h towards -y_h
+
+  prop_theta_downwash = atan2( - UVW_h(eU), mr.v_induced - UVW_h(eW));
+  prop_phi_downwash   = atan2(   UVW_h(eV), mr.v_induced - UVW_h(eW));
+
+  mr.force(eX) = F_h_mr(1);
+  mr.force(eY) = F_h_mr(2);
+  mr.force(eZ) = F_h_mr(3);
+
+  mr.moment(eL) =  M_h_mr(1);
+  mr.moment(eM) =  M_h_mr(2); 
+  mr.moment(eN) =  M_h_mr(3);
+
+  /* TAIL ROTOR */
+
+  FGColumnVector3 F_h_tr(0.0, 0.0, 0.0);
+  FGColumnVector3 M_h_tr(0.0, 0.0, 0.0);
+
+  if (tailRotorPresent) {
+    FGColumnVector3  vHub_ca_tr = tr.hub_vel_body2ca(UVW_h,PQR_h);
+    FGColumnVector3 avFus_ca_tr = tr.fus_angvel_body2ca(PQR_h);
+
+    tr.calc_flow_and_thrust(dt, rho, tail_col, vHub_ca_tr(eU), vHub_ca_tr(eW));
+    tr.calc_coning_angle(rho, tail_col);
+
+    // test code for cantered tail rotor, see if it has a notable effect. /SH79/ eqn(47)
+    if (fabs(tr.CantAngleD3)>1e-5) {
+      double tan_d3 = tan(tr.CantAngleD3);
+      double d_t0t;
+      double ca_dt = dt/12.0;
+      for (int i = 0; i<12; i++) {
+        d_t0t = 1/0.1*(tail_col - tr.a0 * tan_d3 - effective_tail_col);
+        effective_tail_col += d_t0t*ca_dt;
+      }
+    } else {
+      effective_tail_col = tail_col;
+    }
+
+    tr.calc_torque(rho, effective_tail_col);
+    tr.calc_flapping_angles(rho, effective_tail_col, avFus_ca_tr);
+    tr.calc_drag_and_side_forces(rho, effective_tail_col);
+
+    F_h_tr = tr.body_forces();
+    M_h_tr = tr.body_moments(F_h_tr); 
+  }
+
+  tr.force(eX)  =   F_h_tr(1) ;
+  tr.force(eY)  =   F_h_tr(2) ;
+  tr.force(eZ)  =   F_h_tr(3) ;
+  tr.moment(eL) =   M_h_tr(1) ;
+  tr.moment(eM) =   M_h_tr(2) ;
+  tr.moment(eN) =   M_h_tr(3) ;
+
+/* 
+    TODO: 
+      check negative mr.Torque conditions
+      freewheel factor: assure [0..1] just multiply with available power
+      rotorbrake: just steal from available power
+
+*/
+
+  // calculate new RPM, assuming a stiff connection between engine and rotor. 
+
+  double engine_hp     =  PowerAvailable/2.24; // 'undo' force via the estimation factor used in aeromatic
+  double engine_torque =  550.0*engine_hp/mr.Omega;
+  double Omega_dot     = (engine_torque - mr.Torque) / mr.PolarMoment;
+
+  RPM += ( Omega_dot * dt )/(2.0*M_PI) * 60.0;
+
+  if (0 && dump_req) {
+    printf("# SENSE      :  % d % d\n", mr.flags & eRotCW ? -1 : 1, tr.flags & eRotCW ? -1 : 1);
+    printf("# vi         :  % f % f\n", mr.v_induced, tr.v_induced);
+    printf("# a0 a1 b1   :  % f % f % f\n", mr.a0, mr.a_1, mr.b_1 );
+    printf("# m  forces  :  % f % f % f\n", mr.force(eX), mr.force(eY), mr.force(eZ) );
+    printf("# m  moments :  % f % f % f\n", mr.moment(eL), mr.moment(eM), mr.moment(eN) );
+    printf("# t  forces  :  % f % f % f\n", tr.force(eX), tr.force(eY), tr.force(eZ) );
+    printf("# t  moments :  % f % f % f\n", tr.moment(eL), tr.moment(eM), tr.moment(eN) );
+  }
+
+  // finally set vFn & vMn
+  vFn = mr.force  + tr.force;
+  vMn = mr.moment + tr.moment;
+
+  // and just lie here
+  Thrust = 0.0; 
+
+  // return unmodified thrust to the turbine. 
+  // :TK: As far as I can see the return value is unused.
+  return PowerAvailable;
+
+}  // Calculate
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+// FGThruster does return 0.0 (the implicit direct thruster)
+// piston CALL:  return Thruster->Calculate((Eng_HP * hptoftlbssec)-Thruster->GetPowerRequired());
+
+double FGRotor::GetPowerRequired(void)
+{
+  PowerRequired = 0.0;
+  return PowerRequired;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGRotor::bind(void) {
+
+  string property_name, base_property_name;
+  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum);
+
+  PropertyManager->Tie( base_property_name + "/rotor-rpm", this, &FGRotor::GetRPM );
+  PropertyManager->Tie( base_property_name + "/thrust-mr-lbs", &mr.Thrust );
+  PropertyManager->Tie( base_property_name + "/vi-mr-fps", &mr.v_induced );
+  PropertyManager->Tie( base_property_name + "/a0-mr-rad", &mr.a0 );
+  PropertyManager->Tie( base_property_name + "/a1-mr-rad", &mr.a1s ); // s means shaft axes
+  PropertyManager->Tie( base_property_name + "/b1-mr-rad", &mr.b1s );
+  PropertyManager->Tie( base_property_name + "/thrust-tr-lbs", &tr.Thrust );
+  PropertyManager->Tie( base_property_name + "/vi-tr-fps", &tr.v_induced );
+
+  // lambda
+  PropertyManager->Tie( base_property_name + "/inflow-ratio", &prop_inflow_ratio_lambda );
+  // mu
+  PropertyManager->Tie( base_property_name + "/advance-ratio", &prop_advance_ratio_mu );
+  // nu
+  PropertyManager->Tie( base_property_name + "/induced-inflow-ratio", &prop_inflow_ratio_induced_nu );
+
+  PropertyManager->Tie( base_property_name + "/torque-mr-lbsft", &prop_mr_torque );
+  PropertyManager->Tie( base_property_name + "/thrust-coefficient", &prop_thrust_coefficient );
+  PropertyManager->Tie( base_property_name + "/main-rotor-rpm", &mr.ActualRPM );
+  PropertyManager->Tie( base_property_name + "/tail-rotor-rpm", &tr.ActualRPM );
+
+  // position of the downwash
+  PropertyManager->Tie( base_property_name + "/theta-downwash-rad", &prop_theta_downwash );
+  PropertyManager->Tie( base_property_name + "/phi-downwash-rad", &prop_phi_downwash );  
+
+  // nodes to use via get<xyz>Value
+  prop_collective_ctrl = PropertyManager->GetNode(base_property_name + "/collective-ctrl-rad",true);
+  prop_lateral_ctrl = PropertyManager->GetNode(base_property_name + "/lateral-ctrl-rad",true);
+  prop_longitudinal_ctrl = PropertyManager->GetNode(base_property_name + "/longitudinal-ctrl-rad",true);
+  prop_antitorque_ctrl =   PropertyManager->GetNode(base_property_name + "/antitorque-ctrl-rad",true);
+
+  prop_rotorbrake =   PropertyManager->GetNode(base_property_name + "/rotorbrake-hp", true);
+  prop_freewheel_factor =   PropertyManager->GetNode(base_property_name + "/freewheel-factor", true);
+
+  PropertyManager->Tie( base_property_name + "/dump-flag", &prop_DumpFlag );
+
+  return true;
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 string FGRotor::GetThrusterLabels(int id, string delimeter)
 {
-  return "";
+
+  std::ostringstream buf;
+
+  buf << Name << " RPM (engine " << id << ")";
+
+  return buf.str();
+
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 string FGRotor::GetThrusterValues(int id, string delimeter)
 {
-  return "";
+  std::ostringstream buf;
+
+  buf << RPM;
+
+  return buf.str();
 }
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -109,7 +1082,7 @@ void FGRotor::Debug(int from)
 
   if (debug_lvl & 1) { // Standard console startup message output
     if (from == 0) { // Constructor
-
+      cout << "\n    Rotor Name: " << Name << endl;
     }
   }
   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
@@ -129,4 +1102,6 @@ void FGRotor::Debug(int from)
     }
   }
 }
-}
+
+} // namespace JSBSim 
+
index 6188f40d9fa2e3ce5f246e635d8227e4608cc07e..0663fba46ac474b2584c9f2fa10c025dc74f460b 100644 (file)
@@ -1,10 +1,10 @@
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
  Header:       FGRotor.h
- Author:       Jon S. Berndt
+ Author:       T. Kreitler
  Date started: 08/24/00
 
- ------------- Copyright (C) 2000  Jon S. Berndt (jon@jsbsim.org) -------------
+ ------------- Copyright (C) 2010  T. Kreitler -------------
 
  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
@@ -25,7 +25,7 @@
 
 HISTORY
 --------------------------------------------------------------------------------
-08/24/00  JSB  Created
+01/01/10  T.Kreitler test implementation
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 SENTRY
@@ -39,12 +39,14 @@ INCLUDES
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
 #include "FGThruster.h"
+#include "math/FGTable.h"
+#include "math/FGRungeKutta.h"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_ROTOR "$Id$"
+#define ID_ROTOR "$Id: FGRotor.h,v 1.6 2010/06/02 04:05:13 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -56,7 +58,145 @@ namespace JSBSim {
 CLASS DOCUMENTATION
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-/** Models a rotor (such as for a helicopter); NOT YET IMPLEMENTED.
+/** Models a rotor system. The default configuration consists of main and
+    tail rotor. A practical way to define the positions is to start with an
+    imaginary gear-box near the cg of the vehicle. 
+
+    In this case the location in the thruster definition should be
+    approximately equal to the cg defined in the <tt>fdm_config/mass_balance</tt>
+    section. If the default orientation (roll=pitch=yaw=0) is used the
+    positions of the rotor hubs are now defined relative to the location
+    of the thruster (i.e. the cg-centered body coordinate system).
+
+
+<h3>Configuration File Format:</h3>
+@code
+<rotor name="{string}" variant="{string}">
+  <diameter unit="{LENGTH}"> {number} </diameter>
+  <numblades> {number} </numblades>
+  <xhub unit="{LENGTH}">  {number} </xhub>
+  <zhub unit="{LENGTH}"> {number} </zhub>
+  <nominalrpm> {number} </nominalrpm>
+  <minrpm>   {number} </minrpm>
+  <chord unit="{LENGTH}"> {number} </chord>
+  <liftcurveslope Xunit="1/RAD"> {number} </liftcurveslope>
+  <flappingmoment unit="{MOMENT}"> {number} </flappingmoment>
+  <twist unit="{ANGLE}"> {number} </twist>
+  <massmoment Xunit="SLUG*FT"> {number} </massmoment>
+  <tiplossfactor> {number} </tiplossfactor>
+  <polarmoment unit="{MOMENT}"> {number}</polarmoment>
+  <inflowlag> {number} </inflowlag>
+  <shafttilt unit="{ANGLE}"> {number} </shafttilt>
+  <hingeoffset unit="{LENGTH}"> {number} </hingeoffset>
+  <tailrotor>
+    <diameter unit="{LENGTH}"> {number} </diameter>
+    <numblades> {number} </numblades>
+    <xhub unit="{LENGTH}">{number} </xhub>
+    <zhub unit="{LENGTH}">{number} </zhub>
+    <nominalrpm> {number} </nominalrpm>
+    <chord unit="{LENGTH}"> {number} </chord>
+    <liftcurveslope Xunit="1/RAD"> {number} </liftcurveslope>
+    <flappingmoment unit="{MOMENT}"> {number} </flappingmoment>
+    <twist unit="RAD"> {number} </twist>
+    <massmoment Xunit="SLUG*FT"> {number} </massmoment>
+    <tiplossfactor> {number} </tiplossfactor>
+    <inflowlag> {number} </inflowlag>
+    <hingeoffset unit="{LENGTH}"> {number} </hingeoffset>
+    <cantangle unit="{ANGLE}"> {number} </cantangle>
+  </tailrotor>
+  <cgroundeffect> {number} </cgroundeffect>
+  <groundeffectshift unit="{LENGTH}"> {number} </groundeffectshift>
+</rotor>
+
+//  LENGTH means any of the supported units, same for ANGLE and MOMENT.
+//  Xunit-attributes are a hint for currently unsupported units, so 
+//  values must be provided accordingly.
+
+@endcode
+
+<h3>Configuration Parameters:</h3>
+
+  Brief description and the symbol frequently found in the literature.
+
+<pre>
+    \<diameter>           - Rotor disk diameter (R).
+    \<numblades>          - Number of blades (b).
+    \<xhub>               - Relative height in body coordinate system, thus usually negative.
+    \<zhub>               - Relative distance in body coordinate system, close to zero 
+                             for main rotor, and usually negative for the tail rotor. 
+    \<nominalrpm>         - RPM at which the rotor usally operates. 
+    \<minrpm>             - Lowest RPM generated by the code, optional.
+    \<chord>              - Blade chord, (c).
+    \<liftcurveslope>     - Slope of curve of section lift against section angle of attack,
+                             per rad (a).
+    \<flappingmoment>     - Flapping moment of inertia (I_b).
+    \<twist>              - Blade twist from root to tip, (theta_1).
+    \<massmoment>         - Blade mass moment. (Biege/Widerstands-moment)
+    \<tiplossfactor>      - Tip-loss factor. The Blade fraction that produces lift.
+                              Value usually ranges between 0.95 - 1.0, optional (B).
+    \<polarmoment>        - Moment of inertia for the whole rotor disk, optional.
+    \<inflowlag>          - Rotor inflow time constant, sec.
+    \<shafttilt>          - Orientation of the rotor shaft, negative angles define
+                              a 'forward' tilt. Used by main rotor, optional.
+    \<hingeoffset>        - Rotor flapping-hinge offset (e).
+    
+    Experimental properties
+    
+    \<cantangle>          - Flapping hinge cantangle used by tail rotor, optional.
+    \<cgroundeffect>      - Parameter for exponent in ground effect approximation. Value should
+                              be in the range 0.2 - 0.35, 0.0 disables, optional.
+    \<groundeffectshift>  - Further adjustment of ground effect. 
+
+</pre>
+
+<h3>Notes:</h3>  
+
+   The behavior of the rotor is controlled/influenced by 5 inputs.<ul>
+     <li> The power provided by the engine. This is handled by the regular engine controls.</li>
+     <li> The collective control input. This is read from the <tt>fdm</tt> property 
+          <tt>propulsion/engine[x]/collective-ctrl-rad</tt>.</li>
+     <li> The lateral cyclic input. Read from
+          <tt>propulsion/engine[x]/lateral-ctrl-rad</tt>.</li>
+     <li> The longitudinal cyclic input. Read from 
+          <tt>propulsion/engine[x]/longitudinal-ctrl-rad</tt>.</li>
+     <li> The tail collective (aka antitorque, aka pedal) control input. Read from
+          <tt>propulsion/engine[x]/antitorque-ctrl-rad</tt>.</li>
+
+   </ul>
+
+   In order to keep the rotor speed constant, use of a RPM-Governor system is encouraged.
+
+   It is possible to use different orientation/locations for the rotor system, but then xhub
+   and zhub are no longer aligned to the body frame and need proper recalculation.
+
+   To model a standalone main rotor just omit the <tailrotor/> element. If you provide
+   a plain <tailrotor/> element all tail rotor parameters are estimated.
+   
+   The 'sense' parameter from the thruster is interpreted as follows, sense=1 means
+   counter clockwise rotation of the main rotor, as viewed from above. This is as a far
+   as I know more popular than clockwise rotation, which is defined by setting sense to
+   -1 (to be honest, I'm just 99.9% sure that the orientation is handled properly).
+   
+   Concerning coaxial designs: By providing the 'variant' attribute with value 'coaxial'
+   a Kamov-style rotor is modeled - i.e. the rotor produces no torque.
+
+
+<h3>References:</h3>  
+
+    <dl>    
+    <dt>/SH79/</dt><dd>Shaugnessy, J. D., Deaux, Thomas N., and Yenni, Kenneth R.,
+              "Development and Validation of a Piloted Simulation of a 
+              Helicopter and External Sling Load",  NASA TP-1285, 1979.</dd>
+    <dt>/BA41/</dt><dd>Bailey,F.J.,Jr., "A Simplified Theoretical Method of Determining
+              the Characteristics of a Lifting Rotor in Forward Flight", NACA Rep.716, 1941.</dd>
+    <dt>/AM50/</dt><dd>Amer, Kenneth B.,"Theory of Helicopter Damping in Pitch or Roll and a
+              Comparison With Flight Measurements", NACA TN-2136, 1950.</dd>
+    <dt>/TA77/</dt><dd>Talbot, Peter D., Corliss, Lloyd D., "A Mathematical Force and Moment
+              Model of a UH-1H Helicopter for Flight Dynamics Simulations", NASA TM-73,254, 1977.</dd>   
+    </dl>
+
+    @author Thomas Kreitler
+    @version $Id: FGRotor.h,v 1.6 2010/06/02 04:05:13 jberndt Exp $
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -65,18 +205,197 @@ CLASS DECLARATION
 
 class FGRotor : public FGThruster {
 
+   enum eRotorFlags {eNone=0, eMain=1, eTail=2, eCoaxial=4, eRotCW=8} ;
+   struct rotor {
+
+     virtual ~rotor();
+     void zero();
+     void configure(int f, const rotor *xmain = NULL);
+
+     // assist in parameter retrieval
+     double cnf_elem(const string& ename, double default_val=0.0, const string& unit = "", bool tell=false);
+     double cnf_elem(const string& ename, double default_val=0.0, bool tell=false);
+
+     // rotor dynamics
+     void calc_flow_and_thrust(double dt, double rho, double theta_0, double Uw, double Ww, double flow_scale = 1.0);
+
+     void calc_torque(double rho, double theta_0);
+     void calc_coning_angle(double rho, double theta_0);
+     void calc_flapping_angles(double rho, double theta_0, const FGColumnVector3 &pqr_fus_w);
+     void calc_drag_and_side_forces(double rho, double theta_0);
+
+     // transformations
+     FGColumnVector3 hub_vel_body2ca( const FGColumnVector3 &uvw, const FGColumnVector3 &pqr, 
+                                      double a_ic = 0.0 , double b_ic = 0.0 );
+     FGColumnVector3 fus_angvel_body2ca( const FGColumnVector3 &pqr);
+
+     FGColumnVector3 body_forces(double a_ic = 0.0 , double b_ic = 0.0 );
+     FGColumnVector3 body_moments(FGColumnVector3 F_h, double a_ic = 0.0 , double b_ic = 0.0 );
+         
+     // bookkeeping
+     int flags                  ;
+     Element *parent            ;
+
+     // used in flow calculation
+     // FGRK4 rk                  ;  // use this after checking
+     FGRKFehlberg rk            ;
+     int          reports       ;
+
+     // configuration parameters
+     double Radius              ;
+     int    BladeNum            ;
+     double RelDistance_xhub    ;
+     double RelShift_yhub       ;
+     double RelHeight_zhub      ;
+     double NominalRPM          ;
+     double MinRPM              ;
+     double BladeChord          ;
+     double LiftCurveSlope      ;
+     double BladeFlappingMoment ;
+     double BladeTwist          ;
+     double BladeMassMoment     ;
+     double TipLossB            ;
+     double PolarMoment         ;
+     double InflowLag           ;
+     double ShaftTilt           ;
+     double HingeOffset         ;
+     double HingeOffset_hover   ;
+     double CantAngleD3         ;
+
+     double theta_shaft         ;
+     double phi_shaft           ;
+
+     // derived parameters
+     double LockNumberByRho     ;
+     double solidity            ; // aka sigma
+     double RpmRatio            ; // main_to_tail, hmm
+     double R[5]                ; // Radius powers
+     double B[6]                ; // TipLossB powers
+
+     FGMatrix33 BodyToShaft     ; // [S]T, see /SH79/ eqn(17,18)
+     FGMatrix33 ShaftToBody     ; // [S]
+
+     // dynamic values
+     double ActualRPM           ;
+     double Omega               ; // must be > 0 
+     double beta_orient         ;
+     double a0                  ; // coning angle (rad)
+     double a_1, b_1, a_dw      ;
+     double a1s, b1s            ; // cyclic flapping relative to shaft axes, /SH79/ eqn(43)
+     double H_drag, J_side      ;
+
+     double Torque              ;
+     double Thrust              ;
+     double Ct                  ;
+     double lambda              ; // inflow ratio
+     double mu                  ; // tip-speed ratio 
+     double nu                  ; // induced inflow ratio
+     double v_induced           ; // always positive [ft/s]
+
+     // results
+     FGColumnVector3 force      ;
+     FGColumnVector3 moment     ;
+
+
+     // declare the problem function
+     class dnuFunction : public FGRungeKuttaProblem {
+       public:
+         void update_params(rotor *r, double ct_t01, double fs, double w);
+       private:
+         double pFunc(double x, double y);
+         // some shortcuts
+         double k_sat, ct_lambda, k_wor, k_theta, mu2, k_flowscale;
+     } flowEquation;
+
+
+   };
+
+
 public:
-  /// Constructor
-  FGRotor(FGFDMExec *FDMExec, Element* rotor_element, int num);
+  /** Constructor
+      @param exec pointer to executive structure
+      @param rotor_element pointer to XML element in the config file
+      @param num the number of this rotor  */
+  FGRotor(FGFDMExec *exec, Element* rotor_element, int num);
+
   /// Destructor
   ~FGRotor();
 
+  void SetRPM(double rpm) {RPM = rpm;}
+
+  /** Calculates forces and moments created by the rotor(s) and updates 
+      vFn,vMn state variables. RPM changes are handled inside, too. 
+      The RPM change is based on estimating the torque provided by the engine.
+
+      @param PowerAvailable here this is the thrust (not power) provided by a turbine
+      @return PowerAvailable */
   double Calculate(double);
+
+  double GetRPM(void)     const { return RPM;           }
+  double GetDiameter(void)      { return mr.Radius*2.0; }
+
+  // Stubs. Right now this rotor-to-engine interface is just a hack.
+  double GetTorque(void)        { return 0.0; /* return mr.Torque;*/  }
+  double GetPowerRequired(void); 
+
+  // Stubs. Only main rotor RPM is returned
   string GetThrusterLabels(int id, string delimeter);
   string GetThrusterValues(int id, string delimeter);
 
 private:
+
+  bool bind(void);
+
+  double RPM;
+  double Sense; // default is counter clockwise rotation of the main rotor (viewed from above)
+  bool   tailRotorPresent;
+
   void Debug(int from);
+
+  FGPropertyManager* PropertyManager;
+
+  rotor mr;
+  rotor tr; 
+
+  Filter damp_hagl;
+
+  double rho;
+  
+  double effective_tail_col; // /SH79/ eqn(47)
+
+  double ground_effect_exp;
+  double ground_effect_shift;
+
+  double hover_threshold;
+  double hover_scale;
+
+  // fdm imported controls
+  FGPropertyManager* prop_collective_ctrl;
+  FGPropertyManager* prop_lateral_ctrl;
+  FGPropertyManager* prop_longitudinal_ctrl;
+  FGPropertyManager* prop_antitorque_ctrl;
+
+  FGPropertyManager* prop_freewheel_factor;
+  FGPropertyManager* prop_rotorbrake;
+
+  // fdm export ...
+  double prop_inflow_ratio_lambda;
+  double prop_advance_ratio_mu;
+  double prop_inflow_ratio_induced_nu;
+  double prop_mr_torque;
+  double prop_coning_angle;
+
+  double prop_theta_downwash;
+  double prop_phi_downwash;
+
+  double prop_thrust_coefficient;
+  double prop_lift_coefficient;
+
+  double dt; // deltaT doesn't do the thing 
+
+  // devel/debug stuff  
+  int prop_DumpFlag;   // causes 1-time dump on stdout
+
 };
 }
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index f05831b73a0bf6ab7129a32784644f16cb781d0c..c9d38dab871b08c8396143f284d4a122098df3dd 100644 (file)
@@ -48,7 +48,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGTank.cpp,v 1.28 2010/01/24 19:26:04 jberndt Exp $";
 static const char *IdHdr = ID_TANK;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -66,6 +66,7 @@ FGTank::FGTank(FGFDMExec* exec, Element* el, int tank_number)
   InitialTemperature = Temperature = -9999.0;
   Ixx = Iyy = Izz = 0.0;
   Radius = Contents = Standpipe = Length = InnerRadius = 0.0;
+  InitialStandpipe = 0.0;
   Capacity = 0.00001;
   Priority = InitialPriority = 1;
   PropertyManager = Exec->GetPropertyManager();
index 55930543f660ef5c4f4227ebc135434bff683ceb..12e7e5fc9e6b2899399888ea4d9028f1966e45f8 100644 (file)
@@ -52,7 +52,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_TANK "$Id$"
+#define ID_TANK "$Id: FGTank.h,v 1.21 2010/02/05 05:53:00 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -195,6 +195,9 @@ public:
   /// Destructor
   ~FGTank();
 
+  enum TankType {ttUNKNOWN, ttFUEL, ttOXIDIZER};
+  enum GrainType {gtUNKNOWN, gtCYLINDRICAL, gtENDBURNING};
+
   /** Removes fuel from the tank.
       This function removes fuel from a tank. If the tank empties, it is
       deselected.
@@ -275,6 +278,8 @@ public:
   const FGColumnVector3 GetXYZ(void);
   const double GetXYZ(int idx);
 
+  const GrainType GetGrainType(void) {return grainType;}
+
   double Fill(double amount);
   void SetContents(double amount);
   void SetContentsGallons(double gallons);
@@ -282,9 +287,6 @@ public:
   void SetStandpipe(double amount) { Standpipe = amount; }
   void SetSelected(bool sel) { sel==true ? SetPriority(1):SetPriority(0); }
 
-  enum TankType {ttUNKNOWN, ttFUEL, ttOXIDIZER};
-  enum GrainType {gtUNKNOWN, gtCYLINDRICAL, gtENDBURNING};
-
 private:
   TankType Type;
   GrainType grainType;
index 32a508ee17c9f55111a805fe138d776d94537d9d..064177a2b31670a7316879ca1cf6c2dfd57aed84 100644 (file)
@@ -45,7 +45,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGThruster.cpp,v 1.12 2009/10/24 22:59:30 jberndt Exp $";
 static const char *IdHdr = ID_THRUSTER;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 886b678dc5c96d89b09b17b808812ab63c7e0ba0..118005f5a408b0498619efcf6c82230cb7197b8d 100644 (file)
@@ -46,7 +46,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_THRUSTER "$Id$"
+#define ID_THRUSTER "$Id: FGThruster.h,v 1.15 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -74,7 +74,7 @@ CLASS DOCUMENTATION
     1.57 (pi/2) results in no thrust at all.
  
     @author Jon Berndt
-    @version $Id$
+    @version $Id: FGThruster.h,v 1.15 2009/10/24 22:59:30 jberndt Exp $
     */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index b690d72f0cbf5e5b54cec99af18d763f1f1e3ceb..c61667b4b2ddc98fac8c9757b62fbab7036e37f8 100644 (file)
@@ -42,15 +42,16 @@ INCLUDES
 #include <iostream>
 #include <sstream>
 #include "FGTurbine.h"
-#include "FGState.h"
-#include "models/FGPropulsion.h"
 #include "FGThruster.h"
+#include "models/FGPropulsion.h"
+#include "models/FGAuxiliary.h"
+#include "models/FGAtmosphere.h"
 
 using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGTurbine.cpp,v 1.27 2010/05/24 11:26:37 jberndt Exp $";
 static const char *IdHdr = ID_TURBINE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -118,7 +119,7 @@ double FGTurbine::Calculate(void)
 
   TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
   double qbar = Auxiliary->Getqbar();
-  dt = State->Getdt() * Propulsion->GetRate();
+  dt = FDMExec->GetDeltaT() * Propulsion->GetRate();
   ThrottlePos = FCS->GetThrottlePos(EngineNumber);
   if (ThrottlePos > 1.0) {
     AugmentCmd = ThrottlePos - 1.0;
@@ -145,7 +146,7 @@ double FGTurbine::Calculate(void)
 
   if (!Running && Cutoff && Starter) {
      if (phase == tpOff) phase = tpSpinUp;
-     }
+  }
 
   // start
   if ((Starter == true) || (qbar > 30.0)) {
@@ -223,7 +224,7 @@ double FGTurbine::Run()
 
   if (!Augmentation) {
     correctedTSFC = TSFC * sqrt(T/389.7) * (0.84 + (1-N2norm)*(1-N2norm));
-    FuelFlow_pph = Seek(&FuelFlow_pph, thrust * correctedTSFC, 1000.0, 100000);
+    FuelFlow_pph = Seek(&FuelFlow_pph, thrust * correctedTSFC, 1000.0, 10000.0);
     if (FuelFlow_pph < IdleFF) FuelFlow_pph = IdleFF;
     NozzlePosition = Seek(&NozzlePosition, 1.0 - N2norm, 0.8, 0.8);
     thrust = thrust * (1.0 - BleedDemand);
@@ -388,7 +389,7 @@ double FGTurbine::Trim()
 
 double FGTurbine::CalcFuelNeed(void)
 {
-  double dT = State->Getdt() * Propulsion->GetRate();
+  double dT = FDMExec->GetDeltaT() * Propulsion->GetRate();
   FuelFlowRate = FuelFlow_pph / 3600.0; // Calculates flow in lbs/sec from lbs/hr
   FuelExpended = FuelFlowRate * dT;     // Calculates fuel expended in this time step
   return FuelExpended;
@@ -539,12 +540,12 @@ void FGTurbine::bindmodel()
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 int FGTurbine::InitRunning(void) {
-  State->SuspendIntegration();
+  FDMExec->SuspendIntegration();
   Cutoff=false;
   Running=true;  
   N2=IdleN2;
   Calculate();
-  State->ResumeIntegration();
+  FDMExec->ResumeIntegration();
   return phase==tpRun;
 }
 
index 9eebc335d9dc7c0be7ec989a622ebe5e26304374..1fff92c6789256876d2cf29f43c487dd9415e86b 100644 (file)
@@ -42,7 +42,7 @@ INCLUDES
 
 #include "FGEngine.h"
 
-#define ID_TURBINE "$Id$"
+#define ID_TURBINE "$Id: FGTurbine.h,v 1.18 2009/10/24 22:59:30 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -146,7 +146,7 @@ CLASS DOCUMENTATION
     /engine/direct.xml
 </pre>
     @author David P. Culp
-    @version "$Id$"
+    @version "$Id: FGTurbine.h,v 1.18 2009/10/24 22:59:30 jberndt Exp $"
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
index 9ebef96df9b4ced5f41fd20cadd556073f2be0b6..f384877fc502f8fce0599c7c15c1f74ad8c3aa10 100755 (executable)
@@ -44,16 +44,15 @@ INCLUDES
 #include <iostream>
 #include <sstream>
 #include "FGTurboProp.h"
-
 #include "FGPropeller.h"
-#include "FGState.h"
+#include "models/FGPropulsion.h"
 #include "models/FGAuxiliary.h"
 
 using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGTurboProp.cpp,v 1.16 2010/02/25 05:21:36 jberndt Exp $";
 static const char *IdHdr = ID_TURBOPROP;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -162,7 +161,7 @@ bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
 double FGTurboProp::Calculate(void)
 {
   TAT = (Auxiliary->GetTotalTemperature() - 491.69) * 0.5555556;
-  dt = State->Getdt() * Propulsion->GetRate();
+  dt = FDMExec->GetDeltaT() * Propulsion->GetRate();
 
   ThrottleCmd = FCS->GetThrottleCmd(EngineNumber);
 
@@ -406,7 +405,7 @@ double FGTurboProp::Start(void)
 
 double FGTurboProp::CalcFuelNeed(void)
 {
-  double dT = State->Getdt() * Propulsion->GetRate();
+  double dT = FDMExec->GetDeltaT() * Propulsion->GetRate();
   FuelFlowRate = FuelFlow_pph / 3600.0;
   FuelExpended = FuelFlowRate * dT;
   return FuelExpended;
@@ -505,12 +504,12 @@ string FGTurboProp::GetEngineValues(const string& delimiter)
 
 int FGTurboProp::InitRunning(void)
 {
-  State->SuspendIntegration();
+  FDMExec->SuspendIntegration();
   Cutoff=false;
   Running=true;  
   N2=16.0;
   Calculate();
-  State->ResumeIntegration();
+  FDMExec->ResumeIntegration();
   return phase==tpRun;
 }
 
index cb10f85b99dcce08f030a75fbb30c8cf00a93fe2..66febb1915fde6c262e1953ff744f543d1e9ace6 100755 (executable)
@@ -46,7 +46,7 @@ INCLUDES
 #include "input_output/FGXMLElement.h"
 #include "math/FGTable.h"
 
-#define ID_TURBOPROP "$Id$"
+#define ID_TURBOPROP "$Id: FGTurboProp.h,v 1.11 2009/10/26 03:48:42 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS