1
0
Fork 0

Some autopilot works

- add new <update-interval-secs> for autopilot components.
  This does what it says.
- add new method to PeriodicalValue to normalize symmetric around zero
- move the DigitalFilterImplementation out of the header file
- refactor NoiseSpikeFilter: spare some cpu-cycles and respect periodical
  output
This commit is contained in:
Torsten Dreyer 2012-02-12 11:41:21 +01:00
parent a8d5ac90c6
commit 5ebdcdc3d5
7 changed files with 60 additions and 33 deletions

View file

@ -133,6 +133,9 @@ protected:
it != _output_list.end(); ++it) it != _output_list.end(); ++it)
(*it)->setDoubleValue( value ); (*it)->setDoubleValue( value );
} }
public:
const PeriodicalValue * getPeriodicalValue() const { return _periodical; }
}; };
inline void AnalogComponent::disabled( double dt ) inline void AnalogComponent::disabled( double dt )

View file

@ -85,8 +85,10 @@ Autopilot::Autopilot( SGPropertyNode_ptr rootNode, SGPropertyNode_ptr configNode
component->set_name( buf.str() ); component->set_name( buf.str() );
} }
SG_LOG( SG_AUTOPILOT, SG_INFO, "adding autopilot component \"" << childName << "\" as \"" << component->get_name() << "\"" ); double updateInterval = node->getDoubleValue( "update-interval-secs", 0.0 );
add_component(component);
SG_LOG( SG_AUTOPILOT, SG_INFO, "adding autopilot component \"" << childName << "\" as \"" << component->get_name() << "\" with interval=" << updateInterval );
add_component(component,updateInterval);
} }
} }
@ -105,7 +107,7 @@ void Autopilot::unbind()
_rootNode->untie( "serviceable" ); _rootNode->untie( "serviceable" );
} }
void Autopilot::add_component( Component * component ) void Autopilot::add_component( Component * component, double updateInterval )
{ {
if( component == NULL ) return; if( component == NULL ) return;
@ -119,7 +121,7 @@ void Autopilot::add_component( Component * component )
if( name != component->get_name() ) if( name != component->get_name() )
SG_LOG( SG_ALL, SG_WARN, "Duplicate autopilot component " << component->get_name() << ", renamed to " << name ); SG_LOG( SG_ALL, SG_WARN, "Duplicate autopilot component " << component->get_name() << ", renamed to " << name );
set_subsystem( name.c_str(), component ); set_subsystem( name.c_str(), component, updateInterval );
} }
void Autopilot::update( double dt ) void Autopilot::update( double dt )

View file

@ -54,7 +54,7 @@ public:
std::string get_name() const { return _name; } std::string get_name() const { return _name; }
void set_name( const std::string & name ) { _name = name; } void set_name( const std::string & name ) { _name = name; }
void add_component( Component * component ); void add_component( Component * component, double updateInterval );
protected: protected:

View file

