]> git.mxchange.org Git - flightgear.git/blobdiff - src/Autopilot/xmlauto.hxx
Merge branch 'timoore/fire-fix'
[flightgear.git] / src / Autopilot / xmlauto.hxx
index a09b73a2ac1312bfb300d541ff80bffc918495d5..a29d49e236b827f86030bc01e1cb200d694ccced 100644 (file)
 #ifndef _XMLAUTO_HXX
 #define _XMLAUTO_HXX 1
 
-#ifndef __cplusplus
-# error This library requires C++
-#endif
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
+/* 
+Torsten Dreyer:
+I'd like to deprecate the so called autopilot helper function
+(which is now part of the AutopilotGroup::update() method).
+Every property calculated within this helper can be calculated
+using filters defined in an external autopilot definition file.
+The complete set of calculations may be extracted into a separate
+configuration file. The current implementation is able to hande 
+multiple config files and autopilots. The helper doubles code
+and writes properties used only by a few aircraft.
+*/
+// FIXME: this should go into config.h and/or configure
+// or removed along with the "helper" one day.
+#define XMLAUTO_USEHELPER
 
 #include <simgear/compiler.h>
 
-#include STL_STRING
+#include <string>
 #include <vector>
 #include <deque>
 
-SG_USING_STD(string);
-SG_USING_STD(vector);
-SG_USING_STD(deque);
-
 #include <simgear/props/props.hxx>
 #include <simgear/structure/subsystem_mgr.hxx>
+#include <simgear/props/condition.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 : public SGReferenced {
+private:
+     double             value;    // The value as a constant or initializer for the property
+     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;
 
-#include <Main/fg_props.hxx>
+public:
+    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();
+    }
+
+};
 
 /**
  * Base class for other autopilot components
  */
 
