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 );
scale = NULL;
min = NULL;
max = NULL;
+ periodical = NULL;
if( node == NULL )
return;
abs = n->getBoolValue();
}
+ if( (n = node->getChild( "period" )) != NULL ) {
+ periodical = new FGPeriodicalValue( n );
+ }
+
SGPropertyNode *valueNode = node->getChild( "value" );
if ( valueNode != NULL ) {
value = valueNode->getDoubleValue();
if( value > m )
value = m;
}
+
+ if( periodical ) {
+ value = periodical->normalize( value );
+ }
return abs ? fabs(value) : value;
}
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);
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 );
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/props/condition.hxx>
+typedef SGSharedPtr<class FGXMLAutoInput> FGXMLAutoInput_ptr;
+typedef SGSharedPtr<class FGPeriodicalValue> FGPeriodicalValue_ptr;
+
+class FGPeriodicalValue : public SGReferenced {
+private:
+ FGXMLAutoInput_ptr minPeriod; // The minimum value of the period
+ FGXMLAutoInput_ptr maxPeriod; // The maximum value of the period
+public:
+ FGPeriodicalValue( SGPropertyNode_ptr node );
+ double normalize( double value );
+};
class FGXMLAutoInput : public SGReferenced {
private:
double value; // The value as a constant or initializer for the property
bool abs; // return absolute value
SGPropertyNode_ptr property; // The name of the property containing the value
- SGSharedPtr<FGXMLAutoInput> offset; // A fixed offset, defaults to zero
- SGSharedPtr<FGXMLAutoInput> scale; // A constant scaling factor defaults to one
- SGSharedPtr<FGXMLAutoInput> min; // A minimum clip defaults to no clipping
- SGSharedPtr<FGXMLAutoInput> max; // A maximum clip defaults to no clipping
+ FGXMLAutoInput_ptr offset; // A fixed offset, defaults to zero
+ FGXMLAutoInput_ptr scale; // A constant scaling factor defaults to one
+ FGXMLAutoInput_ptr min; // A minimum clip defaults to no clipping
+ FGXMLAutoInput_ptr max; // A maximum clip defaults to no clipping
+ FGPeriodicalValue_ptr periodical; //
SGSharedPtr<const SGCondition> _condition;
public:
};
-class FGXMLAutoInputList : public std::vector<SGSharedPtr<FGXMLAutoInput> > {
+class FGXMLAutoInputList : public std::vector<FGXMLAutoInput_ptr> {
public:
- FGXMLAutoInput * get_active() {
+ FGXMLAutoInput_ptr get_active() {
for (iterator it = begin(); it != end(); ++it) {
if( (*it)->is_enabled() )
return *it;
}
double get_value( double def = 0.0 ) {
- FGXMLAutoInput * input = get_active();
+ FGXMLAutoInput_ptr input = get_active();
return input == NULL ? def : input->get_value();
}
FGXMLAutoInputList referenceInput;
FGXMLAutoInputList uminInput;
FGXMLAutoInputList umaxInput;
+ FGPeriodicalValue_ptr periodical;
// debug flag
bool debug;
bool enabled;
bool isPropertyEnabled();
};
+typedef SGSharedPtr<FGXMLAutoComponent> FGXMLAutoComponent_ptr;
+
/**
* Roy Ovesen's PID controller
bool build( SGPropertyNode_ptr );
protected:
- typedef std::vector<SGSharedPtr<FGXMLAutoComponent> > comp_list;
+ typedef std::vector<FGXMLAutoComponent_ptr> comp_list;
private: