]> git.mxchange.org Git - flightgear.git/blobdiff - src/Autopilot/xmlauto.cxx
Merge branch 'torsten/auto'
[flightgear.git] / src / Autopilot / xmlauto.cxx
index ff149a99c0c04daba89b25662ae54088bee08f9d..d37164a721a06103b4f1611541cfa66040c61533 100644 (file)
@@ -65,7 +65,7 @@ double FGPeriodicalValue::normalize( double value )
 
   if( phase > SGLimitsd::min() ) {
     while( value < min ) value += phase;
-    while( value > max ) value -= phase;
+    while( value >= max ) value -= phase;
   } else {
     value = min; // phase is zero
   }
@@ -729,6 +729,10 @@ bool FGDigitalFilter::parseNodeHook(const string& aName, SGPropertyNode* aNode)
       filterType = gain;
     } else if (val == "reciprocal") {
       filterType = reciprocal;
+    } else if (val == "differential") {
+      filterType = differential;
+      // use a constant of two samples for current and previous input value
+      samplesInput.push_back( new FGXMLAutoInput(NULL, 2.0 ) ); 
     }
   } else if (aName == "filter-time" ) {
     TfInput.push_back( new FGXMLAutoInput( aNode, 1.0 ) );
@@ -768,79 +772,176 @@ void FGDigitalFilter::update(double dt)
         do_feedback();
     }
 
