1 // autopilot.cxx - an even more flexible, generic way to build autopilots
3 // Written by Torsten Dreyer
4 // Based heavily on work created by Curtis Olson, started January 2004.
6 // Copyright (C) 2004 Curtis L. Olson - http://www.flightgear.org/~curt
7 // Copyright (C) 2010 Torsten Dreyer - Torsten (at) t3r (dot) de
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License as
11 // published by the Free Software Foundation; either version 2 of the
12 // License, or (at your option) any later version.
14 // This program is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // General Public License for more details.
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28 #include "functor.hxx"
29 #include "predictor.hxx"
30 #include "digitalfilter.hxx"
31 #include "pisimplecontroller.hxx"
32 #include "pidcontroller.hxx"
33 #include "autopilot.hxx"
35 #include "flipflop.hxx"
37 #include "Main/fg_props.hxx"
39 using namespace FGXMLAutopilot;
41 Autopilot::Autopilot( SGPropertyNode_ptr rootNode, SGPropertyNode_ptr configNode ) :
42 _name("unnamed autopilot"),
46 map<string,FunctorBase<Component> *> componentForge;
47 componentForge["pid-controller"] = new CreateAndConfigureFunctor<PIDController,Component>();
48 componentForge["pi-simple-controller"] = new CreateAndConfigureFunctor<PISimpleController,Component>();
49 componentForge["predict-simple"] = new CreateAndConfigureFunctor<Predictor,Component>();
50 componentForge["filter"] = new CreateAndConfigureFunctor<DigitalFilter,Component>();
51 componentForge["logic"] = new CreateAndConfigureFunctor<Logic,Component>();
52 componentForge["flipflop"] = new CreateAndConfigureFunctor<FlipFlop,Component>();
54 if( configNode == NULL ) configNode = rootNode;
56 int count = configNode->nChildren();
57 for ( int i = 0; i < count; ++i ) {
58 SGPropertyNode_ptr node = configNode->getChild(i);
59 string childName = node->getName();
60 if( componentForge.count(childName) == 0 ) {
61 SG_LOG( SG_AUTOPILOT, SG_BULK, "unhandled element <" << childName << ">" << endl );
65 Component * component = (*componentForge[childName])(node);
66 if( component->get_name().length() == 0 ) {
68 buf << "unnamed_component_" << i;
69 component->set_name( buf.str() );
72 SG_LOG( SG_AUTOPILOT, SG_INFO, "adding autopilot component \"" << childName << "\" as \"" << component->get_name() << "\"" );
73 add_component(component);
77 Autopilot::~Autopilot()
81 void Autopilot::bind()
83 fgTie( _rootNode->getNode("serviceable", true)->getPath().c_str(), this,
84 &Autopilot::is_serviceable, &Autopilot::set_serviceable );
87 void Autopilot::unbind()
89 _rootNode->untie( "serviceable" );
92 void Autopilot::add_component( Component * component )
94 if( component == NULL ) return;
96 std::string name = component->get_name();
97 if( get_subsystem( name.c_str() ) != NULL ) {
98 SG_LOG( SG_ALL, SG_ALERT, "Duplicate autopilot component " << name << " ignored" );
101 set_subsystem( name.c_str(), component );
104 void Autopilot::update( double dt )
106 if( !_serviceable || dt <= SGLimitsd::min() )
108 SGSubsystemGroup::update( dt );