From 90e313a8dd6b60fbb14f47ea48a969f33924dfd7 Mon Sep 17 00:00:00 2001 From: torsten Date: Wed, 24 Feb 2010 22:15:48 +0000 Subject: [PATCH] New feature: added "filters" "logic filters" use well known conditions to drive output properties. Example for bax = baz & (foo | bar). my first logic element foo bar baz bax --- src/Autopilot/xmlauto.cxx | 59 +++++++++++++++++++++++++++++++++++++-- src/Autopilot/xmlauto.hxx | 44 +++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 3 deletions(-) diff --git a/src/Autopilot/xmlauto.cxx b/src/Autopilot/xmlauto.cxx index 119083f66..136ea647d 100644 --- a/src/Autopilot/xmlauto.cxx +++ b/src/Autopilot/xmlauto.cxx @@ -848,9 +848,58 @@ void FGDigitalFilter::update(double dt) } } +FGXMLAutoLogic::FGXMLAutoLogic(SGPropertyNode * node ) : + FGXMLAutoComponent(), + inverted(false) +{ + parseNode(node); +} + +bool FGXMLAutoLogic::parseNodeHook(const std::string& aName, SGPropertyNode* aNode) +{ + if (aName == "input") { + input = sgReadCondition( fgGetNode("/"), aNode ); + } else if (aName == "inverted") { + inverted = aNode->getBoolValue(); + } else { + return false; + } + + return true; +} + +void FGXMLAutoLogic::update(double dt) +{ + if ( isPropertyEnabled() ) { + if ( !enabled ) { + // we have just been enabled + } + enabled = true; + } else { + enabled = false; + do_feedback(); + } + + if ( !enabled || dt < SGLimitsd::min() ) + return; + + if( input == NULL ) { + if ( debug ) cout << "No input for " << get_name() << endl; + return; + } + + bool i = input->test(); + + if ( debug ) cout << "Updating " << get_name() << ": " << (inverted ? !i : i) << endl; + + set_output_value( i ); +} + + FGXMLAutopilotGroup::FGXMLAutopilotGroup() : - SGSubsystemGroup(), - average(0.0), // average/filtered prediction + SGSubsystemGroup() +#ifdef XMLAUTO_USEHELPER + ,average(0.0), // average/filtered prediction v_last(0.0), // last velocity last_static_pressure(0.0), vel(fgGetNode( "/velocities/airspeed-kt", true )), @@ -874,6 +923,7 @@ FGXMLAutopilotGroup::FGXMLAutopilotGroup() : static_pressure(fgGetNode( "/systems/static[0]/pressure-inhg", true )), pressure_rate(fgGetNode( "/autopilot/internal/pressure-rate", true )), track(fgGetNode( "/orientation/track-deg", true )) +#endif { } @@ -881,7 +931,7 @@ void FGXMLAutopilotGroup::update( double dt ) { // update all configured autopilots SGSubsystemGroup::update( dt ); - +#ifdef XMLAUTO_USEHELPER // update helper values double v = vel->getDoubleValue(); double a = 0.0; @@ -940,6 +990,7 @@ void FGXMLAutopilotGroup::update( double dt ) pressure_rate->setDoubleValue(current_pressure_rate); last_static_pressure = current_static_pressure; } +#endif } void FGXMLAutopilotGroup::reinit() @@ -1062,6 +1113,8 @@ bool FGXMLAutopilot::build( SGPropertyNode_ptr config_props ) { components.push_back( new FGPredictor( node ) ); } else if ( name == "filter" ) { components.push_back( new FGDigitalFilter( node ) ); + } else if ( name == "logic" ) { + components.push_back( new FGXMLAutoLogic( node ) ); } else { SG_LOG( SG_AUTOPILOT, SG_WARN, "Unknown top level autopilot section: " << name ); // return false; diff --git a/src/Autopilot/xmlauto.hxx b/src/Autopilot/xmlauto.hxx index 6d7d3f2aa..d3b5fa34e 100644 --- a/src/Autopilot/xmlauto.hxx +++ b/src/Autopilot/xmlauto.hxx @@ -24,6 +24,21 @@ #ifndef _XMLAUTO_HXX #define _XMLAUTO_HXX 1 +/* +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 #include @@ -190,6 +205,17 @@ public: (*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( std::vector ::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()); } @@ -367,6 +393,22 @@ public: void update(double dt); }; +class FGXMLAutoLogic : public FGXMLAutoComponent +{ +private: + SGSharedPtr 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. * @@ -382,6 +424,7 @@ public: private: std::vector _autopilotNames; +#ifdef XMLAUTO_USEHELPER double average; double v_last; double last_static_pressure; @@ -406,6 +449,7 @@ private: SGPropertyNode_ptr static_pressure; SGPropertyNode_ptr pressure_rate; SGPropertyNode_ptr track; +#endif }; class FGXMLAutopilot : public SGSubsystem -- 2.39.5