-class FGXMLAutoComponent {
+class FGXMLAutoComponent : public SGReferenced {
 
-protected:
-
-    string name;
+private:
+    simgear::PropertyList output_list;
 
+    SGSharedPtr<const SGCondition> _condition;
     SGPropertyNode_ptr enable_prop;
+    std::string * enable_value;
+
     SGPropertyNode_ptr passive_mode;
-    string enable_value;
     bool honor_passive;
-    bool enabled;
 
-    SGPropertyNode_ptr input_prop;
-    SGPropertyNode_ptr r_n_prop;
-    double r_n_value;
-    vector <SGPropertyNode_ptr> output_list;
+    std::string name;
 
-public:
+    /* 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();
+
+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;
 
-    FGXMLAutoComponent() :
-      enable_prop( NULL ),
-      passive_mode( fgGetNode("/autopilot/locks/passive-mode", true) ),
-      enable_value( "" ),
-      honor_passive( false ),
-      enabled( false ),
-      input_prop( NULL ),
-      r_n_prop( NULL ),
-      r_n_value( 0.0 )
-    { }
+    
+    inline void do_feedback() {
+        if( feedback_if_disabled ) do_feedback_if_disabled();
+    }
 
-    virtual ~FGXMLAutoComponent() {}
+public:
+    
+    virtual ~FGXMLAutoComponent();
 
     virtual void update (double dt)=0;
     
-    inline const string& get_name() { return name; }
+    inline const std::string& get_name() { return name; }
+
+    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( simgear::PropertyList::iterator it = output_list.begin();
+             it != output_list.end(); ++it)
+          (*it)->setDoubleValue( clamp( value ) );
+    }
+
+    inline void set_output_value( bool 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( simgear::PropertyList::iterator it = output_list.begin();
+             it != output_list.end(); ++it)
+          (*it)->setBoolValue( value ); // don't use clamp here, bool is clamped anyway
+    }
+
+    inline double get_output_value() {
+      return output_list.size() == 0 ? 0.0 : clamp(output_list[0]->getDoubleValue());
+    }
+
+    /* 
+       Returns true if the enable-condition is true.
+
+       If a <condition> is defined, this condition is evaluated, 
+       <prop> and <value> tags are ignored.
+
+       If a <prop> is defined and no <value> is defined, the property
+       named in the <prop></prop> tags is evaluated as boolean.
+
+       If a <prop> is defined a a <value> is defined, the property named
+       in <prop></prop> is compared (as a string) to the value defined in
+       <value></value>
+
+       Returns true, if neither <condition> nor <prop> exists
+
+       Examples:
+       Using a <condition> tag
+       <enable>
+         <condition>
+           <!-- any legal condition goes here and is evaluated -->
+         </condition>
+         <prop>This is ignored</prop>
+         <value>This is also ignored</value>
+       </enable>
+
+       Using a single boolean property
+       <enable>
+         <prop>/some/property/that/is/evaluated/as/boolean</prop>
+       </enable>
+
+       Using <prop> == <value>
+       This is the old style behaviour
+       <enable>
+         <prop>/only/true/if/this/equals/true</prop>
+         <value>true<value>
+       </enable>
+    */
+    bool isPropertyEnabled();
 };
 
+typedef SGSharedPtr<FGXMLAutoComponent> FGXMLAutoComponent_ptr;
+
 
 /**
  * Roy Ovesen's PID controller
@@ -98,19 +273,11 @@ class FGPIDController : public FGXMLAutoComponent {
 
 private:
 
-    // debug flag
-    bool debug;
-
-    // Input values
-    double y_n;                 // measured process value
-    double r_n;                 // reference (set point) value
-    double y_scale;             // scale process input from property system
-    double r_scale;             // scale reference input from property system
-    double y_offset;
-    double r_offset;
 
     // Configuration values
-    double Kp;                  // proportional gain
+    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
@@ -120,12 +287,6 @@ private:
                                 // calculating derivative error
                                 // (usually 0.0)
 
-    double Ti;                  // Integrator time (sec)
-    double Td;                  // Derivator time (sec)
-
-    double u_min;               // Minimum output clamp
-    double u_max;               // Maximum output clamp
-
     // Previous state tracking values
     double ep_n_1;              // ep[n-1]  (prop error)
     double edf_n_1;             // edf[n-1] (derivative error)
@@ -134,7 +295,9 @@ private:
     double desiredTs;            // desired sampling interval (sec)
     double elapsedTime;          // elapsed time (sec)
     
-    
+
+protected:
+  bool parseConfigHook(const std::string& aName, SGPropertyNode* aNode);
     
 public:
 
@@ -142,7 +305,6 @@ public:
     FGPIDController( SGPropertyNode *node, bool old );
     ~FGPIDController() {}
 
-    void update_old( double dt );
     void update( double dt );
 };
 
@@ -156,32 +318,15 @@ class FGPISimpleController : public FGXMLAutoComponent {
 private:
 
     // proportional component data
-    bool proportional;
-    double Kp;
-    SGPropertyNode_ptr offset_prop;
-    double offset_value;
+    FGXMLAutoInputList Kp;
 
     // integral component data
-    bool integral;
-    double Ki;
+    FGXMLAutoInputList Ki;
     double int_sum;
 
-    // post functions for output
-    bool clamp;
-
-    // debug flag
-    bool debug;
-
-    // Input values
-    double y_n;                 // measured process value
-    double r_n;                 // reference (set point) value
-    double y_scale;             // scale process input from property system
-    double r_scale;             // scale reference input from property system
-
-    double u_min;               // Minimum output clamp
-    double u_max;               // Maximum output clamp
+protected:
+  bool parseConfigHook(const std::string& aName, SGPropertyNode* aNode);
 
-    
 public:
 
     FGPISimpleController( SGPropertyNode *node );
@@ -198,21 +343,15 @@ public:
 class FGPredictor : public FGXMLAutoComponent {
 
 private:
-
-    // proportional component data
     double last_value;
     double average;
-    double seconds;
-    double filter_gain;
+    FGXMLAutoInputList seconds;
+    FGXMLAutoInputList filter_gain;
 
-    // debug flag
-    bool debug;
+protected:
+  bool parseNodeHook(const std::string& aName, SGPropertyNode* aNode);
 
-    // Input values
-    double ivalue;                 // input value
-    
 public:
-
     FGPredictor( SGPropertyNode *node );
     ~FGPredictor() {}
 
@@ -235,16 +374,20 @@ public:
 class FGDigitalFilter : public FGXMLAutoComponent
 {
 private:
-    double Tf;            // Filter time [s]
-    unsigned int samples; // Number of input samples to average
-    double rateOfChange;  // The maximum allowable rate of change [1/s]
-    deque <double> output;
-    deque <double> input;
-    enum filterTypes { exponential, doubleExponential, movingAverage, noiseSpike };
+    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]
+
+    std::deque <double> output;
+    std::deque <double> input;
+    enum filterTypes { exponential, doubleExponential, movingAverage,
+                       noiseSpike, gain, reciprocal, differential, none };
     filterTypes filterType;
 
-    bool debug;
-
+protected:
+  bool parseNodeHook(const std::string& aName, SGPropertyNode* aNode);
+  
 public:
     FGDigitalFilter(SGPropertyNode *node);
     ~FGDigitalFilter() {}
@@ -252,11 +395,65 @@ public:
     void update(double dt);
 };
 
+class FGXMLAutoLogic : public FGXMLAutoComponent
+{
+private:
+    SGSharedPtr<SGCondition> input;
+    bool inverted;
+
+protected:
+    bool parseNodeHook(const std::string& aName, SGPropertyNode* aNode);
+
+public:
+    FGXMLAutoLogic(SGPropertyNode * node );
+    ~FGXMLAutoLogic() {}
+
+    void update(double dt);
+};
+
 /**
  * Model an autopilot system.
  * 
  */
 
+class FGXMLAutopilotGroup : public SGSubsystemGroup
+{
+public:
+    FGXMLAutopilotGroup();
+    void init();
+    void reinit();
+    void update( double dt );
+private:
+    std::vector<std::string> _autopilotNames;
+
+#ifdef XMLAUTO_USEHELPER
+    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;
+#endif
+};
+
 class FGXMLAutopilot : public SGSubsystem
 {
 
@@ -271,17 +468,15 @@ public:
     void unbind();
     void update( double dt );
 
-    bool build();
 
+    bool build( SGPropertyNode_ptr );
 protected:
-
-    typedef vector<FGXMLAutoComponent *> comp_list;
+    typedef std::vector<FGXMLAutoComponent_ptr> comp_list;
 
 private:
-
     bool serviceable;
-    SGPropertyNode_ptr config_props;
     comp_list components;
+    
 };