-    if ( enabled && dt > 0.0 ) {
-        /*
-         * Exponential filter
-         *
-         * Output[n] = alpha*Input[n] + (1-alpha)*Output[n-1]
-         *
-         */
-         if( debug ) cout << "Updating " << get_name()
-                          << " dt " << dt << endl;
-
-        if (filterType == exponential)
-        {
-            double alpha = 1 / ((TfInput.get_value()/dt) + 1);
-            output.push_front(alpha * input[0] + 
-                              (1 - alpha) * output[0]);
-        } 
-        else if (filterType == doubleExponential)
+    if ( !enabled || dt < SGLimitsd::min() ) 
+        return;
+
+    /*
+     * Exponential filter
+     *
+     * Output[n] = alpha*Input[n] + (1-alpha)*Output[n-1]
+     *
+     */
+     if( debug ) cout << "Updating " << get_name()
+                      << " dt " << dt << endl;
+
+    if (filterType == exponential)
+    {
+        double alpha = 1 / ((TfInput.get_value()/dt) + 1);
+        output.push_front(alpha * input[0] + 
+                          (1 - alpha) * output[0]);
+    } 
+    else if (filterType == doubleExponential)
+    {
+        double alpha = 1 / ((TfInput.get_value()/dt) + 1);
+        output.push_front(alpha * alpha * input[0] + 
+                          2 * (1 - alpha) * output[0] -
+                          (1 - alpha) * (1 - alpha) * output[1]);
+    }
+    else if (filterType == movingAverage)
+    {
+        output.push_front(output[0] + 
+                          (input[0] - input.back()) / samplesInput.get_value());
+    }
+    else if (filterType == noiseSpike)
+    {
+        double maxChange = rateOfChangeInput.get_value() * dt;
+
+        if ((output[0] - input[0]) > maxChange)
         {
-            double alpha = 1 / ((TfInput.get_value()/dt) + 1);
-            output.push_front(alpha * alpha * input[0] + 
-                              2 * (1 - alpha) * output[0] -
-                              (1 - alpha) * (1 - alpha) * output[1]);
+            output.push_front(output[0] - maxChange);
         }
-        else if (filterType == movingAverage)
+        else if ((output[0] - input[0]) < -maxChange)
         {
-            output.push_front(output[0] + 
-                              (input[0] - input.back()) / samplesInput.get_value());
+            output.push_front(output[0] + maxChange);
         }
-        else if (filterType == noiseSpike)
+        else if (fabs(input[0] - output[0]) <= maxChange)
         {
-            double maxChange = rateOfChangeInput.get_value() * dt;
-
-            if ((output[0] - input[0]) > maxChange)
-            {
-                output.push_front(output[0] - maxChange);
-            }
-            else if ((output[0] - input[0]) < -maxChange)
-            {
-                output.push_front(output[0] + maxChange);
-            }
-            else if (fabs(input[0] - output[0]) <= maxChange)
-            {
-                output.push_front(input[0]);
-            }
+            output.push_front(input[0]);
         }
-        else if (filterType == gain)
-        {
-            output[0] = gainInput.get_value() * input[0];
+    }
+    else if (filterType == gain)
+    {
+        output[0] = gainInput.get_value() * input[0];
+    }
+    else if (filterType == reciprocal)
+    {
+        if (input[0] != 0.0) {
+            output[0] = gainInput.get_value() / input[0];
         }
-        else if (filterType == reciprocal)
-        {
-            if (input[0] != 0.0) {
-                output[0] = gainInput.get_value() / input[0];
-            }
+    }
+    else if (filterType == differential)
+    {
+        if( dt > SGLimitsd::min() ) {
+            output[0] = (input[0]-input[1]) * TfInput.get_value() / dt;
         }
+    }
 
-        output[0] = clamp(output[0]) ;
-        set_output_value( output[0] );
+    output[0] = clamp(output[0]) ;
+    set_output_value( output[0] );
 
-        output.resize(2);
+    output.resize(2);
 
-        if (debug)
-        {
-            cout << "input:" << input[0] 
-                 << "\toutput:" << output[0] << endl;
-        }
+    if (debug)
+    {
+        cout << "input:" << input[0] 
+             << "\toutput:" << output[0] << endl;
     }
 }
 
-FGXMLAutopilotGroup::FGXMLAutopilotGroup()
+FGXMLAutopilotGroup::FGXMLAutopilotGroup() :
+  SGSubsystemGroup(),
+  average(0.0), // average/filtered prediction
+  v_last(0.0),  // last velocity
+  last_static_pressure(0.0),
+  vel(fgGetNode( "/velocities/airspeed-kt", true )),
+  // Estimate speed in 5,10 seconds
+  lookahead5(fgGetNode( "/autopilot/internal/lookahead-5-sec-airspeed-kt", true )),
+  lookahead10(fgGetNode( "/autopilot/internal/lookahead-10-sec-airspeed-kt", true )),
+  bug(fgGetNode( "/autopilot/settings/heading-bug-deg", true )),
+  mag_hdg(fgGetNode( "/orientation/heading-magnetic-deg", true )),
+  bug_error(fgGetNode( "/autopilot/internal/heading-bug-error-deg", true )),
+  fdm_bug_error(fgGetNode( "/autopilot/internal/fdm-heading-bug-error-deg", true )),
+  target_true(fgGetNode( "/autopilot/settings/true-heading-deg", true )),
+  true_hdg(fgGetNode( "/orientation/heading-deg", true )),
+  true_error(fgGetNode( "/autopilot/internal/true-heading-error-deg", true )),
+  target_nav1(fgGetNode( "/instrumentation/nav[0]/radials/target-auto-hdg-deg", true )),
+  true_nav1(fgGetNode( "/autopilot/internal/nav1-heading-error-deg", true )),
+  true_track_nav1(fgGetNode( "/autopilot/internal/nav1-track-error-deg", true )),
+  nav1_course_error(fgGetNode( "/autopilot/internal/nav1-course-error", true )),
+  nav1_selected_course(fgGetNode( "/instrumentation/nav[0]/radials/selected-deg", true )),
+  vs_fps(fgGetNode( "/velocities/vertical-speed-fps", true )),
+  vs_fpm(fgGetNode( "/autopilot/internal/vert-speed-fpm", true )),
+  static_pressure(fgGetNode( "/systems/static[0]/pressure-inhg", true )),
+  pressure_rate(fgGetNode( "/autopilot/internal/pressure-rate", true )),
+  track(fgGetNode( "/orientation/track-deg", true ))
 {
 }
 
+void FGXMLAutopilotGroup::update( double dt )
+{
+    // update all configured autopilots
+    SGSubsystemGroup::update( dt );
+
+    // update helper values
+    double v = vel->getDoubleValue();
+    double a = 0.0;
+    if ( dt > 0.0 ) {
+        a = (v - v_last) / dt;
+
+        if ( dt < 1.0 ) {
+            average = (1.0 - dt) * average + dt * a;
+        } else {
+            average = a;
+        }
+
+        lookahead5->setDoubleValue( v + average * 5.0 );
+        lookahead10->setDoubleValue( v + average * 10.0 );
+        v_last = v;
+    }
+
+    // Calculate heading bug error normalized to +/- 180.0
+    double diff = bug->getDoubleValue() - mag_hdg->getDoubleValue();
+    SG_NORMALIZE_RANGE(diff, -180.0, 180.0);
+    bug_error->setDoubleValue( diff );
+
+    fdm_bug_error->setDoubleValue( diff );
+
+    // Calculate true heading error normalized to +/- 180.0
+    diff = target_true->getDoubleValue() - true_hdg->getDoubleValue();
+    SG_NORMALIZE_RANGE(diff, -180.0, 180.0);
+    true_error->setDoubleValue( diff );
+
+    // Calculate nav1 target heading error normalized to +/- 180.0
+    diff = target_nav1->getDoubleValue() - true_hdg->getDoubleValue();
+    SG_NORMALIZE_RANGE(diff, -180.0, 180.0);
+    true_nav1->setDoubleValue( diff );
+
+    // Calculate true groundtrack
+    diff = target_nav1->getDoubleValue() - track->getDoubleValue();
+    SG_NORMALIZE_RANGE(diff, -180.0, 180.0);
+    true_track_nav1->setDoubleValue( diff );
+
+    // Calculate nav1 selected course error normalized to +/- 180.0
+    diff = nav1_selected_course->getDoubleValue() - mag_hdg->getDoubleValue();
+    SG_NORMALIZE_RANGE( diff, -180.0, 180.0 );
+    nav1_course_error->setDoubleValue( diff );
+
+    // Calculate vertical speed in fpm
+    vs_fpm->setDoubleValue( vs_fps->getDoubleValue() * 60.0 );
+
+
+    // Calculate static port pressure rate in [inhg/s].
+    // Used to determine vertical speed.
+    if ( dt > 0.0 ) {
+        double current_static_pressure = static_pressure->getDoubleValue();
+        double current_pressure_rate = 
+            ( current_static_pressure - last_static_pressure ) / dt;
+
+        pressure_rate->setDoubleValue(current_pressure_rate);
+        last_static_pressure = current_static_pressure;
+    }
+}
+
 void FGXMLAutopilotGroup::reinit()
 {
     for( vector<string>::size_type i = 0; i < _autopilotNames.size(); i++ ) {
@@ -928,8 +1029,6 @@ FGXMLAutopilot::~FGXMLAutopilot() {
  */
 void FGXMLAutopilot::init() 
 {
-  latNode = fgGetNode("/position/latitude-deg");
-  lonNode = fgGetNode("/position/longitude-deg");
 }
 
 
@@ -973,132 +1072,12 @@ bool FGXMLAutopilot::build( SGPropertyNode_ptr config_props ) {
     return true;
 }
 
-
-/*
- * Update helper values
- */
-void FGXMLAutopilot::update_helper( double dt ) {
-    // Estimate speed in 5,10 seconds
-    static SGPropertyNode_ptr vel = fgGetNode( "/velocities/airspeed-kt", true );
-    static SGPropertyNode_ptr lookahead5
-        = fgGetNode( "/autopilot/internal/lookahead-5-sec-airspeed-kt", true );
-    static SGPropertyNode_ptr lookahead10
-        = fgGetNode( "/autopilot/internal/lookahead-10-sec-airspeed-kt", true );
-
-    static double average = 0.0; // average/filtered prediction
-    static double v_last = 0.0;  // last velocity
-
-    double v = vel->getDoubleValue();
-    double a = 0.0;
-    if ( dt > 0.0 ) {
-        a = (v - v_last) / dt;
-
-        if ( dt < 1.0 ) {
-            average = (1.0 - dt) * average + dt * a;
-        } else {
-            average = a;
-        }
-
-        lookahead5->setDoubleValue( v + average * 5.0 );
-        lookahead10->setDoubleValue( v + average * 10.0 );
-        v_last = v;
-    }
-
-    // Calculate heading bug error normalized to +/- 180.0
-    static SGPropertyNode_ptr bug
-        = fgGetNode( "/autopilot/settings/heading-bug-deg", true );
-    static SGPropertyNode_ptr mag_hdg
-        = fgGetNode( "/orientation/heading-magnetic-deg", true );
-    static SGPropertyNode_ptr bug_error
-        = fgGetNode( "/autopilot/internal/heading-bug-error-deg", true );
-
-    double diff = bug->getDoubleValue() - mag_hdg->getDoubleValue();
-    SG_NORMALIZE_RANGE(diff, -180.0, 180.0);
-    bug_error->setDoubleValue( diff );
-
-    static SGPropertyNode_ptr fdm_bug_error
-        = fgGetNode( "/autopilot/internal/fdm-heading-bug-error-deg", true );
-    fdm_bug_error->setDoubleValue( diff );
-
-    // Calculate true heading error normalized to +/- 180.0
-    static SGPropertyNode_ptr target_true
-        = fgGetNode( "/autopilot/settings/true-heading-deg", true );
-    static SGPropertyNode_ptr true_hdg
-        = fgGetNode( "/orientation/heading-deg", true );
-    static SGPropertyNode_ptr true_error
-        = fgGetNode( "/autopilot/internal/true-heading-error-deg", true );
-
-    diff = target_true->getDoubleValue() - true_hdg->getDoubleValue();
-    SG_NORMALIZE_RANGE(diff, -180.0, 180.0);
-    true_error->setDoubleValue( diff );
-
-    // Calculate nav1 target heading error normalized to +/- 180.0
-    static SGPropertyNode_ptr target_nav1
-        = fgGetNode( "/instrumentation/nav[0]/radials/target-auto-hdg-deg", true );
-    static SGPropertyNode_ptr true_nav1
-        = fgGetNode( "/autopilot/internal/nav1-heading-error-deg", true );
-    static SGPropertyNode_ptr true_track_nav1
-        = fgGetNode( "/autopilot/internal/nav1-track-error-deg", true );
-
-    diff = target_nav1->getDoubleValue() - true_hdg->getDoubleValue();
-    SG_NORMALIZE_RANGE(diff, -180.0, 180.0);
-    true_nav1->setDoubleValue( diff );
-
-    // Calculate true groundtrack
-    SGGeod currentPosition(SGGeod::fromDeg(
-        lonNode->getDoubleValue(), latNode->getDoubleValue()));
-    double true_track = SGGeodesy::courseDeg(lastPosition, currentPosition);
-    lastPosition = currentPosition;
-    diff = target_nav1->getDoubleValue() - true_track;
-    SG_NORMALIZE_RANGE(diff, -180.0, 180.0);
-    true_track_nav1->setDoubleValue( diff );
-
-    // Calculate nav1 selected course error normalized to +/- 180.0
-    static SGPropertyNode_ptr nav1_course_error
-        = fgGetNode( "/autopilot/internal/nav1-course-error", true );
-    static SGPropertyNode_ptr nav1_selected_course
-        = fgGetNode( "/instrumentation/nav[0]/radials/selected-deg", true );
-
-    diff = nav1_selected_course->getDoubleValue() - mag_hdg->getDoubleValue();
-    SG_NORMALIZE_RANGE( diff, -180.0, 180.0 );
-    nav1_course_error->setDoubleValue( diff );
-
-    // Calculate vertical speed in fpm
-    static SGPropertyNode_ptr vs_fps
-        = fgGetNode( "/velocities/vertical-speed-fps", true );
-    static SGPropertyNode_ptr vs_fpm
-        = fgGetNode( "/autopilot/internal/vert-speed-fpm", true );
-
-    vs_fpm->setDoubleValue( vs_fps->getDoubleValue() * 60.0 );
-
-
-    // Calculate static port pressure rate in [inhg/s].
-    // Used to determine vertical speed.
-    static SGPropertyNode_ptr static_pressure
-        = fgGetNode( "/systems/static[0]/pressure-inhg", true );
-    static SGPropertyNode_ptr pressure_rate
-        = fgGetNode( "/autopilot/internal/pressure-rate", true );
-
-    static double last_static_pressure = 0.0;
-
-    if ( dt > 0.0 ) {
-        double current_static_pressure = static_pressure->getDoubleValue();
-        double current_pressure_rate = 
-            ( current_static_pressure - last_static_pressure ) / dt;
-
-        pressure_rate->setDoubleValue(current_pressure_rate);
-        last_static_pressure = current_static_pressure;
-    }
-}
-
-
 /*
  * Update the list of autopilot components
  */
 
-void FGXMLAutopilot::update( double dt ) {
-    update_helper( dt );
-
+void FGXMLAutopilot::update( double dt ) 
+{
     unsigned int i;
     for ( i = 0; i < components.size(); ++i ) {
         components[i]->update( dt );