#ifndef _XMLAUTO_HXX
#define _XMLAUTO_HXX 1
-#ifndef __cplusplus
-# error This library requires C++
-#endif
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
#include <simgear/compiler.h>
#include <string>
#include <vector>
#include <deque>
-using std::string;
-using std::vector;
-using std::deque;
-
#include <simgear/props/props.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/props/condition.hxx>
-#include <Main/fg_props.hxx>
+typedef SGSharedPtr<class FGXMLAutoInput> FGXMLAutoInput_ptr;
+typedef SGSharedPtr<class FGPeriodicalValue> FGPeriodicalValue_ptr;
+class FGPeriodicalValue : public SGReferenced {
+private:
+ FGXMLAutoInput_ptr minPeriod; // The minimum value of the period
+ FGXMLAutoInput_ptr maxPeriod; // The maximum value of the period
+public:
+ FGPeriodicalValue( SGPropertyNode_ptr node );
+ double normalize( double value );
+};
-class FGXMLAutoInput {
+class FGXMLAutoInput : public SGReferenced {
private:
- SGPropertyNode_ptr property; // The name of the property containing the value
double value; // The value as a constant or initializer for the property
- double offset; // A fixed offset
- double scale; // A constant scaling factor
+ bool abs; // return absolute value
+ SGPropertyNode_ptr property; // The name of the property containing the value
+ FGXMLAutoInput_ptr offset; // A fixed offset, defaults to zero
+ FGXMLAutoInput_ptr scale; // A constant scaling factor defaults to one
+ FGXMLAutoInput_ptr min; // A minimum clip defaults to no clipping
+ FGXMLAutoInput_ptr max; // A maximum clip defaults to no clipping
+ FGPeriodicalValue_ptr periodical; //
+ SGSharedPtr<const SGCondition> _condition;
public:
- FGXMLAutoInput() :
- property(NULL),
- value(0.0),
- offset(0.0),
- scale(1.0) {}
-
- void parse( SGPropertyNode_ptr, double value = 0.0, double offset = 0.0, double scale = 1.0 );
- inline double getValue() {
- if( property != NULL ) value = property->getDoubleValue();
- return value * scale + offset;
+ FGXMLAutoInput( SGPropertyNode_ptr node = NULL, double value = 0.0, double offset = 0.0, double scale = 1.0 );
+
+ void parse( SGPropertyNode_ptr, double value = 0.0, double offset = 0.0, double scale = 1.0 );
+
+ /* get the value of this input, apply scale and offset and clipping */
+ double get_value();
+
+ /* set the input value after applying offset and scale */
+ void set_value( double value );
+
+ inline double get_scale() {
+ return scale == NULL ? 1.0 : scale->get_value();
+ }
+
+ inline double get_offset() {
+ return offset == NULL ? 0.0 : offset->get_value();
+ }
+
+ inline bool is_enabled() {
+ return _condition == NULL ? true : _condition->test();
+ }
+
+};
+
+class FGXMLAutoInputList : public std::vector<FGXMLAutoInput_ptr> {
+ public:
+ FGXMLAutoInput_ptr get_active() {
+ for (iterator it = begin(); it != end(); ++it) {
+ if( (*it)->is_enabled() )
+ return *it;
+ }
+ return NULL;
+ }
+
+ double get_value( double def = 0.0 ) {
+ FGXMLAutoInput_ptr input = get_active();
+ return input == NULL ? def : input->get_value();
}
+
};
/**
class FGXMLAutoComponent : public SGReferenced {
private:
- bool clamp;
- vector <SGPropertyNode_ptr> output_list;
+ std::vector <SGPropertyNode_ptr> output_list;
SGSharedPtr<const SGCondition> _condition;
SGPropertyNode_ptr enable_prop;
- string * enable_value;
+ std::string * enable_value;
SGPropertyNode_ptr passive_mode;
bool honor_passive;
- string name;
-protected:
+ std::string name;
+
+ /* Feed back output property to input property if
+ this filter is disabled. This is for multi-stage
+ filter where one filter sits behind a pid-controller
+ to provide changes of the overall output to the pid-
+ controller.
+ feedback is disabled by default.
+ */
+ bool feedback_if_disabled;
+ void do_feedback_if_disabled();
- FGXMLAutoInput valueInput;
- FGXMLAutoInput referenceInput;
- FGXMLAutoInput uminInput;
- FGXMLAutoInput umaxInput;
+protected:
+ FGXMLAutoComponent();
+
+ /*
+ * Parse a component specification read from a property-list.
+ * Calls the hook methods below to allow derived classes to
+ * specialise parsing bevaiour.
+ */
+ void parseNode(SGPropertyNode* aNode);
+
+ /**
+ * Helper to parse the config section
+ */
+ void parseConfig(SGPropertyNode* aConfig);
+
+ /*
+ * Over-rideable hook method to allow derived classes to refine top-level
+ * node parsing. Return true if the node was handled, false otherwise.
+ */
+ virtual bool parseNodeHook(const std::string& aName, SGPropertyNode* aNode);
+
+ /**
+ * Over-rideable hook method to allow derived classes to refine config
+ * node parsing. Return true if the node was handled, false otherwise.
+ */
+ virtual bool parseConfigHook(const std::string& aName, SGPropertyNode* aNode);
+
+ FGXMLAutoInputList valueInput;
+ FGXMLAutoInputList referenceInput;
+ FGXMLAutoInputList uminInput;
+ FGXMLAutoInputList umaxInput;
+ FGPeriodicalValue_ptr periodical;
// debug flag
bool debug;
bool enabled;
-public:
+
+ inline void do_feedback() {
+ if( feedback_if_disabled ) do_feedback_if_disabled();
+ }
- FGXMLAutoComponent( SGPropertyNode *node);
+public:
+
virtual ~FGXMLAutoComponent();
virtual void update (double dt)=0;
- inline const string& get_name() { return name; }
-
- inline double Clamp( double value ) {
- if( clamp ) {
- double d = umaxInput.getValue();
- if( value > d ) value = d;
- d = uminInput.getValue();
- if( value < d ) value = d;
- }
- return value;
- }
+ inline const std::string& get_name() { return name; }
- inline void setOutputValue( double value ) {
+ double clamp( double value );
+
+ inline void set_output_value( double value ) {
// passive_ignore == true means that we go through all the
// motions, but drive the outputs. This is analogous to
// running the autopilot with the "servos" off. This is
// helpful for things like flight directors which position
// their vbars from the autopilot computations.
if ( honor_passive && passive_mode->getBoolValue() ) return;
- for ( unsigned i = 0; i < output_list.size(); ++i ) {
- output_list[i]->setDoubleValue( Clamp(value) );
- }
+ for( std::vector <SGPropertyNode_ptr>::iterator it = output_list.begin(); it != output_list.end(); ++it)
+ (*it)->setDoubleValue( clamp( value ) );
}
- inline double getOutputValue() {
- return output_list.size() == 0 ? 0.0 : Clamp(output_list[0]->getDoubleValue());
+ inline double get_output_value() {
+ return output_list.size() == 0 ? 0.0 : clamp(output_list[0]->getDoubleValue());
}
/*
bool isPropertyEnabled();
};
+typedef SGSharedPtr<FGXMLAutoComponent> FGXMLAutoComponent_ptr;
+
/**
* Roy Ovesen's PID controller
// Configuration values
- FGXMLAutoInput Kp; // proportional gain
- FGXMLAutoInput Ti; // Integrator time (sec)
- FGXMLAutoInput Td; // Derivator time (sec)
+ FGXMLAutoInputList Kp; // proportional gain
+ FGXMLAutoInputList Ti; // Integrator time (sec)
+ FGXMLAutoInputList Td; // Derivator time (sec)
double alpha; // low pass filter weighing factor (usually 0.1)
double beta; // process value weighing factor for
double desiredTs; // desired sampling interval (sec)
double elapsedTime; // elapsed time (sec)
-
+
+protected:
+ bool parseConfigHook(const std::string& aName, SGPropertyNode* aNode);
public:
FGPIDController( SGPropertyNode *node, bool old );
~FGPIDController() {}
- void update_old( double dt );
void update( double dt );
};
private:
// proportional component data
- FGXMLAutoInput Kp;
+ FGXMLAutoInputList Kp;
// integral component data
- FGXMLAutoInput Ki;
+ FGXMLAutoInputList Ki;
double int_sum;
+protected:
+ bool parseConfigHook(const std::string& aName, SGPropertyNode* aNode);
public:
class FGPredictor : public FGXMLAutoComponent {
private:
-
- // proportional component data
double last_value;
double average;
- double seconds;
- double filter_gain;
+ FGXMLAutoInputList seconds;
+ FGXMLAutoInputList filter_gain;
- // Input values
- double ivalue; // input value
-
-public:
+protected:
+ bool parseNodeHook(const std::string& aName, SGPropertyNode* aNode);
+public:
FGPredictor( SGPropertyNode *node );
~FGPredictor() {}
class FGDigitalFilter : public FGXMLAutoComponent
{
private:
- FGXMLAutoInput samplesInput; // Number of input samples to average
- FGXMLAutoInput rateOfChangeInput; // The maximum allowable rate of change [1/s]
- FGXMLAutoInput gainInput; //
- FGXMLAutoInput TfInput; // Filter time [s]
+ FGXMLAutoInputList samplesInput; // Number of input samples to average
+ FGXMLAutoInputList rateOfChangeInput; // The maximum allowable rate of change [1/s]
+ FGXMLAutoInputList gainInput; //
+ FGXMLAutoInputList TfInput; // Filter time [s]
- deque <double> output;
- deque <double> input;
+ std::deque <double> output;
+ std::deque <double> input;
enum filterTypes { exponential, doubleExponential, movingAverage,
- noiseSpike, gain, reciprocal };
+ noiseSpike, gain, reciprocal, differential, none };
filterTypes filterType;
+protected:
+ bool parseNodeHook(const std::string& aName, SGPropertyNode* aNode);
+
public:
FGDigitalFilter(SGPropertyNode *node);
~FGDigitalFilter() {}
*
*/
+class FGXMLAutopilotGroup : public SGSubsystemGroup
+{
+public:
+ FGXMLAutopilotGroup();
+ void init();
+ void reinit();
+ void update( double dt );
+private:
+ std::vector<std::string> _autopilotNames;
+
+ double average;
+ double v_last;
+ double last_static_pressure;
+
+ SGPropertyNode_ptr vel;
+ SGPropertyNode_ptr lookahead5;
+ SGPropertyNode_ptr lookahead10;
+ SGPropertyNode_ptr bug;
+ SGPropertyNode_ptr mag_hdg;
+ SGPropertyNode_ptr bug_error;
+ SGPropertyNode_ptr fdm_bug_error;
+ SGPropertyNode_ptr target_true;
+ SGPropertyNode_ptr true_hdg;
+ SGPropertyNode_ptr true_error;
+ SGPropertyNode_ptr target_nav1;
+ SGPropertyNode_ptr true_nav1;
+ SGPropertyNode_ptr true_track_nav1;
+ SGPropertyNode_ptr nav1_course_error;
+ SGPropertyNode_ptr nav1_selected_course;
+ SGPropertyNode_ptr vs_fps;
+ SGPropertyNode_ptr vs_fpm;
+ SGPropertyNode_ptr static_pressure;
+ SGPropertyNode_ptr pressure_rate;
+ SGPropertyNode_ptr track;
+};
+
class FGXMLAutopilot : public SGSubsystem
{
void unbind();
void update( double dt );
- bool build();
+ bool build( SGPropertyNode_ptr );
protected:
-
- typedef vector<SGSharedPtr<FGXMLAutoComponent> > comp_list;
+ typedef std::vector<FGXMLAutoComponent_ptr> comp_list;
private:
-
bool serviceable;
- SGPropertyNode_ptr config_props;
comp_list components;
+
};