From 677c3e3e9ab9598c40a23cc89f99235d618b3a6f Mon Sep 17 00:00:00 2001 From: david Date: Sat, 25 Jan 2003 19:49:27 +0000 Subject: [PATCH] Added a Gyro helper class to factor out some common code for managing a spinning gyro. Changed FGInstrumentMgr to inherit from FGSubsystemGroup, greatly simplifying the (already simple) class. I should probably rename this to FGInstrumentGroup or something similar, but not today. Added the gyroscopic turn indicator (part of the TC). --- src/Instrumentation/Makefile.am | 4 +- src/Instrumentation/attitude_indicator.cxx | 33 +++----- src/Instrumentation/attitude_indicator.hxx | 7 +- src/Instrumentation/gyro.cxx | 69 +++++++++++++++++ src/Instrumentation/gyro.hxx | 88 ++++++++++++++++++++++ src/Instrumentation/heading_indicator.cxx | 34 +++------ src/Instrumentation/heading_indicator.hxx | 5 +- src/Instrumentation/instrument_mgr.cxx | 48 ++---------- src/Instrumentation/instrument_mgr.hxx | 10 +-- src/Instrumentation/turn_indicator.cxx | 73 ++++++++++++++++++ src/Instrumentation/turn_indicator.hxx | 63 ++++++++++++++++ 11 files changed, 332 insertions(+), 102 deletions(-) create mode 100644 src/Instrumentation/gyro.cxx create mode 100644 src/Instrumentation/gyro.hxx create mode 100644 src/Instrumentation/turn_indicator.cxx create mode 100644 src/Instrumentation/turn_indicator.hxx diff --git a/src/Instrumentation/Makefile.am b/src/Instrumentation/Makefile.am index c21a11273..02eff900c 100644 --- a/src/Instrumentation/Makefile.am +++ b/src/Instrumentation/Makefile.am @@ -1,9 +1,11 @@ noinst_LIBRARIES = libInstrumentation.a libInstrumentation_a_SOURCES = instrument_mgr.cxx instrument_mgr.hxx \ + gyro.cxx gyro.hxx \ airspeed_indicator.cxx airspeed_indicator.hxx \ - altimeter.cxx altimeter.hxx \ attitude_indicator.cxx attitude_indicator.hxx \ + altimeter.cxx altimeter.hxx \ + turn_indicator.cxx turn_indicator.hxx \ heading_indicator.cxx heading_indicator.hxx \ vertical_speed_indicator.cxx vertical_speed_indicator.hxx diff --git a/src/Instrumentation/attitude_indicator.cxx b/src/Instrumentation/attitude_indicator.cxx index 5378e15ed..02a249e4c 100644 --- a/src/Instrumentation/attitude_indicator.cxx +++ b/src/Instrumentation/attitude_indicator.cxx @@ -24,9 +24,6 @@ AttitudeIndicator::init () { // TODO: allow index of pump and AI // to be configured. - _serviceable_node = - fgGetNode("/instrumentation/attitude-indicator/serviceable", true); - _spin_node = fgGetNode("/instrumentation/attitude-indicator/spin", 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); @@ -41,36 +38,26 @@ AttitudeIndicator::init () void AttitudeIndicator::bind () { + fgTie("/instrumentation/attitude-indicator/serviceable", + &_gyro, &Gyro::is_serviceable); + fgTie("/instrumentation/attitude-indicator/spin", + &_gyro, &Gyro::get_spin_norm, &Gyro::set_spin_norm); } void AttitudeIndicator::unbind () { + fgUntie("/instrumentation/attitude-indicator/serviceable"); + fgUntie("/instrumentation/attitude-indicator/spin"); } void AttitudeIndicator::update (double dt) { - // First, calculate the bogo-spin from 0 to 1. - // All numbers are made up. - - double spin = _spin_node->getDoubleValue(); - spin -= 0.005 * dt; // spin decays every 0.5% every second. - - // spin increases up to 25% every second - // if suction is available and the gauge - // is serviceable. - if (_serviceable_node->getBoolValue()) { - double suction = _suction_node->getDoubleValue(); - double step = 0.25 * (suction / 5.0) * dt; - if ((spin + step) <= (suction / 5.0)) - spin += step; - } - if (spin > 1.0) - spin = 1.0; - else if (spin < 0.0) - spin = 0.0; - _spin_node->setDoubleValue(spin); + // Get the spin from the gyro + _gyro.set_power_norm(_suction_node->getDoubleValue()/5.0); + _gyro.update(dt); + double spin = _gyro.get_spin_norm(); // Next, calculate the indicated roll // and pitch, introducing errors. diff --git a/src/Instrumentation/attitude_indicator.hxx b/src/Instrumentation/attitude_indicator.hxx index 26196eb03..32bc8b72f 100644 --- a/src/Instrumentation/attitude_indicator.hxx +++ b/src/Instrumentation/attitude_indicator.hxx @@ -14,6 +14,8 @@ #include #include
+#include "gyro.hxx" + /** * Model a vacuum-powered attitude indicator. @@ -23,7 +25,6 @@ * Input properties: * * /instrumentation/attitude-indicator/serviceable - * /instrumentation/attitude-indicator/spin * /orientation/pitch-deg * /orientation/roll-deg * /systems/vacuum[0]/suction-inhg @@ -48,8 +49,8 @@ public: private: - SGPropertyNode_ptr _serviceable_node; - SGPropertyNode_ptr _spin_node; + Gyro _gyro; + SGPropertyNode_ptr _pitch_in_node; SGPropertyNode_ptr _roll_in_node; SGPropertyNode_ptr _suction_node; diff --git a/src/Instrumentation/gyro.cxx b/src/Instrumentation/gyro.cxx new file mode 100644 index 000000000..3cb5b3152 --- /dev/null +++ b/src/Instrumentation/gyro.cxx @@ -0,0 +1,69 @@ +// gyro.cxx - simple implementation of a spinning gyro model. + +#include "gyro.hxx" + +Gyro::Gyro () + : _serviceable(true), + _power_norm(0.0), + _spin_norm(0.0) +{ +} + +Gyro::~Gyro () +{ +} + +void +Gyro::update (double delta_time_sec) +{ + // spin decays 0.5% every second + _spin_norm -= 0.005 * delta_time_sec; + + // power can increase spin by 25% + // every second, but only up to the + // level of power available + if (_serviceable) { + double step = 0.25 * _power_norm * delta_time_sec; + if ((_spin_norm + step) <= _power_norm) + _spin_norm += step; + } + + // clamp the spin to 0.0:1.0 + if (_spin_norm < 0.0) + _spin_norm = 0.0; + else if (_spin_norm > 1.0) + _spin_norm = 1.0; +} + +void +Gyro::set_power_norm (double power_norm) +{ + _power_norm = power_norm; +} + +double +Gyro::get_spin_norm () const +{ + return _spin_norm; +} + +void +Gyro::set_spin_norm (double spin_norm) +{ + _spin_norm = spin_norm; +} + +bool +Gyro::is_serviceable () const +{ + return _serviceable; +} + +void +Gyro::set_serviceable (bool serviceable) +{ + _serviceable = serviceable; +} + +// end of gyro.cxx + diff --git a/src/Instrumentation/gyro.hxx b/src/Instrumentation/gyro.hxx new file mode 100644 index 000000000..eee834cb6 --- /dev/null +++ b/src/Instrumentation/gyro.hxx @@ -0,0 +1,88 @@ +// gyro.hxx - simple model of a spinning gyro. + +#ifndef __INSTRUMENTATION_GYRO_HXX +#define __INSTRUMENTATION_GYRO_HXX 1 + +/** + * Simple model of a spinning gyro. + * + * The gyro decelerates gradually if no power is available to keep it + * spinning, and spins up quickly when power becomes available. + */ +class Gyro +{ +public: + + /** + * Constructor. + */ + Gyro (); + + + /** + * Destructor. + */ + virtual ~Gyro (); + + + /** + * Update the gyro. + * + * @param delta_time_sec The elapsed time since the last update. + * @param power_norm The power available to drive the gyro, from + * 0.0 to 1.0. + */ + virtual void update (double delta_time_sec); + + + /** + * Set the power available to the gyro. + * + * @param power_norm The amount of power (vacuum or electrical) + * available to keep the gyro spinning, from 0.0 (none) to + * 1.0 (full power) + */ + virtual void set_power_norm (double power_norm); + + + /** + * Get the gyro's current spin. + * + * @return The spin from 0.0 (not spinning) to 1.0 (full speed). + */ + virtual double get_spin_norm () const; + + + /** + * Set the gyro's current spin. + * + * @spin_norm The spin from 0.0 (not spinning) to 1.0 (full speed). + */ + virtual void set_spin_norm (double spin_norm); + + + /** + * Test if the gyro is serviceable. + * + * @return true if the gyro is serviceable, false otherwise. + */ + virtual bool is_serviceable () const; + + + /** + * Set the gyro's serviceability. + * + * @param serviceable true if the gyro is functional, false otherwise. + */ + virtual void set_serviceable (bool serviceable); + + +private: + + bool _serviceable; + double _power_norm; + double _spin_norm; + +}; + +#endif // __INSTRUMENTATION_GYRO_HXX diff --git a/src/Instrumentation/heading_indicator.cxx b/src/Instrumentation/heading_indicator.cxx index 5ca92fd6e..66fdd833c 100644 --- a/src/Instrumentation/heading_indicator.cxx +++ b/src/Instrumentation/heading_indicator.cxx @@ -19,10 +19,6 @@ HeadingIndicator::~HeadingIndicator () void HeadingIndicator::init () { - _serviceable_node = - fgGetNode("/instrumentation/heading-indicator/serviceable", true); - _spin_node = - fgGetNode("/instrumentation/heading-indicator/spin", true); _offset_node = fgGetNode("/instrumentation/heading-indicator/offset-deg", true); _heading_in_node = fgGetNode("/orientation/heading-deg", true); @@ -37,36 +33,26 @@ HeadingIndicator::init () void HeadingIndicator::bind () { + fgTie("/instrumentation/heading-indicator/serviceable", + &_gyro, &Gyro::is_serviceable); + fgTie("/instrumentation/heading-indicator/spin", + &_gyro, &Gyro::get_spin_norm, &Gyro::set_spin_norm); } void HeadingIndicator::unbind () { + fgUntie("/instrumentation/heading-indicator/serviceable"); + fgUntie("/instrumentation/heading-indicator/spin"); } void HeadingIndicator::update (double dt) { - // First, calculate the bogo-spin from 0 to 1. - // All numbers are made up. - - double spin = _spin_node->getDoubleValue(); - spin -= 0.005 * dt; // spin decays every 0.5% every second. - - // spin increases up to 25% every second - // if suction is available and the gauge - // is serviceable. - if (_serviceable_node->getBoolValue()) { - double suction = _suction_node->getDoubleValue(); - double step = 0.25 * (suction / 5.0) * dt; - if ((spin + step) <= (suction / 5.0)) - spin += step; - } - if (spin > 1.0) - spin = 1.0; - else if (spin < 0.0) - spin = 0.0; - _spin_node->setDoubleValue(spin); + // Get the spin from the gyro + _gyro.set_power_norm(_suction_node->getDoubleValue()/5.0); + _gyro.update(dt); + double spin = _gyro.get_spin_norm(); // Next, calculate time-based precession double offset = _offset_node->getDoubleValue(); diff --git a/src/Instrumentation/heading_indicator.hxx b/src/Instrumentation/heading_indicator.hxx index 7941010fa..90d62104c 100644 --- a/src/Instrumentation/heading_indicator.hxx +++ b/src/Instrumentation/heading_indicator.hxx @@ -14,6 +14,8 @@ #include #include
+#include "gyro.hxx" + /** * Model a vacuum-powered heading indicator. @@ -47,10 +49,9 @@ public: private: + Gyro _gyro; double _last_heading_deg; - SGPropertyNode_ptr _serviceable_node; - SGPropertyNode_ptr _spin_node; 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 38504df7a..410245cb7 100644 --- a/src/Instrumentation/instrument_mgr.cxx +++ b/src/Instrumentation/instrument_mgr.cxx @@ -6,57 +6,25 @@ #include "instrument_mgr.hxx" #include "airspeed_indicator.hxx" -#include "altimeter.hxx" #include "attitude_indicator.hxx" +#include "altimeter.hxx" +#include "turn_indicator.hxx" #include "heading_indicator.hxx" #include "vertical_speed_indicator.hxx" FGInstrumentMgr::FGInstrumentMgr () { - // NO-OP + set_subsystem("asi", new AirspeedIndicator); + set_subsystem("ai", new AttitudeIndicator); + set_subsystem("alt", new Altimeter); + set_subsystem("ti", new TurnIndicator); + set_subsystem("hi", new HeadingIndicator); + set_subsystem("vsi", new VerticalSpeedIndicator); } FGInstrumentMgr::~FGInstrumentMgr () { - for (unsigned int i = 0; i < _instruments.size(); i++) { - delete _instruments[i]; - _instruments[i] = 0; - } -} - -void -FGInstrumentMgr::init () -{ - // TODO: replace with XML configuration - _instruments.push_back(new AirspeedIndicator); - _instruments.push_back(new Altimeter); - _instruments.push_back(new AttitudeIndicator); - _instruments.push_back(new HeadingIndicator); - _instruments.push_back(new VerticalSpeedIndicator); - - // Initialize the individual instruments - for (unsigned int i = 0; i < _instruments.size(); i++) - _instruments[i]->init(); -} - -void -FGInstrumentMgr::bind () -{ - // NO-OP -} - -void -FGInstrumentMgr::unbind () -{ - // NO-OP -} - -void -FGInstrumentMgr::update (double dt) -{ - for (unsigned int i = 0; i < _instruments.size(); i++) - _instruments[i]->update(dt); } // end of instrument_manager.cxx diff --git a/src/Instrumentation/instrument_mgr.hxx b/src/Instrumentation/instrument_mgr.hxx index 6e0bf4d12..68a229404 100644 --- a/src/Instrumentation/instrument_mgr.hxx +++ b/src/Instrumentation/instrument_mgr.hxx @@ -30,21 +30,13 @@ SG_USING_STD(vector); * In the initial draft, the instruments present are hard-coded, but they * will soon be configurable for individual aircraft. */ -class FGInstrumentMgr : public FGSubsystem +class FGInstrumentMgr : public FGSubsystemGroup { public: FGInstrumentMgr (); virtual ~FGInstrumentMgr (); - virtual void init (); - virtual void bind (); - virtual void unbind (); - virtual void update (double dt); - -private: - vector _instruments; - }; #endif // __INSTRUMENT_MGR_HXX diff --git a/src/Instrumentation/turn_indicator.cxx b/src/Instrumentation/turn_indicator.cxx new file mode 100644 index 000000000..5e0523974 --- /dev/null +++ b/src/Instrumentation/turn_indicator.cxx @@ -0,0 +1,73 @@ +// turn_indicator.cxx - an electric-powered turn indicator. +// Written by David Megginson, started 2003. +// +// This file is in the Public Domain and comes with no warranty. + +#include "turn_indicator.hxx" +#include
+#include
+ + +TurnIndicator::TurnIndicator () +{ +} + +TurnIndicator::~TurnIndicator () +{ +} + +void +TurnIndicator::init () +{ + _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); +} + +void +TurnIndicator::bind () +{ + fgTie("/instrumentation/turn-indicator/serviceable", + &_gyro, &Gyro::is_serviceable); + fgTie("/instrumentation/turn-indicator/spin", + &_gyro, &Gyro::get_spin_norm, &Gyro::set_spin_norm); +} + +void +TurnIndicator::unbind () +{ + fgUntie("/instrumentation/turn-indicator/serviceable"); + fgUntie("/instrumentation/turn-indicator/spin"); +} + +void +TurnIndicator::update (double dt) +{ + // Get the spin from the gyro + _gyro.set_power_norm(_electric_current_node->getDoubleValue()/60.0); + _gyro.update(dt); + double spin = _gyro.get_spin_norm(); + + // Calculate the indicated rate + double factor = 1.0 - ((1.0 - spin) * (1.0 - spin) * (1.0 - spin)); + double rate = ((_roll_rate_node->getDoubleValue() / 20.0) + + (_yaw_rate_node->getDoubleValue() / 3.0)); + + // Clamp the rate + if (rate < -2.5) + rate = -2.5; + else if (rate > 2.5) + rate = 2.5; + + // Add a lag, based on gyro spin + rate = fgGetLowPass(_last_rate, rate, dt/(factor*3)); + _last_rate = rate; + + // Publish the indicated rate + _rate_out_node->setDoubleValue(rate); +} + +// end of turn_indicator.cxx diff --git a/src/Instrumentation/turn_indicator.hxx b/src/Instrumentation/turn_indicator.hxx new file mode 100644 index 000000000..e730f7476 --- /dev/null +++ b/src/Instrumentation/turn_indicator.hxx @@ -0,0 +1,63 @@ +// turn_indicator.hxx - an electric-powered turn indicator. +// Written by David Megginson, started 2003. +// +// This file is in the Public Domain and comes with no warranty. + + +#ifndef __INSTRUMENTS_TURN_INDICATOR_HXX +#define __INSTRUMENTS_TURN_INDICATOR_HXX 1 + +#ifndef __cplusplus +# error This library requires C++ +#endif + +#include +#include
+ +#include "gyro.hxx" + + +/** + * Model an electric-powered turn indicator. + * + * This class does not model the slip/skid ball; that is properly + * a separate instrument. + * + * Input properties: + * + * /instrumentation/turn-indicator/serviceable + * /instrumentation/turn-indicator/spin + * /orientation/roll-rate-degps + * /orientation/yaw-rate-degps + * /systems/electrical/outputs/turn-coordinator + * + * Output properties: + * + * /instrumentation/turn-indicator/indicated-turn-rate + */ +class TurnIndicator : public FGSubsystem +{ + +public: + + TurnIndicator (); + virtual ~TurnIndicator (); + + virtual void init (); + virtual void bind (); + virtual void unbind (); + virtual void update (double dt); + +private: + + Gyro _gyro; + double _last_rate; + + SGPropertyNode_ptr _roll_rate_node; + SGPropertyNode_ptr _yaw_rate_node; + SGPropertyNode_ptr _electric_current_node; + SGPropertyNode_ptr _rate_out_node; + +}; + +#endif // __INSTRUMENTS_TURN_INDICATOR_HXX -- 2.39.5