]> git.mxchange.org Git - flightgear.git/blobdiff - src/Autopilot/xmlauto.cxx
Merge branch 'torsten/auto'
[flightgear.git] / src / Autopilot / xmlauto.cxx
index 6d542855787ee720bc80f7a92336bdac8d13e37a..d37164a721a06103b4f1611541cfa66040c61533 100644 (file)
 using std::cout;
 using std::endl;
 
+FGPeriodicalValue::FGPeriodicalValue( SGPropertyNode_ptr root )
+{
+  SGPropertyNode_ptr minNode = root->getChild( "min" );
+  SGPropertyNode_ptr maxNode = root->getChild( "max" );
+  if( minNode == NULL || maxNode == NULL ) {
+    SG_LOG(SG_AUTOPILOT, SG_ALERT, "periodical defined, but no <min> and/or <max> tag. Period ignored." );
+  } else {
+    minPeriod = new FGXMLAutoInput( minNode );
+    maxPeriod = new FGXMLAutoInput( maxNode );
+  }
+}
+
+double FGPeriodicalValue::normalize( double value )
+{
+  if( !(minPeriod && maxPeriod )) return value;
+
+  double p1 = minPeriod->get_value();
+  double p2 = maxPeriod->get_value();
+
+  double min = std::min<double>(p1,p2);
+  double max = std::max<double>(p1,p2);
+  double phase = fabs(max - min);
+
+  if( phase > SGLimitsd::min() ) {
+    while( value < min ) value += phase;
+    while( value >= max ) value -= phase;
+  } else {
+    value = min; // phase is zero
+  }
+
+  return value;
+}
+
 FGXMLAutoInput::FGXMLAutoInput( SGPropertyNode_ptr node, double value, double offset, double scale) :
   value(0.0),
   abs(false),
