]> git.mxchange.org Git - flightgear.git/commitdiff
Synchronized with JSBSim/CVS.
authorAnders Gidenstam <anders@gidenstam.org>
Sun, 22 Sep 2013 15:56:58 +0000 (17:56 +0200)
committerAnders Gidenstam <anders@gidenstam.org>
Mon, 23 Sep 2013 20:30:44 +0000 (22:30 +0200)
23 files changed:
src/FDM/JSBSim/CMakeLists.txt
src/FDM/JSBSim/FGJSBBase.h
src/FDM/JSBSim/input_output/FGOutputTextFile.cpp
src/FDM/JSBSim/input_output/FGScript.cpp
src/FDM/JSBSim/input_output/FGScript.h
src/FDM/JSBSim/input_output/FGXMLElement.cpp
src/FDM/JSBSim/math/FGFunction.cpp
src/FDM/JSBSim/math/FGFunction.h
src/FDM/JSBSim/models/FGAerodynamics.cpp
src/FDM/JSBSim/models/FGAerodynamics.h
src/FDM/JSBSim/models/FGAuxiliary.cpp
src/FDM/JSBSim/models/FGFCS.cpp
src/FDM/JSBSim/models/FGFCS.h
src/FDM/JSBSim/models/FGOutput.cpp
src/FDM/JSBSim/models/FGPropagate.cpp
src/FDM/JSBSim/models/FGPropagate.h
src/FDM/JSBSim/models/FGPropulsion.cpp
src/FDM/JSBSim/models/flight_control/FGAngles.cpp [new file with mode: 0755]
src/FDM/JSBSim/models/flight_control/FGAngles.h [new file with mode: 0755]
src/FDM/JSBSim/models/flight_control/FGFCSComponent.cpp
src/FDM/JSBSim/models/flight_control/FGFCSComponent.h
src/FDM/JSBSim/models/flight_control/FGWaypoint.cpp [new file with mode: 0755]
src/FDM/JSBSim/models/flight_control/FGWaypoint.h [new file with mode: 0755]

