#include <string>
#include <vector>
+#include <simgear/props/props_io.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/structure/exception.hxx>
#include <Main/fg_props.hxx>
+#include <boost/foreach.hpp>
-
+using std::vector;
using simgear::PropertyList;
+using FGXMLAutopilot::Autopilot;
-class FGXMLAutopilotGroupImplementation : public FGXMLAutopilotGroup
+class FGXMLAutopilotGroupImplementation:
+ public FGXMLAutopilotGroup
{
-public:
+ public:
+ FGXMLAutopilotGroupImplementation(const std::string& nodeName):
+ FGXMLAutopilotGroup(),
+ _nodeName(nodeName)
+ {}
+
+ virtual void addAutopilot( const std::string& name,
+ SGPropertyNode_ptr apNode,
+ SGPropertyNode_ptr config );
+ virtual void removeAutopilot( const std::string & name );
void init();
+ InitStatus incrementalInit();
void reinit();
- void update( double dt );
-private:
+
+ private:
void initFrom( SGPropertyNode_ptr rootNode, const char * childName );
- vector<string> _autopilotNames;
+ std::string _nodeName;
};
-void FGXMLAutopilotGroupImplementation::update( double dt )
+//------------------------------------------------------------------------------
+void FGXMLAutopilotGroupImplementation::addAutopilot( const std::string& name,
+ SGPropertyNode_ptr apNode,
+ SGPropertyNode_ptr config )
+{
+ if( has_subsystem(name) )
+ {
+ SG_LOG( SG_AUTOPILOT,
+ SG_ALERT,
+ "NOT adding duplicate " << _nodeName << " name '" << name << "'");
+ return;
+ }
+
+ Autopilot* ap = new Autopilot(apNode, config);
+ ap->set_name( name );
+
+ double updateInterval = config->getDoubleValue("update-interval-secs", 0.0);
+ set_subsystem( name, ap, updateInterval );
+}
+
+//------------------------------------------------------------------------------
+void FGXMLAutopilotGroupImplementation::removeAutopilot(const std::string& name)
{
- // update all configured autopilots
- SGSubsystemGroup::update( dt );
+ Autopilot* ap = static_cast<Autopilot*>(get_subsystem(name));
+ if( !ap )
+ {
+ SG_LOG( SG_AUTOPILOT,
+ SG_ALERT,
+ "CAN NOT remove unknown " << _nodeName << " '" << name << "'");
+ return;
+ }
+
+ remove_subsystem(name);
}
+//------------------------------------------------------------------------------
void FGXMLAutopilotGroupImplementation::reinit()
{
- SGSubsystemGroup::unbind();
+ SGSubsystemGroup::unbind();
+ clearSubsystems();
- for( vector<string>::size_type i = 0; i < _autopilotNames.size(); i++ ) {
- FGXMLAutopilot::Autopilot * ap = (FGXMLAutopilot::Autopilot*)get_subsystem( _autopilotNames[i] );
- if( ap == NULL ) continue; // ?
- remove_subsystem( _autopilotNames[i] );
- delete ap;
- }
- _autopilotNames.clear();
- init();
+ init();
+}
+
+//------------------------------------------------------------------------------
+SGSubsystem::InitStatus FGXMLAutopilotGroupImplementation::incrementalInit()
+{
+ init();
+ return INIT_DONE;
}
+//------------------------------------------------------------------------------
void FGXMLAutopilotGroupImplementation::init()
{
- static const char * nodeNames[] = {
- "autopilot",
- "property-rule"
- };
- for( unsigned i = 0; i < sizeof(nodeNames)/sizeof(nodeNames[0]); i++ )
- initFrom( fgGetNode( "/sim/systems" ), nodeNames[i] );
-
- SGSubsystemGroup::bind();
- SGSubsystemGroup::init();
+ initFrom(fgGetNode("/sim/systems"), _nodeName.c_str());
+
+ SGSubsystemGroup::bind();
+ SGSubsystemGroup::init();
}
-void FGXMLAutopilotGroupImplementation::initFrom( SGPropertyNode_ptr rootNode, const char * childName )
+//------------------------------------------------------------------------------
+void FGXMLAutopilotGroupImplementation::initFrom( SGPropertyNode_ptr rootNode,
+ const char* childName )
{
- if( rootNode == NULL )
- return;
-
- PropertyList autopilotNodes = rootNode->getChildren(childName);
- for( PropertyList::size_type i = 0; i < autopilotNodes.size(); i++ ) {
- SGPropertyNode_ptr pathNode = autopilotNodes[i]->getNode( "path" );
- if( pathNode == NULL ) {
- SG_LOG( SG_ALL, SG_WARN, "No configuration file specified for this property-rule!");
- continue;
- }
-
- string apName;
- SGPropertyNode_ptr nameNode = autopilotNodes[i]->getNode( "name" );
- if( nameNode != NULL ) {
- apName = nameNode->getStringValue();
- } else {
+ if( !rootNode )
+ return;
+
+ BOOST_FOREACH( SGPropertyNode_ptr autopilotNode,
+ rootNode->getChildren(childName) )
+ {
+ SGPropertyNode_ptr pathNode = autopilotNode->getNode("path");
+ if( !pathNode )
+ {
+ SG_LOG
+ (
+ SG_AUTOPILOT,
+ SG_WARN,
+ "No configuration file specified for this " << childName << "!"
+ );
+ continue;
+ }
+
+ std::string apName;
+ SGPropertyNode_ptr nameNode = autopilotNode->getNode( "name" );
+ if( nameNode != NULL ) {
+ apName = nameNode->getStringValue();
+ } else {
+ std::ostringstream buf;
+ buf << "unnamed_autopilot_" << autopilotNode->getIndex();
+ apName = buf.str();
+ }
+
+ {
+ // check for duplicate names
+ std::string name = apName;
+ for( unsigned i = 0; get_subsystem( apName.c_str() ) != NULL; i++ ) {
std::ostringstream buf;
- buf << "unnamed_autopilot_" << i;
+ buf << name << "_" << i;
apName = buf.str();
- }
-
- {
- // check for duplicate names
- string name = apName;
- for( unsigned i = 0; get_subsystem( apName.c_str() ) != NULL; i++ ) {
- ostringstream buf;
- buf << name << "_" << i;
- apName = buf.str();
- }
- if( apName != name )
- SG_LOG( SG_ALL, SG_WARN, "Duplicate property-rule configuration name " << name << ", renamed to " << apName );
- }
-
- SGPath config = globals->resolve_maybe_aircraft_path(pathNode->getStringValue());
- if (config.isNull())
- {
- SG_LOG( SG_ALL, SG_ALERT, "Cannot find property-rule configuration file '" << pathNode->getStringValue() << "'." );
- }
- else
- {
- SG_LOG( SG_ALL, SG_INFO, "Reading property-rule configuration from " << config.str() );
-
- try {
- SGPropertyNode_ptr root = new SGPropertyNode();
- readProperties( config.str(), root );
-
- SG_LOG( SG_AUTOPILOT, SG_INFO, "adding property-rule subsystem " << apName );
- FGXMLAutopilot::Autopilot * ap = new FGXMLAutopilot::Autopilot( autopilotNodes[i], root );
- ap->set_name( apName );
- set_subsystem( apName, ap );
- _autopilotNames.push_back( apName );
-
- } catch (const sg_exception& e) {
- SG_LOG( SG_AUTOPILOT, SG_ALERT, "Failed to load property-rule configuration: "
- << config.str() << ":" << e.getMessage() );
- continue;
- }
- }
+ }
+ if( apName != name )
+ SG_LOG
+ (
+ SG_AUTOPILOT,
+ SG_WARN,
+ "Duplicate " << childName << " configuration name " << name
+ << ", renamed to " << apName
+ );
}
+
+ addAutopilotFromFile(apName, autopilotNode, pathNode->getStringValue());
+ }
+}
+
+void FGXMLAutopilotGroup::addAutopilotFromFile( const std::string& name,
+ SGPropertyNode_ptr apNode,
+ const char* path )
+{
+ SGPath config = globals->resolve_maybe_aircraft_path(path);
+ if( config.isNull() )
+ {
+ SG_LOG
+ (
+ SG_AUTOPILOT,
+ SG_ALERT,
+ "Cannot find property-rule configuration file '" << path << "'."
+ );
+ return;
+ }
+ SG_LOG
+ (
+ SG_AUTOPILOT,
+ SG_INFO,
+ "Reading property-rule configuration from " << config.str()
+ );
+
+ try
+ {
+ SGPropertyNode_ptr configNode = new SGPropertyNode();
+ readProperties( config.str(), configNode );
+
+ SG_LOG(SG_AUTOPILOT, SG_INFO, "adding property-rule subsystem " << name);
+ addAutopilot(name, apNode, configNode);
+ }
+ catch (const sg_exception& e)
+ {
+ SG_LOG
+ (
+ SG_AUTOPILOT,
+ SG_ALERT,
+ "Failed to load property-rule configuration: " << config.str()
+ << ": " << e.getMessage()
+ );
+ return;
+ }
}
-FGXMLAutopilotGroup * FGXMLAutopilotGroup::createInstance()
+//------------------------------------------------------------------------------
+FGXMLAutopilotGroup*
+FGXMLAutopilotGroup::createInstance(const std::string& nodeName)
{
- return new FGXMLAutopilotGroupImplementation();
+ return new FGXMLAutopilotGroupImplementation(nodeName);
}