// autopilot.cxx - an even more flexible, generic way to build autopilots // // Written by Torsten Dreyer // Based heavily on work created by Curtis Olson, started January 2004. // // Copyright (C) 2004 Curtis L. Olson - http://www.flightgear.org/~curt // Copyright (C) 2010 Torsten Dreyer - Torsten (at) t3r (dot) de // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // #ifdef HAVE_CONFIG_H # include #endif #include "functor.hxx" #include "predictor.hxx" #include "digitalfilter.hxx" #include "pisimplecontroller.hxx" #include "pidcontroller.hxx" #include "autopilot.hxx" #include "logic.hxx" #include "flipflop.hxx" #include "Main/fg_props.hxx" using namespace FGXMLAutopilot; Autopilot::Autopilot( SGPropertyNode_ptr rootNode, SGPropertyNode_ptr configNode ) : _name("unnamed autopilot"), _serviceable(true), _rootNode(rootNode) { map *> componentForge; componentForge["pid-controller"] = new CreateAndConfigureFunctor(); componentForge["pi-simple-controller"] = new CreateAndConfigureFunctor(); componentForge["predict-simple"] = new CreateAndConfigureFunctor(); componentForge["filter"] = new CreateAndConfigureFunctor(); componentForge["logic"] = new CreateAndConfigureFunctor(); componentForge["flipflop"] = new CreateAndConfigureFunctor(); if( configNode == NULL ) configNode = rootNode; int count = configNode->nChildren(); 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 << ">" << endl ); continue; } Component * component = (*componentForge[childName])(node); if( component->get_name().length() == 0 ) { ostringstream buf; buf << "unnamed_component_" << i; component->set_name( buf.str() ); } SG_LOG( SG_AUTOPILOT, SG_INFO, "adding autopilot component \"" << childName << "\" as \"" << component->get_name() << "\"" ); add_component(component); } } Autopilot::~Autopilot() { } void Autopilot::bind() { fgTie( _rootNode->getNode("serviceable", true)->getPath().c_str(), this, &Autopilot::is_serviceable, &Autopilot::set_serviceable ); } void Autopilot::unbind() { _rootNode->untie( "serviceable" ); } void Autopilot::add_component( Component * component ) { if( component == NULL ) return; std::string name = component->get_name(); if( get_subsystem( name.c_str() ) != NULL ) { SG_LOG( SG_ALL, SG_ALERT, "Duplicate autopilot component " << name << " ignored" ); return; } set_subsystem( name.c_str(), component ); } void Autopilot::update( double dt ) { if( !_serviceable || dt <= SGLimitsd::min() ) return; SGSubsystemGroup::update( dt ); }