]> git.mxchange.org Git - flightgear.git/blobdiff - src/Autopilot/xmlauto.cxx
James Turner:
[flightgear.git] / src / Autopilot / xmlauto.cxx
index 8ab25c9b82e0d5bcecd760f162848bf3c94f3d5d..17ea68cbaf949a4a7ee28f4f1488fea24a084a1d 100644 (file)
 #  include <config.h>
 #endif
 
+#include <iostream>
+
 #include <simgear/structure/exception.hxx>
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/sg_inlines.h>
+#include <simgear/props/props_io.hxx>
 
 #include <Main/fg_props.hxx>
 #include <Main/globals.hxx>
@@ -34,6 +37,8 @@
 
 #include "xmlauto.hxx"
 
+using std::cout;
+using std::endl;
 
 FGPIDController::FGPIDController( SGPropertyNode *node ):
     debug( false ),
@@ -124,51 +129,151 @@ FGPIDController::FGPIDController( SGPropertyNode *node ):
                 i++;
             }
         } else if ( cname == "config" ) {
-            SGPropertyNode *prop;
+            SGPropertyNode *config;
 
-            prop = child->getChild( "Ts" );
-            if ( prop != NULL ) {
-                desiredTs = prop->getDoubleValue();
+            config = child->getChild( "Ts" );
+            if ( config != NULL ) {
+                desiredTs = config->getDoubleValue();
             }
             
-            prop = child->getChild( "Kp" );
-            if ( prop != NULL ) {
-                Kp = prop->getDoubleValue();
+            config = child->getChild( "Kp" );
+            if ( config != NULL ) {
+                SGPropertyNode *val = config->getChild( "value" );
+                if ( val != NULL ) {
+                    Kp = val->getDoubleValue();
+                }
+
+                SGPropertyNode *prop = config->getChild( "prop" );
+                if ( prop != NULL ) {
+                    Kp_prop = fgGetNode( prop->getStringValue(), true );
+                    if ( val != NULL ) {
+                        Kp_prop->setDoubleValue(Kp);
+                    }
+                }
+
+                // output deprecated usage warning
+                if (val == NULL && prop == NULL) {
+                    Kp = config->getDoubleValue();
+                    SG_LOG( SG_AUTOPILOT, SG_WARN, "Deprecated Kp config. Please use <prop> and/or <value> tags." );
+                    if ( name.length() ) {
+                        SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+                    }
+                }
             }
 
-            prop = child->getChild( "beta" );
-            if ( prop != NULL ) {
-                beta = prop->getDoubleValue();
+            config = child->getChild( "beta" );
+            if ( config != NULL ) {
+                beta = config->getDoubleValue();
             }
 
-            prop = child->getChild( "alpha" );
-            if ( prop != NULL ) {
-                alpha = prop->getDoubleValue();
+            config = child->getChild( "alpha" );
+            if ( config != NULL ) {
+                alpha = config->getDoubleValue();
             }
 
-            prop = child->getChild( "gamma" );
-            if ( prop != NULL ) {
-                gamma = prop->getDoubleValue();
+            config = child->getChild( "gamma" );
+            if ( config != NULL ) {
+                gamma = config->getDoubleValue();
             }
 
-            prop = child->getChild( "Ti" );
-            if ( prop != NULL ) {
-                Ti = prop->getDoubleValue();
+            config = child->getChild( "Ti" );
+            if ( config != NULL ) {
+                SGPropertyNode *val = config->getChild( "value" );
+                if ( val != NULL ) {
+                    Ti = val->getDoubleValue();
+                }
+
+                SGPropertyNode *prop = config->getChild( "prop" );
+                if ( prop != NULL ) {
+                    Ti_prop = fgGetNode( prop->getStringValue(), true );
+                    if ( val != NULL ) {
+                        Ti_prop->setDoubleValue(Kp);
+                    }
+                }
+
+                // output deprecated usage warning
+                if (val == NULL && prop == NULL) {
+                Ti = config->getDoubleValue();
+                    SG_LOG( SG_AUTOPILOT, SG_WARN, "Deprecated Ti config. Please use <prop> and/or <value> tags." );
+                    if ( name.length() ) {
+                        SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+                    }
+                }
             }
 
-            prop = child->getChild( "Td" );
-            if ( prop != NULL ) {
-                Td = prop->getDoubleValue();
+            config = child->getChild( "Td" );
+            if ( config != NULL ) {
+                SGPropertyNode *val = config->getChild( "value" );
+                if ( val != NULL ) {
+                    Td = val->getDoubleValue();
+                }
+
+                SGPropertyNode *prop = config->getChild( "prop" );
+                if ( prop != NULL ) {
+                    Td_prop = fgGetNode( prop->getStringValue(), true );
+                    if ( val != NULL ) {
+                        Td_prop->setDoubleValue(Kp);
+                    }
+                }
+
+                // output deprecated usage warning
+                if (val == NULL && prop == NULL) {
+                Td = config->getDoubleValue();
+                    SG_LOG( SG_AUTOPILOT, SG_WARN, "Deprecated Td config. Please use <prop> and/or <value> tags." );
+                    if ( name.length() ) {
+                        SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+                    }
+                }
             }
 
-            prop = child->getChild( "u_min" );
-            if ( prop != NULL ) {
-                u_min = prop->getDoubleValue();
+            config = child->getChild( "u_min" );
+            if ( config != NULL ) {
+                SGPropertyNode *val = config->getChild( "value" );
+                if ( val != NULL ) {
+                    u_min = val->getDoubleValue();
+                }
+
+                SGPropertyNode *prop = config->getChild( "prop" );
+                if ( prop != NULL ) {
+                    umin_prop = fgGetNode( prop->getStringValue(), true );
+                    if ( val != NULL ) {
+                        umin_prop->setDoubleValue(u_min);
+                    }
+                }
+
+                // output deprecated usage warning
+                if (val == NULL && prop == NULL) {
+                u_min = config->getDoubleValue();
+                    SG_LOG( SG_AUTOPILOT, SG_WARN, "Deprecated u_min config. Please use <prop> and/or <value> tags." );
+                    if ( name.length() ) {
+                        SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+                    }
+                }
             }
 
-            prop = child->getChild( "u_max" );
-            if ( prop != NULL ) {
-                u_max = prop->getDoubleValue();
+            config = child->getChild( "u_max" );
+            if ( config != NULL ) {
+                SGPropertyNode *val = config->getChild( "value" );
+                if ( val != NULL ) {
+                    u_max = val->getDoubleValue();
+                }
+
+                SGPropertyNode *prop = config->getChild( "prop" );
+                if ( prop != NULL ) {
+                    umax_prop = fgGetNode( prop->getStringValue(), true );
+                    if ( val != NULL ) {
+                        umax_prop->setDoubleValue(u_max);
+                    }
+                }
+
+                // output deprecated usage warning
+                if (val == NULL && prop == NULL) {
+                u_max = config->getDoubleValue();
+                    SG_LOG( SG_AUTOPILOT, SG_WARN, "Deprecated u_max config. Please use <prop> and/or <value> tags." );
+                    if ( name.length() ) {
+                        SG_LOG( SG_AUTOPILOT, SG_WARN, "Section = " << name );
+                    }
+                }
             }
         } else {
             SG_LOG( SG_AUTOPILOT, SG_WARN, "Error in autopilot config logic" );
@@ -240,6 +345,10 @@ void FGPIDController::update( double dt ) {
     double delta_u_n = 0.0; // incremental output
     double u_n = 0.0;       // absolute output
     double Ts;              // sampling interval (sec)
+    if (umin_prop != NULL)u_min = umin_prop->getDoubleValue();
+    if (umax_prop != NULL)u_max = umax_prop->getDoubleValue();
+    if (Ti_prop != NULL)Ti = Ti_prop->getDoubleValue();
+    if (Td_prop != NULL)Td = Td_prop->getDoubleValue();
     
     elapsedTime += dt;
     if ( elapsedTime <= desiredTs ) {
@@ -311,6 +420,9 @@ void FGPIDController::update( double dt ) {
 
         // Calculates the incremental output:
         if ( Ti > 0.0 ) {
+            if (Kp_prop != NULL) {
+                Kp = Kp_prop->getDoubleValue();
+            }
             delta_u_n = Kp * ( (ep_n - ep_n_1)
                                + ((Ts/Ti) * e_n)
                                + ((Td/Ts) * (edf_n - 2*edf_n_1 + edf_n_2)) );
@@ -443,7 +555,24 @@ FGPISimpleController::FGPISimpleController( SGPropertyNode *node ):
 
             prop = child->getChild( "Kp" );
             if ( prop != NULL ) {
+                SGPropertyNode *val = prop->getChild( "value" );
+                if ( val != NULL ) {
+                    Kp = val->getDoubleValue();
+                }
+
+                SGPropertyNode *prop1 = prop->getChild( "prop" );
+                if ( prop1 != NULL ) {
+                    Kp_prop = fgGetNode( prop1->getStringValue(), true );
+                    if ( val != NULL ) {
+                        Kp_prop->setDoubleValue(Kp);
+                    }
+                }
+
+                // output deprecated usage warning
+                if (val == NULL && prop1 == NULL) {
                 Kp = prop->getDoubleValue();
+                    SG_LOG( SG_AUTOPILOT, SG_WARN, "Deprecated Kp config. Please use <prop> and/or <value> tags." );
+                }
                 proportional = true;
             }
 
@@ -455,13 +584,47 @@ FGPISimpleController::FGPISimpleController( SGPropertyNode *node ):
 
             prop = child->getChild( "u_min" );
             if ( prop != NULL ) {
+                SGPropertyNode *val = prop->getChild( "value" );
+                if ( val != NULL ) {
+                    u_min = val->getDoubleValue();
+                }
+
+                SGPropertyNode *prop1 = prop->getChild( "prop" );
+                if ( prop1 != NULL ) {
+                    umin_prop = fgGetNode( prop1->getStringValue(), true );
+                    if ( val != NULL ) {
+                        umin_prop->setDoubleValue(u_min);
+                    }
+                }
+
+                // output deprecated usage warning
+                if (val == NULL && prop1 == NULL) {
                 u_min = prop->getDoubleValue();
+                    SG_LOG( SG_AUTOPILOT, SG_WARN, "Deprecated u_min config. Please use <prop> and/or <value> tags." );
+                }
                 clamp = true;
             }
 
             prop = child->getChild( "u_max" );
             if ( prop != NULL ) {
+                SGPropertyNode *val = prop->getChild( "value" );
+                if ( val != NULL ) {
+                    u_max = val->getDoubleValue();
+                }
+
+                SGPropertyNode *prop1 = prop->getChild( "prop" );
+                if ( prop1 != NULL ) {
+                    umax_prop = fgGetNode( prop1->getStringValue(), true );
+                    if ( val != NULL ) {
+                        umax_prop->setDoubleValue(u_max);
+                    }
+                }
+
+                // output deprecated usage warning
+                if (val == NULL && prop1 == NULL) {
                 u_max = prop->getDoubleValue();
+                    SG_LOG( SG_AUTOPILOT, SG_WARN, "Deprecated u_max config. Please use <prop> and/or <value> tags." );
+                }
                 clamp = true;
             }
         } else {
@@ -475,6 +638,10 @@ FGPISimpleController::FGPISimpleController( SGPropertyNode *node ):
 
 
 void FGPISimpleController::update( double dt ) {
+    if (umin_prop != NULL)u_min = umin_prop->getDoubleValue();
+    if (umax_prop != NULL)u_max = umax_prop->getDoubleValue();
+    if (Kp_prop != NULL)Kp = Kp_prop->getDoubleValue();
+
     if (enable_prop != NULL && enable_prop->getStringValue() == enable_value) {
         if ( !enabled ) {
             // we have just been enabled, zero out int_sum
@@ -627,10 +794,15 @@ void FGPredictor::update( double dt ) {
 }
 
 
-FGDigitalFilter::FGDigitalFilter(SGPropertyNode *node)
+FGDigitalFilter::FGDigitalFilter(SGPropertyNode *node):
+    Tf( 1.0 ),
+    samples( 1 ),
+    rateOfChange( 1.0 ),
+    gainFactor( 1.0 ),
+    gain_prop( NULL ),
+    output_min_clamp( -std::numeric_limits<double>::max() ),
+    output_max_clamp( std::numeric_limits<double>::max() )
 {
-    samples = 1;
-
     int i;
     for ( i = 0; i < node->nChildren(); ++i ) {
         SGPropertyNode *child = node->getChild(i);
@@ -662,6 +834,10 @@ FGDigitalFilter::FGDigitalFilter(SGPropertyNode *node)
                 filterType = movingAverage;
             } else if (cval == "noise-spike") {
                 filterType = noiseSpike;
+            } else if (cval == "gain") {
+                filterType = gain;
+            } else if (cval == "reciprocal") {
+                filterType = reciprocal;
             }
         } else if ( cname == "input" ) {
             input_prop = fgGetNode( child->getStringValue(), true );
@@ -671,6 +847,20 @@ FGDigitalFilter::FGDigitalFilter(SGPropertyNode *node)
             samples = child->getIntValue();
         } else if ( cname == "max-rate-of-change" ) {
             rateOfChange = child->getDoubleValue();
+        } else if ( cname == "gain" ) {
+            SGPropertyNode *val = child->getChild( "value" );
+            if ( val != NULL ) {
+                gainFactor = val->getDoubleValue();
+            }
+            SGPropertyNode *prop = child->getChild( "prop" );
+            if ( prop != NULL ) {
+                gain_prop = fgGetNode( prop->getStringValue(), true );
+                gain_prop->setDoubleValue(gainFactor);
+            }
+        } else if ( cname == "u_min" ) {
+            output_min_clamp = child->getDoubleValue();
+        } else if ( cname == "u_max" ) {
+            output_max_clamp = child->getDoubleValue();
         } else if ( cname == "output" ) {
             SGPropertyNode *tmp = fgGetNode( child->getStringValue(), true );
             output_list.push_back( tmp );
@@ -683,23 +873,21 @@ FGDigitalFilter::FGDigitalFilter(SGPropertyNode *node)
 
 void FGDigitalFilter::update(double dt)
 {
-    if ( input_prop != NULL && 
-         enable_prop != NULL && 
-         enable_prop->getStringValue() == enable_value) {
+    if ( (input_prop != NULL && 
+          enable_prop != NULL && 
+          enable_prop->getStringValue() == enable_value) ||
+         (enable_prop == NULL &&
+          input_prop != NULL) ) {
+
         input.push_front(input_prop->getDoubleValue());
         input.resize(samples + 1, 0.0);
+
         if ( !enabled ) {
             // first time being enabled, initialize output to the
             // value of the output property to avoid bumping.
             output.push_front(output_list[0]->getDoubleValue());
-            output.resize(1);
         }
 
-        enabled = true;
-    } else if (enable_prop == NULL &&
-               input_prop != NULL) {
-        input.push_front(input_prop->getDoubleValue());
-        input.resize(samples + 1, 0.0);
         enabled = true;
     } else {
         enabled = false;
@@ -718,11 +906,6 @@ void FGDigitalFilter::update(double dt)
             double alpha = 1 / ((Tf/dt) + 1);
             output.push_front(alpha * input[0] + 
                               (1 - alpha) * output[0]);
-            unsigned int i;
-            for ( i = 0; i < output_list.size(); ++i ) {
-                output_list[i]->setDoubleValue( output[0] );
-            }
-            output.resize(1);
         } 
         else if (filterType == doubleExponential)
         {
@@ -730,21 +913,11 @@ void FGDigitalFilter::update(double dt)
             output.push_front(alpha * alpha * input[0] + 
                               2 * (1 - alpha) * output[0] -
                               (1 - alpha) * (1 - alpha) * output[1]);
-            unsigned int i;
-            for ( i = 0; i < output_list.size(); ++i ) {
-                output_list[i]->setDoubleValue( output[0] );
-            }
-            output.resize(2);
         }
         else if (filterType == movingAverage)
         {
             output.push_front(output[0] + 
                               (input[0] - input.back()) / samples);
-            unsigned int i;
-            for ( i = 0; i < output_list.size(); ++i ) {
-                output_list[i]->setDoubleValue( output[0] );
-            }
-            output.resize(1);
         }
         else if (filterType == noiseSpike)
         {
@@ -762,13 +935,37 @@ void FGDigitalFilter::update(double dt)
             {
                 output.push_front(input[0]);
             }
-
-            unsigned int i;
-            for ( i = 0; i < output_list.size(); ++i ) {
-                output_list[i]->setDoubleValue( output[0] );
+        }
+        else if (filterType == gain)
+        {
+            if (gain_prop != NULL) {
+                gainFactor = gain_prop->getDoubleValue();
             }
-            output.resize(1);
+            output[0] = gainFactor * input[0];
         }
+        else if (filterType == reciprocal)
+        {
+            if (gain_prop != NULL) {
+                gainFactor = gain_prop->getDoubleValue();
+            }
+            if (input[0] != 0.0) {
+                output[0] = gainFactor / input[0];
+            }
+        }
+
+        if (output[0] < output_min_clamp) {
+            output[0] = output_min_clamp;
+        }
+        else if (output[0] > output_max_clamp) {
+            output[0] = output_max_clamp;
+        }
+
+        unsigned int i;
+        for ( i = 0; i < output_list.size(); ++i ) {
+            output_list[i]->setDoubleValue( output[0] );
+        }
+        output.resize(2);
+
         if (debug)
         {
             cout << "input:" << input[0] 
@@ -1009,3 +1206,4 @@ void FGXMLAutopilot::update( double dt ) {
         components[i]->update( dt );
     }
 }
+