From f614545fc5a6f0fb12a05344d9ee41b2a49cc04a Mon Sep 17 00:00:00 2001 From: ehofman Date: Sat, 16 Oct 2004 12:37:39 +0000 Subject: [PATCH] Roy Vegard Ovesen: 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. --- src/Instrumentation/adf.cxx | 92 +++++-- src/Instrumentation/adf.hxx | 5 + src/Instrumentation/airspeed_indicator.cxx | 59 ++++- src/Instrumentation/airspeed_indicator.hxx | 15 +- src/Instrumentation/altimeter.cxx | 51 +++- src/Instrumentation/altimeter.hxx | 13 +- src/Instrumentation/attitude_indicator.cxx | 81 ++++-- src/Instrumentation/attitude_indicator.hxx | 23 +- src/Instrumentation/clock.cxx | 43 +++- src/Instrumentation/clock.hxx | 4 + src/Instrumentation/dme.cxx | 60 ++++- src/Instrumentation/dme.hxx | 18 +- src/Instrumentation/gps.cxx | 240 +++++++++++------- src/Instrumentation/gps.hxx | 11 + src/Instrumentation/heading_indicator.cxx | 56 +++- src/Instrumentation/heading_indicator.hxx | 17 +- src/Instrumentation/instrument_mgr.cxx | 129 +++++++++- src/Instrumentation/instrument_mgr.hxx | 5 + src/Instrumentation/mag_compass.cxx | 37 ++- src/Instrumentation/mag_compass.hxx | 8 +- src/Instrumentation/slip_skid_ball.cxx | 38 ++- src/Instrumentation/slip_skid_ball.hxx | 8 +- src/Instrumentation/turn_indicator.cxx | 47 +++- src/Instrumentation/turn_indicator.hxx | 10 +- .../vertical_speed_indicator.cxx | 43 +++- .../vertical_speed_indicator.hxx | 11 +- src/Systems/pitot.cxx | 39 ++- src/Systems/pitot.hxx | 14 +- src/Systems/static.cxx | 37 ++- src/Systems/static.hxx | 11 +- src/Systems/system_mgr.cxx | 80 +++++- src/Systems/system_mgr.hxx | 10 +- src/Systems/vacuum.cxx | 46 +++- src/Systems/vacuum.hxx | 10 +- 34 files changed, 1079 insertions(+), 292 deletions(-) diff --git a/src/Instrumentation/adf.cxx b/src/Instrumentation/adf.cxx index 83757887d..e6d02a140 100644 --- a/src/Instrumentation/adf.cxx +++ b/src/Instrumentation/adf.cxx @@ -13,6 +13,10 @@ #include "adf.hxx" +#include +#include +#include + // 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; diff --git a/src/Instrumentation/adf.hxx b/src/Instrumentation/adf.hxx index f897cb5e4..6f584803c 100644 --- a/src/Instrumentation/adf.hxx +++ b/src/Instrumentation/adf.hxx @@ -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; }; diff --git a/src/Instrumentation/airspeed_indicator.cxx b/src/Instrumentation/airspeed_indicator.cxx index 2b80fbd96..cbdd75902 100644 --- a/src/Instrumentation/airspeed_indicator.cxx +++ b/src/Instrumentation/airspeed_indicator.cxx @@ -15,9 +15,44 @@ // 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 diff --git a/src/Instrumentation/airspeed_indicator.hxx b/src/Instrumentation/airspeed_indicator.hxx index 0572a0eb1..6f10b9ddb 100644 --- a/src/Instrumentation/airspeed_indicator.hxx +++ b/src/Instrumentation/airspeed_indicator.hxx @@ -20,21 +20,22 @@ * * 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; diff --git a/src/Instrumentation/altimeter.cxx b/src/Instrumentation/altimeter.cxx index 2a9578705..39a0c105d 100644 --- a/src/Instrumentation/altimeter.cxx +++ b/src/Instrumentation/altimeter.cxx @@ -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 diff --git a/src/Instrumentation/altimeter.hxx b/src/Instrumentation/altimeter.hxx index 73c1c2c02..f75c207bd 100644 --- a/src/Instrumentation/altimeter.hxx +++ b/src/Instrumentation/altimeter.hxx @@ -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; diff --git a/src/Instrumentation/attitude_indicator.cxx b/src/Instrumentation/attitude_indicator.cxx index a6cdfba26..82cb4c6a0 100644 --- a/src/Instrumentation/attitude_indicator.cxx +++ b/src/Instrumentation/attitude_indicator.cxx @@ -13,6 +13,32 @@ #include
+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 diff --git a/src/Instrumentation/attitude_indicator.hxx b/src/Instrumentation/attitude_indicator.hxx index b71e742c2..1895760ad 100644 --- a/src/Instrumentation/attitude_indicator.hxx +++ b/src/Instrumentation/attitude_indicator.hxx @@ -20,29 +20,28 @@ /** * 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; diff --git a/src/Instrumentation/clock.cxx b/src/Instrumentation/clock.cxx index 994c357c0..6f1db3e39 100644 --- a/src/Instrumentation/clock.cxx +++ b/src/Instrumentation/clock.cxx @@ -12,6 +12,35 @@ #include
+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 diff --git a/src/Instrumentation/clock.hxx b/src/Instrumentation/clock.hxx index 0e35f0441..44e734406 100644 --- a/src/Instrumentation/clock.hxx +++ b/src/Instrumentation/clock.hxx @@ -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; diff --git a/src/Instrumentation/dme.cxx b/src/Instrumentation/dme.cxx index 5aea2a8ba..272d40763 100644 --- a/src/Instrumentation/dme.cxx +++ b/src/Instrumentation/dme.cxx @@ -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); } diff --git a/src/Instrumentation/dme.hxx b/src/Instrumentation/dme.hxx index 2604b831d..1fc5781c6 100644 --- a/src/Instrumentation/dme.hxx +++ b/src/Instrumentation/dme.hxx @@ -25,22 +25,23 @@ * /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; + }; diff --git a/src/Instrumentation/gps.cxx b/src/Instrumentation/gps.cxx index 847d6a2e8..9e2e9cdf4 100644 --- a/src/Instrumentation/gps.cxx +++ b/src/Instrumentation/gps.cxx @@ -27,6 +27,31 @@ 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); diff --git a/src/Instrumentation/gps.hxx b/src/Instrumentation/gps.hxx index c28c26d3a..fabf4e776 100644 --- a/src/Instrumentation/gps.hxx +++ b/src/Instrumentation/gps.hxx @@ -12,6 +12,7 @@ #endif #include +#include #include @@ -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; + }; diff --git a/src/Instrumentation/heading_indicator.cxx b/src/Instrumentation/heading_indicator.cxx index 8f323366a..beeef54e9 100644 --- a/src/Instrumentation/heading_indicator.cxx +++ b/src/Instrumentation/heading_indicator.cxx @@ -8,6 +8,32 @@ #include
+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 diff --git a/src/Instrumentation/heading_indicator.hxx b/src/Instrumentation/heading_indicator.hxx index 75b1bc5c3..4ba772d22 100644 --- a/src/Instrumentation/heading_indicator.hxx +++ b/src/Instrumentation/heading_indicator.hxx @@ -20,25 +20,24 @@ /** * 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; diff --git a/src/Instrumentation/instrument_mgr.cxx b/src/Instrumentation/instrument_mgr.cxx index b9f4c359b..c59426d42 100644 --- a/src/Instrumentation/instrument_mgr.cxx +++ b/src/Instrumentation/instrument_mgr.cxx @@ -3,6 +3,17 @@ // // This file is in the Public Domain and comes with no warranty. +#include +#include +#include + +#include +#include +#include + +#include
+#include
+#include
#include "instrument_mgr.hxx" #include "airspeed_indicator.hxx" @@ -23,23 +34,117 @@ 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 diff --git a/src/Instrumentation/instrument_mgr.hxx b/src/Instrumentation/instrument_mgr.hxx index 11649adab..88a9c8bed 100644 --- a/src/Instrumentation/instrument_mgr.hxx +++ b/src/Instrumentation/instrument_mgr.hxx @@ -31,6 +31,11 @@ public: FGInstrumentMgr (); virtual ~FGInstrumentMgr (); + bool build (); + +private: + SGPropertyNode *config_props; + bool enabled; }; diff --git a/src/Instrumentation/mag_compass.cxx b/src/Instrumentation/mag_compass.cxx index 3ef4be2ee..378dd4bdd 100644 --- a/src/Instrumentation/mag_compass.cxx +++ b/src/Instrumentation/mag_compass.cxx @@ -17,6 +17,30 @@ #include
+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 diff --git a/src/Instrumentation/mag_compass.hxx b/src/Instrumentation/mag_compass.hxx index 8f7aafe27..5bc176e02 100644 --- a/src/Instrumentation/mag_compass.hxx +++ b/src/Instrumentation/mag_compass.hxx @@ -20,7 +20,7 @@ * * Input properties: * - * /instrumentation/magnetic-compass/serviceable + * /instrumentation/"name"/serviceable * /orientation/heading-deg * /orientation/beta-deg * /environment/magnetic-variation-deg @@ -31,13 +31,14 @@ * * 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; diff --git a/src/Instrumentation/slip_skid_ball.cxx b/src/Instrumentation/slip_skid_ball.cxx index 9ebff9ba7..d0ec8886f 100644 --- a/src/Instrumentation/slip_skid_ball.cxx +++ b/src/Instrumentation/slip_skid_ball.cxx @@ -8,6 +8,29 @@ #include
+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 diff --git a/src/Instrumentation/slip_skid_ball.hxx b/src/Instrumentation/slip_skid_ball.hxx index 4c11c1df5..7266cdfce 100644 --- a/src/Instrumentation/slip_skid_ball.hxx +++ b/src/Instrumentation/slip_skid_ball.hxx @@ -22,19 +22,20 @@ * * 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; diff --git a/src/Instrumentation/turn_indicator.cxx b/src/Instrumentation/turn_indicator.cxx index 1edb0bb4d..26b3c8f69 100644 --- a/src/Instrumentation/turn_indicator.cxx +++ b/src/Instrumentation/turn_indicator.cxx @@ -13,6 +13,29 @@ #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 diff --git a/src/Instrumentation/turn_indicator.hxx b/src/Instrumentation/turn_indicator.hxx index 5d5028cf1..d1b2a2917 100644 --- a/src/Instrumentation/turn_indicator.hxx +++ b/src/Instrumentation/turn_indicator.hxx @@ -25,21 +25,22 @@ * * 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; diff --git a/src/Instrumentation/vertical_speed_indicator.cxx b/src/Instrumentation/vertical_speed_indicator.cxx index 11f72fa45..72ff151f4 100644 --- a/src/Instrumentation/vertical_speed_indicator.cxx +++ b/src/Instrumentation/vertical_speed_indicator.cxx @@ -10,6 +10,32 @@ #include
+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(); } diff --git a/src/Instrumentation/vertical_speed_indicator.hxx b/src/Instrumentation/vertical_speed_indicator.hxx index f7df642e8..0c2a5a3a9 100644 --- a/src/Instrumentation/vertical_speed_indicator.hxx +++ b/src/Instrumentation/vertical_speed_indicator.hxx @@ -20,18 +20,19 @@ * * 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; diff --git a/src/Systems/pitot.cxx b/src/Systems/pitot.cxx index 5cfc6188b..71b27fc7a 100644 --- a/src/Systems/pitot.cxx +++ b/src/Systems/pitot.cxx @@ -8,8 +8,34 @@ #include
-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 diff --git a/src/Systems/pitot.hxx b/src/Systems/pitot.hxx index 80be710f0..e606fe4e6 100644 --- a/src/Systems/pitot.hxx +++ b/src/Systems/pitot.hxx @@ -11,6 +11,11 @@ # error This library requires C++ #endif +#include + +#include STL_STRING +SG_USING_STD(string); + #include #include @@ -23,21 +28,22 @@ * * 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; diff --git a/src/Systems/static.cxx b/src/Systems/static.cxx index 866845bef..bac6ddf25 100644 --- a/src/Systems/static.cxx +++ b/src/Systems/static.cxx @@ -8,8 +8,33 @@ #include
-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 diff --git a/src/Systems/static.hxx b/src/Systems/static.hxx index 56a0a4ed1..fcacd925b 100644 --- a/src/Systems/static.hxx +++ b/src/Systems/static.hxx @@ -21,13 +21,13 @@ * 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; diff --git a/src/Systems/system_mgr.cxx b/src/Systems/system_mgr.cxx index fbd6ee6a0..21bf3f5cf 100644 --- a/src/Systems/system_mgr.cxx +++ b/src/Systems/system_mgr.cxx @@ -3,6 +3,17 @@ // // This file is in the Public Domain and comes with no warranty. +#include +#include +#include + +#include
+#include
+#include
+ +#include +#include +#include #include "system_mgr.hxx" #include "electrical.hxx" @@ -15,15 +26,76 @@ 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 diff --git a/src/Systems/system_mgr.hxx b/src/Systems/system_mgr.hxx index 02c102a7e..e783532e2 100644 --- a/src/Systems/system_mgr.hxx +++ b/src/Systems/system_mgr.hxx @@ -16,14 +16,14 @@ #endif #include +#include #include /** * 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 diff --git a/src/Systems/vacuum.cxx b/src/Systems/vacuum.cxx index 3e6311d60..bede8ed77 100644 --- a/src/Systems/vacuum.cxx +++ b/src/Systems/vacuum.cxx @@ -7,9 +7,42 @@ #include
+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); diff --git a/src/Systems/vacuum.hxx b/src/Systems/vacuum.hxx index a18036c77..d3034e16f 100644 --- a/src/Systems/vacuum.hxx +++ b/src/Systems/vacuum.hxx @@ -22,19 +22,20 @@ * * 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; -- 2.39.5