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).
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
{
// 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);
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.
#include <simgear/misc/props.hxx>
#include <Main/fgfs.hxx>
+#include "gyro.hxx"
+
/**
* Model a vacuum-powered attitude indicator.
* Input properties:
*
* /instrumentation/attitude-indicator/serviceable
- * /instrumentation/attitude-indicator/spin
* /orientation/pitch-deg
* /orientation/roll-deg
* /systems/vacuum[0]/suction-inhg
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;
--- /dev/null
+// 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
+
--- /dev/null
+// 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
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);
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();
#include <simgear/misc/props.hxx>
#include <Main/fgfs.hxx>
+#include "gyro.hxx"
+
/**
* Model a vacuum-powered heading indicator.
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;
#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
* 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<FGSubsystem *> _instruments;
-
};
#endif // __INSTRUMENT_MGR_HXX
--- /dev/null
+// 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 <Main/fg_props.hxx>
+#include <Main/util.hxx>
+
+
+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
--- /dev/null
+// 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 <simgear/misc/props.hxx>
+#include <Main/fgfs.hxx>
+
+#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