]> git.mxchange.org Git - flightgear.git/commitdiff
Roy Vegard Ovesen:
authorehofman <ehofman>
Sat, 16 Oct 2004 12:37:39 +0000 (12:37 +0000)
committerehofman <ehofman>
Sat, 16 Oct 2004 12:37:39 +0000 (12:37 +0000)
Instrumentation and systems are now configureable from xml files. The two
generic configurations generic-systems.xml and generic-instrumentation.xml
configures the systems and instrumentation as it was hardcoded. You can
override the generic configurations in a similar way as you override the
autopilot configuration.

34 files changed:
src/Instrumentation/adf.cxx
src/Instrumentation/adf.hxx
src/Instrumentation/airspeed_indicator.cxx
src/Instrumentation/airspeed_indicator.hxx
src/Instrumentation/altimeter.cxx
src/Instrumentation/altimeter.hxx
src/Instrumentation/attitude_indicator.cxx
src/Instrumentation/attitude_indicator.hxx
src/Instrumentation/clock.cxx
src/Instrumentation/clock.hxx
src/Instrumentation/dme.cxx
src/Instrumentation/dme.hxx
src/Instrumentation/gps.cxx
src/Instrumentation/gps.hxx
src/Instrumentation/heading_indicator.cxx
src/Instrumentation/heading_indicator.hxx
src/Instrumentation/instrument_mgr.cxx
src/Instrumentation/instrument_mgr.hxx
src/Instrumentation/mag_compass.cxx
src/Instrumentation/mag_compass.hxx
src/Instrumentation/slip_skid_ball.cxx
src/Instrumentation/slip_skid_ball.hxx
src/Instrumentation/turn_indicator.cxx
src/Instrumentation/turn_indicator.hxx
src/Instrumentation/vertical_speed_indicator.cxx
src/Instrumentation/vertical_speed_indicator.hxx
src/Systems/pitot.cxx
src/Systems/pitot.hxx
src/Systems/static.cxx
src/Systems/static.hxx
src/Systems/system_mgr.cxx
src/Systems/system_mgr.hxx
src/Systems/vacuum.cxx
src/Systems/vacuum.hxx

index 83757887dbb10e07941bf73f8f2b2089553467fa..e6d02a1400dd0ce2fafa028ac52ab19c2d70e3e2 100644 (file)
 
 #include "adf.hxx"
 
+#include <iostream>
+#include <string>
+#include <sstream>
+
 
 // Use a bigger number to be more responsive, or a smaller number
 // to be more sluggish.
@@ -48,6 +52,38 @@ adjust_range (double transmitter_elevation_ft, double aircraft_altitude_ft,
 }
 
 
+ADF::ADF (SGPropertyNode *node )
+    :
+    _time_before_search_sec(0),
+    _last_frequency_khz(-1),
+    _transmitter_valid(false),
+    _transmitter_elevation_ft(0),
+    _transmitter_range_nm(0),
+    _ident_count(0),
+    _last_ident_time(0),
+    _last_volume(-1),
+    name("adf"),
+    num(0)
+{
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = child->getIntValue();
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in adf config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
+
+
 ADF::ADF ()
     : _time_before_search_sec(0),
       _last_frequency_khz(-1),
@@ -56,7 +92,9 @@ ADF::ADF ()
       _transmitter_range_nm(0),
       _ident_count(0),
       _last_ident_time(0),
-      _last_volume(-1)
+      _last_volume(-1),
+      name("adf"),
+      num(0)
 {
 }
 
@@ -67,24 +105,34 @@ ADF::~ADF ()
 void
 ADF::init ()
 {
+    string branch;
+    branch = "/instrumentation/" + name;
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
     _longitude_node = fgGetNode("/position/longitude-deg", true);
     _latitude_node = fgGetNode("/position/latitude-deg", true);
     _altitude_node = fgGetNode("/position/altitude-ft", true);
     _heading_node = fgGetNode("/orientation/heading-deg", true);
-    _serviceable_node = fgGetNode("/instrumentation/adf/serviceable", true);
-    _error_node = fgGetNode("/instrumentation/adf/error-deg", true);
+    _serviceable_node = node->getChild("serviceable", 0, true);
+    _error_node = node->getChild("error-deg", 0, true);
     _electrical_node = fgGetNode("/systems/electrical/outputs/adf", true);
-    _frequency_node =
-        fgGetNode("/instrumentation/adf/frequencies/selected-khz", true);
-    _mode_node = fgGetNode("/instrumentation/adf/mode", true);
-
-    _in_range_node = fgGetNode("/instrumentation/adf/in-range", true);
-    _bearing_node =
-        fgGetNode("/instrumentation/adf/indicated-bearing-deg", true);
-    _ident_node = fgGetNode("/instrumentation/adf/ident", true);
-    _volume_node = fgGetNode("/instrumentation/adf/volume-norm", true);
-    _ident_audible_node = fgGetNode("/instrumentation/adf/ident-audible", true);
+    branch = branch + "/frequencies";
+    SGPropertyNode *fnode = node->getChild("frequencies", 0, true);
+    _frequency_node = fnode->getChild("selected-khz", 0, true);
+    _mode_node = node->getChild("mode", 0, true);
+    _volume_node = node->getChild("volume-norm", 0, true);
+    _in_range_node = node->getChild("in-range", 0, true);
+    _bearing_node = node->getChild("indicated-bearing-deg", 0, true);
+    _ident_node = node->getChild("ident", 0, true);
+    _ident_audible_node = node->getChild("ident-audible", 0, true);
+
     morse.init();
+
+    std::ostringstream temp;
+    temp << name << num;
+    adf_ident = temp.str();
+
+    _serviceable_node->setBoolValue(true);
 }
 
 void
@@ -164,7 +212,7 @@ ADF::update (double delta_time_sec)
             _last_volume = volume;
 
             SGSoundSample *sound;
-            sound = globals->get_soundmgr()->find( "adf-ident" );
+            sound = globals->get_soundmgr()->find( adf_ident );
             if ( sound != NULL )
                 sound->set_volume( volume );
             else
@@ -178,8 +226,8 @@ ADF::update (double delta_time_sec)
         }
 
         if ( _ident_count < 4 ) {
-            if ( !globals->get_soundmgr()->is_playing("adf-ident") ) {
-                globals->get_soundmgr()->play_once( "adf-ident" );
+            if ( !globals->get_soundmgr()->is_playing(adf_ident) ) {
+                globals->get_soundmgr()->play_once( adf_ident );
                 ++_ident_count;
             }
         }
@@ -187,7 +235,7 @@ ADF::update (double delta_time_sec)
         _in_range_node->setBoolValue(false);
         set_bearing(delta_time_sec, 90);
         _ident_node->setStringValue("");
-        globals->get_soundmgr()->stop( "adf-ident" );
+        globals->get_soundmgr()->stop( adf_ident );
     }
 }
 
