1
0
Fork 0

New feature: added <logic> "filters"

"logic filters" use well known conditions to drive output properties. Example for bax = baz & (foo | bar).

 <logic>
    <name>my first logic element</name>
    <input>
      <or>
        <property>foo</property>
        <property>bar</property>
      </or>
      <property>baz</property>
    </input>
    <output>bax</output>
  </logic>
This commit is contained in:
torsten 2010-02-24 22:15:48 +00:00 committed by Tim Moore
parent 4ae8c90f76
commit 90e313a8dd
2 changed files with 100 additions and 3 deletions

View file

@ -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;

View file

@ -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 <simgear/compiler.h>
#include <string>
@ -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 <SGPropertyNode_ptr>::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<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.
*
@ -382,6 +424,7 @@ public:
private:
std::vector<std::string> _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