diff --git a/src/Autopilot/analogcomponent.cxx b/src/Autopilot/analogcomponent.cxx index 752c3eced..2102f4c31 100644 --- a/src/Autopilot/analogcomponent.cxx +++ b/src/Autopilot/analogcomponent.cxx @@ -49,65 +49,88 @@ double AnalogComponent::clamp( double value ) const return value; } -bool AnalogComponent::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +bool AnalogComponent::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - SG_LOG( SG_AUTOPILOT, SG_BULK, "AnalogComponent::configure(" << nodeName << ")" ); - if( Component::configure( nodeName, configNode ) ) + SG_LOG + ( + SG_AUTOPILOT, + SG_BULK, + "AnalogComponent::configure(" << cfg_name << ")" + ); + + if( Component::configure(cfg_node, cfg_name, prop_root) ) return true; - if ( nodeName == "feedback-if-disabled" ) { - _feedback_if_disabled = configNode->getBoolValue(); + if( cfg_name == "feedback-if-disabled" ) + { + _feedback_if_disabled = cfg_node.getBoolValue(); return true; } - if ( nodeName == "output" ) { - // grab all and childs - int found = 0; - // backwards compatibility: allow elements - SGPropertyNode_ptr prop; - for( int i = 0; (prop = configNode->getChild("prop", i)) != NULL; i++ ) { - SGPropertyNode *tmp = fgGetNode( prop->getStringValue(), true ); - _output_list.push_back( tmp ); - found++; - } - for( int i = 0; (prop = configNode->getChild("property", i)) != NULL; i++ ) { - SGPropertyNode *tmp = fgGetNode( prop->getStringValue(), true ); - _output_list.push_back( tmp ); - found++; + if( cfg_name == "output" ) + { + // grab all and childs. + bool found = false; + for( int i = 0; i < cfg_node.nChildren(); ++i ) + { + SGPropertyNode& child = *cfg_node.getChild(i); + const std::string& name = child.getNameString(); + + // Allow "prop" for backwards compatiblity + if( name != "property" && name != "prop" ) + continue; + + _output_list.push_back( prop_root.getNode(child.getStringValue(), true) ); + found = true; } // no elements, text node of is property name - if( found == 0 ) - _output_list.push_back( fgGetNode(configNode->getStringValue(), true ) ); + if( !found ) + _output_list.push_back + ( + prop_root.getNode(cfg_node.getStringValue(), true) + ); return true; } - if( nodeName == "input" ) { - _valueInput.push_back( new InputValue( configNode ) ); + if( cfg_name == "input" ) + { + _valueInput.push_back( new InputValue(prop_root, cfg_node) ); return true; } - if( nodeName == "reference" ) { - _referenceInput.push_back( new InputValue( configNode ) ); + if( cfg_name == "reference" ) + { + _referenceInput.push_back( new InputValue(prop_root, cfg_node) ); return true; } - if( nodeName == "min" || nodeName == "u_min" ) { - _minInput.push_back( new InputValue( configNode ) ); + if( cfg_name == "min" || cfg_name == "u_min" ) + { + _minInput.push_back( new InputValue(prop_root, cfg_node) ); return true; } - if( nodeName == "max" || nodeName == "u_max" ) { - _maxInput.push_back( new InputValue( configNode ) ); + if( cfg_name == "max" || cfg_name == "u_max" ) + { + _maxInput.push_back( new InputValue(prop_root, cfg_node) ); return true; } - if( nodeName == "period" ) { - _periodical = new PeriodicalValue( configNode ); + if( cfg_name == "period" ) + { + _periodical = new PeriodicalValue(prop_root, cfg_node); return true; } - SG_LOG( SG_AUTOPILOT, SG_BULK, "AnalogComponent::configure(" << nodeName << ") [unhandled]" ); + SG_LOG + ( + SG_AUTOPILOT, + SG_BULK, + "AnalogComponent::configure(" << cfg_name << ") [unhandled]" + ); return false; } diff --git a/src/Autopilot/analogcomponent.hxx b/src/Autopilot/analogcomponent.hxx index c111f0995..852f7432a 100644 --- a/src/Autopilot/analogcomponent.hxx +++ b/src/Autopilot/analogcomponent.hxx @@ -83,14 +83,17 @@ protected: AnalogComponent(); /** - * @brief This method configures this analog component from a property node. Gets - * called multiple times from the base class configure method for every - config node. - * @param nodeName the name of the configuration node provided in configNode - * @param configNode the configuration node itself + * @brief This method configures this analog component from a property node. + * Gets called multiple times from the base class configure method + * for every configuration node. + * @param cfg_name Name of the configuration node provided in cfg_node + * @param cfg_node Configuration node itself + * @param prop_root Property root for all relative paths * @return true if the node was handled, false otherwise. */ - virtual bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + virtual bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); /** * @brief clamp the given value if <min> and/or <max> inputs were given diff --git a/src/Autopilot/autopilot.cxx b/src/Autopilot/autopilot.cxx index 7e5f67e6d..8fa6a5cc8 100644 --- a/src/Autopilot/autopilot.cxx +++ b/src/Autopilot/autopilot.cxx @@ -49,9 +49,10 @@ using namespace FGXMLAutopilot; class StateMachineComponent : public Component { public: - StateMachineComponent(SGPropertyNode_ptr config) + StateMachineComponent( SGPropertyNode& cfg, + SGPropertyNode& props_root ) { - inner = simgear::StateMachine::createFromPlist(config, globals->get_props()); + inner = simgear::StateMachine::createFromPlist(&cfg, &props_root); } virtual bool configure( const std::string & nodeName, SGPropertyNode_ptr config) @@ -73,9 +74,10 @@ class StateMachineFunctor : public FunctorBase { public: virtual ~StateMachineFunctor() {} - virtual Component* operator()( SGPropertyNode_ptr configNode ) + virtual Component* operator()( SGPropertyNode& cfg, + SGPropertyNode& prop_root ) { - return new StateMachineComponent(configNode); + return new StateMachineComponent(cfg, prop_root); } }; @@ -91,6 +93,28 @@ ComponentForge::~ComponentForge() delete it->second; } +void readInterfaceProperties( SGPropertyNode_ptr prop_root, + SGPropertyNode_ptr cfg ) +{ + simgear::PropertyList cfg_props = cfg->getChildren("property"); + for( simgear::PropertyList::iterator it = cfg_props.begin(); + it != cfg_props.end(); + ++it ) + { + SGPropertyNode_ptr prop = prop_root->getNode((*it)->getStringValue(), true); + SGPropertyNode* val = (*it)->getNode("_attr_/value"); + + if( val ) + { + prop->setDoubleValue( val->getDoubleValue() ); + + // TODO should we keep the _attr_ node, as soon as the property browser is + // able to cope with it? + (*it)->removeChild("_attr_", 0, false); + } + } +} + static ComponentForge componentForge; Autopilot::Autopilot( SGPropertyNode_ptr rootNode, SGPropertyNode_ptr configNode ) : @@ -109,18 +133,44 @@ Autopilot::Autopilot( SGPropertyNode_ptr rootNode, SGPropertyNode_ptr configNode componentForge["state-machine"] = new StateMachineFunctor(); } - if( configNode == NULL ) configNode = rootNode; + if( !configNode ) + configNode = rootNode; + + // property-root can be set in config file and overridden in the local system + // node. This allows using the same autopilot multiple times but with + // different paths (with all relative property paths being relative to the + // node specified with property-root) + SGPropertyNode_ptr prop_root_node = rootNode->getChild("property-root"); + if( !prop_root_node ) + prop_root_node = configNode->getChild("property-root"); + + SGPropertyNode_ptr prop_root = + fgGetNode(prop_root_node ? prop_root_node->getStringValue() : "/", true); + + // Just like the JSBSim interface properties for systems, create properties + // given in the autopilot file and set to given (default) values. + readInterfaceProperties(prop_root, configNode); + + // Afterwards read the properties specified in local system node to allow + // overriding initial or default values. This allows reusing components with + // just different "parameter" values. + readInterfaceProperties(prop_root, rootNode); int count = configNode->nChildren(); - for ( int i = 0; i < count; ++i ) { + for( int i = 0; i < count; ++i ) + { SGPropertyNode_ptr node = configNode->getChild(i); string childName = node->getName(); - if( componentForge.count(childName) == 0 ) { - SG_LOG( SG_AUTOPILOT, SG_BULK, "unhandled element <" << childName << ">" << std::endl ); + if( childName == "property" + || childName == "property-root" ) + continue; + if( componentForge.count(childName) == 0 ) + { + SG_LOG(SG_AUTOPILOT, SG_BULK, "unhandled element <" << childName << ">"); continue; } - Component * component = (*componentForge[childName])(node); + Component * component = (*componentForge[childName])(*prop_root, *node); if( component->get_name().length() == 0 ) { std::ostringstream buf; buf << "unnamed_component_" << i; diff --git a/src/Autopilot/component.cxx b/src/Autopilot/component.cxx index f1c289412..21054a82f 100644 --- a/src/Autopilot/component.cxx +++ b/src/Autopilot/component.cxx @@ -40,64 +40,82 @@ Component::~Component() delete _enable_value; } -bool Component::configure( SGPropertyNode_ptr configNode ) +//------------------------------------------------------------------------------ +bool Component::configure( SGPropertyNode& prop_root, + SGPropertyNode& cfg ) { - for (int i = 0; i < configNode->nChildren(); ++i ) { - SGPropertyNode_ptr prop; - - SGPropertyNode_ptr child = configNode->getChild(i); + for( int i = 0; i < cfg.nChildren(); ++i ) + { + SGPropertyNode_ptr child = cfg.getChild(i); std::string cname(child->getName()); - if( configure( cname, child ) ) - continue; - - } // for configNode->nChildren() + if( !configure(*child, cname, prop_root) ) + SG_LOG + ( + SG_AUTOPILOT, + SG_INFO, + "Component::configure: unknown node: " << cname + ); + } return true; } -bool Component::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +//------------------------------------------------------------------------------ +bool Component::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - SG_LOG( SG_AUTOPILOT, SG_BULK, "Component::configure(" << nodeName << ")" << std::endl ); + SG_LOG + ( + SG_AUTOPILOT, + SG_BULK, + "Component::configure(" << cfg_name << ")" + ); - if ( nodeName == "name" ) { - _name = configNode->getStringValue(); + if ( cfg_name == "name" ) { + _name = cfg_node.getStringValue(); return true; } - if ( nodeName == "debug" ) { - _debug = configNode->getBoolValue(); + if ( cfg_name == "debug" ) { + _debug = cfg_node.getBoolValue(); return true; } - if ( nodeName == "enable" ) { + if ( cfg_name == "enable" ) { SGPropertyNode_ptr prop; - if( (prop = configNode->getChild("condition")) != NULL ) { + if( (prop = cfg_node.getChild("condition")) != NULL ) { _condition = sgReadCondition(fgGetNode("/"), prop); return true; } - if ( (prop = configNode->getChild( "property" )) != NULL ) { + if ( (prop = cfg_node.getChild( "property" )) != NULL ) { _enable_prop = fgGetNode( prop->getStringValue(), true ); } - if ( (prop = configNode->getChild( "prop" )) != NULL ) { + if ( (prop = cfg_node.getChild( "prop" )) != NULL ) { _enable_prop = fgGetNode( prop->getStringValue(), true ); } - if ( (prop = configNode->getChild( "value" )) != NULL ) { + if ( (prop = cfg_node.getChild( "value" )) != NULL ) { delete _enable_value; _enable_value = new std::string(prop->getStringValue()); } - if ( (prop = configNode->getChild( "honor-passive" )) != NULL ) { + if ( (prop = cfg_node.getChild( "honor-passive" )) != NULL ) { _honor_passive = prop->getBoolValue(); } return true; } // enable - SG_LOG( SG_AUTOPILOT, SG_BULK, "Component::configure(" << nodeName << ") [unhandled]" << std::endl ); + SG_LOG + ( + SG_AUTOPILOT, + SG_BULK, + "Component::configure(" << cfg_name << ") [unhandled]" + ); return false; } diff --git a/src/Autopilot/component.hxx b/src/Autopilot/component.hxx index cf8634a4a..63f77c06f 100644 --- a/src/Autopilot/component.hxx +++ b/src/Autopilot/component.hxx @@ -47,9 +47,10 @@ private: protected: - virtual bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + virtual bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); - /** * @brief the implementation of the update() method of the SGSubsystem */ @@ -97,11 +98,15 @@ public: virtual ~Component(); /** - * @brief configure this component from a property node. Iterates through all nodes found - * as childs under configNode and calls configure of the derived class for each child. - * @param configNode the property node containing the configuration + * @brief configure this component from a property node. Iterates through + * all nodes found as children under configNode and calls configure + * of the derived class for each child. + * + * @param prop_root Property root for all relative paths + * @param cfg Property node containing the configuration */ - bool configure( SGPropertyNode_ptr configNode ); + bool configure( SGPropertyNode& prop_root, + SGPropertyNode& cfg ); /** * @brief getter for the name property diff --git a/src/Autopilot/digitalcomponent.cxx b/src/Autopilot/digitalcomponent.cxx index 5e3e9fb22..1957e0977 100644 --- a/src/Autopilot/digitalcomponent.cxx +++ b/src/Autopilot/digitalcomponent.cxx @@ -56,13 +56,15 @@ bool DigitalComponent::InputMap::get_value( const std::string & name ) const /some/property */ -bool DigitalComponent::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +bool DigitalComponent::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - if( Component::configure( nodeName, configNode ) ) + if( Component::configure(cfg_node, cfg_name, prop_root) ) return true; - if (nodeName == "input") { - SGPropertyNode_ptr nameNode = configNode->getNode("name"); + if (cfg_name == "input") { + SGPropertyNode_ptr nameNode = cfg_node.getNode("name"); string name; if( nameNode != NULL ) { name = nameNode->getStringValue(); @@ -71,12 +73,12 @@ bool DigitalComponent::configure( const std::string & nodeName, SGPropertyNode_p buf << "Input" << _input.size(); name = buf.str(); } - _input[name] = sgReadCondition( fgGetNode("/"), configNode ); + _input[name] = sgReadCondition(&prop_root, &cfg_node); return true; } - if (nodeName == "output") { - SGPropertyNode_ptr n = configNode->getNode("name"); + if (cfg_name == "output") { + SGPropertyNode_ptr n = cfg_node.getNode("name"); string name; if( n != NULL ) { name = n->getStringValue(); @@ -89,20 +91,20 @@ bool DigitalComponent::configure( const std::string & nodeName, SGPropertyNode_p DigitalOutput_ptr o = new DigitalOutput(); _output[name] = o; - if( (n = configNode->getNode("inverted")) != NULL ) + if( (n = cfg_node.getNode("inverted")) != NULL ) o->setInverted( n->getBoolValue() ); - if( (n = configNode->getNode("property")) != NULL ) - o->setProperty( fgGetNode( n->getStringValue(), true ) ); + if( (n = cfg_node.getNode("property")) != NULL ) + o->setProperty( prop_root.getNode(n->getStringValue(), true) ); - if( configNode->nChildren() == 0 ) - o->setProperty( fgGetNode( configNode->getStringValue(), true ) ); + if( cfg_node.nChildren() == 0 ) + o->setProperty( prop_root.getNode(cfg_node.getStringValue(), true) ); return true; } - if (nodeName == "inverted") { - _inverted = configNode->getBoolValue(); + if (cfg_name == "inverted") { + _inverted = cfg_node.getBoolValue(); return true; } diff --git a/src/Autopilot/digitalcomponent.hxx b/src/Autopilot/digitalcomponent.hxx index ebcee36fd..ade691635 100644 --- a/src/Autopilot/digitalcomponent.hxx +++ b/src/Autopilot/digitalcomponent.hxx @@ -122,11 +122,14 @@ protected: /** * @brief Over-rideable hook method to allow derived classes to refine top-level * node parsing. - * @param aName - * @param aNode + * @param cfg_node + * @param cfg_name + * @param prop_root * @return true if the node was handled, false otherwise. */ - virtual bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + virtual bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); }; } diff --git a/src/Autopilot/digitalfilter.cxx b/src/Autopilot/digitalfilter.cxx index 99eabafe3..70214ba21 100644 --- a/src/Autopilot/digitalfilter.cxx +++ b/src/Autopilot/digitalfilter.cxx @@ -42,13 +42,16 @@ namespace FGXMLAutopilot { */ class DigitalFilterImplementation : public SGReferenced { protected: - virtual bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode) = 0; + virtual bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) = 0; public: virtual ~DigitalFilterImplementation() {} DigitalFilterImplementation(); virtual void initialize( double initvalue ) {} virtual double compute( double dt, double input ) = 0; - bool configure( SGPropertyNode_ptr configNode ); + bool configure( SGPropertyNode& cfg, + SGPropertyNode& prop_root ); void setDigitalFilter( DigitalFilter * digitalFilter ) { _digitalFilter = digitalFilter; } @@ -61,7 +64,9 @@ protected: class GainFilterImplementation : public DigitalFilterImplementation { protected: InputValueList _gainInput; - bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); public: GainFilterImplementation() : _gainInput(1.0) {} double compute( double dt, double input ); @@ -75,7 +80,9 @@ public: class DerivativeFilterImplementation : public GainFilterImplementation { InputValueList _TfInput; double _input_1; - bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); public: DerivativeFilterImplementation(); double compute( double dt, double input ); @@ -85,7 +92,9 @@ public: class ExponentialFilterImplementation : public GainFilterImplementation { protected: InputValueList _TfInput; - bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); bool _isSecondOrder; double _output_1, _output_2; public: @@ -99,7 +108,9 @@ protected: InputValueList _samplesInput; double _output_1; std::deque _inputQueue; - bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); public: MovingAverageFilterImplementation(); double compute( double dt, double input ); @@ -110,7 +121,9 @@ class NoiseSpikeFilterImplementation : public DigitalFilterImplementation { protected: double _output_1; InputValueList _rateOfChangeInput; - bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); public: NoiseSpikeFilterImplementation(); double compute( double dt, double input ); @@ -122,7 +135,9 @@ protected: double _output_1; InputValueList _rateOfChangeMax; InputValueList _rateOfChangeMin ; - bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); public: RateLimitFilterImplementation(); double compute( double dt, double input ); @@ -136,7 +151,9 @@ protected: InputValueList _maxInput; double _input_1; double _output_1; - bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); public: IntegratorFilterImplementation(); double compute( double dt, double input ); @@ -148,7 +165,9 @@ protected: InputValueList _TfInput; double _input_1; double _output_1; - bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); public: HighPassFilterImplementation(); double compute( double dt, double input ); @@ -160,7 +179,9 @@ protected: InputValueList _TfbInput; double _input_1; double _output_1; - bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); public: LeadLagFilterImplementation(); double compute( double dt, double input ); @@ -180,18 +201,17 @@ DigitalFilterImplementation::DigitalFilterImplementation() : { } -bool DigitalFilterImplementation::configure( SGPropertyNode_ptr configNode ) +//------------------------------------------------------------------------------ +bool DigitalFilterImplementation::configure( SGPropertyNode& cfg, + SGPropertyNode& prop_root ) { - for (int i = 0; i < configNode->nChildren(); ++i ) { - SGPropertyNode_ptr prop; + for (int i = 0; i < cfg.nChildren(); ++i ) + { + SGPropertyNode_ptr child = cfg.getChild(i); - SGPropertyNode_ptr child = configNode->getChild(i); - string cname(child->getName()); - - if( configure( cname, child ) ) + if( configure(*child, child->getNameString(), prop_root) ) continue; - - } // for configNode->nChildren() + } return true; } @@ -204,10 +224,12 @@ double GainFilterImplementation::compute( double dt, double input ) return _gainInput.get_value() * input; } -bool GainFilterImplementation::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +bool GainFilterImplementation::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - if (nodeName == "gain" ) { - _gainInput.push_back( new InputValue( configNode, 1 ) ); + if (cfg_name == "gain" ) { + _gainInput.push_back( new InputValue(prop_root, cfg_node, 1) ); return true; } @@ -239,14 +261,16 @@ void DerivativeFilterImplementation::initialize( double initvalue ) _input_1 = initvalue; } - -bool DerivativeFilterImplementation::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +//------------------------------------------------------------------------------ +bool DerivativeFilterImplementation::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - if( GainFilterImplementation::configure( nodeName, configNode ) ) + if( GainFilterImplementation::configure(cfg_node, cfg_name, prop_root) ) return true; - if (nodeName == "filter-time" ) { - _TfInput.push_back( new InputValue( configNode, 1 ) ); + if (cfg_name == "filter-time" ) { + _TfInput.push_back( new InputValue(prop_root, cfg_node, 1) ); return true; } @@ -299,10 +323,12 @@ double MovingAverageFilterImplementation::compute( double dt, double input ) return output_0; } -bool MovingAverageFilterImplementation::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +bool MovingAverageFilterImplementation::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - if (nodeName == "samples" ) { - _samplesInput.push_back( new InputValue( configNode, 1 ) ); + if (cfg_name == "samples" ) { + _samplesInput.push_back( new InputValue(prop_root, cfg_node, 1) ); return true; } @@ -337,10 +363,13 @@ double NoiseSpikeFilterImplementation::compute( double dt, double input ) return (_output_1 = _output_1 + copysign( maxChange, delta )); } -bool NoiseSpikeFilterImplementation::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +//------------------------------------------------------------------------------ +bool NoiseSpikeFilterImplementation::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - if (nodeName == "max-rate-of-change" ) { - _rateOfChangeInput.push_back( new InputValue( configNode, 1 ) ); + if (cfg_name == "max-rate-of-change" ) { + _rateOfChangeInput.push_back( new InputValue(prop_root, cfg_node, 1) ); return true; } @@ -379,14 +408,16 @@ double RateLimitFilterImplementation::compute( double dt, double input ) return (output); } -bool RateLimitFilterImplementation::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +bool RateLimitFilterImplementation::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - if (nodeName == "max-rate-of-change" ) { - _rateOfChangeMax.push_back( new InputValue( configNode, 1 ) ); + if (cfg_name == "max-rate-of-change" ) { + _rateOfChangeMax.push_back( new InputValue(prop_root, cfg_node, 1) ); return true; } - if (nodeName == "min-rate-of-change" ) { - _rateOfChangeMin.push_back( new InputValue( configNode, 1 ) ); + if (cfg_name == "min-rate-of-change" ) { + _rateOfChangeMin.push_back( new InputValue(prop_root, cfg_node, 1) ); return true; } @@ -431,18 +462,21 @@ double ExponentialFilterImplementation::compute( double dt, double input ) return (_output_1 = output_0); } -bool ExponentialFilterImplementation::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +//------------------------------------------------------------------------------ +bool ExponentialFilterImplementation::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - if( GainFilterImplementation::configure( nodeName, configNode ) ) + if( GainFilterImplementation::configure(cfg_node, cfg_name, prop_root) ) return true; - if (nodeName == "filter-time" ) { - _TfInput.push_back( new InputValue( configNode, 1 ) ); + if (cfg_name == "filter-time" ) { + _TfInput.push_back( new InputValue(prop_root, cfg_node, 1) ); return true; } - if (nodeName == "type" ) { - string type(configNode->getStringValue()); + if (cfg_name == "type" ) { + string type(cfg_node.getStringValue()); _isSecondOrder = type == "double-exponential"; } @@ -462,17 +496,20 @@ void IntegratorFilterImplementation::initialize( double initvalue ) _input_1 = _output_1 = initvalue; } - -bool IntegratorFilterImplementation::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +//------------------------------------------------------------------------------ +bool IntegratorFilterImplementation::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - if( GainFilterImplementation::configure( nodeName, configNode ) ) + if( GainFilterImplementation::configure(cfg_node, cfg_name, prop_root) ) return true; - if (nodeName == "u_min" ) { - _minInput.push_back( new InputValue( configNode, 1 ) ); + + if (cfg_name == "u_min" ) { + _minInput.push_back( new InputValue(prop_root, cfg_node, 1) ); return true; } - if (nodeName == "u_max" ) { - _maxInput.push_back( new InputValue( configNode, 1 ) ); + if (cfg_name == "u_max" ) { + _maxInput.push_back( new InputValue(prop_root, cfg_node, 1) ); return true; } return false; @@ -523,13 +560,16 @@ double HighPassFilterImplementation::compute( double dt, double input ) return output; } -bool HighPassFilterImplementation::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +//------------------------------------------------------------------------------ +bool HighPassFilterImplementation::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - if( GainFilterImplementation::configure( nodeName, configNode ) ) + if( GainFilterImplementation::configure(cfg_node, cfg_name, prop_root) ) return true; - if (nodeName == "filter-time" ) { - _TfInput.push_back( new InputValue( configNode, 1 ) ); + if (cfg_name == "filter-time" ) { + _TfInput.push_back( new InputValue(prop_root, cfg_node, 1) ); return true; } @@ -570,24 +610,27 @@ double LeadLagFilterImplementation::compute( double dt, double input ) return output; } -bool LeadLagFilterImplementation::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +//------------------------------------------------------------------------------ +bool LeadLagFilterImplementation::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - if( GainFilterImplementation::configure( nodeName, configNode ) ) + if( GainFilterImplementation::configure(cfg_node, cfg_name, prop_root) ) return true; - if (nodeName == "filter-time-a" ) { - _TfaInput.push_back( new InputValue( configNode, 1 ) ); + if (cfg_name == "filter-time-a" ) { + _TfaInput.push_back( new InputValue(prop_root, cfg_node, 1) ); return true; } - if (nodeName == "filter-time-b" ) { - _TfbInput.push_back( new InputValue( configNode, 1 ) ); + if (cfg_name == "filter-time-b" ) { + _TfbInput.push_back( new InputValue(prop_root, cfg_node, 1) ); return true; } return false; } -/* --------------------------------------------------------------------------------- */ -/* Digital Filter Component Implementation */ -/* --------------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ +/* Digital Filter Component Implementation */ +/* -------------------------------------------------------------------------- */ DigitalFilter::DigitalFilter() : AnalogComponent(), @@ -602,7 +645,10 @@ DigitalFilter::~DigitalFilter() static map *> componentForge; -bool DigitalFilter::configure(const string& nodeName, SGPropertyNode_ptr configNode) +//------------------------------------------------------------------------------ +bool DigitalFilter::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { if( componentForge.empty() ) { componentForge["gain"] = new CreateAndConfigureFunctor(); @@ -618,23 +664,24 @@ bool DigitalFilter::configure(const string& nodeName, SGPropertyNode_ptr configN componentForge["integrator"] = new CreateAndConfigureFunctor(); } - SG_LOG( SG_AUTOPILOT, SG_BULK, "DigitalFilter::configure(" << nodeName << ")" << endl ); - if( AnalogComponent::configure( nodeName, configNode ) ) + SG_LOG(SG_AUTOPILOT, SG_BULK, "DigitalFilter::configure(" << cfg_name << ")"); + + if( AnalogComponent::configure(cfg_node, cfg_name, prop_root) ) return true; - if (nodeName == "type" ) { - string type( configNode->getStringValue() ); + if (cfg_name == "type" ) { + string type( cfg_node.getStringValue() ); if( componentForge.count(type) == 0 ) { SG_LOG( SG_AUTOPILOT, SG_BULK, "unhandled filter type <" << type << ">" << endl ); return true; } - _implementation = (*componentForge[type])( configNode->getParent() ); + _implementation = (*componentForge[type])(*cfg_node.getParent(), prop_root); _implementation->setDigitalFilter( this ); return true; } - if( nodeName == "initialize-to" ) { - string s( configNode->getStringValue() ); + if( cfg_name == "initialize-to" ) { + string s( cfg_node.getStringValue() ); if( s == "input" ) { _initializeTo = INITIALIZE_INPUT; } else if( s == "output" ) { @@ -647,7 +694,12 @@ bool DigitalFilter::configure(const string& nodeName, SGPropertyNode_ptr configN return true; } - SG_LOG( SG_AUTOPILOT, SG_BULK, "DigitalFilter::configure(" << nodeName << ") [unhandled]" << endl ); + SG_LOG + ( + SG_AUTOPILOT, + SG_BULK, + "DigitalFilter::configure(" << cfg_name << ") [unhandled]" + ); return false; // not handled by us, let the base class try } diff --git a/src/Autopilot/digitalfilter.hxx b/src/Autopilot/digitalfilter.hxx index 3b7afabbd..244279a5a 100644 --- a/src/Autopilot/digitalfilter.hxx +++ b/src/Autopilot/digitalfilter.hxx @@ -47,8 +47,10 @@ private: }; protected: - bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode); - void update( bool firstTime, double dt); + virtual bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); + virtual void update( bool firstTime, double dt); InputValueList _Tf; InputValueList _samples; diff --git a/src/Autopilot/flipflop.cxx b/src/Autopilot/flipflop.cxx index b22adfa9a..484f89d05 100644 --- a/src/Autopilot/flipflop.cxx +++ b/src/Autopilot/flipflop.cxx @@ -264,7 +264,9 @@ public: */ class MonoFlopImplementation : public JKFlipFlopImplementation { protected: - virtual bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + virtual bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); InputValueList _time; double _t; public: @@ -288,13 +290,16 @@ public: using namespace FGXMLAutopilot; -bool MonoFlopImplementation::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +//------------------------------------------------------------------------------ +bool MonoFlopImplementation::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - if( JKFlipFlopImplementation::configure( nodeName, configNode ) ) + if( JKFlipFlopImplementation::configure(cfg_node, cfg_name, prop_root) ) return true; - if (nodeName == "time") { - _time.push_back( new InputValue( configNode ) ); + if (cfg_name == "time") { + _time.push_back( new InputValue(prop_root, cfg_node) ); return true; } @@ -371,18 +376,18 @@ bool JKFlipFlopImplementation::onRaisingEdge( DigitalComponent::InputMap input, return false; // signal no change } -bool FlipFlopImplementation::configure( SGPropertyNode_ptr configNode ) +//------------------------------------------------------------------------------ +bool FlipFlopImplementation::configure( SGPropertyNode& prop_root, + SGPropertyNode& cfg ) { - for (int i = 0; i < configNode->nChildren(); ++i ) { - SGPropertyNode_ptr prop; - - SGPropertyNode_ptr child = configNode->getChild(i); + for( int i = 0; i < cfg.nChildren(); ++i ) + { + SGPropertyNode_ptr child = cfg.getChild(i); string cname(child->getName()); - if( configure( cname, child ) ) + if( configure(*child, cname, prop_root) ) continue; - - } // for configNode->nChildren() + } return true; } @@ -390,7 +395,10 @@ bool FlipFlopImplementation::configure( SGPropertyNode_ptr configNode ) static map *> componentForge; -bool FlipFlop::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +//------------------------------------------------------------------------------ +bool FlipFlop::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { if( componentForge.empty() ) { componentForge["RS"] = new CreateAndConfigureFunctor(); @@ -401,46 +409,51 @@ bool FlipFlop::configure( const std::string & nodeName, SGPropertyNode_ptr confi componentForge["monostable"] = new CreateAndConfigureFunctor(); } - if( DigitalComponent::configure( nodeName, configNode ) ) + if( DigitalComponent::configure(cfg_node, cfg_name, prop_root) ) return true; - if( nodeName == "type" ) { - string type(configNode->getStringValue()); + if( cfg_name == "type" ) { + string type(cfg_node.getStringValue()); if( componentForge.count(type) == 0 ) { - SG_LOG( SG_AUTOPILOT, SG_BULK, "unhandled flip-flop type <" << type << ">" << endl ); + SG_LOG + ( + SG_AUTOPILOT, + SG_BULK, + "unhandled flip-flop type <" << type << ">" + ); return true; } - _implementation = (*componentForge[type])( configNode->getParent() ); + _implementation = (*componentForge[type])(prop_root, *cfg_node.getParent()); return true; } - if (nodeName == "set"||nodeName == "S") { - _input["S"] = sgReadCondition( fgGetNode("/"), configNode ); + if (cfg_name == "set"||cfg_name == "S") { + _input["S"] = sgReadCondition(&prop_root, &cfg_node); return true; } - if (nodeName == "reset" || nodeName == "R" ) { - _input["R"] = sgReadCondition( fgGetNode("/"), configNode ); + if (cfg_name == "reset" || cfg_name == "R" ) { + _input["R"] = sgReadCondition(&prop_root, &cfg_node); return true; } - if (nodeName == "J") { - _input["J"] = sgReadCondition( fgGetNode("/"), configNode ); + if (cfg_name == "J") { + _input["J"] = sgReadCondition(&prop_root, &cfg_node); return true; } - if (nodeName == "K") { - _input["K"] = sgReadCondition( fgGetNode("/"), configNode ); + if (cfg_name == "K") { + _input["K"] = sgReadCondition(&prop_root, &cfg_node); return true; } - if (nodeName == "D") { - _input["D"] = sgReadCondition( fgGetNode("/"), configNode ); + if (cfg_name == "D") { + _input["D"] = sgReadCondition(&prop_root, &cfg_node); return true; } - if (nodeName == "clock") { - _input["clock"] = sgReadCondition( fgGetNode("/"), configNode ); + if (cfg_name == "clock") { + _input["clock"] = sgReadCondition(&prop_root, &cfg_node); return true; } diff --git a/src/Autopilot/flipflop.hxx b/src/Autopilot/flipflop.hxx index e81c551a1..343020e75 100644 --- a/src/Autopilot/flipflop.hxx +++ b/src/Autopilot/flipflop.hxx @@ -36,7 +36,10 @@ protected: * as childs under configNode and calls configure of the derived class for each child. * @param configNode the property node containing the configuration */ - virtual bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) { return false; } + virtual bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) + { return false; } public: virtual ~FlipFlopImplementation() {} /** @@ -53,7 +56,8 @@ public: * as childs under configNode and calls configure of the derived class for each child. * @param configNode the property node containing the configuration */ - bool configure( SGPropertyNode_ptr configNode ); + bool configure( SGPropertyNode& prop_root, + SGPropertyNode& cfg ); }; /** @@ -69,7 +73,9 @@ protected: * @param aNode * @return true if the node was handled, false otherwise. */ - virtual bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + virtual bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); /** * @brief Implementation of the pure virtual function of the Component class. Gets called from diff --git a/src/Autopilot/functor.hxx b/src/Autopilot/functor.hxx index 4b1fda6f0..7d4f247cb 100644 --- a/src/Autopilot/functor.hxx +++ b/src/Autopilot/functor.hxx @@ -32,15 +32,18 @@ namespace FGXMLAutopilot { template class FunctorBase { public: virtual ~FunctorBase() {} - virtual TBase * operator()( SGPropertyNode_ptr configNode ) = 0; + virtual TBase * operator()( SGPropertyNode& prop_root, + SGPropertyNode& cfg ) = 0; }; template class CreateAndConfigureFunctor : public FunctorBase { public: - virtual TBase * operator()( SGPropertyNode_ptr configNode ) { + virtual TBase * operator()( SGPropertyNode& prop_root, + SGPropertyNode& cfg ) + { TBase * base = new TClass(); - base->configure( configNode ); + base->configure(prop_root, cfg); return base; } }; diff --git a/src/Autopilot/inputvalue.cxx b/src/Autopilot/inputvalue.cxx index 331aede8d..8246bc5c0 100644 --- a/src/Autopilot/inputvalue.cxx +++ b/src/Autopilot/inputvalue.cxx @@ -25,23 +25,37 @@ using namespace FGXMLAutopilot; -PeriodicalValue::PeriodicalValue( SGPropertyNode_ptr root ) +//------------------------------------------------------------------------------ +PeriodicalValue::PeriodicalValue( SGPropertyNode& prop_root, + SGPropertyNode& cfg ) { - 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 and/or tag. Period ignored." ); - } else { - minPeriod = new InputValue( minNode ); - maxPeriod = new InputValue( maxNode ); + SGPropertyNode_ptr minNode = cfg.getChild( "min" ); + SGPropertyNode_ptr maxNode = cfg.getChild( "max" ); + if( !minNode || !maxNode ) + { + SG_LOG + ( + SG_AUTOPILOT, + SG_ALERT, + "periodical defined, but no and/or tag. Period ignored." + ); + } + else + { + minPeriod = new InputValue(prop_root, *minNode); + maxPeriod = new InputValue(prop_root, *maxNode); } } +//------------------------------------------------------------------------------ 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 { double minValue = minPeriod->get_value(); @@ -52,101 +66,100 @@ double PeriodicalValue::normalizeSymmetric( double value ) const return value > width_2 ? width_2 - value : value; } -InputValue::InputValue( SGPropertyNode_ptr node, double value, double offset, double scale) : +//------------------------------------------------------------------------------ +InputValue::InputValue( SGPropertyNode& prop_root, + SGPropertyNode& cfg, + double value, + double offset, + double scale ): _value(0.0), _abs(false) { - parse( node, value, offset, scale ); + parse(prop_root, cfg, value, offset, scale); } - -void InputValue::parse( SGPropertyNode_ptr node, double aValue, double aOffset, double aScale ) +//------------------------------------------------------------------------------ +void InputValue::parse( SGPropertyNode& prop_root, + SGPropertyNode& cfg, + double aValue, + double aOffset, + double aScale ) { - _value = aValue; - _property = NULL; - _offset = NULL; - _scale = NULL; - _min = NULL; - _max = NULL; - _periodical = NULL; + _value = aValue; + _property = NULL; + _offset = NULL; + _scale = NULL; + _min = NULL; + _max = NULL; + _periodical = NULL; - if( node == NULL ) - return; + SGPropertyNode * n; - SGPropertyNode * n; + if( (n = cfg.getChild("condition")) != NULL ) + _condition = sgReadCondition(&prop_root, n); - if( (n = node->getChild("condition")) != NULL ) { - _condition = sgReadCondition(fgGetNode("/"), n); + if( (n = cfg.getChild( "scale" )) != NULL ) + _scale = new InputValue(prop_root, *n, aScale); + + if( (n = cfg.getChild( "offset" )) != NULL ) + _offset = new InputValue(prop_root, *n, aOffset); + + if( (n = cfg.getChild( "max" )) != NULL ) + _max = new InputValue(prop_root, *n); + + if( (n = cfg.getChild( "min" )) != NULL ) + _min = new InputValue(prop_root, *n); + + if( (n = cfg.getChild( "abs" )) != NULL ) + _abs = n->getBoolValue(); + + if( (n = cfg.getChild( "period" )) != NULL ) + _periodical = new PeriodicalValue(prop_root, *n); + + + SGPropertyNode *valueNode = cfg.getChild("value"); + if( valueNode != NULL ) + _value = valueNode->getDoubleValue(); + + if( (n = cfg.getChild("expression")) != NULL ) + { + _expression = SGReadDoubleExpression(&prop_root, n->getChild(0)); + return; + } + + // if no element, check for element for backwards + // compatibility + if( (n = cfg.getChild("property")) + || (n = cfg.getChild("prop" )) ) + { + _property = prop_root.getNode(n->getStringValue(), true); + if( valueNode ) + { + // initialize property with given value + // if both and exist + double s = get_scale(); + if( s != 0 ) + _property->setDoubleValue( (_value - get_offset())/s ); + else + _property->setDoubleValue(0); // if scale is zero, value*scale is zero } - if( (n = node->getChild( "scale" )) != NULL ) { - _scale = new InputValue( n, aScale ); - } + return; + } // of have a or - if( (n = node->getChild( "offset" )) != NULL ) { - _offset = new InputValue( n, aOffset ); - } - if( (n = node->getChild( "max" )) != NULL ) { - _max = new InputValue( n ); - } - - if( (n = node->getChild( "min" )) != NULL ) { - _min = new InputValue( n ); - } - - if( (n = node->getChild( "abs" )) != NULL ) { - _abs = n->getBoolValue(); - } - - if( (n = node->getChild( "period" )) != NULL ) { - _periodical = new PeriodicalValue( n ); - } - - SGPropertyNode *valueNode = node->getChild( "value" ); - if ( valueNode != NULL ) { - _value = valueNode->getDoubleValue(); - } - - if ((n = node->getChild("expression")) != NULL) { - _expression = SGReadDoubleExpression(fgGetNode("/"), n->getChild(0)); - return; - } - - n = node->getChild( "property" ); - // if no element, check for element for backwards - // compatibility - if( n == NULL ) - n = node->getChild( "prop" ); - - if ( n != NULL ) { - _property = fgGetNode( n->getStringValue(), true ); - if ( valueNode != NULL ) { - // initialize property with given value - // if both and exist - double s = get_scale(); - if( s != 0 ) - _property->setDoubleValue( (_value - get_offset())/s ); - else - _property->setDoubleValue( 0 ); // if scale is zero, value*scale is zero - } - - return; - } // of have a or - - - if (valueNode == NULL) { - // no , or element, use text node - const char * textnode = node->getStringValue(); - char * endp = NULL; - // try to convert to a double value. If the textnode does not start with a number - // endp will point to the beginning of the string. We assume this should be - // a property name - _value = strtod( textnode, &endp ); - if( endp == textnode ) { - _property = fgGetNode( textnode, true ); - } - } + if( !valueNode ) + { + // no , or element, use text node + const char * textnode = cfg.getStringValue(); + char * endp = NULL; + // try to convert to a double value. If the textnode does not start with a number + // endp will point to the beginning of the string. We assume this should be + // a property name + _value = strtod( textnode, &endp ); + if( endp == textnode ) + _property = prop_root.getNode(textnode, true); + } } void InputValue::set_value( double aValue ) diff --git a/src/Autopilot/inputvalue.hxx b/src/Autopilot/inputvalue.hxx index c85bfd74a..de5dd4900 100644 --- a/src/Autopilot/inputvalue.hxx +++ b/src/Autopilot/inputvalue.hxx @@ -44,7 +44,8 @@ private: InputValue_ptr minPeriod; // The minimum value of the period InputValue_ptr maxPeriod; // The maximum value of the period public: - PeriodicalValue( SGPropertyNode_ptr node ); + PeriodicalValue( SGPropertyNode& prop_root, + SGPropertyNode& cfg ); double normalize( double value ) const; double normalizeSymmetric( double value ) const; }; @@ -70,9 +71,25 @@ private: SGSharedPtr _expression; ///< expression to generate the value public: - InputValue( SGPropertyNode_ptr node = NULL, double value = 0.0, double offset = 0.0, double scale = 1.0 ); - - void parse( SGPropertyNode_ptr, double value = 0.0, double offset = 0.0, double scale = 1.0 ); + InputValue( SGPropertyNode& prop_root, + SGPropertyNode& node, + double value = 0.0, + double offset = 0.0, + double scale = 1.0 ); + + /** + * + * @param prop_root Root node for all properties with relative path + * @param cfg Configuration node + * @param value Default initial value + * @param offset Default initial offset + * @param scale Default initial scale + */ + void parse( SGPropertyNode& prop_root, + SGPropertyNode& cfg, + double value = 0.0, + double offset = 0.0, + double scale = 1.0 ); /* get the value of this input, apply scale and offset and clipping */ double get_value() const; diff --git a/src/Autopilot/pidcontroller.cxx b/src/Autopilot/pidcontroller.cxx index cff8da0db..19f16dbd7 100644 --- a/src/Autopilot/pidcontroller.cxx +++ b/src/Autopilot/pidcontroller.cxx @@ -193,54 +193,62 @@ void PIDController::update( bool firstTime, double dt ) } } -bool PIDController::configure( const std::string & nodeName, SGPropertyNode_ptr configNode ) +//------------------------------------------------------------------------------ +bool PIDController::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - SG_LOG( SG_AUTOPILOT, SG_BULK, "PIDController::configure(" << nodeName << ")" << endl ); + SG_LOG(SG_AUTOPILOT, SG_BULK, "PIDController::configure(" << cfg_name << ")"); - if( AnalogComponent::configure( nodeName, configNode ) ) + if( AnalogComponent::configure(cfg_node, cfg_name, prop_root) ) return true; - if( nodeName == "config" ) { - Component::configure( configNode ); + if( cfg_name == "config" ) { + Component::configure(prop_root, cfg_node); return true; } - if (nodeName == "Ts") { - desiredTs = configNode->getDoubleValue(); + if (cfg_name == "Ts") { + desiredTs = cfg_node.getDoubleValue(); return true; } - if (nodeName == "Kp") { - Kp.push_back( new InputValue(configNode) ); + if (cfg_name == "Kp") { + Kp.push_back( new InputValue(prop_root, cfg_node) ); return true; } - if (nodeName == "Ti") { - Ti.push_back( new InputValue(configNode) ); + if (cfg_name == "Ti") { + Ti.push_back( new InputValue(prop_root, cfg_node) ); return true; } - if (nodeName == "Td") { - Td.push_back( new InputValue(configNode) ); + if (cfg_name == "Td") { + Td.push_back( new InputValue(prop_root, cfg_node) ); return true; } - if (nodeName == "beta") { - beta = configNode->getDoubleValue(); + if (cfg_name == "beta") { + beta = cfg_node.getDoubleValue(); return true; } - if (nodeName == "alpha") { - alpha = configNode->getDoubleValue(); + if (cfg_name == "alpha") { + alpha = cfg_node.getDoubleValue(); return true; } - if (nodeName == "gamma") { - gamma = configNode->getDoubleValue(); + if (cfg_name == "gamma") { + gamma = cfg_node.getDoubleValue(); return true; } - SG_LOG( SG_AUTOPILOT, SG_BULK, "PIDController::configure(" << nodeName << ") [unhandled]" << endl ); + SG_LOG + ( + SG_AUTOPILOT, + SG_BULK, + "PIDController::configure(" << cfg_name << ") [unhandled]" + ); return false; } diff --git a/src/Autopilot/pidcontroller.hxx b/src/Autopilot/pidcontroller.hxx index da69a7389..4590de6e5 100644 --- a/src/Autopilot/pidcontroller.hxx +++ b/src/Autopilot/pidcontroller.hxx @@ -62,7 +62,9 @@ private: double elapsedTime; // elapsed time (sec) protected: - bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode); + virtual bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); public: PIDController(); ~PIDController() {} diff --git a/src/Autopilot/pisimplecontroller.cxx b/src/Autopilot/pisimplecontroller.cxx index 643471d75..6a9a4328d 100644 --- a/src/Autopilot/pisimplecontroller.cxx +++ b/src/Autopilot/pisimplecontroller.cxx @@ -25,32 +25,33 @@ using namespace FGXMLAutopilot; -using std::endl; -using std::cout; - +//------------------------------------------------------------------------------ PISimpleController::PISimpleController() : AnalogComponent(), _int_sum( 0.0 ) { } -bool PISimpleController::configure( const std::string& nodeName, SGPropertyNode_ptr configNode) +//------------------------------------------------------------------------------ +bool PISimpleController::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - if( AnalogComponent::configure( nodeName, configNode ) ) + if( AnalogComponent::configure(cfg_node, cfg_name, prop_root) ) return true; - if( nodeName == "config" ) { - Component::configure( configNode ); + if( cfg_name == "config" ) { + Component::configure(prop_root, cfg_node); return true; } - if (nodeName == "Kp") { - _Kp.push_back( new InputValue(configNode) ); + if (cfg_name == "Kp") { + _Kp.push_back( new InputValue(prop_root, cfg_node) ); return true; } - if (nodeName == "Ki") { - _Ki.push_back( new InputValue(configNode) ); + if (cfg_name == "Ki") { + _Ki.push_back( new InputValue(prop_root, cfg_node) ); return true; } @@ -64,15 +65,15 @@ void PISimpleController::update( bool firstTime, double dt ) _int_sum = 0.0; } - if ( _debug ) cout << "Updating " << get_name() << endl; + if ( _debug ) std::cout << "Updating " << get_name() << std::endl; double y_n = _valueInput.get_value(); double r_n = _referenceInput.get_value(); double error = r_n - y_n; - if ( _debug ) cout << "input = " << y_n + if ( _debug ) std::cout << "input = " << y_n << " reference = " << r_n << " error = " << error - << endl; + << std::endl; double prop_comp = clamp(error * _Kp.get_value()); _int_sum += error * _Ki.get_value() * dt; @@ -83,9 +84,9 @@ void PISimpleController::update( bool firstTime, double dt ) if( output != clamped_output ) // anti-windup _int_sum = clamped_output - prop_comp; - if ( _debug ) cout << "prop_comp = " << prop_comp - << " int_sum = " << _int_sum << endl; + if ( _debug ) std::cout << "prop_comp = " << prop_comp + << " int_sum = " << _int_sum << std::endl; set_output_value( clamped_output ); - if ( _debug ) cout << "output = " << clamped_output << endl; + if ( _debug ) std::cout << "output = " << clamped_output << std::endl; } diff --git a/src/Autopilot/pisimplecontroller.hxx b/src/Autopilot/pisimplecontroller.hxx index 06dcb01a2..3753df021 100644 --- a/src/Autopilot/pisimplecontroller.hxx +++ b/src/Autopilot/pisimplecontroller.hxx @@ -49,7 +49,9 @@ private: double _int_sum; protected: - bool configure( const std::string & nodeName, SGPropertyNode_ptr configNode ); + virtual bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); public: diff --git a/src/Autopilot/predictor.cxx b/src/Autopilot/predictor.cxx index 9e7c8030e..b7051e0c1 100644 --- a/src/Autopilot/predictor.cxx +++ b/src/Autopilot/predictor.cxx @@ -25,41 +25,49 @@ using namespace FGXMLAutopilot; -using std::endl; -using std::cout; - +//------------------------------------------------------------------------------ Predictor::Predictor () : - AnalogComponent(), - _average(0.0) + AnalogComponent(), + _last_value(0), + _average(0) { } -bool Predictor::configure(const std::string& nodeName, SGPropertyNode_ptr configNode) +//------------------------------------------------------------------------------ +bool Predictor::configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ) { - SG_LOG( SG_AUTOPILOT, SG_BULK, "Predictor::configure(" << nodeName << ")" << endl ); + SG_LOG( SG_AUTOPILOT, SG_BULK, "Predictor::configure(" << cfg_name << ")"); - if( AnalogComponent::configure( nodeName, configNode ) ) + if( AnalogComponent::configure(cfg_node, cfg_name, prop_root) ) return true; - if( nodeName == "config" ) { - Component::configure( configNode ); + if( cfg_name == "config" ) { + Component::configure(prop_root, cfg_node); return true; } - if (nodeName == "seconds") { - _seconds.push_back( new InputValue( configNode, 0 ) ); + if (cfg_name == "seconds") { + _seconds.push_back( new InputValue(prop_root, cfg_node, 0) ); return true; } - if (nodeName == "filter-gain") { - _filter_gain.push_back( new InputValue( configNode, 0 ) ); + if (cfg_name == "filter-gain") { + _filter_gain.push_back( new InputValue(prop_root, cfg_node, 0) ); return true; } - SG_LOG( SG_AUTOPILOT, SG_BULK, "Predictor::configure(" << nodeName << ") [unhandled]" << endl ); + SG_LOG + ( + SG_AUTOPILOT, + SG_BULK, + "Predictor::configure(" << cfg_name << ") [unhandled]" + ); return false; } +//------------------------------------------------------------------------------ void Predictor::update( bool firstTime, double dt ) { double ivalue = _valueInput.get_value(); @@ -80,5 +88,3 @@ void Predictor::update( bool firstTime, double dt ) _last_value = ivalue; } - - diff --git a/src/Autopilot/predictor.hxx b/src/Autopilot/predictor.hxx index e4c21b514..7221d5ec2 100644 --- a/src/Autopilot/predictor.hxx +++ b/src/Autopilot/predictor.hxx @@ -53,7 +53,9 @@ private: InputValueList _filter_gain; protected: - bool configure(const std::string& nodeName, SGPropertyNode_ptr configNode ); + virtual bool configure( SGPropertyNode& cfg_node, + const std::string& cfg_name, + SGPropertyNode& prop_root ); public: Predictor();