@@ -220,16 +268,16 @@ ADF::search (double frequency_khz, double longitude_rad,
         _last_ident = ident;
         _ident_node->setStringValue(ident.c_str());
 
-        if ( globals->get_soundmgr()->exists( "adf-ident" ) ) {
-            // stop is required! -- remove alone wouldn't stop immediately
-            globals->get_soundmgr()->stop( "adf-ident" );
-            globals->get_soundmgr()->remove( "adf-ident" );
+        if ( globals->get_soundmgr()->exists( adf_ident ) ) {
+           // stop is required! -- remove alone wouldn't stop immediately
+            globals->get_soundmgr()->stop( adf_ident );
+            globals->get_soundmgr()->remove( adf_ident );
         }
 
         SGSoundSample *sound;
         sound = morse.make_ident( ident, LO_FREQUENCY );
         sound->set_volume(_last_volume = 0);
-        globals->get_soundmgr()->add( sound, "adf-ident" );
+        globals->get_soundmgr()->add( sound, adf_ident );
 
         int offset = (int)(sg_random() * 30.0);
         _ident_count = offset / 4;
index f897cb5e401495aeb04ae8543c2ed866fcc30e8e..6f584803c6bf26bb38b773b45e5bc31e87237946 100644 (file)
@@ -50,6 +50,7 @@ class ADF : public SGSubsystem
 
 public:
 
+    ADF ( SGPropertyNode *node );
     ADF ();
     virtual ~ADF ();
 
@@ -94,6 +95,10 @@ private:
     int _ident_count;
     time_t _last_ident_time;
     double _last_volume;
+
+    string name;
+    int num;
+    string adf_ident;
 };
 
 
index 2b80fbd96c3b9e1c3eef2112e277557beb371f54..cbdd75902d19e59487604cc3ff56abc70610ce58 100644 (file)
 // A higher number means more responsive.
 #define RESPONSIVENESS 50.0
 
+AirspeedIndicator::AirspeedIndicator ( SGPropertyNode *node )
+    :
+    name("airspeed-indicator"),
+    num(0),
+    pitot_port("/systems/pitot"),
+    static_port("/systems/static")
+{
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = child->getIntValue();
+        } else if ( cname == "pitot-port" ) {
+            pitot_port = cval;
+        } else if ( cname == "static-port" ) {
+            static_port = cval;
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in aispeed-indicator config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
 
-AirspeedIndicator::AirspeedIndicator ()
+
+AirspeedIndicator::AirspeedIndicator ( int i )
+    :
+    name("airspeed-indicator"),
+    num(0),
+    pitot_port("/systems/pitot"),
+    static_port("/systems/static")
 {
+    num = i;
 }
 
 AirspeedIndicator::~AirspeedIndicator ()
@@ -27,17 +62,19 @@ AirspeedIndicator::~AirspeedIndicator ()
 void
 AirspeedIndicator::init ()
 {
-    _serviceable_node =
-        fgGetNode("/instrumentation/airspeed-indicator/serviceable",
-                  true);
-    _total_pressure_node =
-        fgGetNode("/systems/pitot/total-pressure-inhg", true);
-    _static_pressure_node =
-        fgGetNode("/systems/static/pressure-inhg", true);
+    string branch;
+    branch = "/instrumentation/" + name;
+    pitot_port += "/total-pressure-inhg";
+    static_port += "/pressure-inhg";
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
+    _serviceable_node = node->getChild("serviceable", 0, true);
+    _total_pressure_node = fgGetNode(pitot_port.c_str(), true);
+    _static_pressure_node = fgGetNode(static_port.c_str(), true);
     _density_node = fgGetNode("/environment/density-slugft3", true);
-    _speed_node =
-        fgGetNode("/instrumentation/airspeed-indicator/indicated-speed-kt",
-                  true);
+    _speed_node = node->getChild("indicated-speed-kt", 0, true);
+
+    _serviceable_node->setBoolValue(true);
 }
 
 #ifndef FPSTOKTS
index 0572a0eb120b5a97c2fec2a6c5cdcb72ccadb6e6..6f10b9ddb01a5fab3154e6e08891cd8171419759 100644 (file)
  *
  * Input properties:
  *
- * /instrumentation/airspeed-indicator/serviceable
- * /systems/pitot[0]/total-pressure-inhg
- * /systems/static[0]/pressure-inhg
+ * /instrumentation/"name"/serviceable
+ * "pitot_port"/total-pressure-inhg
+ * "static_port"/pressure-inhg
  * /environment/density-slugft3
  *
  * Output properties:
  *
- * /instrumentation/airspeed-indicator/indicated-speed-kt
+ * /instrumentation/"name"/indicated-speed-kt
  */
 class AirspeedIndicator : public SGSubsystem
 {
 
 public:
 
-    AirspeedIndicator ();
+    AirspeedIndicator ( SGPropertyNode *node );
+    AirspeedIndicator ( int i);
     virtual ~AirspeedIndicator ();
 
     virtual void init ();
@@ -42,6 +43,10 @@ public:
 
 private:
 
+    string name;
+    int num;
+    string pitot_port;
+    string static_port;
     SGPropertyNode_ptr _serviceable_node;
     SGPropertyNode_ptr _total_pressure_node;
     SGPropertyNode_ptr _static_pressure_node;
index 2a9578705ce73b54cc8a7aad7668278972e320fc..39a0c105dce9c26a611138c8f0051429f4ca597c 100644 (file)
@@ -45,6 +45,36 @@ static double altitude_data[][2] = {
 };
 
 
+Altimeter::Altimeter ( SGPropertyNode *node )
+    : _altitude_table(new SGInterpTable),
+      name("altimeter"),
+      num(0),
+      static_port("/systems/static")
+{
+
+    for (int i = 0; altitude_data[i][0] != -1; i++)
+        _altitude_table->addEntry(altitude_data[i][0], altitude_data[i][1]);
+
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = child->getIntValue();
+        } else if ( cname == "static-port" ) {
+            static_port = cval;
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in altimeter config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
+
 Altimeter::Altimeter ()
     : _altitude_table(new SGInterpTable)
 {
@@ -61,14 +91,19 @@ Altimeter::~Altimeter ()
 void
 Altimeter::init ()
 {
-    _serviceable_node =
-        fgGetNode("/instrumentation/altimeter/serviceable", true);
-    _setting_node =
-        fgGetNode("/instrumentation/altimeter/setting-inhg", true);
-    _pressure_node =
-        fgGetNode("/systems/static/pressure-inhg", true);
-    _altitude_node =
-        fgGetNode("/instrumentation/altimeter/indicated-altitude-ft", true);
+    string branch;
+    branch = "/instrumentation/" + name;
+    static_port += "/pressure-inhg";
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
+
+    _serviceable_node = node->getChild("serviceable", 0, true);
+    _setting_node = node->getChild("setting-inhg", 0, true);
+    _pressure_node = fgGetNode(static_port.c_str(), true);
+    _altitude_node = node->getChild("indicated-altitude-ft", 0, true);
+
+    _serviceable_node->setBoolValue(true);
+    _setting_node->setDoubleValue(29.92);
 }
 
 void
index 73c1c2c02aa628f6b80fde0c28d7c65df4f83150..f75c207bdb2bc74d874209e2106d79f78f2851af 100644 (file)
@@ -23,19 +23,20 @@ class SGInterpTable;
  *
  * Input properties:
  *
- * /instrumentation/altimeter/serviceable
- * /instrumentation/altimeter/setting-inhg
- * /systems/static[0]/pressure-inhg
+ * /instrumentation/"name"/serviceable
+ * /instrumentation/"name"/setting-inhg
+ * "static_port"/pressure-inhg
  *
  * Output properties:
  *
- * /instrumentation/altimeter/indicated-altitude-ft
+ * /instrumentation/"name"/indicated-altitude-ft
  */
 class Altimeter : public SGSubsystem
 {
 
 public:
 
+    Altimeter (SGPropertyNode *node);
     Altimeter ();
     virtual ~Altimeter ();
 
@@ -44,6 +45,10 @@ public:
 
 private:
 
+    string name;
+    int num;
+    string static_port;
+
     SGPropertyNode_ptr _serviceable_node;
     SGPropertyNode_ptr _setting_node;
     SGPropertyNode_ptr _pressure_node;
index a6cdfba2628a0e66192f4c1e90c9afefcc12455c..82cb4c6a0f24bc871d2b412184d363eadcbc80bc 100644 (file)
 #include <Main/util.hxx>
 
 
+AttitudeIndicator::AttitudeIndicator ( SGPropertyNode *node )
+    :
+    name("attitude-indicator"),
+    num(0),
+    vacuum_system("/systems/vacuum")
+{
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = (int) child->getDoubleValue();
+        } else if ( cname == "vacuum-system" ) {
+            vacuum_system = cval;
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in attitude-indicator config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
+
 AttitudeIndicator::AttitudeIndicator ()
 {
 }
@@ -24,46 +50,49 @@ AttitudeIndicator::~AttitudeIndicator ()
 void
 AttitudeIndicator::init ()
 {
-                                // TODO: allow index of pump and AI
-                                // to be configured.
+    string branch;
+    branch = "/instrumentation/" + name;
+    vacuum_system += "/suction-inhg";
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
+    
     _pitch_in_node = fgGetNode("/orientation/pitch-deg", true);
     _roll_in_node = fgGetNode("/orientation/roll-deg", true);
-    _suction_node = fgGetNode("/systems/vacuum[0]/suction-inhg", true);
-    _tumble_flag_node =
-        fgGetNode("/instrumentation/attitude-indicator/config/tumble-flag",
-                  true);
-    _caged_node =
-        fgGetNode("/instrumentation/attitude-indicator/caged-flag", true);
-    _tumble_node =
-        fgGetNode("/instrumentation/attitude-indicator/tumble-norm", true);
-    _pitch_int_node =
-        fgGetNode("/instrumentation/attitude-indicator/internal-pitch-deg",
-                  true);
-    _roll_int_node =
-        fgGetNode("/instrumentation/attitude-indicator/internal-roll-deg",
-                  true);
-    _pitch_out_node =
-        fgGetNode("/instrumentation/attitude-indicator/indicated-pitch-deg",
-                  true);
-    _roll_out_node =
-        fgGetNode("/instrumentation/attitude-indicator/indicated-roll-deg",
-                  true);
+    _suction_node = fgGetNode(vacuum_system.c_str(), true);
+    SGPropertyNode *cnode = node->getChild("config", 0, true);
+    _tumble_flag_node = cnode->getChild("tumble-flag", 0, true);
+    _caged_node = node->getChild("caged-flag", 0, true);
+    _tumble_node = node->getChild("tumble-norm", 0, true);
+    _pitch_int_node = node->getChild("internal-pitch-deg", 0, true);
+    _roll_int_node = node->getChild("internal-roll-deg", 0, true);
+    _pitch_out_node = node->getChild("indicated-pitch-deg", 0, true);
+    _roll_out_node = node->getChild("indicated-roll-deg", 0, true);
+
+    //_serviceable_node->setBoolValue(true);
 }
 
 void
 AttitudeIndicator::bind ()
 {
-    fgTie("/instrumentation/attitude-indicator/serviceable",
+    string branch;
+    branch = "/instrumentation/" + name + "/serviceable";
+
+    fgTie(branch.c_str(),
           &_gyro, &Gyro::is_serviceable, &Gyro::set_serviceable);
-    fgTie("/instrumentation/attitude-indicator/spin",
+    branch = "/instrumentation/" + name + "/spin";
+    fgTie(branch.c_str(),
           &_gyro, &Gyro::get_spin_norm, &Gyro::set_spin_norm);
 }
 
 void
 AttitudeIndicator::unbind ()
 {
-    fgUntie("/instrumentation/attitude-indicator/serviceable");
-    fgUntie("/instrumentation/attitude-indicator/spin");
+    string branch;
+    branch = "/instrumentation/" + name + "/serviceable";
+
+    fgUntie(branch.c_str());
+    branch = "/instrumentation/" + name + "/spin";
+    fgUntie(branch.c_str());
 }
 
 void
index b71e742c21f188ee31668e98bb3c6afb75f66fc3..1895760ad471a8c0b2fa7f887ddc63fa22e418d7 100644 (file)
 /**
  * Model a vacuum-powered attitude indicator.
  *
- * This first, simple draft is hard-wired to vacuum pump #1.
- *
  * Input properties:
  *
- * /instrumentation/attitude-indicator/config/tumble-flag
- * /instrumentation/attitude-indicator/serviceable
- * /instrumentation/attitude-indicator/caged-flag
- * /instrumentation/attitude-indicator/tumble-norm
+ * /instrumentation/"name"/config/tumble-flag
+ * /instrumentation/"name"/serviceable
+ * /instrumentation/"name"/caged-flag
+ * /instrumentation/"name"/tumble-norm
  * /orientation/pitch-deg
  * /orientation/roll-deg
- * /systems/vacuum[0]/suction-inhg
+ * "vacuum-system"/suction-inhg
  *
  * Output properties:
  *
- * /instrumentation/attitude-indicator/indicated-pitch-deg
- * /instrumentation/attitude-indicator/indicated-roll-deg
- * /instrumentation/attitude-indicator/tumble-norm
+ * /instrumentation/"name"/indicated-pitch-deg
+ * /instrumentation/"name"/indicated-roll-deg
+ * /instrumentation/"name"/tumble-norm
  */
 class AttitudeIndicator : public SGSubsystem
 {
 
 public:
 
+    AttitudeIndicator ( SGPropertyNode *node );
     AttitudeIndicator ();
     virtual ~AttitudeIndicator ();
 
@@ -53,6 +52,10 @@ public:
 
 private:
 
+    string name;
+    int num;
+    string vacuum_system;
+
     Gyro _gyro;
 
     SGPropertyNode_ptr _tumble_flag_node;
index 994c357c05f26e0d47e900ee0b9516e65e6d090a..6f1db3e391dcbc86343ee42d3f2519575d961a53 100644 (file)
 #include <Main/util.hxx>
 
 
+Clock::Clock ( SGPropertyNode *node )
+    : _is_serviceable(true),
+      _gmt_time_sec(0),
+      _offset_sec(0),
+      _indicated_sec(0),
+      _standstill_offset(0),
+      name("clock"),
+      num(0)
+{
+    _indicated_string[0] = '\0';
+
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = child->getIntValue();
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in clock config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
+
 Clock::Clock ()
     : _is_serviceable(true),
       _gmt_time_sec(0),
@@ -29,10 +58,16 @@ Clock::~Clock ()
 void
 Clock::init ()
 {
-    _serviceable_node = fgGetNode("/instrumentation/clock/serviceable", true);
-    _offset_node      = fgGetNode("/instrumentation/clock/offset-sec", true);
-    _sec_node         = fgGetNode("/instrumentation/clock/indicated-sec", true);
-    _string_node      = fgGetNode("/instrumentation/clock/indicated-string", true);
+    string branch;
+    branch = "/instrumentation/" + name;
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
+    _serviceable_node = node->getChild("serviceable", 0, true);
+    _offset_node = node->getChild("offset-sec", 0, true);
+    _sec_node = node->getChild("indicated-sec", 0, true);
+    _string_node = node->getChild("indicated-string", 0, true);
+
+    _serviceable_node->setBoolValue(true);
 }
 
 void
index 0e35f0441dca13211fdc359fef955aa4d1b92ef4..44e7344065e881941215c9e045a47e4648937ca9 100644 (file)
@@ -35,6 +35,7 @@ class Clock : public SGSubsystem
 
 public:
 
+    Clock ( SGPropertyNode *node );
     Clock ();
     virtual ~Clock ();
 
@@ -50,6 +51,9 @@ private:
     char _indicated_string[16];
     long _standstill_offset;
 
+    string name;
+    int num;
+
     SGPropertyNode_ptr _serviceable_node;
     SGPropertyNode_ptr _offset_node;
     SGPropertyNode_ptr _sec_node;
index 5aea2a8ba6ab74176c29cc7a0de7ec8633553d44..272d407636937ce4c63f7bd8234e340b26c9f9ce 100644 (file)
@@ -36,6 +36,35 @@ adjust_range (double transmitter_elevation_ft, double aircraft_altitude_ft,
 }
 
 
+DME::DME ( SGPropertyNode *node )
+    : _last_distance_nm(0),
+      _last_frequency_mhz(-1),
+      _time_before_search_sec(0),
+      _transmitter_valid(false),
+      _transmitter_elevation_ft(0),
+      _transmitter_range_nm(0),
+      _transmitter_bias(0.0),
+      name("dme"),
+      num(0)
+{
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = child->getIntValue();
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in dme config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
+
 DME::DME ()
     : _last_distance_nm(0),
       _last_frequency_mhz(-1),
@@ -54,22 +83,25 @@ DME::~DME ()
 void
 DME::init ()
 {
+    string branch;
+    branch = "/instrumentation/" + name;
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
+
     _longitude_node = fgGetNode("/position/longitude-deg", true);
     _latitude_node = fgGetNode("/position/latitude-deg", true);
     _altitude_node = fgGetNode("/position/altitude-ft", true);
-    _serviceable_node = fgGetNode("/instrumentation/dme/serviceable", true);
+    _serviceable_node = node->getChild("serviceable", 0, true);
     _electrical_node = fgGetNode("/systems/electrical/outputs/dme", true);
-    _source_node = fgGetNode("/instrumentation/dme/frequencies/source", true);
-    _frequency_node =
-        fgGetNode("/instrumentation/dme/frequencies/selected-mhz", true);
-
-    _in_range_node = fgGetNode("/instrumentation/dme/in-range", true);
-    _distance_node =
-        fgGetNode("/instrumentation/dme/indicated-distance-nm", true);
-    _speed_node =
-        fgGetNode("/instrumentation/dme/indicated-ground-speed-kt", true);
-    _time_node =
-        fgGetNode("/instrumentation/dme/indicated-time-min", true);
+    SGPropertyNode *fnode = node->getChild("frequencies", 0, true);
+    _source_node = fnode->getChild("source", 0, true);
+    _frequency_node = fnode->getChild("selected-mhz", 0, true);
+    _in_range_node = node->getChild("in-range", 0, true);
+    _distance_node = node->getChild("indicated-distance-nm", 0, true);
+    _speed_node = node->getChild("indicated-ground-speed", 0, true);
+    _time_node = node->getChild("indicated-time-min", 0, true);
+
+    _serviceable_node->setBoolValue(true);
 }
 
 void
@@ -78,7 +110,9 @@ DME::update (double delta_time_sec)
                                 // Figure out the source
     const char * source = _source_node->getStringValue();
     if (source[0] == '\0') {
-        source = "/instrumentation/dme/frequencies/selected-mhz";
+        string branch;
+        branch = "/instrumentation/" + name + "/frequencies/selected-mhz";
+        source = branch.c_str();
         _source_node->setStringValue(source);
     }
 
index 2604b831db641fa4159d83f2c46719c3aa1c21b3..1fc5781c6601b7db2d96ab4af9e544342110457b 100644 (file)
  * /position/latitude-deg
  * /position/altitude-ft
  * /systems/electrical/outputs/dme
- * /instrumentation/dme/serviceable
- * /instrumentation/dme/frequencies/source
- * /instrumentation/dme/frequencies/selected-mhz
+ * /instrumentation/"name"/serviceable
+ * /instrumentation/"name"/frequencies/source
+ * /instrumentation/"name"/frequencies/selected-mhz
  *
  * Output properties:
  *
- * /instrumentation/dme/in-range
- * /instrumentation/dme/indicated-distance-nm
- * /instrumentation/dme/indicated-ground-speed-kt
- * /instrumentation/dme/indicated-time-kt
+ * /instrumentation/"name"/in-range
+ * /instrumentation/"name"/indicated-distance-nm
+ * /instrumentation/"name"/indicated-ground-speed-kt
+ * /instrumentation/"name"/indicated-time-kt
  */
 class DME : public SGSubsystem
 {
 
 public:
 
+    DME ( SGPropertyNode *node );
     DME ();
     virtual ~DME ();
 
@@ -75,6 +76,9 @@ private:
     double _transmitter_range_nm;
     double _transmitter_bias;
 
+    string name;
+    int num;
+
 };
 
 
index 847d6a2e85c9fbaa1a2a87c457c37162abd18855..9e2e9cdf493d1de2e819a8fcb9db38cbc5f120a3 100644 (file)
 SG_USING_STD(string);
 
 
+GPS::GPS ( SGPropertyNode *node)
+    : _last_valid(false),
+      _last_longitude_deg(0),
+      _last_latitude_deg(0),
+      _last_altitude_m(0),
+      _last_speed_kts(0)
+{
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = child->getIntValue();
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in gps config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
+
 GPS::GPS ()
     : _last_valid(false),
       _last_longitude_deg(0),
@@ -43,120 +68,118 @@ GPS::~GPS ()
 void
 GPS::init ()
 {
+    route = new SGRoute;
+    route->clear();
+
+    string branch;
+    branch = "/instrumentation/" + name;
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
+
     _longitude_node = fgGetNode("/position/longitude-deg", true);
     _latitude_node = fgGetNode("/position/latitude-deg", true);
     _altitude_node = fgGetNode("/position/altitude-ft", true);
     _magvar_node = fgGetNode("/environment/magnetic-variation-deg", true);
-    _serviceable_node = fgGetNode("/instrumentation/gps/serviceable", true);
+    _serviceable_node = node->getChild("serviceable", 0, true);
     _electrical_node = fgGetNode("/systems/electrical/outputs/gps", true);
-    _wp0_longitude_node = 
-        fgGetNode("/instrumentation/gps/wp/wp[0]/longitude-deg", true);
-    _wp0_latitude_node =
-        fgGetNode("/instrumentation/gps/wp/wp[0]/latitude-deg", true);
-    _wp0_altitude_node =
-       fgGetNode("/instrumentation/gps/wp/wp[0]/altitude-ft", true);
-    _wp0_ID_node =
-        fgGetNode("/instrumentation/gps/wp/wp[0]/ID", true);
-    _wp0_name_node =
-        fgGetNode("/instrumentation/gps/wp/wp[0]/name", true);
-    _wp0_course_node = 
-        fgGetNode("/instrumentation/gps/wp/wp[0]/desired-course-deg", true);
-    _wp0_waypoint_type_node =
-       fgGetNode("/instrumentation/gps/wp/wp[0]/waypoint-type", true);
-    _wp1_longitude_node = 
-        fgGetNode("/instrumentation/gps/wp/wp[1]/longitude-deg", true);
-    _wp1_latitude_node =
-        fgGetNode("/instrumentation/gps/wp/wp[1]/latitude-deg", true);
-    _wp1_altitude_node =
-       fgGetNode("/instrumentation/gps/wp/wp[1]/altitude-ft", true);
-    _wp1_ID_node =
-        fgGetNode("/instrumentation/gps/wp/wp[1]/ID", true);
-    _wp1_name_node =
-        fgGetNode("/instrumentation/gps/wp/wp[1]/name", true);
-    _wp1_course_node = 
-        fgGetNode("/instrumentation/gps/wp/wp[1]/desired-course-deg", true);
-    _wp1_waypoint_type_node =
-       fgGetNode("/instrumentation/gps/wp/wp[1]/waypoint-type", true);
-    _get_nearest_airport_node =
-       fgGetNode("/instrumentation/gps/wp/wp[1]/get-nearest-airport", true);
-    _tracking_bug_node =
-       fgGetNode("/instrumentation/gps/tracking-bug", true);
-
-    _raim_node = fgGetNode("/instrumentation/gps/raim", true);
+
+    SGPropertyNode *wp_node = node->getChild("wp", 0, true);
+    SGPropertyNode *wp0_node = wp_node->getChild("wp", 0, true);
+    SGPropertyNode *wp1_node = wp_node->getChild("wp", 1, true);
+    addWp = wp1_node->getChild("Add-to-route", 0, true);
+
+    _wp0_longitude_node = wp0_node->getChild("longitude-deg", 0, true);
+    _wp0_latitude_node = wp0_node->getChild("latitude-deg", 0, true);
+    _wp0_altitude_node = wp0_node->getChild("altitude-deg", 0, true);
+    _wp0_ID_node = wp0_node->getChild("ID", 0, true);
+    _wp0_name_node = wp0_node->getChild("name", 0, true);
+    _wp0_course_node = wp0_node->getChild("desired-course-deg", 0, true);
+    _wp0_waypoint_type_node = wp0_node->getChild("waypoint-type", 0, true);
+    _wp0_distance_node = wp0_node->getChild("distance-nm", 0, true);
+    _wp0_ttw_node = wp0_node->getChild("TTW", 0, true);
+    _wp0_bearing_node = wp0_node->getChild("bearing-true-deg", 0, true);
+    _wp0_mag_bearing_node = wp0_node->getChild("bearing-mag-deg", 0, true);
+    _wp0_course_deviation_node =
+        wp0_node->getChild("course-deviation-deg", 0, true);
+    _wp0_course_error_nm_node = wp0_node->getChild("course-error-nm", 0, true);
+    _wp0_to_flag_node = wp0_node->getChild("to-flag", 0, true);
+    _true_wp0_bearing_error_node =
+        wp0_node->getChild("true-bearing-error-deg", 0, true);
+    _magnetic_wp0_bearing_error_node =
+        wp0_node->getChild("magnetic-bearing-error-deg", 0, true);
+
+    _wp1_longitude_node = wp1_node->getChild("longitude-deg", 0, true);
+    _wp1_latitude_node = wp1_node->getChild("latitude-deg", 0, true);
+    _wp1_altitude_node = wp1_node->getChild("altitude-deg", 0, true);
+    _wp1_ID_node = wp1_node->getChild("ID", 0, true);
+    _wp1_name_node = wp1_node->getChild("name", 0, true);
+    _wp1_course_node = wp1_node->getChild("desired-course-deg", 0, true);
+    _wp1_waypoint_type_node = wp1_node->getChild("waypoint-type", 0, true);
+    _wp1_distance_node = wp1_node->getChild("distance-nm", 0, true);
+    _wp1_ttw_node = wp1_node->getChild("TTW", 0, true);
+    _wp1_bearing_node = wp1_node->getChild("bearing-true-deg", 0, true);
+    _wp1_mag_bearing_node = wp1_node->getChild("bearing-mag-deg", 0, true);
+    _wp1_course_deviation_node =
+        wp1_node->getChild("course-deviation-deg", 0, true);
+    _wp1_course_error_nm_node = wp1_node->getChild("course-error-nm", 0, true);
+    _wp1_to_flag_node = wp1_node->getChild("to-flag", 0, true);
+    _true_wp1_bearing_error_node =
+        wp1_node->getChild("true-bearing-error-deg", 0, true);
+    _magnetic_wp1_bearing_error_node =
+        wp1_node->getChild("magnetic-bearing-error-deg", 0, true);
+    _get_nearest_airport_node = 
+        wp1_node->getChild("get-nearest-airport", 0, true);
+
+    _tracking_bug_node = node->getChild("tracking-bug", 0, true);
+    _raim_node = node->getChild("raim", 0, true);
+
     _indicated_longitude_node =
-        fgGetNode("/instrumentation/gps/indicated-longitude-deg", true);
+        node->getChild("indicated-longitude-deg", 0, true);
     _indicated_latitude_node =
-        fgGetNode("/instrumentation/gps/indicated-latitude-deg", true);
+        node->getChild("indicated-latitude-deg", 0, true);
     _indicated_altitude_node =
-        fgGetNode("/instrumentation/gps/indicated-altitude-ft", true);
+        node->getChild("indicated-altitude-ft", 0, true);
     _indicated_vertical_speed_node =
-       fgGetNode("/instrumentation/gps/indicated-vertical-speed", true);
+        node->getChild("indicated-vertical-speed", 0, true);
     _true_track_node =
-        fgGetNode("/instrumentation/gps/indicated-track-true-deg", true);
+        node->getChild("indicated-track-true-deg", 0, true);
     _magnetic_track_node =
-        fgGetNode("/instrumentation/gps/indicated-track-magnetic-deg", true);
+        node->getChild("indicated-track_magnetic-deg", 0, true);
     _speed_node =
-        fgGetNode("/instrumentation/gps/indicated-ground-speed-kt", true);
-    _wp0_distance_node =
-        fgGetNode("/instrumentation/gps/wp/wp[0]/distance-nm", true);
-    _wp0_ttw_node =
-        fgGetNode("/instrumentation/gps/wp/wp[0]/TTW",true);
-    _wp0_bearing_node =
-        fgGetNode("/instrumentation/gps/wp/wp[0]/bearing-true-deg", true);
-    _wp0_mag_bearing_node =
-        fgGetNode("/instrumentation/gps/wp/wp[0]/bearing-mag-deg", true);
-    _wp0_course_deviation_node =
-        fgGetNode("/instrumentation/gps/wp/wp[0]/course-deviation-deg", true);
-    _wp0_course_error_nm_node =
-        fgGetNode("/instrumentation/gps/wp/wp[0]/course-error-nm", true);
-    _wp0_to_flag_node =
-        fgGetNode("/instrumentation/gps/wp/wp[0]/to-flag", true);
-    _wp1_distance_node =
-        fgGetNode("/instrumentation/gps/wp/wp[1]/distance-nm", true);
-    _wp1_ttw_node =
-        fgGetNode("/instrumentation/gps/wp/wp[1]/TTW",true);
-    _wp1_bearing_node =
-        fgGetNode("/instrumentation/gps/wp/wp[1]/bearing-true-deg", true);
-    _wp1_mag_bearing_node =
-        fgGetNode("/instrumentation/gps/wp/wp[1]/bearing-mag-deg", true);
-    _wp1_course_deviation_node =
-        fgGetNode("/instrumentation/gps/wp/wp[1]/course-deviation-deg", true);
-    _wp1_course_error_nm_node =
-        fgGetNode("/instrumentation/gps/wp/wp[1]/course-error-nm", true);
-    _wp1_to_flag_node =
-        fgGetNode("/instrumentation/gps/wp/wp[1]/to-flag", true);
+        node->getChild("indicated-ground-speed-kt", 0, true);
     _odometer_node =
-        fgGetNode("/instrumentation/gps/odometer", true);
+        node->getChild("odometer", 0, true);
     _trip_odometer_node =
-        fgGetNode("/instrumentation/gps/trip-odometer", true);
+        node->getChild("trip-odometer", 0, true);
     _true_bug_error_node =
-       fgGetNode("/instrumentation/gps/true-bug-error-deg", true);
+        node->getChild("true-bug-error-deg", 0, true);
     _magnetic_bug_error_node =
-        fgGetNode("/instrumentation/gps/magnetic-bug-error-deg", true);
-    _true_wp0_bearing_error_node =
-       fgGetNode("/instrumentation/gps/wp/wp[0]/true-bearing-error-deg", true);
-    _magnetic_wp0_bearing_error_node =
-       fgGetNode("/instrumentation/gps/wp/wp[0]/magnetic-bearing-error-deg", true);
-    _true_wp1_bearing_error_node =
-       fgGetNode("/instrumentation/gps/wp/wp[1]/true-bearing-error-deg", true);
-    _magnetic_wp1_bearing_error_node =
-       fgGetNode("/instrumentation/gps/wp/wp[1]/magnetic-bearing-error-deg", true);
+        node->getChild("magnetic-bug-error-deg", 0, true);
+
     _leg_distance_node =
-        fgGetNode("/instrumentation/gps/wp/leg-distance-nm", true);
+        wp_node->getChild("leg-distance-nm", 0, true);
     _leg_course_node =
-        fgGetNode("/instrumentation/gps/wp/leg-true-course-deg", true);
+        wp_node->getChild("leg-true-course-deg", 0, true);
     _leg_magnetic_course_node =
-        fgGetNode("/instrumentation/gps/wp/leg-mag-course-deg", true);
+        wp_node->getChild("leg-mag-course-deg", 0, true);
     _alt_dist_ratio_node =
-        fgGetNode("/instrumentation/gps/wp/alt-dist-ratio", true);
+        wp_node->getChild("alt-dist-ratio", 0, true);
     _leg_course_deviation_node =
-        fgGetNode("/instrumentation/gps/wp/leg-course-deviation-deg", true);
+        wp_node->getChild("leg-course-deviation-deg", 0, true);
     _leg_course_error_nm_node =
-        fgGetNode("/instrumentation/gps/wp/leg-course-error-nm", true);
+        wp_node->getChild("leg-course-error-nm", 0, true);
     _leg_to_flag_node =
-        fgGetNode("/instrumentation/gps/wp/leg-to-flag", true);
+        wp_node->getChild("leg-to-flag", 0, true);
     _alt_deviation_node =
-        fgGetNode("/instrumentation/gps/wp/alt-deviation-ft", true);
+        wp_node->getChild("alt-deviation-ft", 0, true);
+
+    _route = node->getChild("route", 0, true);
+    popWp = _route->getChild("Pop-WP", 0, true);
+
+    addWp->setBoolValue(false);
+    popWp->setBoolValue(false);
+
+    _serviceable_node->setBoolValue(true);
 }
 
 void
@@ -634,6 +657,43 @@ GPS::update (double delta_time_sec)
        _true_bug_error_node->setDoubleValue(true_bug_error);
        _magnetic_bug_error_node->setDoubleValue(magnetic_bug_error);
 
+
+        // Add WP 1 to the route.
+        if ( addWp->getBoolValue() )
+        {
+            addWp->setBoolValue(false);
+
+            SGWayPoint tempWp( _wp1_longitude_node->getDoubleValue(),
+                               _wp1_latitude_node->getDoubleValue(),
+                               _wp1_altitude_node->getDoubleValue(),
+                               SGWayPoint::WGS84,
+                               _wp1_ID_node->getStringValue(),
+                               _wp1_name_node->getStringValue() );
+
+            route->add_waypoint(tempWp);
+
+            SGPropertyNode *wp = 
+                _route->getChild("Waypoint", route->size()-1, true);
+            SGPropertyNode *id = wp->getChild("ID", 0, true);
+            SGPropertyNode *name = wp->getChild("Name", 0, true);
+            SGPropertyNode *lat = wp->getChild("Latitude", 0, true);
+            SGPropertyNode *lon = wp->getChild("Longitude", 0, true);
+            SGPropertyNode *alt = wp->getChild("Altitude", 0, true);
+            
+            id->setStringValue( tempWp.get_id().c_str() );
+            name->setStringValue( tempWp.get_name().c_str() );
+            lat->setDoubleValue( tempWp.get_target_lat() );
+            lon->setDoubleValue( tempWp.get_target_lon() );
+            alt->setDoubleValue( tempWp.get_target_alt() );
+        }
+
+        if ( popWp->getBoolValue() )
+        {
+            popWp->setBoolValue(false);
+
+            route->delete_first();
+        }
+
     } else {
         _true_track_node->setDoubleValue(0.0);
         _magnetic_track_node->setDoubleValue(0.0);
index c28c26d3a4f4773233f582c8fe820fa196ac9e85..fabf4e776916dea7380ea1dce7b5b08ee38d21ff 100644 (file)
@@ -12,6 +12,7 @@
 #endif
 
 #include <simgear/props/props.hxx>
+#include <simgear/route/route.hxx>
 #include <simgear/structure/subsystem_mgr.hxx>
 
 
@@ -66,6 +67,7 @@ class GPS : public SGSubsystem
 
 public:
 
+    GPS (SGPropertyNode *node);
     GPS ();
     virtual ~GPS ();
 
@@ -139,6 +141,12 @@ private:
     SGPropertyNode_ptr _leg_to_flag_node;
     SGPropertyNode_ptr _alt_deviation_node;
 
+    SGPropertyNode *_route;
+    SGPropertyNode *addWp;
+    SGPropertyNode *popWp;
+
+    SGRoute *route;
+
     bool _last_valid;
     double _last_longitude_deg;
     double _last_latitude_deg;
@@ -164,6 +172,9 @@ private:
     double range_error;
     double elapsed_time;
 
+    string name;
+    int num;
+
 };
 
 
index 8f323366adcd3e32e7bf2834f426b54345f3a620..beeef54e95767f6502901d40b49ebaa9bafc735a 100644 (file)
@@ -8,6 +8,32 @@
 #include <Main/util.hxx>
 
 
+HeadingIndicator::HeadingIndicator ( SGPropertyNode *node )
+    :
+    name("heading-indicator"),
+    num(0),
+    vacuum_system("/systems/vacuum")
+{
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = child->getIntValue();
+        } else if ( cname == "vacuum-system" ) {
+            vacuum_system = cval;
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in heading-indicator config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
+
 HeadingIndicator::HeadingIndicator ()
 {
 }
@@ -19,31 +45,41 @@ HeadingIndicator::~HeadingIndicator ()
 void
 HeadingIndicator::init ()
 {
-    _offset_node =
-        fgGetNode("/instrumentation/heading-indicator/offset-deg", true);
+    string branch;
+    branch = "/instrumentation/" + name;
+    vacuum_system += "/suction-inhg";
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
+    _offset_node = node->getChild("offset-deg", 0, true);
     _heading_in_node = fgGetNode("/orientation/heading-deg", true);
-    _suction_node = fgGetNode("/systems/vacuum[0]/suction-inhg", true);
-    _heading_out_node =
-        fgGetNode("/instrumentation/heading-indicator/indicated-heading-deg",
-                  true);
+    _suction_node = fgGetNode(vacuum_system.c_str(), true);
+    _heading_out_node = node->getChild("indicated-heading-deg", 0, true);
     _last_heading_deg = (_heading_in_node->getDoubleValue() +
                          _offset_node->getDoubleValue());
+
+    //_serviceable_node->setBoolValue(true);
 }
 
 void
 HeadingIndicator::bind ()
 {
-    fgTie("/instrumentation/heading-indicator/serviceable",
+    string branch;
+    branch = "/instrumentation/" + name + "/serviceable";
+    fgTie(branch.c_str(),
           &_gyro, &Gyro::is_serviceable, &Gyro::set_serviceable);
-    fgTie("/instrumentation/heading-indicator/spin",
+    branch = "/instrumentation/" + name + "/spin";
+    fgTie(branch.c_str(),
           &_gyro, &Gyro::get_spin_norm, &Gyro::set_spin_norm);
 }
 
 void
 HeadingIndicator::unbind ()
 {
-    fgUntie("/instrumentation/heading-indicator/serviceable");
-    fgUntie("/instrumentation/heading-indicator/spin");
+    string branch;
+    branch = "/instrumentation/" + name + "/serviceable";
+    fgUntie(branch.c_str());
+    branch = "/instrumentation/" + name + "/spin";
+    fgUntie(branch.c_str());
 }
 
 void
index 75b1bc5c3c41493e149412a54dc9b87cd3aed067..4ba772d22a93ddb11ba110e54046329f00f7aa26 100644 (file)
 /**
  * Model a vacuum-powered heading indicator.
  *
- * This first, simple draft is hard-wired to vacuum pump #1.
- *
  * Input properties:
  *
- * /instrumentation/heading-indicator/serviceable
- * /instrumentation/heading-indicator/spin
- * /instrumentation/heading-indicator/offset-deg
+ * /instrumentation/"name"/serviceable
+ * /instrumentation/"name"/spin
+ * /instrumentation/"name"/offset-deg
  * /orientation/heading-deg
- * /systems/vacuum[0]/suction-inhg
+ * "vacuum_system"/suction-inhg
  *
  * Output properties:
  *
- * /instrumentation/heading-indicator/indicated-heading-deg
+ * /instrumentation/"name"/indicated-heading-deg
  */
 class HeadingIndicator : public SGSubsystem
 {
 
 public:
 
+    HeadingIndicator ( SGPropertyNode *node );
     HeadingIndicator ();
     virtual ~HeadingIndicator ();
 
@@ -52,6 +51,10 @@ private:
     Gyro _gyro;
     double _last_heading_deg;
 
+    string name;
+    int num;
+    string vacuum_system;
+
     SGPropertyNode_ptr _offset_node;
     SGPropertyNode_ptr _heading_in_node;
     SGPropertyNode_ptr _suction_node;
index b9f4c359b845be2f1ba083e8d9b50f379b89c94c..c59426d429a057f13e3e9c9bc43c4a51d147f103 100644 (file)
@@ -3,6 +3,17 @@
 //
 // This file is in the Public Domain and comes with no warranty.
 
+#include <iostream>
+#include <string>
+#include <sstream>
+
+#include <simgear/structure/exception.hxx>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/sg_inlines.h>
+
+#include <Main/fg_props.hxx>
+#include <Main/globals.hxx>
+#include <Main/util.hxx>
 
 #include "instrument_mgr.hxx"
 #include "airspeed_indicator.hxx"
 
 FGInstrumentMgr::FGInstrumentMgr ()
 {
-    set_subsystem("asi", new AirspeedIndicator);
+    //set_subsystem("asi", new AirspeedIndicator(0));
+    //set_subsystem("asi-backup", new AirspeedIndicator(1, 1, 1));
     set_subsystem("annunciator", new Annunciator);
-    set_subsystem("ai", new AttitudeIndicator);
-    set_subsystem("alt", new Altimeter);
-    set_subsystem("ti", new TurnIndicator);
-    set_subsystem("ball", new SlipSkidBall);
-    set_subsystem("hi", new HeadingIndicator);
-    set_subsystem("vsi", new VerticalSpeedIndicator);
-    set_subsystem("compass", new MagCompass);
-    set_subsystem("dme", new DME, 1.0);
-    set_subsystem("adf", new ADF, 0.15);
-    set_subsystem("gps", new GPS, 0.45);
-    set_subsystem("clock", new Clock, 0.25);
+    //set_subsystem("ai", new AttitudeIndicator);
+    //set_subsystem("alt", new Altimeter);
+    //set_subsystem("ti", new TurnIndicator);
+    //set_subsystem("ball", new SlipSkidBall);
+    //set_subsystem("hi", new HeadingIndicator);
+    //set_subsystem("vsi", new VerticalSpeedIndicator);
+    //set_subsystem("compass", new MagCompass);
+    //set_subsystem("dme", new DME, 1.0);
+    //set_subsystem("adf", new ADF, 0.15);
+    //set_subsystem("gps", new GPS, 0.45);
+    //set_subsystem("clock", new Clock, 0.25);
+    //set_subsystem("nhi", new NewHeadingIndicator);
+
+    config_props = new SGPropertyNode;
+
+    SGPropertyNode *path_n = fgGetNode("/sim/instrumentation/path");
+
+    if (path_n) {
+        SGPath config( globals->get_fg_root() );
+        config.append( path_n->getStringValue() );
+
+        SG_LOG( SG_ALL, SG_INFO, "Reading instruments from "
+                << config.str() );
+        try {
+            readProperties( config.str(), config_props );
+
+            if ( build() ) {
+                enabled = true;
+            } else {
+                SG_LOG( SG_ALL, SG_ALERT,
+                        "Detected an internal inconsistancy in the instrumentation");
+                SG_LOG( SG_ALL, SG_ALERT,
+                        " system specification file.  See earlier errors for" );
+                SG_LOG( SG_ALL, SG_ALERT,
+                        " details.");
+                exit(-1);
+            }        
+        } catch (const sg_exception& exc) {
+            SG_LOG( SG_ALL, SG_ALERT, "Failed to load instrumentation system model: "
+                    << config.str() );
+        }
+
+    } else {
+        SG_LOG( SG_ALL, SG_WARN,
+                "No instrumentation model specified for this model!");
+    }
+
+    delete config_props;
 }
 
 FGInstrumentMgr::~FGInstrumentMgr ()
 {
 }
 
+bool FGInstrumentMgr::build ()
+{
+    SGPropertyNode *node;
+    int i;
+
+    int count = config_props->nChildren();
+    for ( i = 0; i < count; ++i ) {
+        node = config_props->getChild(i);
+        string name = node->getName();
+        std::ostringstream temp;
+        temp << i;
+        if ( name == "adf" ) {
+            set_subsystem( "instrument" + temp.str(), 
+                           new ADF( node ), 0.15 );
+        } else if ( name == "airspeed-indicator" ) {
+            set_subsystem( "instrument" + temp.str(), 
+                           new AirspeedIndicator( node ) );
+        } else if ( name == "altimeter" ) {
+            set_subsystem( "instrument" + temp.str(), 
+                           new Altimeter( node ) );
+        } else if ( name == "attitude-indicator" ) {
+            set_subsystem( "instrument" + temp.str(), 
+                           new AttitudeIndicator( node ) );
+        } else if ( name == "clock" ) {
+            set_subsystem( "instrument" + temp.str(), 
+                           new Clock( node ), 0.25 );
+        } else if ( name == "dme" ) {
+            set_subsystem( "instrument" + temp.str(), 
+                           new DME( node ), 1.0 );
+        } else if ( name == "heading-indicator" ) {
+            set_subsystem( "instrument" + temp.str(), 
+                           new HeadingIndicator( node ) );
+        } else if ( name == "magnetic-compass" ) {
+            set_subsystem( "instrument" + temp.str(), 
+                           new MagCompass( node ) );
+        } else if ( name == "slip-skid-ball" ) {
+            set_subsystem( "instrument" + temp.str(), 
+                           new SlipSkidBall( node ) );
+        } else if ( name == "turn-indicator" ) {
+            set_subsystem( "instrument" + temp.str(), 
+                           new TurnIndicator( node ) );
+        } else if ( name == "vertical-speed-indicator" ) {
+            set_subsystem( "instrument" + temp.str(), 
+                           new VerticalSpeedIndicator( node ) );
+        } else if ( name == "gps" ) {
+            set_subsystem( "instrument" + temp.str(), 
+                           new GPS( node ), 0.45 );
+        } else {
+            SG_LOG( SG_ALL, SG_ALERT, "Unknown top level section: " 
+                    << name );
+            return false;
+        }
+    }
+    return true;
+}
+
 // end of instrument_manager.cxx
index 11649adabf21d88998fb28d3bf00bede1290ebf0..88a9c8bed656fd7a0a2dddd51103869aa9f8c524 100644 (file)
@@ -31,6 +31,11 @@ public:
 
     FGInstrumentMgr ();
     virtual ~FGInstrumentMgr ();
+    bool build ();
+
+private:
+    SGPropertyNode *config_props;
+    bool enabled;
 
 };
 
index 3ef4be2ee3de9f6c3af11a1ffd96ae98c2755673..378dd4bdd3efeac168723179341ff3bc460f3597 100644 (file)
 #include <Main/util.hxx>
 
 
+MagCompass::MagCompass ( SGPropertyNode *node )
+    : _error_deg(0.0),
+      _rate_degps(0.0),
+      name("magnetic-compass"),
+      num(0)
+{
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = child->getIntValue();
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in magnetic-compass config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
+
 MagCompass::MagCompass ()
     : _error_deg(0.0),
       _rate_degps(0.0)
@@ -30,8 +54,11 @@ MagCompass::~MagCompass ()
 void
 MagCompass::init ()
 {
-    _serviceable_node =
-        fgGetNode("/instrumentation/magnetic-compass/serviceable", true);
+    string branch;
+    branch = "/instrumentation/" + name;
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
+    _serviceable_node = node->getChild("serviceable", 0, true);
     _heading_node =
         fgGetNode("/orientation/heading-deg", true);
     _beta_node =
@@ -46,9 +73,9 @@ MagCompass::init ()
         fgGetNode("/accelerations/ned/east-accel-fps_sec", true);
     _down_accel_node =
         fgGetNode("/accelerations/ned/down-accel-fps_sec", true);
-    _out_node =
-        fgGetNode("/instrumentation/magnetic-compass/indicated-heading-deg",
-                  true);
+    _out_node = node->getChild("indicated-heading-deg", 0, true);
+
+    _serviceable_node->setBoolValue(true);
 }
 
 void
index 8f7aafe275f98957ea71f1876eb574f5bc7faec4..5bc176e0248e3239a63802b2fdb93dfbd750ad9d 100644 (file)
@@ -20,7 +20,7 @@
  *
  * Input properties:
  *
- * /instrumentation/magnetic-compass/serviceable
+ * /instrumentation/"name"/serviceable
  * /orientation/heading-deg
  * /orientation/beta-deg
  * /environment/magnetic-variation-deg
  *
  * Output properties:
  *
- * /instrumentation/magnetic-compass/indicated-heading-deg
+ * /instrumentation/"name"/indicated-heading-deg
  */
 class MagCompass : public SGSubsystem
 {
 
 public:
 
+    MagCompass ( SGPropertyNode *node);
     MagCompass ();
     virtual ~MagCompass ();
 
@@ -49,6 +50,9 @@ private:
     double _error_deg;
     double _rate_degps;
 
+    string name;
+    int num;
+
     SGPropertyNode_ptr _serviceable_node;
     SGPropertyNode_ptr _heading_node;
     SGPropertyNode_ptr _beta_node;
index 9ebff9ba73d9aafe2828f1d561685b17d1ab73c5..d0ec8886fc76639e3b7e11dcf042d224b657ba03 100644 (file)
@@ -8,6 +8,29 @@
 #include <Main/util.hxx>
 
 
+SlipSkidBall::SlipSkidBall ( SGPropertyNode *node)
+    :
+    name("slip-skid-ball"),
+    num(0)
+{
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = child->getIntValue();
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in slip-skid-ball config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
+
 SlipSkidBall::SlipSkidBall ()
 {
 }
@@ -19,14 +42,17 @@ SlipSkidBall::~SlipSkidBall ()
 void
 SlipSkidBall::init ()
 {
-    _serviceable_node =
-        fgGetNode("/instrumentation/slip-skid-ball/serviceable", true);
+    string branch;
+    branch = "/instrumentation/" + name;
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
+    _serviceable_node = node->getChild("serviceable", 0, true);
     _y_accel_node = fgGetNode("/accelerations/pilot/y-accel-fps_sec", true);
     _z_accel_node = fgGetNode("/accelerations/pilot/z-accel-fps_sec", true);
-    _out_node =
-        fgGetNode("/instrumentation/slip-skid-ball/indicated-slip-skid", true);
-    _override_node =
-        fgGetNode("/instrumentation/slip-skid-ball/override", true);
+    _out_node = node->getChild("indicated-slip-skid", 0, true);
+    _override_node = node->getChild("iverride", 0, true);
+
+    _serviceable_node->setBoolValue(true);
 }
 
 void
index 4c11c1df595d75fb489756866044f097ce214b9e..7266cdfce4c2b3033d10adf454bb81fb9eed29f9 100644 (file)
  *
  * Input properties:
  *
- * /instrumentation/slip-skid-ball/serviceable
+ * /instrumentation/"name"/serviceable
  * /accelerations/pilot/y-accel-fps_sec
  * /accelerations/pilot/z-accel-fps_sec
  *
  * Output properties:
  *
- * /instrumentation/slip-skid-ball/indicated-slip-skid
+ * /instrumentation/"name"/indicated-slip-skid
  */
 class SlipSkidBall : public SGSubsystem
 {
 
 public:
 
+    SlipSkidBall ( SGPropertyNode *node );
     SlipSkidBall ();
     virtual ~SlipSkidBall ();
 
@@ -46,6 +47,9 @@ private:
     Gyro _gyro;
     double _last_pos;
 
+    string name;
+    int num;
+
     SGPropertyNode_ptr _serviceable_node;
     SGPropertyNode_ptr _y_accel_node;
     SGPropertyNode_ptr _z_accel_node;
index 1edb0bb4d3e09a4771c2b4788180f85b22aaf743..26b3c8f690fd8fef3ee14964c96b4d59284a64c2 100644 (file)
 #define RESPONSIVENESS 0.5
 
 
+TurnIndicator::TurnIndicator ( SGPropertyNode *node) :
+    _last_rate(0),
+    name("turn-indicator"),
+    num(0)
+{
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = child->getIntValue();
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in turn-indicator config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
+
 TurnIndicator::TurnIndicator () :
     _last_rate(0)
 {
@@ -25,28 +48,40 @@ TurnIndicator::~TurnIndicator ()
 void
 TurnIndicator::init ()
 {
+    string branch;
+    branch = "/instrumentation/" + name;
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
     _roll_rate_node = fgGetNode("/orientation/roll-rate-degps", true);
     _yaw_rate_node = fgGetNode("/orientation/yaw-rate-degps", true);
     _electric_current_node = 
         fgGetNode("/systems/electrical/outputs/turn-coordinator", true);
-    _rate_out_node = 
-        fgGetNode("/instrumentation/turn-indicator/indicated-turn-rate", true);
+    _rate_out_node = node->getChild("indicated-turn-rate", 0, true);
+
+    //_serviceable_node->setBoolValue(true);
+    
 }
 
 void
 TurnIndicator::bind ()
 {
-    fgTie("/instrumentation/turn-indicator/serviceable",
+    string branch;
+    branch = "/instrumentation/" + name + "/serviceable";
+    fgTie(branch.c_str(),
           &_gyro, &Gyro::is_serviceable, &Gyro::set_serviceable);
-    fgTie("/instrumentation/turn-indicator/spin",
+    branch = "/instrumentation/" + name + "/spin";
+    fgTie(branch.c_str(),
           &_gyro, &Gyro::get_spin_norm, &Gyro::set_spin_norm);
 }
 
 void
 TurnIndicator::unbind ()
 {
-    fgUntie("/instrumentation/turn-indicator/serviceable");
-    fgUntie("/instrumentation/turn-indicator/spin");
+    string branch;
+    branch = "/instrumentation/" + name + "/serviceable";
+    fgUntie(branch.c_str());
+    branch = "/instrumentation/" + name + "/spin";
+    fgUntie(branch.c_str());
 }
 
 void
index 5d5028cf1c49805752d817472b75e0b6c6f5def2..d1b2a291708bc3b5b4656838fd064fe72a9b5d32 100644 (file)
  *
  * Input properties:
  *
- * /instrumentation/turn-indicator/serviceable
- * /instrumentation/turn-indicator/spin
+ * /instrumentation/"name"/serviceable
+ * /instrumentation/"name"/spin
  * /orientation/roll-rate-degps
  * /orientation/yaw-rate-degps
  * /systems/electrical/outputs/turn-coordinator
  *
  * Output properties:
  *
- * /instrumentation/turn-indicator/indicated-turn-rate
+ * /instrumentation/"name"/indicated-turn-rate
  */
 class TurnIndicator : public SGSubsystem
 {
 
 public:
 
+    TurnIndicator ( SGPropertyNode *node );
     TurnIndicator ();
     virtual ~TurnIndicator ();
 
@@ -53,6 +54,9 @@ private:
     Gyro _gyro;
     double _last_rate;
 
+    string name;
+    int num;
+
     SGPropertyNode_ptr _roll_rate_node;
     SGPropertyNode_ptr _yaw_rate_node;
     SGPropertyNode_ptr _electric_current_node;
index 11f72fa4566cedc343d8a0654cf88e71c6ee3fe7..72ff151f41cb00322905e3a427b0d1bf000db252 100644 (file)
 #include <Main/util.hxx>
 
 
+VerticalSpeedIndicator::VerticalSpeedIndicator ( SGPropertyNode *node )
+    : _internal_pressure_inhg(29.92),
+      name("vertical-speed-indicator"),
+      num(0),
+      static_port("/systems/static")
+{
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = child->getIntValue();
+        } else if ( cname == "static-port" ) {
+            static_port = cval;
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in vertical-speed-indicator config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
+
 VerticalSpeedIndicator::VerticalSpeedIndicator ()
     : _internal_pressure_inhg(29.92)
 {
@@ -22,15 +48,16 @@ VerticalSpeedIndicator::~VerticalSpeedIndicator ()
 void
 VerticalSpeedIndicator::init ()
 {
-    _serviceable_node =
-        fgGetNode("/instrumentation/vertical-speed-indicator/serviceable",
-                  true);
-    _pressure_node =
-        fgGetNode("/systems/static/pressure-inhg", true);
-    _speed_node =
-        fgGetNode("/instrumentation/vertical-speed-indicator/indicated-speed-fpm",
-                  true);
+    string branch;
+    branch = "/instrumentation/" + name;
+    static_port += "/pressure-inhg";
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
+    _serviceable_node = node->getChild("serviceable", 0, true);
+    _pressure_node = fgGetNode(static_port.c_str(), true);
+    _speed_node = node->getChild("indicated-speed-fpm", 0, true);
 
+    _serviceable_node->setBoolValue(true);
                                 // Initialize at ambient pressure
     _internal_pressure_inhg = _pressure_node->getDoubleValue();
 }
index f7df642e8aefd6f1d2e8b2b8bf487167da836469..0c2a5a3a92209ba889a413a60443f50667191893 100644 (file)
  *
  * Input properties:
  *
- * /instrumentation/vertical-speed-indicator/serviceable
- * /systems/static[0]/pressure-inhg
+ * /instrumentation/"name"/serviceable
+ * "static_port"/pressure-inhg
  *
  * Output properties:
  *
- * /instrumentation/vertical-speed-indicator/indicated-speed-fpm
+ * /instrumentation/"name"/indicated-speed-fpm
  */
 class VerticalSpeedIndicator : public SGSubsystem
 {
 
 public:
 
+    VerticalSpeedIndicator ( SGPropertyNode *node );
     VerticalSpeedIndicator ();
     virtual ~VerticalSpeedIndicator ();
 
@@ -42,6 +43,10 @@ private:
 
     double _internal_pressure_inhg;
 
+    string name;
+    int num;
+    string static_port;
+
     SGPropertyNode_ptr _serviceable_node;
     SGPropertyNode_ptr _pressure_node;
     SGPropertyNode_ptr _speed_node;
index 5cfc6188b20ad514bbe96d5fba8ff99d946c78f2..71b27fc7a05a3884938a6f8e95ef592635023090 100644 (file)
@@ -8,8 +8,34 @@
 #include <Main/util.hxx>
 
 
-PitotSystem::PitotSystem ()
+
+PitotSystem::PitotSystem ( SGPropertyNode *node )
+    :
+    name("pitot"),
+    num(0)
 {
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = child->getIntValue();
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in systems config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
+
+PitotSystem::PitotSystem ( int i )
+{
+    num = i;
+    name = "pitot";
 }
 
 PitotSystem::~PitotSystem ()
@@ -19,12 +45,17 @@ PitotSystem::~PitotSystem ()
 void
 PitotSystem::init ()
 {
-    _serviceable_node = fgGetNode("/systems/pitot[0]/serviceable", true);
+    string branch;
+    branch = "/systems/" + name;
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
+    _serviceable_node = node->getChild("serviceable", 0, true);
     _pressure_node = fgGetNode("/environment/pressure-inhg", true);
     _density_node = fgGetNode("/environment/density-slugft3", true);
     _velocity_node = fgGetNode("/velocities/airspeed-kt", true);
-    _total_pressure_node =
-        fgGetNode("/systems/pitot[0]/total-pressure-inhg", true);
+    _total_pressure_node = node->getChild("total-pressure-inhg", 0, true);
+
+    _serviceable_node->setBoolValue(true);
 }
 
 void
index 80be710f09f3ca4be89623f3dae99e334bee01d6..e606fe4e622cd51ff600e4f4ed0ef8929e8fce12 100644 (file)
 # error This library requires C++
 #endif
 
+#include <simgear/compiler.h>
+
+#include STL_STRING
+SG_USING_STD(string);
+
 #include <simgear/props/props.hxx>
 #include <simgear/structure/subsystem_mgr.hxx>
 
  *
  * Input properties:
  *
- * /systems/pitot[0]/serviceable
+ * /systems/"name"/serviceable
  * /environment/pressure-slugft3
  * /environment/density-slugft3
  * /velocities/airspeed-kt
  *
  * Output properties:
  *
- * /systems/pitot[0]/total-pressure-inhg
+ * /systems/"name"/total-pressure-inhg
  */
 class PitotSystem : public SGSubsystem
 {
 
 public:
 
-    PitotSystem ();
+    PitotSystem ( SGPropertyNode *node );
+    PitotSystem ( int i );
     virtual ~PitotSystem ();
 
     virtual void init ();
@@ -47,6 +53,8 @@ public:
 
 private:
 
+    int num;
+    string name;
     SGPropertyNode_ptr _serviceable_node;
     SGPropertyNode_ptr _pressure_node;
     SGPropertyNode_ptr _density_node;
index 866845befdb8b0d19b0431c1fc0385c143859b80..bac6ddf25aba7caa50c44d8924777d120c431ad5 100644 (file)
@@ -8,8 +8,33 @@
 #include <Main/util.hxx>
 
 
-StaticSystem::StaticSystem ()
+StaticSystem::StaticSystem ( SGPropertyNode *node )
+    :
+    name("static"),
+    num(0)
 {
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = child->getIntValue();
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in systems config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
+
+StaticSystem::StaticSystem ( int i )
+{
+    name = "static";
+    num = i;
 }
 
 StaticSystem::~StaticSystem ()
@@ -19,9 +44,15 @@ StaticSystem::~StaticSystem ()
 void
 StaticSystem::init ()
 {
-    _serviceable_node = fgGetNode("/systems/static[0]/serviceable", true);
+    string branch;
+    branch = "/systems/" + name;
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
+    _serviceable_node = node->getChild("serviceable", 0, true);
     _pressure_in_node = fgGetNode("/environment/pressure-inhg", true);
-    _pressure_out_node = fgGetNode("/systems/static[0]/pressure-inhg", true);
+    _pressure_out_node = node->getChild("pressure-inhg", 0, true);
+
+    _serviceable_node->setBoolValue(true);
 }
 
 void
index 56a0a4ed14e42095d8bb39de45082af39e8e2da4..fcacd925b6e05c07bdd2c120c17cd7798caadf1e 100644 (file)
  * Input properties:
  *
  * /environment/pressure-inhg
- * /systems/static[0]/serviceable
+ * /systems/"name"/serviceable
  *
  * Output properties:
  *
- * /systems/static[0]/pressure-inhg
+ * /systems/"name"/pressure-inhg
  *
- * TODO: support multiple static ports and specific locations
+ * TODO: support specific locations
  * TODO: support alternate air with errors
  */
 class StaticSystem : public SGSubsystem
@@ -35,7 +35,8 @@ class StaticSystem : public SGSubsystem
 
 public:
 
-    StaticSystem ();
+    StaticSystem ( SGPropertyNode *node );
+    StaticSystem ( int i );
     virtual ~StaticSystem ();
 
     virtual void init ();
@@ -45,6 +46,8 @@ public:
 
 private:
 
+    string name;
+    int num;
     SGPropertyNode_ptr _serviceable_node;
     SGPropertyNode_ptr _pressure_in_node;
     SGPropertyNode_ptr _pressure_out_node;
index fbd6ee6a0c7ae5e64f3f9cc87cf5e94d087d861e..21bf3f5cf0bb7f51141a516af8f5af0fd726f139 100644 (file)
@@ -3,6 +3,17 @@
 //
 // This file is in the Public Domain and comes with no warranty.
 
+#include <simgear/structure/exception.hxx>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/sg_inlines.h>
+
+#include <Main/fg_props.hxx>
+#include <Main/globals.hxx>
+#include <Main/util.hxx>
+
+#include <iostream>
+#include <string>
+#include <sstream>
 
 #include "system_mgr.hxx"
 #include "electrical.hxx"
 FGSystemMgr::FGSystemMgr ()
 {
     set_subsystem( "electrical", new FGElectricalSystem );
-    set_subsystem( "pitot", new PitotSystem );
-    set_subsystem( "static", new StaticSystem );
-    set_subsystem( "vacuum-l", new VacuumSystem(0) );
-    set_subsystem( "vacuum-r", new VacuumSystem(1) );
     set_subsystem( "submodel", new SubmodelSystem() );
+
+    config_props = new SGPropertyNode;
+
+    SGPropertyNode *path_n = fgGetNode("/sim/systems/path");
+
+    if (path_n) {
+        SGPath config( globals->get_fg_root() );
+        config.append( path_n->getStringValue() );
+
+        SG_LOG( SG_ALL, SG_INFO, "Reading systems from "
+                << config.str() );
+        try {
+            readProperties( config.str(), config_props );
+
+            if ( build() ) {
+                enabled = true;
+            } else {
+                SG_LOG( SG_ALL, SG_ALERT,
+                        "Detected an internal inconsistancy in the systems");
+                SG_LOG( SG_ALL, SG_ALERT,
+                        " system specification file.  See earlier errors for" );
+                SG_LOG( SG_ALL, SG_ALERT,
+                        " details.");
+                exit(-1);
+            }        
+        } catch (const sg_exception& exc) {
+            SG_LOG( SG_ALL, SG_ALERT, "Failed to load systems system model: "
+                    << config.str() );
+        }
+
+    } else {
+        SG_LOG( SG_ALL, SG_WARN,
+                "No systems model specified for this model!");
+    }
+
+    delete config_props;
 }
 
 FGSystemMgr::~FGSystemMgr ()
 {
 }
 
+bool FGSystemMgr::build ()
+{
+    SGPropertyNode *node;
+    int i;
+
+    int count = config_props->nChildren();
+    for ( i = 0; i < count; ++i ) {
+        node = config_props->getChild(i);
+        string name = node->getName();
+        std::ostringstream temp;
+        temp << i;
+        if ( name == "pitot" ) {
+            set_subsystem( "system" + temp.str(), 
+                           new PitotSystem( node ) );
+        } else if ( name == "static" ) {
+            set_subsystem( "system" + temp.str(), 
+                           new StaticSystem( node ) );
+        } else if ( name == "vacuum" ) {
+            set_subsystem( "system" + temp.str(), 
+                           new VacuumSystem( node ) );
+        } else {
+            SG_LOG( SG_ALL, SG_ALERT, "Unknown top level section: " 
+                    << name );
+            return false;
+        }
+    }
+    return true;
+}
+
 // end of system_manager.cxx
index 02c102a7e87e36c815bbcc92458e268e2ee364bd..e783532e22741083cb7cabab1aa679c460ba22fe 100644 (file)
 #endif
 
 #include <simgear/compiler.h>
+#include <simgear/props/props.hxx>
 #include <simgear/structure/subsystem_mgr.hxx>
 
 
 /**
  * Manage aircraft systems.
  *
- * In the initial draft, the systems present are hard-coded, but they
- * will soon be configurable for individual aircraft.
+ * Multiple aircraft systems can be configured for each aircraft.
  */
 class FGSystemMgr : public SGSubsystemGroup
 {
@@ -31,6 +31,12 @@ public:
 
     FGSystemMgr ();
     virtual ~FGSystemMgr ();
+    bool build ();
+
+private:
+    SGPropertyNode *config_props;
+    bool enabled;
+
 };
 
 #endif // __SYSTEM_MGR_HXX
index 3e6311d60f399a0560abc9d1a8eb70ef76b56d85..bede8ed77cf716288527e2dd8e10118f88c93cd6 100644 (file)
@@ -7,9 +7,42 @@
 #include <Main/fg_props.hxx>
 
 
+VacuumSystem::VacuumSystem ( SGPropertyNode *node )
+    :
+    name("vacuum"),
+    num(0),
+    rpm("/engines/engine[0]/rpm"),
+    scale(1.0)
+
+{
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "name" ) {
+            name = cval;
+        } else if ( cname == "number" ) {
+            num = child->getIntValue();
+        } else if ( cname == "rpm" ) {
+            rpm = cval;
+        } else if ( cname == "scale" ) {
+            scale = child->getDoubleValue();
+        } else {
+            SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in vacuum config logic" );
+            if ( name.length() ) {
+                SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+            }
+        }
+    }
+}
+
 VacuumSystem::VacuumSystem( int i )
 {
+    name = "vacuum";
     num = i;
+    rpm = "/engines/engine[0]/rpm";
+    scale = 1.0;
 }
 
 VacuumSystem::~VacuumSystem ()
@@ -19,13 +52,16 @@ VacuumSystem::~VacuumSystem ()
 void
 VacuumSystem::init()
 {
-                                // TODO: allow index of engine to be
-                                // configured.
-    SGPropertyNode *node = fgGetNode("/systems/vacuum", num, true );
+    string branch;
+    branch = "/systems/" + name;
+
+    SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
     _serviceable_node = node->getChild("serviceable", 0, true);
-    _rpm_node = fgGetNode("/engines/engine[0]/rpm", true);
+    _rpm_node = fgGetNode(rpm.c_str(), true);
     _pressure_node = fgGetNode("/environment/pressure-inhg", true);
     _suction_node = node->getChild("suction-inhg", 0, true);
+
+    _serviceable_node->setBoolValue(true);
 }
 
 void
@@ -48,7 +84,7 @@ VacuumSystem::update (double dt)
     if (!_serviceable_node->getBoolValue()) {
         suction = 0.0;
     } else {
-        double rpm = _rpm_node->getDoubleValue();
+        double rpm = _rpm_node->getDoubleValue() * scale;
         double pressure = _pressure_node->getDoubleValue();
         // This magic formula yields about 4 inhg at 700 rpm
         suction = pressure * rpm / (rpm + 4875.0);
index a18036c77b2ffaa76b30c60a70795d6ec22c1fa8..d3034e16fb6b9037d24daf8c9cee0983571b992e 100644 (file)
  *
  * Input properties:
  *
- * /engines/engine[0]/rpm
+ * "rpm"
  * /environment/pressure-inhg
- * /systems/vacuum[0]/serviceable
+ * /systems/"name"/serviceable
  *
  * Output properties:
  *
- * /systems/vacuum[n]/suction-inhg
+ * /systems/"name"/suction-inhg
  */
 class VacuumSystem : public SGSubsystem
 {
 
 public:
 
+    VacuumSystem( SGPropertyNode *node );
     VacuumSystem( int i );
     virtual ~VacuumSystem ();
 
@@ -45,7 +46,10 @@ public:
 
 private:
 
+    string name;
     int num;
+    string rpm;
+    double scale;
     SGPropertyNode_ptr _serviceable_node;
     SGPropertyNode_ptr _rpm_node;
     SGPropertyNode_ptr _pressure_node;