-  property(NULL),
-  offset(NULL),
-  scale(NULL),
-  min(NULL),
-  max(NULL),
   _condition(NULL) 
 {
   parse( node, value, offset, scale );
@@ -62,6 +90,7 @@ void FGXMLAutoInput::parse( SGPropertyNode_ptr node, double aValue, double aOffs
     scale = NULL;
     min = NULL;
     max = NULL;
+    periodical = NULL;
 
     if( node == NULL )
         return;
@@ -69,7 +98,7 @@ void FGXMLAutoInput::parse( SGPropertyNode_ptr node, double aValue, double aOffs
     SGPropertyNode * n;
 
     if( (n = node->getChild("condition")) != NULL ) {
-        _condition = sgReadCondition(node, n);
+        _condition = sgReadCondition(fgGetNode("/"), n);
     }
 
     if( (n = node->getChild( "scale" )) != NULL ) {
@@ -92,6 +121,10 @@ void FGXMLAutoInput::parse( SGPropertyNode_ptr node, double aValue, double aOffs
       abs = n->getBoolValue();
     }
 
+    if( (n = node->getChild( "period" )) != NULL ) {
+      periodical = new FGPeriodicalValue( n );
+    }
+
     SGPropertyNode *valueNode = node->getChild( "value" );
     if ( valueNode != NULL ) {
         value = valueNode->getDoubleValue();
@@ -161,6 +194,10 @@ double FGXMLAutoInput::get_value()
         if( value > m )
             value = m;
     }
+
+    if( periodical ) {
+      value = periodical->normalize( value );
+    }
     
     return abs ? fabs(value) : value;
 }
@@ -200,7 +237,7 @@ void FGXMLAutoComponent::parseNode(SGPropertyNode* aNode)
       debug = child->getBoolValue();
     } else if ( cname == "enable" ) {
       if( (prop = child->getChild("condition")) != NULL ) {
-        _condition = sgReadCondition(child, prop);
+        _condition = sgReadCondition(fgGetNode("/"), prop);
       } else {
          if ( (prop = child->getChild( "prop" )) != NULL ) {
              enable_prop = fgGetNode( prop->getStringValue(), true );
@@ -246,6 +283,8 @@ void FGXMLAutoComponent::parseNode(SGPropertyNode* aNode)
         umaxInput.push_back( new FGXMLAutoInput( child ) );
     } else if ( cname == "u_max" ) {
         umaxInput.push_back( new FGXMLAutoInput( child ) );
+    } else if ( cname == "period" ) {
+      periodical = new FGPeriodicalValue( child );
     } else {
       SG_LOG(SG_AUTOPILOT, SG_ALERT, "malformed autopilot definition - unrecognized node:" 
         << cname << " in section " << name);
@@ -314,6 +353,11 @@ void FGXMLAutoComponent::do_feedback_if_disabled()
 
 double FGXMLAutoComponent::clamp( double value )
 {
+    //If this is a periodical value, normalize it into our domain 
+    // before clamping
+    if( periodical )
+      value = periodical->normalize( value );
+
     // clamp, if either min or max is defined
     if( uminInput.size() + umaxInput.size() > 0 ) {
         double d = umaxInput.get_value( 0.0 );
@@ -685,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 ) );
@@ -724,116 +772,263 @@ 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;
     }
 }
 
-
-FGXMLAutopilot::FGXMLAutopilot() {
+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 );
 
-FGXMLAutopilot::~FGXMLAutopilot() {
+    // 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 FGXMLAutopilot::init() {
-    config_props = fgGetNode( "/autopilot/new-config", true );
+void FGXMLAutopilotGroup::reinit()
+{
+    for( vector<string>::size_type i = 0; i < _autopilotNames.size(); i++ ) {
+      FGXMLAutopilot * ap = (FGXMLAutopilot*)get_subsystem( _autopilotNames[i] );
+      if( ap == NULL ) continue; // ?
+      remove_subsystem( _autopilotNames[i] );
+      delete ap;
+    }
+    _autopilotNames.clear();
+    init();
+}
 
-    SGPropertyNode *path_n = fgGetNode("/sim/systems/autopilot/path");
+void FGXMLAutopilotGroup::init()
+{
+    vector<SGPropertyNode_ptr> autopilotNodes = fgGetNode( "/sim/systems", true )->getChildren("autopilot");
+    if( autopilotNodes.size() == 0 ) {
+        SG_LOG( SG_ALL, SG_WARN, "No autopilot configuration specified for this model!");
+        return;
+    }
+
+    for( vector<SGPropertyNode_ptr>::size_type i = 0; i < autopilotNodes.size(); i++ ) {
+        SGPropertyNode_ptr pathNode = autopilotNodes[i]->getNode( "path" );
+        if( pathNode == NULL ) {
+            SG_LOG( SG_ALL, SG_WARN, "No autopilot configuration file specified for this autopilot!");
+            continue;
+        }
+
+        string apName;
+        SGPropertyNode_ptr nameNode = autopilotNodes[i]->getNode( "name" );
+        if( nameNode != NULL ) {
+            apName = nameNode->getStringValue();
+        } else {
+          std::ostringstream buf;
+          buf <<  "unnamed_autopilot_" << i;
+          apName = buf.str();
+        }
+
+        if( get_subsystem( apName.c_str() ) != NULL ) {
+            SG_LOG( SG_ALL, SG_ALERT, "Duplicate autopilot configuration name " << apName << " ignored" );
+            continue;
+        }
 
-    if ( path_n ) {
         SGPath config( globals->get_fg_root() );
-        config.append( path_n->getStringValue() );
+        config.append( pathNode->getStringValue() );
 
-        SG_LOG( SG_ALL, SG_INFO, "Reading autopilot configuration from "
-                << config.str() );
+        SG_LOG( SG_ALL, SG_INFO, "Reading autopilot configuration from " << config.str() );
+        // FGXMLAutopilot
+        FGXMLAutopilot * ap = new FGXMLAutopilot;
         try {
-            readProperties( config.str(), config_props );
+            SGPropertyNode_ptr root = new SGPropertyNode();
+            readProperties( config.str(), root );
 
-            if ( ! build() ) {
-                SG_LOG( SG_ALL, SG_ALERT,
-                        "Detected an internal inconsistency in the autopilot");
-                SG_LOG( SG_ALL, SG_ALERT,
-                        " configuration.  See earlier errors for" );
+
+            if ( ! ap->build( root ) ) {
                 SG_LOG( SG_ALL, SG_ALERT,
-                        " details.");
-                exit(-1);
+                  "Detected an internal inconsistency in the autopilot configuration." << endl << " See earlier errors for details." );
+                delete ap;
+                continue;
             }        
         } catch (const sg_exception& e) {
             SG_LOG( SG_ALL, SG_ALERT, "Failed to load autopilot configuration: "
                     << config.str() << ":" << e.getMessage() );
+            delete ap;
+            continue;
         }
 
-    } else {
-        SG_LOG( SG_ALL, SG_WARN,
-                "No autopilot configuration specified for this model!");
+        SG_LOG( SG_ALL, SG_INFO, "adding  autopilot subsystem " << apName );
+        set_subsystem( apName, ap );
+        _autopilotNames.push_back( apName );
     }
+
+    SGSubsystemGroup::init();
+}
+
+FGXMLAutopilot::FGXMLAutopilot() {
+}
+
+
+FGXMLAutopilot::~FGXMLAutopilot() {
+}
+
+/* read all /sim/systems/autopilot[n]/path properties, try to read the file specified therein
+ * and configure/add the digital filters specified in that file
+ */
+void FGXMLAutopilot::init() 
+{
 }
 
 
@@ -849,7 +1044,7 @@ void FGXMLAutopilot::bind() {
 void FGXMLAutopilot::unbind() {
 }
 
-bool FGXMLAutopilot::build() {
+bool FGXMLAutopilot::build( SGPropertyNode_ptr config_props ) {
     SGPropertyNode *node;
     int i;
 
@@ -858,6 +1053,7 @@ bool FGXMLAutopilot::build() {
         node = config_props->getChild(i);
         string name = node->getName();
         // cout << name << endl;
+        SG_LOG( SG_ALL, SG_INFO, "adding  autopilot component " << name );
         if ( name == "pid-controller" ) {
             components.push_back( new FGPIDController( node ) );
         } else if ( name == "pi-simple-controller" ) {
@@ -866,160 +1062,22 @@ bool FGXMLAutopilot::build() {
             components.push_back( new FGPredictor( node ) );
         } else if ( name == "filter" ) {
             components.push_back( new FGDigitalFilter( node ) );
-        } else {
-            SG_LOG( SG_ALL, SG_ALERT, "Unknown top level section: " 
-                    << name );
-            return false;
+//        } else {
+//            SG_LOG( SG_ALL, SG_ALERT, "Unknown top level section: " 
+//                    << name );
+//            return false;
         }
     }
 
     return true;
 }
 
-
-/*
- * Update helper values
- */
-static void 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 (based on
-    // DG indicated heading)
-    static SGPropertyNode_ptr bug
-        = fgGetNode( "/autopilot/settings/heading-bug-deg", true );
-    static SGPropertyNode_ptr ind_hdg
-        = fgGetNode( "/instrumentation/heading-indicator/indicated-heading-deg",
-                     true );
-    static SGPropertyNode_ptr ind_bug_error
-        = fgGetNode( "/autopilot/internal/heading-bug-error-deg", true );
-
-    double diff = bug->getDoubleValue() - ind_hdg->getDoubleValue();
-    if ( diff < -180.0 ) { diff += 360.0; }
-    if ( diff > 180.0 ) { diff -= 360.0; }
-    ind_bug_error->setDoubleValue( diff );
-
-    // Calculate heading bug error normalized to +/- 180.0 (based on
-    // actual/nodrift magnetic-heading, i.e. a DG slaved to magnetic
-    // compass.)
-    static SGPropertyNode_ptr mag_hdg
-        = fgGetNode( "/orientation/heading-magnetic-deg", true );
-    static SGPropertyNode_ptr fdm_bug_error
-        = fgGetNode( "/autopilot/internal/fdm-heading-bug-error-deg", true );
-
-    diff = bug->getDoubleValue() - mag_hdg->getDoubleValue();
-    if ( diff < -180.0 ) { diff += 360.0; }
-    if ( diff > 180.0 ) { diff -= 360.0; }
-    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_track
-        = fgGetNode( "/instrumentation/gps/indicated-track-true-deg", true );
-    static SGPropertyNode_ptr true_error
-        = fgGetNode( "/autopilot/internal/true-heading-error-deg", true );
-
-    diff = target_true->getDoubleValue() - true_hdg->getDoubleValue();
-    if ( diff < -180.0 ) { diff += 360.0; }
-    if ( diff > 180.0 ) { diff -= 360.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();
-    if ( diff < -180.0 ) { diff += 360.0; }
-    if ( diff > 180.0 ) { diff -= 360.0; }
-    true_nav1->setDoubleValue( diff );
-
-    diff = target_nav1->getDoubleValue() - true_track->getDoubleValue();
-    if ( diff < -180.0 ) { diff += 360.0; }
-    if ( diff > 180.0 ) { diff -= 360.0; }
-    true_track_nav1->setDoubleValue( diff );
-
-    // Calculate nav1 selected course error normalized to +/- 180.0
-    // (based on DG indicated heading)
-    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() - ind_hdg->getDoubleValue();
-//    if ( diff < -180.0 ) { diff += 360.0; }
-//    if ( diff > 180.0 ) { diff -= 360.0; }
-    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 );