index 85c1fef7c244b209bddbe4e2a4c681210ed6ca7d..5449aa1fc9100a44fc53080e8b4e5ffb77e01494 100644 (file)
@@ -64,6 +64,7 @@ set(HEADERS
     models/atmosphere/FGWinds.h
     models/flight_control/FGAccelerometer.h
     models/flight_control/FGActuator.h
+    models/flight_control/FGAngles.h
     models/flight_control/FGDeadBand.h
     models/flight_control/FGFCSComponent.h
     models/flight_control/FGFCSFunction.h
@@ -77,6 +78,7 @@ set(HEADERS
     models/flight_control/FGSensorOrientation.h
     models/flight_control/FGSummer.h
     models/flight_control/FGSwitch.h
+    models/flight_control/FGWaypoint.h
     models/propulsion/FGElectric.h
     models/propulsion/FGEngine.h
     models/propulsion/FGForce.h
@@ -152,6 +154,7 @@ set(SOURCES
     models/atmosphere/FGWinds.cpp
     models/flight_control/FGAccelerometer.cpp
     models/flight_control/FGActuator.cpp
+    models/flight_control/FGAngles.cpp
     models/flight_control/FGDeadBand.cpp
     models/flight_control/FGFCSComponent.cpp
     models/flight_control/FGFCSFunction.cpp
@@ -164,6 +167,7 @@ set(SOURCES
     models/flight_control/FGSensor.cpp
     models/flight_control/FGSummer.cpp
     models/flight_control/FGSwitch.cpp
+    models/flight_control/FGWaypoint.cpp
     models/propulsion/FGElectric.cpp
     models/propulsion/FGEngine.cpp
     models/propulsion/FGForce.cpp
index 269b550d93e5f173f0e18ece3e988027dc21e205..bcc6e3fdf8be6de82fcf48abc7d14e221f3c846f 100644 (file)
@@ -56,7 +56,7 @@ using std::max;
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_JSBBASE "$Id: FGJSBBase.h,v 1.34 2011/10/22 14:38:30 bcoconni Exp $"
+#define ID_JSBBASE "$Id: FGJSBBase.h,v 1.38 2013/06/20 13:01:48 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -72,7 +72,7 @@ CLASS DOCUMENTATION
 *   This class provides universal constants, utility functions, messaging
 *   functions, and enumerated constants to JSBSim.
     @author Jon S. Berndt
-    @version $Id: FGJSBBase.h,v 1.34 2011/10/22 14:38:30 bcoconni Exp $
+    @version $Id: FGJSBBase.h,v 1.38 2013/06/20 13:01:48 jberndt Exp $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -256,6 +256,13 @@ public:
     return kelvin - 273.15;
   }
 
+  /** Converts from feet to meters
+  *   @param measure The length in feet.
+  *   @return The length in meters. */
+  static double FeetToMeters (double measure) {
+    return measure*0.3048;
+  }
+
   /** Calculate the calibrated airspeed from the Mach number. It uses the
   *   Rayleigh formula for supersonic speeds (See "Introduction to Aerodynamics
   *   of a Compressible Fluid - H.W. Liepmann, A.E. Puckett - Wiley & sons
index f0eb0561c9d5729917917435295e2d27cfe029db..35fe76c01a1c4d9aefd79a7d8aa1eb88e5638514 100644 (file)
@@ -63,7 +63,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGOutputTextFile.cpp,v 1.5 2013/01/12 19:26:59 jberndt Exp $";
+static const char *IdSrc = "$Id: FGOutputTextFile.cpp,v 1.6 2013/09/11 12:51:13 jberndt Exp $";
 static const char *IdHdr = ID_OUTPUTTEXTFILE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -75,6 +75,8 @@ bool FGOutputTextFile::Load(Element* el)
   if(!FGOutputFile::Load(el))
     return false;
 
+  PreLoad(el, PropertyManager);
+
   string type = el->GetAttributeValue("type");
   string delim;
   if (type == "TABULAR") {
@@ -238,6 +240,12 @@ bool FGOutputTextFile::OpenFile(void)
     }
   }
 
+  if (PreFunctions.size() > 0) {
+    for (unsigned int i=0;i<PreFunctions.size();i++) {
+      outstream << delimeter << PreFunctions[i]->GetName();
+    }
+  }
+
   outstream << endl;
   outstream.flush();
 
@@ -382,6 +390,9 @@ void FGOutputTextFile::Print(void)
   for (unsigned int i=0;i<OutputProperties.size();i++) {
     outstream << delimeter << OutputProperties[i]->getDoubleValue();
   }
+  for (unsigned int i=0;i<PreFunctions.size();i++) {
+    outstream << delimeter << PreFunctions[i]->getDoubleValue();
+  }
   outstream.precision(10);
 
   outstream << endl;
index 4d2b6ed0a81846f48bd8d54ec1cd3ee79cc114c8..6ac660c905a39e371f7e18c52ac15f5668fb4368 100644 (file)
@@ -55,7 +55,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGScript.cpp,v 1.51 2013/06/10 01:50:43 jberndt Exp $";
+static const char *IdSrc = "$Id: FGScript.cpp,v 1.52 2013/09/11 12:46:35 jberndt Exp $";
 static const char *IdHdr = ID_FGSCRIPT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -275,6 +275,9 @@ bool FGScript::LoadScript(string script, double deltaT, const string initfile)
 
     // Notify about when this event is triggered?
     if ((notify_element = event_element->FindElement("notify")) != 0) {
+      if (notify_element->HasAttribute("format")) {
+        if (notify_element->GetAttributeValue("format") == "kml") newEvent->NotifyKML = true;
+      }
       newEvent->Notify = true;
       // Check here for new <description> tag that gets echoed
       string notify_description = notify_element->FindElementValue("description");
@@ -284,23 +287,16 @@ bool FGScript::LoadScript(string script, double deltaT, const string initfile)
       notify_property_element = notify_element->FindElement("property");
       while (notify_property_element) {
         notifyPropertyName = notify_property_element->GetDataLine();
-        if (PropertyManager->GetNode(notifyPropertyName)) {
-          newEvent->NotifyProperties.push_back( PropertyManager->GetNode(notifyPropertyName) );
+
+        newEvent->NotifyPropertyNames.push_back(notifyPropertyName);
+        newEvent->NotifyProperties.push_back(0);
           string caption_attribute = notify_property_element->GetAttributeValue("caption");
           if (caption_attribute.empty()) {
             newEvent->DisplayString.push_back(notifyPropertyName);
           } else {
             newEvent->DisplayString.push_back(caption_attribute);
           }
-        } else {
-          cout << endl << fgred << "  Could not find the property named "
-               << notifyPropertyName << " in script" << endl << "  \""
-               << ScriptName << "\". Execution is aborted. Please recheck "
-               << "your input files and scripts." << reset << endl;
-          delete newEvent->Condition;
-          delete newEvent;
-          return false;
-        }
+
         notify_property_element = notify_element->FindNextElement("property");
       }
     }
@@ -313,7 +309,6 @@ bool FGScript::LoadScript(string script, double deltaT, const string initfile)
       newEvent->SetParam.push_back( PropertyManager->GetNode(prop_name) );
       } else {
         newEvent->SetParam.push_back( 0L );
-        cerr << "Property " << prop_name << " will be late-bound." << endl;
       }
       newEvent->SetParamName.push_back( prop_name );
 
@@ -477,15 +472,44 @@ bool FGScript::RunScript(void)
 
       // Print notification values after setting them
       if (thisEvent.Notify && !thisEvent.Notified) {
-        cout << endl << "  Event " << event_ctr << " (" << thisEvent.Name << ")"
-             << " executed at time: " << currentTime << endl;
+        if (thisEvent.NotifyKML) {
+          cout << endl << "<Placemark>" << endl;
+          cout << "  <name> " << currentTime << " seconds" << " </name>" << endl;
+          cout << "  <description>" << endl;
+          cout << "  <![CDATA[" << endl;
+          cout << "  <b>" << thisEvent.Name << " (Event " << event_ctr << ")" << " executed at time: " << currentTime << "</b><br/>" << endl;
+        } else  {
+          cout << endl << underon
+               << highint << thisEvent.Name << normint << underoff
+               << " (Event " << event_ctr << ")" 
+               << " executed at time: " << highint << currentTime << normint << endl;
+        }
         if (!thisEvent.Description.empty()) {
           cout << "    " << thisEvent.Description << endl;
         }
         for (j=0; j<thisEvent.NotifyProperties.size();j++) {
-//          cout << "    " << thisEvent.NotifyProperties[j]->GetRelativeName()
-          cout << "    " << thisEvent.DisplayString[j]
-               << " = " << thisEvent.NotifyProperties[j]->getDoubleValue() << endl;
+          if (thisEvent.NotifyProperties[j] == 0) {
+            if (PropertyManager->HasNode(thisEvent.NotifyPropertyNames[j])) {
+              thisEvent.NotifyProperties[j] = PropertyManager->GetNode(thisEvent.NotifyPropertyNames[j]);
+            } else {
+              throw("Could not find property named "+thisEvent.NotifyPropertyNames[j]+" in script.");
+            }
+          }
+          cout << "    " << thisEvent.DisplayString[j] << " = " << thisEvent.NotifyProperties[j]->getDoubleValue();
+          if (thisEvent.NotifyKML) cout << " <br/>";
+          cout << endl;
+        }
+        if (thisEvent.NotifyKML) {
+          cout << "  ]]>" << endl;
+          cout << "  </description>" << endl;
+          cout << "  <Point>" << endl;
+          cout << "    <altitudeMode> absolute </altitudeMode>" << endl;
+          cout << "    <extrude> 1 </extrude>" << endl;
+          cout << "    <coordinates>" << FDMExec->GetPropagate()->GetLongitudeDeg()
+            << "," << FDMExec->GetPropagate()->GetGeodLatitudeDeg()
+            << "," << FDMExec->GetPropagate()->GetAltitudeASLmeters() << "</coordinates>" << endl;
+          cout << "  </Point>" << endl;
+          cout << "</Placemark>" << endl;
         }
         cout << endl;
         thisEvent.Notified = true;
@@ -561,25 +585,37 @@ void FGScript::Debug(int from)
         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) {
+              if (Events[i].SetParamName[j].size() == 0) {
               cerr << fgred << highint << endl
                    << "  An attempt has been made to access a non-existent property" << endl
                    << "  in this event. Please check the property names used, spelling, etc."
                    << reset << endl;
               exit(-1);
+              } else {
+                cout << endl << "      set " << Events[i].SetParamName[j]
+                     << " to function value (Late Bound)";
             }
+            } else {
             cout << endl << "      set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/")
                  << " to function value";
+            }
           } else {
             if (Events[i].SetParam[j] == 0) {
+              if (Events[i].SetParamName[j].size() == 0) {
               cerr << fgred << highint << endl
                    << "  An attempt has been made to access a non-existent property" << endl
                    << "  in this event. Please check the property names used, spelling, etc."
                    << reset << endl;
               exit(-1);
+              } else {
+                cout << endl << "      set " << Events[i].SetParamName[j]
+                     << " to function value (Late Bound)";
             }
+            } else {
             cout << endl << "      set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/")
                  << " to " << Events[i].SetValue[j];
           }
+          }
 
           switch (Events[i].Type[j]) {
           case FG_VALUE:
@@ -615,10 +651,14 @@ void FGScript::Debug(int from)
         // 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++) {
+            if (Events[i].NotifyKML) {
+              cout << "  Notifications (KML Format):" << endl << "    {" << endl;
+            } else {
+              cout << "  Notifications:" << endl << "    {" << endl;
+            }
+            for (unsigned j=0; j<Events[i].NotifyPropertyNames.size();j++) {
               cout << "      "
-                   << Events[i].NotifyProperties[j]->GetRelativeName("/fdm/jsbsim/")
+                   << Events[i].NotifyPropertyNames[j]
                    << endl;
             }
             cout << "    }" << endl;
index 17abb4b383087cc89d8273222dd9a1933b319437..aac134c7af6bdd34e0ec6c2b22213af49e9b14bb 100644 (file)
@@ -49,7 +49,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FGSCRIPT "$Id: FGScript.h,v 1.24 2013/06/10 01:50:43 jberndt Exp $"
+#define ID_FGSCRIPT "$Id: FGScript.h,v 1.25 2013/09/11 12:46:35 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -158,7 +158,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: FGScript.h,v 1.24 2013/06/10 01:50:43 jberndt Exp $"
+    @version "$Id: FGScript.h,v 1.25 2013/09/11 12:46:35 jberndt Exp $"
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -214,6 +214,7 @@ private:
     bool             Continuous;
     bool             Triggered;
     bool             Notify;
+    bool             NotifyKML;
     bool             Notified;
     double           Delay;
     double           StartTime;
@@ -223,6 +224,7 @@ private:
     vector <FGPropertyNode_ptr>  SetParam;
     vector <std::string>  SetParamName;
     vector <FGPropertyNode_ptr>  NotifyProperties;
+    vector <string>              NotifyPropertyNames;
     vector <string>              DisplayString;
     vector <eAction> Action;
     vector <eType>   Type;
@@ -239,7 +241,7 @@ private:
       Persistent = false;
       Continuous = false;
       Delay = 0.0;
-      Notify = Notified = false;
+      Notify = Notified = NotifyKML = false;
       Name = "";
       StartTime = 0.0;
       TimeSpan = 0.0;
index 45132a2e0ca37e3e144a08e943e27fec9520ace7..72c4f175853f558bce422b11dedcde538e3a9156 100644 (file)
@@ -43,7 +43,7 @@ FORWARD DECLARATIONS
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.38 2012/12/13 04:41:06 jberndt Exp $";
+static const char *IdSrc = "$Id: FGXMLElement.cpp,v 1.39 2013/06/20 04:37:27 jberndt Exp $";
 static const char *IdHdr = ID_XMLELEMENT;
 
 bool Element::converterIsInitialized = false;
@@ -428,22 +428,27 @@ double Element::FindElementValueAsNumberConvertTo(const string& el, const string
   Element* element = FindElement(el);
 
   if (!element) {
-    cerr << "Attempting to get non-existent element " << el << endl;
-    exit(0);
+    throw("Attempting to get the value of a non-existent element "+el);
+//    cerr << "Attempting to get non-existent element " << el << endl;
+//    exit(0);
   }
 
   string supplied_units = element->GetAttributeValue("unit");
 
   if (!supplied_units.empty()) {
     if (convert.find(supplied_units) == convert.end()) {
-      cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
-           << " conversion in FGXMLElement.cpp." << endl;
-      exit(-1);
+      throw("Supplied unit: \"" + supplied_units + "\" does not exist (typo?). Add new unit"
+           + " conversion in FGXMLElement.cpp.");
+//      cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
+//           << " conversion in FGXMLElement.cpp." << endl;
+//      exit(-1);
     }
     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
-      cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
-                   << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
-      exit(-1);
+      throw("Supplied unit: \"" + supplied_units + "\" cannot be converted to "
+                   + target_units + ". Add new unit conversion in FGXMLElement.cpp or fix typo");
+//      cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
+//                   << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
+//      exit(-1);
     }
   }
 
index c64de4b507ff48a1b1d18e19693288d895859d86..328ca06b81b902d22642243ede409ecf3ee1f765 100644 (file)
@@ -43,7 +43,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGFunction.cpp,v 1.50 2013/06/10 02:05:12 jberndt Exp $";
+static const char *IdSrc = "$Id: FGFunction.cpp,v 1.51 2013/09/11 12:49:36 jberndt Exp $";
 static const char *IdHdr = ID_FUNCTION;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -807,14 +807,11 @@ void FGFunction::bind(void)
     }
 
     if (PropertyManager->HasNode(tmp)) {
-      FGPropertyNode* property = PropertyManager->GetNode(tmp);
-      if (property->isTied()) {
         cout << "Property " << tmp << " has already been successfully bound (late)." << endl;
-        return;
+    } else {
+    PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
       }
-    }
 
-    PropertyManager->Tie( tmp, this, &FGFunction::GetValue);
   }
 }
 
index 43fe4212d86b3dc4264e5b22526fdeff10209071..49d3e15164c0dfc3d26dcb892352ebe2f465859c 100644 (file)
@@ -43,7 +43,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FUNCTION "$Id: FGFunction.h,v 1.30 2013/06/10 02:25:18 jberndt Exp $"
+#define ID_FUNCTION "$Id: FGFunction.h,v 1.31 2013/06/20 04:37:27 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -685,7 +685,7 @@ of the three words refers to one or more instances of a property, value, or tabl
        <v> 0.00 </v>  <v> 0.25 </v>
        <v> 0.80 </v>  <v> 0.50 </v>
        <v> 0.90 </v>  <v> 0.60 </v>
-       </interpolate1d>
+     </interpolate1d>
      @endcode
 @author Jon Berndt
 */
index cb6152991af8599b6b22b9206abc264bf4a3909c..02921c230828fc64b2a7b5927c9c2c236622c53c 100644 (file)
@@ -48,7 +48,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.47 2013/06/10 01:59:16 jberndt Exp $";
+static const char *IdSrc = "$Id: FGAerodynamics.cpp,v 1.48 2013/09/11 12:42:14 jberndt Exp $";
 static const char *IdHdr = ID_AERODYNAMICS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -77,6 +77,7 @@ FGAerodynamics::FGAerodynamics(FGFDMExec* FDMExec) : FGModel(FDMExec)
   axisType = atNone;
 
   AeroFunctions = new AeroFunctionArray[6];
+  AeroFunctionsAtCG = new AeroFunctionArray[6];
 
   impending_stall = stall_hyst = 0.0;
   alphaclmin = alphaclmax = 0.0;
@@ -101,8 +102,12 @@ FGAerodynamics::~FGAerodynamics()
   for (i=0; i<6; i++)
     for (j=0; j<AeroFunctions[i].size(); j++)
       delete AeroFunctions[i][j];
+  for (i=0; i<6; i++)
+    for (j=0; j<AeroFunctionsAtCG[i].size(); j++)
+      delete AeroFunctionsAtCG[i][j];
 
   delete[] AeroFunctions;
+  delete[] AeroFunctionsAtCG;
 
   delete AeroRPShift;
 
@@ -165,7 +170,9 @@ bool FGAerodynamics::Run(bool Holding)
   }
 
   vFw.InitMatrix();
+  vFwAtCG.InitMatrix();
   vFnative.InitMatrix();
+  vFnativeAtCG.InitMatrix();
 
   for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
     for (ctr=0; ctr < AeroFunctions[axis_ctr].size(); ctr++) {
@@ -173,6 +180,12 @@ bool FGAerodynamics::Run(bool Holding)
     }
   }
 
+  for (axis_ctr = 0; axis_ctr < 3; axis_ctr++) {
+    for (ctr=0; ctr < AeroFunctionsAtCG[axis_ctr].size(); ctr++) {
+      vFnativeAtCG(axis_ctr+1) += AeroFunctionsAtCG[axis_ctr][ctr]->GetValue();
+    }
+  }
+
   // Note that we still need to convert to wind axes here, because it is
   // used in the L/D calculation, and we still may want to look at Lift
   // and Drag.
@@ -189,19 +202,32 @@ bool FGAerodynamics::Run(bool Holding)
   switch (axisType) {
     case atBodyXYZ:       // Forces already in body axes; no manipulation needed
       vFw = in.Tb2w*vFnative;
-      vFw(eDrag)*=-1; vFw(eLift)*=-1;
       vForces = vFnative;
+      vFw(eDrag)*=-1; vFw(eLift)*=-1;
+
+      vFwAtCG = in.Tb2w*vFnativeAtCG;
+      vForcesAtCG = vFnativeAtCG;
+      vFwAtCG(eDrag)*=-1; vFwAtCG(eLift)*=-1;
       break;
     case atLiftDrag:      // Copy forces into wind axes
       vFw = vFnative;
       vFw(eDrag)*=-1; vFw(eLift)*=-1;
       vForces = in.Tw2b*vFw;
       vFw(eDrag)*=-1; vFw(eLift)*=-1;
+
+      vFwAtCG = vFnativeAtCG;
+      vFwAtCG(eDrag)*=-1; vFwAtCG(eLift)*=-1;
+      vForcesAtCG = in.Tw2b*vFwAtCG;
+      vFwAtCG(eDrag)*=-1; vFwAtCG(eLift)*=-1;
       break;
     case atAxialNormal:   // Convert native forces into Axial|Normal|Side system
       vFw = in.Tb2w*vFnative;
       vFnative(eX)*=-1; vFnative(eZ)*=-1;
       vForces = vFnative;
+
+      vFwAtCG = in.Tb2w*vFnativeAtCG;
+      vFnativeAtCG(eX)*=-1; vFnativeAtCG(eZ)*=-1;
+      vForcesAtCG = vFnativeAtCG;
       break;
     default:
       cerr << endl << "  A proper axis type has NOT been selected. Check "
@@ -211,12 +237,13 @@ bool FGAerodynamics::Run(bool Holding)
 
   // Calculate lift coefficient squared
   if ( in.Qbar > 0) {
-    clsq = vFw(eLift) / (in.Wingarea*in.Qbar);
+    clsq = (vFw(eLift) + vFwAtCG(eLift))/ (in.Wingarea*in.Qbar);
     clsq *= clsq;
   }
 
   // Calculate lift Lift over Drag
-  if ( fabs(vFw(eDrag)) > 0.0) lod = fabs( vFw(eLift) / vFw(eDrag) );
+  if ( fabs(vFw(eDrag) + vFwAtCG(eDrag)) > 0.0)
+    lod = fabs( (vFw(eLift) + vFwAtCG(eLift))/ (vFw(eDrag) + vFwAtCG(eDrag)));
 
   // Calculate aerodynamic reference point shift, if any. The shift
   // takes place in the structual axis. That is, if the shift is positive,
@@ -237,6 +264,10 @@ bool FGAerodynamics::Run(bool Holding)
     }
   }
   vMoments = vMomentsMRC + vDXYZcg*vForces; // M = r X F