@ -32,6 +32,25 @@ using std::cout;
namespace FGXMLAutopilot { namespace FGXMLAutopilot {
/**
*
*
*/
class DigitalFilterImplementation : public SGReferenced {
protected:
virtual bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode) = 0;
public:
DigitalFilterImplementation();
virtual void initialize( double output ) {}
virtual double compute( double dt, double input ) = 0;
bool configure( SGPropertyNode_ptr configNode );
void setDigitalFilter( DigitalFilter * digitalFilter ) { _digitalFilter = digitalFilter; }
protected:
DigitalFilter * _digitalFilter;
};
/* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */
class GainFilterImplementation : public DigitalFilterImplementation { class GainFilterImplementation : public DigitalFilterImplementation {
@ -101,6 +120,10 @@ using namespace FGXMLAutopilot;
/* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------- */
DigitalFilterImplementation::DigitalFilterImplementation() :
_digitalFilter(NULL)
{
}
bool DigitalFilterImplementation::configure( SGPropertyNode_ptr configNode ) bool DigitalFilterImplementation::configure( SGPropertyNode_ptr configNode )
{ {
@ -227,19 +250,17 @@ void NoiseSpikeFilterImplementation::initialize( double output )
double NoiseSpikeFilterImplementation::compute( double dt, double input ) double NoiseSpikeFilterImplementation::compute( double dt, double input )
{ {
double delta = input - _output_1;
if( delta == 0.0 ) return input; // trivial
double maxChange = _rateOfChangeInput.get_value() * dt; double maxChange = _rateOfChangeInput.get_value() * dt;
const PeriodicalValue * periodical = _digitalFilter->getPeriodicalValue();
if( periodical ) delta = periodical->normalizeSymmetric( delta );
double output_0 = _output_1; if( fabs(delta) <= maxChange )
return (_output_1 = input);
if (_output_1 - input > maxChange) { else
output_0 = _output_1 - maxChange; return (_output_1 = _output_1 + copysign( maxChange, delta ));
} else if( _output_1 - input < -maxChange ) {
output_0 = _output_1 + maxChange;
} else if (fabs(input - _output_1) <= maxChange) {
output_0 = input;
}
_output_1 = output_0;
return output_0;
} }
bool NoiseSpikeFilterImplementation::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) bool NoiseSpikeFilterImplementation::configure( const std::string & nodeName, SGPropertyNode_ptr configNode )
@ -318,6 +339,11 @@ DigitalFilter::DigitalFilter() :
{ {
} }
DigitalFilter::~DigitalFilter()
{
}
static map<string,FunctorBase<DigitalFilterImplementation> *> componentForge; static map<string,FunctorBase<DigitalFilterImplementation> *> componentForge;
bool DigitalFilter::configure(const string& nodeName, SGPropertyNode_ptr configNode) bool DigitalFilter::configure(const string& nodeName, SGPropertyNode_ptr configNode)
@ -343,6 +369,7 @@ bool DigitalFilter::configure(const string& nodeName, SGPropertyNode_ptr configN
return true; return true;
} }
_implementation = (*componentForge[type])( configNode->getParent() ); _implementation = (*componentForge[type])( configNode->getParent() );
_implementation->setDigitalFilter( this );
return true; return true;
} }

View file

@ -31,19 +31,6 @@
namespace FGXMLAutopilot { namespace FGXMLAutopilot {
/**
*
*
*/
class DigitalFilterImplementation : public SGReferenced {
protected:
virtual bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode) = 0;
public:
virtual void initialize( double output ) {}
virtual double compute( double dt, double input ) = 0;
bool configure( SGPropertyNode_ptr configNode );
};
/** /**
* brief@ DigitalFilter - a selection of digital filters * brief@ DigitalFilter - a selection of digital filters
* *
@ -51,7 +38,7 @@ public:
class DigitalFilter : public AnalogComponent class DigitalFilter : public AnalogComponent
{ {
private: private:
SGSharedPtr<DigitalFilterImplementation> _implementation; SGSharedPtr<class DigitalFilterImplementation> _implementation;
enum InitializeTo { enum InitializeTo {
INITIALIZE_OUTPUT, INITIALIZE_OUTPUT,
@ -71,7 +58,7 @@ protected:
public: public:
DigitalFilter(); DigitalFilter();
~DigitalFilter() {} ~DigitalFilter();
}; };

View file

@ -34,11 +34,18 @@ PeriodicalValue::PeriodicalValue( SGPropertyNode_ptr root )
} }
} }
double PeriodicalValue::normalize( double value ) double PeriodicalValue::normalize( double value ) const
{ {
return SGMiscd::normalizePeriodic( minPeriod->get_value(), maxPeriod->get_value(), value ); return SGMiscd::normalizePeriodic( minPeriod->get_value(), maxPeriod->get_value(), value );
} }
double PeriodicalValue::normalizeSymmetric( double value ) const
{
value = SGMiscd::normalizePeriodic( minPeriod->get_value(), maxPeriod->get_value(), value );
double width_2 = (maxPeriod->get_value() - minPeriod->get_value())/2;
return value > width_2 ? width_2 - value : value;
}
InputValue::InputValue( SGPropertyNode_ptr node, double value, double offset, double scale) : InputValue::InputValue( SGPropertyNode_ptr node, double value, double offset, double scale) :
_value(0.0), _value(0.0),
_abs(false) _abs(false)

View file

@ -45,7 +45,8 @@ private:
InputValue_ptr maxPeriod; // The maximum value of the period InputValue_ptr maxPeriod; // The maximum value of the period
public: public:
PeriodicalValue( SGPropertyNode_ptr node ); PeriodicalValue( SGPropertyNode_ptr node );
double normalize( double value ); double normalize( double value ) const;
double normalizeSymmetric( double value ) const;
}; };
/** /**