+  // Now add the "at CG" values to base forces - after the moments have been transferred
+  vForces += vForcesAtCG;
+  vFnative += vFnativeAtCG;
+  vFw += vFwAtCG;
 
   RunPostFunctions();
 
@@ -291,10 +322,16 @@ bool FGAerodynamics::Load(Element *element)
   axis_element = document->FindElement("axis");
   while (axis_element) {
     AeroFunctionArray ca;
+    AeroFunctionArray ca_atCG;
     axis = axis_element->GetAttributeValue("name");
     function_element = axis_element->FindElement("function");
     while (function_element) {
       string current_func_name = function_element->GetAttributeValue("name");
+      bool apply_at_cg = false;
+      if (function_element->HasAttribute("apply_at_cg")) {
+        if (function_element->GetAttributeValue("apply_at_cg") == "true") apply_at_cg = true;
+      }
+      if (!apply_at_cg) {
       try {
         ca.push_back( new FGFunction(PropertyManager, function_element) );
       } catch (string const str) {
@@ -302,9 +339,19 @@ bool FGAerodynamics::Load(Element *element)
              << current_func_name << ":" << str << " Aborting." << reset << endl;
         return false;
       }
+      } else {
+        try {
+          ca_atCG.push_back( new FGFunction(PropertyManager, function_element) );
+        } catch (string const str) {
+          cerr << endl << fgred << "Error loading aerodynamic function in " 
+               << current_func_name << ":" << str << " Aborting." << reset << endl;
+          return false;
+        }
+      }
       function_element = axis_element->FindNextElement("function");
     }
     AeroFunctions[AxisIdx[axis]] = ca;
+    AeroFunctionsAtCG[AxisIdx[axis]] = ca_atCG;
     axis_element = document->FindNextElement("axis");
   }
 
index 1ab848ba1c18d216b09d615d85f21b35515b924d..82e766323039a531f76f0c7443820eec47bd382d 100644 (file)
@@ -52,7 +52,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_AERODYNAMICS "$Id: FGAerodynamics.h,v 1.26 2012/07/26 04:33:46 jberndt Exp $"
+#define ID_AERODYNAMICS "$Id: FGAerodynamics.h,v 1.27 2013/09/11 12:42:14 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: 1.26 $
+    @version $Revision: 1.27 $
 */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -237,6 +237,10 @@ private:
   FGColumnVector3 vFnative;
   FGColumnVector3 vFw;
   FGColumnVector3 vForces;
+  AeroFunctionArray* AeroFunctionsAtCG;
+  FGColumnVector3 vFwAtCG;
+  FGColumnVector3 vFnativeAtCG;
+  FGColumnVector3 vForcesAtCG;
   FGColumnVector3 vMoments;
   FGColumnVector3 vMomentsMRC;
   FGColumnVector3 vDXYZcg;
index 557b7e366a362b36373df27860701ecd88a99dad..492458d91ea700e43d0a8292b62551f2dc52d501 100644 (file)
@@ -50,7 +50,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.61 2013/06/10 01:56:14 jberndt Exp $";
+static const char *IdSrc = "$Id: FGAuxiliary.cpp,v 1.62 2013/09/11 12:43:20 jberndt Exp $";
 static const char *IdHdr = ID_AUXILIARY;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -216,7 +216,7 @@ bool FGAuxiliary::Run(bool Holding)
   }
 
   A = pow(((pt-in.Pressure)/in.PressureSL + 1),0.28571);
-  if (MachU > 0.0) {
+  if (abs(MachU) > 0.0) {
     vcas = sqrt(7 * in.PressureSL / in.DensitySL * (A-1));
     veas = sqrt(2 * qbar / in.DensitySL);
     vtrue = 1116.43559 * MachU * sqrt(in.Temperature / 518.67);
index bc9d703c988aa50bd1ab6bc16fe2e0b2f35684a0..855925e1cffe46e9a943c57c394e1145060e0c99 100644 (file)
@@ -59,6 +59,8 @@ INCLUDES
 #include "models/flight_control/FGAccelerometer.h"
 #include "models/flight_control/FGMagnetometer.h"
 #include "models/flight_control/FGGyro.h"
+#include "models/flight_control/FGWaypoint.h"
+#include "models/flight_control/FGAngles.h"
 
 #include "FGFCSChannel.h"
 
@@ -66,7 +68,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGFCS.cpp,v 1.80 2013/01/26 17:06:49 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGFCS.cpp,v 1.81 2013/06/20 04:37:27 jberndt Exp $";
 static const char *IdHdr = ID_FCS;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -623,6 +625,12 @@ bool FGFCS::Load(Element* el, SystemType systype)
           newChannel->Add(new FGMagnetometer(this, component_element));
         } else if (component_element->GetName() == string("gyro")) {
           newChannel->Add(new FGGyro(this, component_element));
+        } else if ((component_element->GetName() == string("waypoint_heading")) ||
+                   (component_element->GetName() == string("waypoint_distance")))
+        {
+          newChannel->Add(new FGWaypoint(this, component_element));
+        } else if (component_element->GetName() == string("angle")) {
+          newChannel->Add(new FGAngles(this, component_element));
         } else {
           cerr << "Unknown FCS component: " << component_element->GetName() << endl;
         }
index 5297f93440978e5ab9acc0d856a43426b8d60436..316cd630a32418e11ac51890ec2bd9059f2fd96d 100644 (file)
@@ -51,7 +51,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FCS "$Id: FGFCS.h,v 1.41 2012/10/15 05:02:29 jberndt Exp $"
+#define ID_FCS "$Id: FGFCS.h,v 1.42 2013/06/20 04:37:27 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -169,7 +169,7 @@ CLASS DOCUMENTATION
     @property gear/tailhook-pos-norm
 
     @author Jon S. Berndt
-    @version $Revision: 1.41 $
+    @version $Revision: 1.42 $
     @see FGActuator
     @see FGDeadBand
     @see FGFCSFunction
@@ -180,6 +180,8 @@ CLASS DOCUMENTATION
     @see FGSensor
     @see FGSummer
     @see FGSwitch
+    @see FGWaypoint
+    @see FGAngles
     @see FGFCSComponent
     @see Element
 */
index b77ba859ee69b15d4303e4b91d9d32ce82c827fe..221c9b7d398fe19c9e1a17cb830e42a79b63fdb6 100644 (file)
@@ -49,7 +49,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGOutput.cpp,v 1.72 2013/01/26 17:06:50 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGOutput.cpp,v 1.73 2013/09/11 12:44:02 jberndt Exp $";
 static const char *IdHdr = ID_OUTPUT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -212,7 +212,9 @@ bool FGOutput::Load(int subSystems, std::string protocol, std::string type,
   unsigned int idx = OutputTypes.size();
   FGOutputType* Output = 0;
 
-  if (debug_lvl > 0) cout << endl << "  Output data set: " << idx << "  ";
+  if (debug_lvl > 0) cout << endl << "  Output data set: " << idx << endl;
+
+  type = to_upper(type);
 
   if (type == "CSV") {
     FGOutputTextFile* OutputTextFile = new FGOutputTextFile(FDMExec);
@@ -258,7 +260,9 @@ bool FGOutput::Load(Element* document)
   string type = document->GetAttributeValue("type");
   FGOutputType* Output = 0;
 
-  if (debug_lvl > 0) cout << endl << "  Output data set: " << idx << "  ";
+  if (debug_lvl > 0) cout << endl << "  Output data set: " << idx << "  " << endl;
+
+  type = to_upper(type);
 
   if (type == "CSV") {
     Output = new FGOutputTextFile(FDMExec);
index 86c9893bfdbca20c12577ec8af74e5c926bcca48..83c3e7f22b0269269b13f49bff046c3211a9b521 100644 (file)
@@ -77,7 +77,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.112 2013/06/10 01:57:52 jberndt Exp $";
+static const char *IdSrc = "$Id: FGPropagate.cpp,v 1.115 2013/09/14 11:26:02 bcoconni Exp $";
 static const char *IdHdr = ID_PROPAGATE;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -509,6 +509,13 @@ double FGPropagate::GetDistanceAGL(void) const
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+double FGPropagate::GetDistanceAGLKm(void) const
+{
+  return VState.vLocation.GetAltitudeAGL(FDMExec->GetSimTime())*0.0003048;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 void FGPropagate::SetDistanceAGL(double tt)
 {
   VState.vLocation.SetAltitudeAGL(tt, FDMExec->GetSimTime());
@@ -517,6 +524,14 @@ void FGPropagate::SetDistanceAGL(double tt)
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+void FGPropagate::SetDistanceAGLKm(double tt)
+{
+  VState.vLocation.SetAltitudeAGL(tt*3280.8399, FDMExec->GetSimTime());
+  UpdateVehicleState();
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
 void FGPropagate::SetVState(const VehicleState& vstate)
 {
   //ToDo: Shouldn't all of these be set from the vstate vector passed in?
@@ -577,9 +592,9 @@ void FGPropagate::DumpState(void)
        <<   "Position" << underoff << endl;
   cout << "    ECI:   " << VState.vInertialPosition.Dump(", ") << " (x,y,z, in ft)" << endl;
   cout << "    ECEF:  " << VState.vLocation << " (x,y,z, in ft)"  << endl;
-  cout << "    Local: " << VState.vLocation.GetLatitudeDeg()
+  cout << "    Local: " << VState.vLocation.GetGeodLatitudeDeg()
                         << ", " << VState.vLocation.GetLongitudeDeg()
-                        << ", " << GetAltitudeASL() << " (lat, lon, alt in deg and ft)" << endl;
+                        << ", " << GetAltitudeASL() << " (geodetic lat, lon, alt ASL in deg and ft)" << endl;
 
   cout << endl << "  " << underon
        <<   "Orientation" << underoff << endl;
@@ -613,6 +628,8 @@ void FGPropagate::WriteStateFile(int num)
   ofstream outfile(filename.c_str());
 
   if (outfile.is_open()) {
+    switch(num) {
+    case 1:
     outfile << "<?xml version=\"1.0\"?>" << endl;
     outfile << "<initialize name=\"reset00\">" << endl;
     outfile << "  <ubody unit=\"FT/SEC\"> " << VState.vUVW(eU) << " </ubody> " << endl;
@@ -626,6 +643,41 @@ void FGPropagate::WriteStateFile(int num)
     outfile << "  <altitude unit=\"FT\"> " << GetDistanceAGL() << " </altitude>" << endl;
     outfile << "</initialize>" << endl;
     outfile.close();
+    break;
+    case 2:
+      outfile << "<?xml version=\"1.0\"?>" << endl;
+      outfile << "<initialize name=\"IC File\" version=\"2.0\">" << endl;
+      outfile << "" << endl;
+      outfile << "  <position frame=\"ECEF\">" << endl;
+      outfile << "    <latitude unit=\"DEG\" type=\"geodetic\"> " << VState.vLocation.GetGeodLatitudeDeg() << " </latitude>" << endl;
+      outfile << "    <longitude unit=\"DEG\"> " << VState.vLocation.GetLongitudeDeg() << " </longitude>" << endl;
+      outfile << "    <altitudeMSL unit=\"FT\"> " << GetAltitudeASL() << " </altitudeMSL>" << endl;
+      outfile << "  </position>" << endl;
+      outfile << "" << endl;
+      outfile << "  <orientation unit=\"DEG\" frame=\"LOCAL\">" << endl;
+      outfile << "    <yaw> " << VState.qAttitudeLocal.GetEulerDeg(eYaw) << " </yaw>" << endl;
+      outfile << "    <pitch> " << VState.qAttitudeLocal.GetEulerDeg(ePitch) << " </pitch>" << endl;
+      outfile << "    <roll> " << VState.qAttitudeLocal.GetEulerDeg(eRoll) << " </roll>" << endl;
+      outfile << "  </orientation>" << endl;
+      outfile << "" << endl;
+      outfile << "  <velocity unit=\"FT/SEC\" frame=\"LOCAL\">" << endl;
+      outfile << "    <x> " << GetVel(eNorth) << " </x>" << endl;
+      outfile << "    <y> " << GetVel(eEast) << " </y>" << endl;
+      outfile << "    <z> " << GetVel(eDown) << " </z>" << endl;
+      outfile << "  </velocity>" << endl;
+      outfile << "" << endl;
+      outfile << "  <attitude_rate unit=\"DEG/SEC\" frame=\"BODY\">" << endl;
+      outfile << "    <roll> " << (VState.vPQR*radtodeg)(eRoll) << " </roll>" << endl;
+      outfile << "    <pitch> " << (VState.vPQR*radtodeg)(ePitch) << " </pitch>" << endl;
+      outfile << "    <yaw> " << (VState.vPQR*radtodeg)(eYaw) << " </yaw>" << endl;
+      outfile << "  </attitude_rate>" << endl;
+      outfile << "" << endl;
+      outfile << "</initialize>" << endl;
+      outfile.close();
+    break;
+    default:
+      throw("When writing a state file, the supplied value must be 1 or 2 for the version number of teh resulting IC file");
+    }
   } else {
     cerr << "Could not open and/or write the state to the initial conditions file: " << filename << endl;
   }
@@ -657,6 +709,7 @@ void FGPropagate::bind(void)
   PropertyManager->Tie("velocities/ri-rad_sec", this, eR, (PMF)&FGPropagate::GetPQRi);
 
   PropertyManager->Tie("velocities/eci-velocity-mag-fps", this, &FGPropagate::GetInertialVelocityMagnitude);
+  PropertyManager->Tie("velocities/ned-velocity-mag-fps", this, &FGPropagate::GetNEDVelocityMagnitude);
 
   PropertyManager->Tie("position/h-sl-ft", this, &FGPropagate::GetAltitudeASL, &FGPropagate::SetAltitudeASL, true);
   PropertyManager->Tie("position/h-sl-meters", this, &FGPropagate::GetAltitudeASLmeters, &FGPropagate::SetAltitudeASLmeters, true);
@@ -668,6 +721,8 @@ void FGPropagate::bind(void)
   PropertyManager->Tie("position/lat-geod-deg", this, &FGPropagate::GetGeodLatitudeDeg);
   PropertyManager->Tie("position/geod-alt-ft", this, &FGPropagate::GetGeodeticAltitude);
   PropertyManager->Tie("position/h-agl-ft", this,  &FGPropagate::GetDistanceAGL, &FGPropagate::SetDistanceAGL);
+  PropertyManager->Tie("position/geod-alt-km", this, &FGPropagate::GetGeodeticAltitudeKm);
+  PropertyManager->Tie("position/h-agl-km", this,  &FGPropagate::GetDistanceAGLKm, &FGPropagate::SetDistanceAGLKm);
   PropertyManager->Tie("position/radius-to-vehicle-ft", this, &FGPropagate::GetRadius);
   PropertyManager->Tie("position/terrain-elevation-asl-ft", this,
                           &FGPropagate::GetTerrainElevation,
index 4fd23ddc4ae630c2e76270a191d30c9bc0cc1afa..5d4acf868b20db033284b1abb45347e75d736838 100644 (file)
@@ -49,7 +49,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.75 2013/06/10 01:58:01 jberndt Exp $"
+#define ID_PROPAGATE "$Id: FGPropagate.h,v 1.78 2013/09/14 11:26:04 bcoconni Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -93,7 +93,7 @@ CLASS DOCUMENTATION
     @endcode
 
     @author Jon S. Berndt, Mathias Froehlich, Bertrand Coconnier
-    @version $Id: FGPropagate.h,v 1.75 2013/06/10 01:58:01 jberndt Exp $
+    @version $Id: FGPropagate.h,v 1.78 2013/09/14 11:26:04 bcoconni Exp $
   */
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -294,6 +294,10 @@ public:
   */
   double GetInertialVelocityMagnitude(void) const { return VState.vInertialVelocity.Magnitude(); }
 
+  /** Retrieves the total local NED velocity in ft/sec.
+  */
+  double GetNEDVelocityMagnitude(void) const { return VState.vUVW.Magnitude(); }
+
   /** Retrieves the inertial velocity vector in ft/sec.
   */
   const FGColumnVector3& GetInertialVelocity(void) const { return VState.vInertialVelocity; }
@@ -419,6 +423,7 @@ public:
 
   double GetTerrainElevation(void) const { return GetLocalTerrainRadius() - VState.vLocation.GetSeaLevelRadius(); }
   double GetDistanceAGL(void)  const;
+  double GetDistanceAGLKm(void)  const;
   double GetRadius(void) const {
       if (VState.vLocation.GetRadius() == 0) return 1.0;
       else return VState.vLocation.GetRadius();
@@ -430,6 +435,7 @@ public:
   double GetGeodLatitudeDeg(void) const { return VState.vLocation.GetGeodLatitudeDeg(); }
 
   double GetGeodeticAltitude(void) const { return VState.vLocation.GetGeodAltitude(); }
+  double GetGeodeticAltitudeKm(void) const { return VState.vLocation.GetGeodAltitude()*0.0003048; }
 
   double GetLongitudeDeg(void) const { return VState.vLocation.GetLongitudeDeg(); }
   double GetLatitudeDeg(void) const { return VState.vLocation.GetLatitudeDeg(); }
@@ -551,6 +557,7 @@ public:
   void SetSeaLevelRadius(double tt);
   void SetTerrainElevation(double tt);
   void SetDistanceAGL(double tt);
+  void SetDistanceAGLKm(double tt);
 
   void SetInitialState(const FGInitialCondition *);
   void SetLocation(const FGLocation& l);
index 731e068121ed850d68fce707440c9411459e8ce7..372795790bc819056b0a73dc1c75ad5cdf4bd85a 100644 (file)
@@ -66,7 +66,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.69 2012/12/12 06:19:57 jberndt Exp $";
+static const char *IdSrc = "$Id: FGPropulsion.cpp,v 1.70 2013/09/11 23:24:49 jentron Exp $";
 static const char *IdHdr = ID_PROPULSION;
 
 extern short debug_lvl;
@@ -693,18 +693,32 @@ void FGPropulsion::SetStarter(int setting)
 
 void FGPropulsion::SetCutoff(int setting)
 {
+  bool bsetting = setting == 0 ? false : true;
+
   if (ActiveEngine < 0) {
     for (unsigned i=0; i<Engines.size(); i++) {
-      if (setting == 0)
-        ((FGTurbine*)Engines[i])->SetCutoff(false);
-      else
-        ((FGTurbine*)Engines[i])->SetCutoff(true);
+      switch (Engines[i]->GetType()) { 
+        case FGEngine::etTurbine:
+          ((FGTurbine*)Engines[i])->SetCutoff(bsetting);
+          break;
+        case FGEngine::etTurboprop:
+          ((FGTurboProp*)Engines[i])->SetCutoff(bsetting);
+          break;
+        default:
+          break;
+      }
     }
   } else {
-    if (setting == 0)
-      ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(false);
-    else
-      ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(true);
+    switch (Engines[ActiveEngine]->GetType()) { 
+      case FGEngine::etTurbine:
+        ((FGTurbine*)Engines[ActiveEngine])->SetCutoff(bsetting);
+        break;
+      case FGEngine::etTurboprop:
+        ((FGTurboProp*)Engines[ActiveEngine])->SetCutoff(bsetting);
+        break;
+      default:
+        break;
+    }
   }
 }
 
@@ -799,7 +813,7 @@ void FGPropulsion::bind(void)
 
   IsBound = true;
   PropertyManager->Tie("propulsion/set-running", this, (iPMF)0, &FGPropulsion::InitRunning, false);
-  if (HaveTurbineEngine) {
+  if (HaveTurbineEngine || HaveTurboPropEngine) {
     PropertyManager->Tie("propulsion/starter_cmd", this, (iPMF)0, &FGPropulsion::SetStarter,  false);
     PropertyManager->Tie("propulsion/cutoff_cmd", this,  (iPMF)0, &FGPropulsion::SetCutoff,   false);
   }
diff --git a/src/FDM/JSBSim/models/flight_control/FGAngles.cpp b/src/FDM/JSBSim/models/flight_control/FGAngles.cpp
new file mode 100755 (executable)
index 0000000..d75daf9
--- /dev/null
@@ -0,0 +1,205 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGAngles.cpp
+ Author:       Jon S. Berndt
+ Date started: 6/2013
+
+ ------------- Copyright (C) 2013 Jon S. Berndt (jon@jsbsim.org) -------------
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA  02111-1307, USA.
+
+ Further information about the GNU Lesser General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+
+HISTORY
+--------------------------------------------------------------------------------
+Created: 6/2013 Jon S. Berndt
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+  The Included Angle to Heading algorithm is used to find the smallest included angle
+  (the angle less than or equal to 180 degrees) to a specified heading from
+  the current heading. The sense of the rotation to get to that angle is also
+  calculated (positive 1 for a clockwise rotation, negative 1 for counter-
+  clockwise).
+  
+  The angle to the heading is calculated as follows:
+
+  Given an angle phi:
+
+  V = cos(phi)i + sin(phi)j     (this is a unit vector)
+
+  The dot product for two, 2D vectors is written:
+
+  V1*V2 = |V1||V2|cos(phi)
+
+  Since the magnitude of a unit vector is 1, we can write the equation as follows:
+
+  V1*V2 = cos(phi)
+
+  or,
+
+  phi  = acos(V1*V2)
+
+  or,
+
+  phi  = acos[ cos(phi1)cos(phi2) + sin(phi1)sin(phi2) ]
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGAngles.h"
+#include "input_output/FGXMLElement.h"
+#include "input_output/FGPropertyManager.h"
+
+using namespace std;
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id: FGAngles.cpp,v 1.1 2013/06/20 04:37:28 jberndt Exp $";
+static const char *IdHdr = ID_ANGLES;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGAngles::FGAngles(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
+{
+  source_angle = 0.0;
+  target_angle = 0.0;
+  source_angle_unit = 1.0;
+  target_angle_unit = 1.0;
+  output_unit = 1.0;
+
+  if (element->FindElement("target_angle") ) {
+    target_angle_pNode = PropertyManager->GetNode(element->FindElementValue("target_angle"));
+    if (element->FindElement("target_angle")->HasAttribute("unit")) {
+      if (element->FindElement("target_angle")->GetAttributeValue("unit") == "DEG") {
+        target_angle_unit = 0.017453293;
+      }
+    }
+  } else {
+    throw("Target angle is required for component: "+Name);
+  }
+
+  if (element->FindElement("source_angle") ) {
+    source_angle_pNode = PropertyManager->GetNode(element->FindElementValue("source_angle"));
+    if (element->FindElement("source_angle")->HasAttribute("unit")) {
+      if (element->FindElement("source_angle")->GetAttributeValue("unit") == "DEG") {
+        source_angle_unit = 0.017453293;
+      }
+    }
+  } else {
+    throw("Source latitude is required for Angles component: "+Name);
+  }
+
+  unit = element->GetAttributeValue("unit");
+  if (!unit.empty()) {
+    if      (unit == "DEG") output_unit = 180.0/M_PI;
+    else if (unit == "RAD") output_unit = 1.0;
+    else throw("Unknown unit "+unit+" in angle component, "+Name);
+  } else {
+    output_unit = 1.0; // Default is radians (1.0) if unspecified
+  }
+
+  FGFCSComponent::bind();
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGAngles::~FGAngles()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+bool FGAngles::Run(void )
+{
+  source_angle = source_angle_pNode->getDoubleValue() * source_angle_unit;
+  target_angle = target_angle_pNode->getDoubleValue() * target_angle_unit;
+
+  double x1 = cos(source_angle);
+  double y1 = sin(source_angle);
+  double x2 = cos(target_angle);
+  double y2 = sin(target_angle);
+
+  double angle_to_heading_rad = acos(x1*x2 + y1*y2);
+  double x1y2 = x1*y2;
+  double x2y1 = x2*y1;
+
+  if (x1y2 >= x2y1) Output =  angle_to_heading_rad * output_unit;
+  else              Output = -angle_to_heading_rad * output_unit;
+
+  Clip();
+  if (IsOutput) SetOutput();
+
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGAngles::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGAngles" << endl;
+    if (from == 1) cout << "Destroyed:    FGAngles" << endl;
+  }
+  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
+  }
+  if (debug_lvl & 8 ) { // Runtime state variables
+  }
+  if (debug_lvl & 16) { // Sanity checking
+  }
+  if (debug_lvl & 64) {
+    if (from == 0) { // Constructor
+      cout << IdSrc << endl;
+      cout << IdHdr << endl;
+    }
+  }
+}
+}
diff --git a/src/FDM/JSBSim/models/flight_control/FGAngles.h b/src/FDM/JSBSim/models/flight_control/FGAngles.h
new file mode 100755 (executable)
index 0000000..4a75bfe
--- /dev/null
@@ -0,0 +1,108 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGAngles.h
+ Author:       Jon Berndt
+ Date started: 6/2013
+
+ ------------- Copyright (C) 2013 Jon S. Berndt (jon@jsbsim.org) -------------
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA  02111-1307, USA.
+
+ Further information about the GNU Lesser General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+HISTORY
+--------------------------------------------------------------------------------
+Created: 6/2013 Jon S. Berndt
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGANGLES_H
+#define FGANGLES_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <string>
+#include "FGFCSComponent.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_ANGLES "$Id: FGAngles.h,v 1.1 2013/06/20 04:37:28 jberndt Exp $"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+class FGFCS;
+class Element;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Provides a way to determine the smallest included angle.
+
+    @code
+    <angle name="component_name" unit="DEG|RAD">
+      <source_angle unit="DEG|RAD">  property_name </source_angle>
+      <target_angle unit="DEG|RAD">  property_name </target_angle>
+      [<clipto>
+        <min> {[-]property name | value} </min>
+        <max> {[-]property name | value} </max>
+      </clipto>]
+      [<output> {property} </output>]
+    </angle>
+    @endcode
+
+    @author Jon S. Berndt
+    @version $Id: FGAngles.h,v 1.1 2013/06/20 04:37:28 jberndt Exp $
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGAngles  : public FGFCSComponent
+{
+public:
+  FGAngles(FGFCS* fcs, Element* element);
+  ~FGAngles();
+
+  bool Run(void);
+
+private:
+  FGPropertyNode_ptr target_angle_pNode;
+  FGPropertyNode_ptr source_angle_pNode;
+  double target_angle;
+  double source_angle;
+  double target_angle_unit;
+  double source_angle_unit;
+  double output_unit;
+  string unit;
+
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#endif
index 0de61898443dab6868e7c9880616b51dac08658c..198ad689fbdfce89e31f3d7999563edeb7013081 100644 (file)
@@ -48,7 +48,7 @@ using namespace std;
 
 namespace JSBSim {
 
-static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.35 2013/01/26 17:06:50 bcoconni Exp $";
+static const char *IdSrc = "$Id: FGFCSComponent.cpp,v 1.36 2013/06/20 04:37:28 jberndt Exp $";
 static const char *IdHdr = ID_FCSCOMPONENT;
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -106,6 +106,12 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
     Type = "GYRO";
   } else if (element->GetName() == string("actuator")) {
     Type = "ACTUATOR";
+  } else if (element->GetName() == string("waypoint_heading")) {
+    Type = "WAYPOINT_HEADING";
+  } else if (element->GetName() == string("waypoint_distance")) {
+    Type = "WAYPOINT_DISTANCE";
+  } else if (element->GetName() == string("angle")) {
+    Type = "ANGLE";
   } else { // illegal component in this channel
     Type = "UNKNOWN";
   }
index d050a2833a31ca144e2c00b91bfb542c72b3e61f..1c0c03ef93f609ff24b97f0b2800fbb0f377202f 100644 (file)
@@ -4,7 +4,7 @@
  Author:       Jon S. Berndt
  Date started: 05/01/2000
 
- ------------- Copyright (C)  -------------
+ ------------- Copyright (C) 2000 Jon S. Berndt (jon@jsbsim.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
@@ -46,7 +46,7 @@ INCLUDES
 DEFINITIONS
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
 
-#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.21 2013/01/26 17:06:50 bcoconni Exp $"
+#define ID_FCSCOMPONENT "$Id: FGFCSComponent.h,v 1.22 2013/06/20 04:37:28 jberndt Exp $"
 
 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 FORWARD DECLARATIONS
@@ -78,9 +78,11 @@ CLASS DOCUMENTATION
     - FGAccelerometer
     - FGGyro
     - FGActuator
+    - FGWaypoint
+    - FGAngle
 
     @author Jon S. Berndt
-    @version $Id: FGFCSComponent.h,v 1.21 2013/01/26 17:06:50 bcoconni Exp $
+    @version $Id: FGFCSComponent.h,v 1.22 2013/06/20 04:37:28 jberndt Exp $
     @see Documentation for the FGFCS class, and for the configuration file class
 */
 
diff --git a/src/FDM/JSBSim/models/flight_control/FGWaypoint.cpp b/src/FDM/JSBSim/models/flight_control/FGWaypoint.cpp
new file mode 100755 (executable)
index 0000000..f95554a
--- /dev/null
@@ -0,0 +1,261 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Module:       FGWaypoint.cpp
+ Author:       Jon S. Berndt
+ Date started: 6/2013
+
+ ------------- Copyright (C) 2013 Jon S. Berndt (jon@jsbsim.org) -------------
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA  02111-1307, USA.
+
+ Further information about the GNU Lesser General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+FUNCTIONAL DESCRIPTION
+--------------------------------------------------------------------------------
+
+HISTORY
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+COMMENTS, REFERENCES,  and NOTES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include "FGWaypoint.h"
+#include "input_output/FGXMLElement.h"
+#include "input_output/FGPropertyManager.h"
+
+using namespace std;
+
+namespace JSBSim {
+
+static const char *IdSrc = "$Id: FGWaypoint.cpp,v 1.2 2013/08/30 04:44:59 jberndt Exp $";
+static const char *IdHdr = ID_WAYPOINT;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS IMPLEMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGWaypoint::FGWaypoint(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
+{
+  if      (Type == "WAYPOINT_HEADING")  WaypointType = eHeading;
+  else if (Type == "WAYPOINT_DISTANCE") WaypointType = eDistance;
+
+  target_latitude_unit = 1.0;
+  target_longitude_unit = 1.0;
+  source_latitude_unit = 1.0;
+  source_longitude_unit = 1.0;
+
+  if (element->FindElement("target_latitude") ) {
+    target_latitude_pNode = PropertyManager->GetNode(element->FindElementValue("target_latitude"));
+    if (element->FindElement("target_latitude")->HasAttribute("unit")) {
+      if (element->FindElement("target_latitude")->GetAttributeValue("unit") == "DEG") {
+        target_latitude_unit = 0.017453293;
+      }
+    }
+  } else {
+    throw("Target latitude is required for waypoint component: "+Name);
+  }
+
+  if (element->FindElement("target_longitude") ) {
+    target_longitude_pNode = PropertyManager->GetNode(element->FindElementValue("target_longitude"));
+    if (element->FindElement("target_longitude")->HasAttribute("unit")) {
+      if (element->FindElement("target_longitude")->GetAttributeValue("unit") == "DEG") {
+        target_longitude_unit = 0.017453293;
+      }
+    }
+  } else {
+    throw("Target longitude is required for waypoint component: "+Name);
+  }
+
+  if (element->FindElement("source_latitude") ) {
+    source_latitude_pNode = PropertyManager->GetNode(element->FindElementValue("source_latitude"));
+    if (element->FindElement("source_latitude")->HasAttribute("unit")) {
+      if (element->FindElement("source_latitude")->GetAttributeValue("unit") == "DEG") {
+        source_latitude_unit = 0.017453293;
+      }
+    }
+  } else {
+    throw("Source latitude is required for waypoint component: "+Name);
+  }
+
+  if (element->FindElement("source_longitude") ) {
+    source_longitude_pNode = PropertyManager->GetNode(element->FindElementValue("source_longitude"));
+    if (element->FindElement("source_longitude")->HasAttribute("unit")) {
+      if (element->FindElement("source_longitude")->GetAttributeValue("unit") == "DEG") {
+        source_longitude_unit = 0.017453293;
+      }
+    }
+  } else {
+    throw("Source longitude is required for waypoint component: "+Name);
+  }
+
+  if (element->FindElement("radius")) {
+    radius = element->FindElementValueAsNumberConvertTo("radius", "FT");
+  } else {
+    radius = 21144000; // Radius of Earth in feet.
+  }
+
+  unit = element->GetAttributeValue("unit");
+  if (WaypointType == eHeading) {
+    if (!unit.empty()) {
+    if      (unit == "DEG") eUnit = eDeg;
+    else if (unit == "RAD") eUnit = eRad;
+    else throw("Unknown unit "+unit+" in HEADING waypoint component, "+Name);
+  } else {
+      eUnit = eRad; // Default is radians if unspecified
+    }
+  } else {
+    if (!unit.empty()) {
+    if      (unit == "FT") eUnit = eFeet;
+    else if (unit == "M")  eUnit = eMeters;
+    else throw("Unknown unit "+unit+" in DISTANCE waypoint component, "+Name);
+    } else {
+      eUnit = eFeet; // Default is feet if unspecified
+    }
+  }
+
+  FGFCSComponent::bind();
+  Debug(0);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+FGWaypoint::~FGWaypoint()
+{
+  Debug(1);
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//  The calculations, below, implement the Haversine formulas to calculate
+//  heading and distance to a set of lat/long coordinates from the current
+//  position. The latitude and longitude are expected to be in radian units
+//  and are measured from the 0 meridian and the equator, with positive 
+//  longitude being east from there, and positive latitude being north.
+//
+//  The basic equations are (lat1, long1 are source positions; lat2
+//  long2 are target positions):
+//
+//  R = earth’s radius
+//  Δlat = lat2 − lat1
+//  Δlong = long2 − long1
+//
+//  For the heading angle calculation:
+//
+//  θ = atan2(sin(Δlong)∙cos(lat2), cos(lat1)∙sin(lat2) − sin(lat1) ∙cos(lat2)∙cos(Δlong) )
+//
+//  For the waypoint distance calculation:
+//
+//  a = sin²(Δlat/2) + cos(lat1)∙cos(lat2)∙sin²(Δlong/2)
+//  c = 2∙atan2(√a, √(1−a))
+//  d = R∙c
+
+bool FGWaypoint::Run(void )
+{
+  target_latitude = target_latitude_pNode->getDoubleValue() * target_latitude_unit;
+  target_longitude = target_longitude_pNode->getDoubleValue() * target_longitude_unit;
+  source_latitude = source_latitude_pNode->getDoubleValue() * source_latitude_unit;
+  source_longitude = source_longitude_pNode->getDoubleValue() * source_longitude_unit;
+
+  double delta_lat_rad = target_latitude  - source_latitude;
+  double delta_lon_rad = target_longitude - source_longitude;
+
+  if (WaypointType == eHeading) {     // Calculate Heading
+
+    double Y = sin(delta_lon_rad) * cos(target_latitude);
+    double X = (cos(source_latitude) * sin(target_latitude))
+               - (sin(source_latitude) * cos(target_latitude) * cos(delta_lon_rad));
+
+    double heading_to_waypoint_rad = atan2(Y, X);
+    if (heading_to_waypoint_rad < 0) heading_to_waypoint_rad += 2.0*M_PI;
+
+    double heading_to_waypoint = 0;
+    if (eUnit == eDeg) heading_to_waypoint = heading_to_waypoint_rad * radtodeg;
+    else               heading_to_waypoint = heading_to_waypoint_rad;
+
+    Output = heading_to_waypoint;
+
+  } else {                            // Calculate Distance
+
+    double distance_a = pow(sin(delta_lat_rad/2.0), 2.0)
+                        + (cos(source_latitude) * cos(target_latitude)
+                          * (pow(sin(delta_lon_rad/2.0), 2.0)));
+
+    double wp_distance = 2.0 * radius * atan2(pow(distance_a, 0.5), pow((1.0 - distance_a), 0.5));
+
+    if (eUnit == eMeters) {
+      Output = FeetToMeters(wp_distance);
+    } else {
+      Output = wp_distance;
+    }
+  }
+
+  Clip();
+  if (IsOutput) SetOutput();
+
+  return true;
+}
+
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+//    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 FGWaypoint::Debug(int from)
+{
+  if (debug_lvl <= 0) return;
+
+  if (debug_lvl & 1) { // Standard console startup message output
+    if (from == 0) { // Constructor
+    }
+  }
+  if (debug_lvl & 2 ) { // Instantiation/Destruction notification
+    if (from == 0) cout << "Instantiated: FGWaypoint" << endl;
+    if (from == 1) cout << "Destroyed:    FGWaypoint" << endl;
+  }
+  if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
+  }
+  if (debug_lvl & 8 ) { // Runtime state variables
+  }
+  if (debug_lvl & 16) { // Sanity checking
+  }
+  if (debug_lvl & 64) {
+    if (from == 0) { // Constructor
+      cout << IdSrc << endl;
+      cout << IdHdr << endl;
+    }
+  }
+}
+}
diff --git a/src/FDM/JSBSim/models/flight_control/FGWaypoint.h b/src/FDM/JSBSim/models/flight_control/FGWaypoint.h
new file mode 100755 (executable)
index 0000000..272d1a3
--- /dev/null
@@ -0,0 +1,133 @@
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ Header:       FGWaypoint.h
+ Author:       Jon Berndt
+ Date started: 6/2013
+
+ ------------- Copyright (C) 2013 Jon S. Berndt (jon@jsbsim.org) -------------
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the Free Software
+ Foundation; either version 2 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ details.
+
+ You should have received a copy of the GNU Lesser General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ Place - Suite 330, Boston, MA  02111-1307, USA.
+
+ Further information about the GNU Lesser General Public License can also be found on
+ the world wide web at http://www.gnu.org.
+
+HISTORY
+--------------------------------------------------------------------------------
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+SENTRY
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#ifndef FGWAYPOINT_H
+#define FGWAYPOINT_H
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+INCLUDES
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#include <string>
+#include "FGFCSComponent.h"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+DEFINITIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+#define ID_WAYPOINT "$Id: FGWaypoint.h,v 1.1 2013/06/20 04:37:28 jberndt Exp $"
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+FORWARD DECLARATIONS
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+namespace JSBSim {
+
+class FGFCS;
+class Element;
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DOCUMENTATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+/** Models a Waypoint object. 
+    The waypoint_heading component returns the heading to a specified waypoint
+    lat/long from another specified point.
+    The waypoint_distance component returns the distance between
+
+    @code
+    <waypoint_heading name="component_name" unit="DEG|RAD">
+      <target_latitude unit="DEG|RAD">  property_name </target_latitude>
+      <target_longitude unit="DEG|RAD"> property_name </target_longitude>
+      <source_latitude unit="DEG|RAD">  property_name </source_latitude>
+      <source_longitude unit="DEG|RAD"> property_name </source_longitude>
+      [<clipto>
+        <min> {[-]property name | value} </min>
+        <max> {[-]property name | value} </max>
+      </clipto>]
+      [<output> {property} </output>]
+    </waypoint_heading>
+
+    <waypoint_distance name="component_name" unit="FT|M">
+      <target_latitude unit="DEG|RAD">  property_name </target_latitude>
+      <target_longitude unit="DEG|RAD"> property_name </target_longitude>
+      <source_latitude unit="DEG|RAD">  property_name </source_latitude>
+      <source_longitude unit="DEG|RAD"> property_name </source_longitude>
+      [<radius> {value} </radius>]
+      [<clipto>
+        <min> {[-]property name | value} </min>
+        <max> {[-]property name | value} </max>
+      </clipto>]
+      [<output> {property} </output>]
+    </waypoint_distance>
+    @endcode
+
+    @author Jon S. Berndt
+    @version $Id: FGWaypoint.h,v 1.1 2013/06/20 04:37:28 jberndt Exp $
+*/
+
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+CLASS DECLARATION
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+class FGWaypoint  : public FGFCSComponent
+{
+public:
+  FGWaypoint(FGFCS* fcs, Element* element);
+  ~FGWaypoint();
+
+  bool Run(void);
+
+private:
+  FGPropertyNode_ptr target_latitude_pNode;
+  FGPropertyNode_ptr target_longitude_pNode;
+  FGPropertyNode_ptr source_latitude_pNode;
+  FGPropertyNode_ptr source_longitude_pNode;
+  double target_latitude;
+  double target_longitude;
+  double source_latitude;
+  double source_longitude;
+  double target_latitude_unit;
+  double target_longitude_unit;
+  double source_latitude_unit;
+  double source_longitude_unit;
+  double radius;
+  string unit;
+  enum {eNone=0, eDeg, eRad, eFeet, eMeters} eUnit;
+  enum {eNoType=0, eHeading, eDistance} WaypointType;
+
+  void Debug(int from);
+};
+}
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#endif