]> git.mxchange.org Git - simgear.git/blobdiff - simgear/hla/HLAFederate.cxx
Merge branch 'timoore/optimizations' into next
[simgear.git] / simgear / hla / HLAFederate.cxx
index 05ba6f782299de4da38be487faae6f45803ed80b..75465af470ddf0d0fc96da1231c67c0e47db60f6 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 - 2011  Mathias Froehlich - Mathias.Froehlich@web.de
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Library General Public
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //
 
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
+
+#include <simgear/compiler.h>
+
 #include "HLAFederate.hxx"
 
-#include "RTI13Federate.hxx"
+#include <algorithm>
+
+#include "simgear/debug/logstream.hxx"
+
 #include "RTIFederate.hxx"
+#include "RTIFederateFactoryRegistry.hxx"
+#include "RTI13FederateFactory.hxx"
 #include "RTIInteractionClass.hxx"
 #include "RTIObjectClass.hxx"
 #include "HLADataElement.hxx"
 namespace simgear {
 
 HLAFederate::HLAFederate() :
-    _version(RTI13)
+    _version(RTI13),
+    _createFederationExecution(true),
+    _timeConstrained(false),
+    _timeRegulating(false),
+    _timeConstrainedByLocalClock(false),
+    _done(false)
 {
+    // For now instantiate the current only available factory here explicitly
+    RTI13FederateFactory::instance();
 }
 
 HLAFederate::~HLAFederate()
 {
+    _clearRTI();
+
+    // Remove the data type references from the data types.
+    // This is to remove the cycles from the data types that might happen if a data type references itself
+    for (DataTypeMap::iterator i = _dataTypeMap.begin(); i != _dataTypeMap.end(); ++i) {
+        i->second->releaseDataTypeReferences();
+    }
 }
 
 HLAFederate::Version
@@ -53,6 +78,22 @@ HLAFederate::setVersion(HLAFederate::Version version)
     return true;
 }
 
+bool
+HLAFederate::setVersion(const std::string& version)
+{
+    if (version == "RTI13")
+        return setVersion(RTI13);
+    else if (version == "RTI1516")
+        return setVersion(RTI1516);
+    else if (version == "RTI1516E")
+        return setVersion(RTI1516E);
+    else {
+        /// at some time think about routing these down to the factory
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Unknown version string in HLAFederate::setVersion!");
+        return false;
+    }
+}
+
 const std::list<std::string>&
 HLAFederate::getConnectArguments() const
 {
@@ -70,6 +111,19 @@ HLAFederate::setConnectArguments(const std::list<std::string>& connectArguments)
     return true;
 }
 
+bool
+HLAFederate::getCreateFederationExecution() const
+{
+    return _createFederationExecution;
+}
+
+bool
+HLAFederate::setCreateFederationExecution(bool createFederationExecution)
+{
+    _createFederationExecution = createFederationExecution;
+    return true;
+}
+
 const std::string&
 HLAFederate::getFederationExecutionName() const
 {
@@ -141,28 +195,9 @@ HLAFederate::setFederateName(const std::string& federateName)
 bool
 HLAFederate::connect(Version version, const std::list<std::string>& stringList)
 {
-    if (_rtiFederate.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Trying to connect to already connected federate!");
-        return false;
-    }
-    switch (version) {
-    case RTI13:
-        _rtiFederate = new RTI13Federate(stringList);
-        _version = version;
-        _connectArguments = stringList;
-        break;
-    case RTI1516:
-        SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516 not yet(!?) supported.");
-        // _rtiFederate = new RTI1516Federate(stringList);
-        break;
-    case RTI1516E:
-        SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516E not yet(!?) supported.");
-        // _rtiFederate = new RTI1516eFederate(stringList);
-        break;
-    default:
-        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Unknown rti version in connect!");
-    }
-    return _rtiFederate.valid();
+    _version = version;
+    _connectArguments = stringList;
+    return connect();
 }
 
 bool
@@ -172,17 +207,22 @@ HLAFederate::connect()
         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Trying to connect to already connected federate!");
         return false;
     }
+
+    SGSharedPtr<RTIFederateFactoryRegistry> registry = RTIFederateFactoryRegistry::instance();
+    if (!registry) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLA: RTIFederateFactoryRegistry is no longer available!");
+        return false;
+    }
+
     switch (_version) {
     case RTI13:
-        _rtiFederate = new RTI13Federate(_connectArguments);
+        _rtiFederate = registry->create("RTI13", _connectArguments);
         break;
     case RTI1516:
-        SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516 not yet(!?) supported.");
-        // _rtiFederate = new RTI1516Federate(_connectArguments);
+        _rtiFederate = registry->create("RTI1516", _connectArguments);
         break;
     case RTI1516E:
-        SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516E not yet(!?) supported.");
-        // _rtiFederate = new RTI1516eFederate(_connectArguments);
+        _rtiFederate = registry->create("RTI1516E", _connectArguments);
         break;
     default:
         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Unknown rti version in connect!");
@@ -197,7 +237,8 @@ HLAFederate::disconnect()
         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
         return false;
     }
-    _rtiFederate = 0;
+
+    _clearRTI();
     return true;
 }
 
@@ -364,6 +405,128 @@ HLAFederate::resignDestroyFederationExecution()
     return success;
 }
 
+bool
+HLAFederate::getTimeConstrained() const
+{
+    return _timeConstrained;
+}
+
+bool
+HLAFederate::setTimeConstrained(bool timeConstrained)
+{
+    _timeConstrained = timeConstrained;
+
+    if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
+        if (_timeConstrained && !_rtiFederate->getTimeConstrainedEnabled()) {
+            if (!enableTimeConstrained())
+                return false;
+        } else if (!_timeConstrained && _rtiFederate->getTimeConstrainedEnabled()) {
+            if (!disableTimeConstrained())
+                return false;
+        }
+
+    }
+
+    return true;
+}
+
+bool
+HLAFederate::getTimeConstrainedByLocalClock() const
+{
+    return _timeConstrainedByLocalClock;
+}
+
+bool
+HLAFederate::setTimeConstrainedByLocalClock(bool timeConstrainedByLocalClock)
+{
+    _timeConstrainedByLocalClock = timeConstrainedByLocalClock;
+
+    if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
+        if (_timeConstrainedByLocalClock) {
+            if (!enableTimeConstrainedByLocalClock())
+                return false;
+        }
+    }
+
+    return true;
+}
+
+bool
+HLAFederate::getTimeRegulating() const
+{
+    return _timeRegulating;
+}
+
+bool
+HLAFederate::setTimeRegulating(bool timeRegulating)
+{
+    _timeRegulating = timeRegulating;
+
+    if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
+        if (_timeRegulating && !_rtiFederate->getTimeRegulationEnabled()) {
+            if (!enableTimeRegulation())
+                return false;
+        } else if (!_timeRegulating && _rtiFederate->getTimeRegulationEnabled()) {
+            if (!disableTimeRegulation())
+                return false;
+        }
+
+    }
+    return true;
+}
+
+bool
+HLAFederate::setLeadTime(const SGTimeStamp& leadTime)
+{
+    if (leadTime < SGTimeStamp::fromSec(0)) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Ignoring negative lead time!");
+        return false;
+    }
+
+    _leadTime = leadTime;
+
+    if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
+        if (!modifyLookahead(_leadTime + SGTimeStamp::fromSec(_timeIncrement.toSecs()*0.9))) {
+            SG_LOG(SG_NETWORK, SG_WARN, "Cannot modify lookahead!");
+            return false;
+        }
+    }
+
+    return true;
+}
+
+const SGTimeStamp&
+HLAFederate::getLeadTime() const
+{
+    return _leadTime;
+}
+
+bool
+HLAFederate::setTimeIncrement(const SGTimeStamp& timeIncrement)
+{
+    if (timeIncrement < SGTimeStamp::fromSec(0)) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Ignoring negative time increment!");
+        return false;
+    }
+
+    _timeIncrement = timeIncrement;
+
+    if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
+        if (!modifyLookahead(_leadTime + SGTimeStamp::fromSec(_timeIncrement.toSecs()*0.9))) {
+            SG_LOG(SG_NETWORK, SG_WARN, "Cannot modify lookahead!");
+            return false;
+        }
+    }
+
+    return true;
+}
+
+const SGTimeStamp&
+HLAFederate::getTimeIncrement() const
+{
+    return _timeIncrement;
+}
+
 bool
 HLAFederate::enableTimeConstrained()
 {
@@ -394,6 +557,19 @@ HLAFederate::disableTimeConstrained()
     return _rtiFederate->disableTimeConstrained();
 }
 
+bool
+HLAFederate::enableTimeConstrainedByLocalClock()
+{
+    // Compute the time offset from the system time to the simulation time
+    SGTimeStamp federateTime;
+    if (!queryFederateTime(federateTime)) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Cannot get federate time!");
+        return false;
+    }
+    _localClockOffset = SGTimeStamp::now() - federateTime;
+    return true;
+}
+
 bool
 HLAFederate::enableTimeRegulation(const SGTimeStamp& lookahead)
 {
@@ -414,6 +590,20 @@ HLAFederate::enableTimeRegulation(const SGTimeStamp& lookahead)
     return true;
 }
 
+bool
+HLAFederate::enableTimeRegulation()
+{
+    if (!enableTimeRegulation(SGTimeStamp::fromSec(0))) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Cannot enable time regulation!");
+        return false;
+    }
+    if (!modifyLookahead(_leadTime + SGTimeStamp::fromSec(_timeIncrement.toSecs()*0.9))) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Cannot modify lookahead!");
+        return false;
+    }
+    return true;
+}
+
 bool
 HLAFederate::disableTimeRegulation()
 {
@@ -481,14 +671,11 @@ HLAFederate::timeAdvanceAvailable()
     }
 
     SGTimeStamp timeStamp;
-    if (!_rtiFederate->queryGALT(timeStamp)) {
-        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not query GALT!");
-        return false;
-    }
-
-    if (!_rtiFederate->timeAdvanceRequestAvailable(timeStamp)) {
-        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
-        return false;
+    if (_rtiFederate->queryGALT(timeStamp)) {
+        if (!_rtiFederate->timeAdvanceRequestAvailable(timeStamp)) {
+            SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
+            return false;
+        }
     }
 
     return processMessages();
@@ -546,31 +733,37 @@ HLAFederate::processMessages()
         _rtiFederate->processMessage();
     }
 
+    if (_timeConstrainedByLocalClock) {
+        SGTimeStamp federateTime;
+        if (!_rtiFederate->queryFederateTime(federateTime)) {
+            SG_LOG(SG_NETWORK, SG_WARN, "HLA: Error querying federate time!");
+            return false;
+        }
+        SGTimeStamp systemTime = federateTime + _localClockOffset;
+        for (;;) {
+            double rest = (systemTime - SGTimeStamp::now()).toSecs();
+            if (rest < 0)
+                break;
+            _rtiFederate->processMessages(rest, rest);
+        }
+    }
+    
     // Now flush just what is left
-    while (!_rtiFederate->processMessages(0, 0));
+    while (_rtiFederate->processMessages(0, 0));
 
     return true;
 }
 
 bool
-HLAFederate::tick(const double& minimum, const double& maximum)
+HLAFederate::readRTI13ObjectModelTemplate(const std::string& objectModel)
 {
-    if (!_rtiFederate.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
-        return false;
-    }
-    return _rtiFederate->processMessages(minimum, maximum);
+    SG_LOG(SG_IO, SG_ALERT, "HLA version RTI13 not yet(!?) supported.");
+    return false;
 }
 
 bool
-HLAFederate::readObjectModelTemplate(const std::string& objectModel,
-                                     HLAFederate::ObjectModelFactory& objectModelFactory)
+HLAFederate::readRTI1516ObjectModelTemplate(const std::string& objectModel)
 {
-    if (!_rtiFederate.valid()) {
-        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
-        return false;
-    }
-
     // The XML version of the federate object model.
     // This one covers the generic attributes, parameters and data types.
     HLAOMTXmlVisitor omtXmlVisitor;
@@ -585,70 +778,110 @@ HLAFederate::readObjectModelTemplate(const std::string& objectModel,
         return false;
     }
 
-    unsigned numObjectClasses = omtXmlVisitor.getNumObjectClasses();
-    for (unsigned i = 0; i < numObjectClasses; ++i) {
-        const HLAOMTXmlVisitor::ObjectClass* objectClass = omtXmlVisitor.getObjectClass(i);
-        std::string objectClassName = objectClass->getName();
+    omtXmlVisitor.setToFederate(*this);
+
+    return resolveObjectModel();
+}
+
+bool
+HLAFederate::readRTI1516EObjectModelTemplate(const std::string& objectModel)
+{
+    SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516E not yet(!?) supported.");
+    return false;
+}
+
+bool
+HLAFederate::resolveObjectModel()
+{
+    if (!_rtiFederate.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+        return false;
+    }
 
-        SGSharedPtr<HLAObjectClass> hlaObjectClass = objectModelFactory.createObjectClass(objectClassName, *this);
-        if (!hlaObjectClass.valid()) {
-            SG_LOG(SG_IO, SG_INFO, "Ignoring object class \"" << objectClassName << "\".");
-            continue;
+    for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) {
+        RTIInteractionClass* rtiInteractionClass = _rtiFederate->createInteractionClass(i->second->getName(), i->second.get());
+        if (!rtiInteractionClass) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLAFederate::_insertInteractionClass(): "
+                   "No RTIInteractionClass found for \"" << i->second->getName() << "\"!");
+            return false;
         }
+        i->second->_setRTIInteractionClass(rtiInteractionClass);
+    }
 
-        bool publish = objectModelFactory.publishObjectClass(objectClassName, objectClass->getSharing());
-        bool subscribe = objectModelFactory.subscribeObjectClass(objectClassName, objectClass->getSharing());
-
-        std::set<unsigned> subscriptions;
-        std::set<unsigned> publications;
-
-        // process the attributes
-        for (unsigned j = 0; j < objectClass->getNumAttributes(); ++j) {
-            const simgear::HLAOMTXmlVisitor::Attribute* attribute;
-            attribute = objectClass->getAttribute(j);
-
-            std::string attributeName = attribute->getName();
-            unsigned index = hlaObjectClass->getAttributeIndex(attributeName);
-
-            if (index == ~0u) {
-                SG_LOG(SG_IO, SG_WARN, "RTI does not know the \"" << attributeName << "\" attribute!");
-                continue;
-            }
-
-            SGSharedPtr<HLADataType> dataType;
-            dataType = omtXmlVisitor.getAttributeDataType(objectClassName, attributeName);
-            if (!dataType.valid()) {
-                SG_LOG(SG_IO, SG_WARN, "Could not find data type for attribute \""
-                       << attributeName << "\" in object class \"" << objectClassName << "\"!");
-            }
-            hlaObjectClass->setAttributeDataType(index, dataType);
-
-            HLAUpdateType updateType = HLAUndefinedUpdate;
-            if (attribute->_updateType == "Periodic")
-                updateType = HLAPeriodicUpdate;
-            else if (attribute->_updateType == "Static")
-                updateType = HLAStaticUpdate;
-            else if (attribute->_updateType == "Conditional")
-                updateType = HLAConditionalUpdate;
-            hlaObjectClass->setAttributeUpdateType(index, updateType);
-
-            if (subscribe && objectModelFactory.subscribeAttribute(objectClassName, attributeName, attribute->_sharing))
-                subscriptions.insert(index);
-            if (publish && objectModelFactory.publishAttribute(objectClassName, attributeName, attribute->_sharing))
-                publications.insert(index);
+    for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) {
+        RTIObjectClass* rtiObjectClass = _rtiFederate->createObjectClass(i->second->getName(), i->second.get());
+        if (!rtiObjectClass) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "HLAFederate::_insertObjectClass(): "
+                   "No RTIObjectClass found for \"" << i->second->getName() << "\"!");
+            return false;
         }
+        i->second->_setRTIObjectClass(rtiObjectClass);
+    }
 
-        if (publish)
-            hlaObjectClass->publish(publications);
-        if (subscribe)
-            hlaObjectClass->subscribe(subscriptions, true);
+    return true;
+}
 
-        _objectClassMap[objectClassName] = hlaObjectClass;
-    }
+const HLADataType*
+HLAFederate::getDataType(const std::string& name) const
+{
+    DataTypeMap::const_iterator i = _dataTypeMap.find(name);
+    if (i == _dataTypeMap.end())
+        return 0;
+    return i->second.get();
+}
 
+bool
+HLAFederate::insertDataType(const std::string& name, const SGSharedPtr<HLADataType>& dataType)
+{
+    if (!dataType.valid())
+        return false;
+    if (_dataTypeMap.find(name) != _dataTypeMap.end()) {
+        SG_LOG(SG_IO, SG_ALERT, "HLAFederate::insertDataType: data type with name \""
+               << name << "\" already known to federate!");
+        return false;
+    }
+    _dataTypeMap.insert(DataTypeMap::value_type(name, dataType));
     return true;
 }
 
+void
+HLAFederate::recomputeDataTypeAlignment()
+{
+    // Finish alignment computations
+    bool changed;
+    do {
+        changed = false;
+        for (DataTypeMap::iterator i = _dataTypeMap.begin(); i != _dataTypeMap.end(); ++i) {
+            if (i->second->recomputeAlignment())
+                changed = true;
+        }
+    } while (changed);
+}
+
+HLAInteractionClass*
+HLAFederate::getInteractionClass(const std::string& name)
+{
+    InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
+    if (i == _interactionClassMap.end())
+        return 0;
+    return i->second.get();
+}
+
+const HLAInteractionClass*
+HLAFederate::getInteractionClass(const std::string& name) const
+{
+    InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
+    if (i == _interactionClassMap.end())
+        return 0;
+    return i->second.get();
+}
+
+HLAInteractionClass*
+HLAFederate::createInteractionClass(const std::string& name)
+{
+    return new HLAInteractionClass(name, this);
+}
+
 HLAObjectClass*
 HLAFederate::getObjectClass(const std::string& name)
 {
@@ -667,22 +900,287 @@ HLAFederate::getObjectClass(const std::string& name) const
     return i->second.get();
 }
 
-HLAInteractionClass*
-HLAFederate::getInteractionClass(const std::string& name)
+HLAObjectClass*
+HLAFederate::createObjectClass(const std::string& name)
 {
-    InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
-    if (i == _interactionClassMap.end())
+    return new HLAObjectClass(name, this);
+}
+
+HLAObjectInstance*
+HLAFederate::getObjectInstance(const std::string& name)
+{
+    ObjectInstanceMap::const_iterator i = _objectInstanceMap.find(name);
+    if (i == _objectInstanceMap.end())
         return 0;
     return i->second.get();
 }
 
-const HLAInteractionClass*
-HLAFederate::getInteractionClass(const std::string& name) const
+const HLAObjectInstance*
+HLAFederate::getObjectInstance(const std::string& name) const
 {
-    InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
-    if (i == _interactionClassMap.end())
+    ObjectInstanceMap::const_iterator i = _objectInstanceMap.find(name);
+    if (i == _objectInstanceMap.end())
         return 0;
     return i->second.get();
 }
 
+HLAObjectInstance*
+HLAFederate::createObjectInstance(HLAObjectClass* objectClass, const std::string& name)
+{
+    return new HLAObjectInstance(objectClass);
+}
+
+void
+HLAFederate::setDone(bool done)
+{
+    _done = done;
+}
+
+bool
+HLAFederate::getDone() const
+{
+    return _done;
+}
+
+bool
+HLAFederate::readObjectModel()
+{
+    // Depending on the actual version, try to find an apropriate
+    // file format for the given file. The first one is always the
+    // version native object model file format.
+    switch (getVersion()) {
+    case RTI13:
+        if (readRTI13ObjectModelTemplate(getFederationObjectModel()))
+            return true;
+        if (readRTI1516ObjectModelTemplate(getFederationObjectModel()))
+            return true;
+        return readRTI1516EObjectModelTemplate(getFederationObjectModel());
+    case RTI1516:
+        if (readRTI1516ObjectModelTemplate(getFederationObjectModel()))
+            return true;
+        if (readRTI1516EObjectModelTemplate(getFederationObjectModel()))
+            return true;
+        return readRTI13ObjectModelTemplate(getFederationObjectModel());
+    case RTI1516E:
+        if (readRTI1516EObjectModelTemplate(getFederationObjectModel()))
+            return true;
+        if (readRTI1516ObjectModelTemplate(getFederationObjectModel()))
+            return true;
+        return readRTI13ObjectModelTemplate(getFederationObjectModel());
+    default:
+        return false;
+    }
+}
+
+bool
+HLAFederate::subscribe()
+{
+    for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) {
+        if (!i->second->subscribe())
+            return false;
+    }
+
+    for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) {
+        if (!i->second->subscribe())
+            return false;
+    }
+
+    return true;
+}
+
+bool
+HLAFederate::publish()
+{
+    for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) {
+        if (!i->second->publish())
+            return false;
+    }
+
+    for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) {
+        if (!i->second->publish())
+            return false;
+    }
+
+    return true;
+}
+
+bool
+HLAFederate::init()
+{
+    // We need to talk to the rti
+    if (!connect())
+        return false;
+    // Join ...
+    if (_createFederationExecution) {
+        if (!createJoinFederationExecution())
+            return false;
+    } else {
+        if (!join())
+            return false;
+    }
+    // Read the xml file containing the object model
+    if (!readObjectModel()) {
+        shutdown();
+        return false;
+    }
+    // start being time constrained if required
+    if (_timeConstrained) {
+        if (!enableTimeConstrained()) {
+            shutdown();
+            return false;
+        }
+    }
+    // Now that we are potentially time constrained, we can subscribe.
+    // This is to make sure we do not get any time stamped message
+    // converted to a non time stamped message by the rti.
+    if (!subscribe()) {
+        shutdown();
+        return false;
+    }
+    // Before we publish anything start getting regulating if required
+    if (_timeRegulating) {
+        if (!enableTimeRegulation()) {
+            shutdown();
+            return false;
+        }
+    }
+    // Note that starting from here, we need to be careful with things
+    // requireing unbounded time. The rest of the federation might wait
+    // for us to finish!
+    
+    // Compute the time offset from the system time to the simulation time
+    if (_timeConstrainedByLocalClock) {
+        if (!enableTimeConstrainedByLocalClock()) {
+            SG_LOG(SG_NETWORK, SG_WARN, "Cannot enable time constrained by local clock!");
+            shutdown();
+            return false;
+        }
+    }
+    
+    // Publish what we want to write
+    if (!publish()) {
+        shutdown();
+        return false;
+    }
+    
+    return true;
+}
+
+bool
+HLAFederate::update()
+{
+    return timeAdvanceBy(_timeIncrement);
+}
+
+bool
+HLAFederate::shutdown()
+{
+    // On shutdown, just try all in order.
+    // If something goes wrong, continue and try to get out here as good as possible.
+    bool ret = true;
+    
+    if (_createFederationExecution) {
+        if (!resignDestroyFederationExecution())
+            ret = false;
+    } else {
+        if (!resign())
+            ret = false;
+    }
+    
+    if (!disconnect())
+        ret = false;
+    
+    return ret;
+}
+
+bool
+HLAFederate::exec()
+{
+    if (!init())
+        return false;
+    
+    while (!getDone()) {
+        if (!update()) {
+            shutdown();
+            return false;
+        }
+    }
+    
+    if (!shutdown())
+        return false;
+    
+    return true;
+}
+
+void
+HLAFederate::_clearRTI()
+{
+    for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i)
+        i->second->_clearRTIInteractionClass();
+    for (ObjectInstanceMap::iterator i = _objectInstanceMap.begin(); i != _objectInstanceMap.end(); ++i)
+        i->second->_clearRTIObjectInstance();
+    for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i)
+        i->second->_clearRTIObjectClass();
+
+    _rtiFederate = 0;
+}
+
+bool
+HLAFederate::_insertInteractionClass(const SGSharedPtr<HLAInteractionClass>& interactionClass)
+{
+    if (!interactionClass.valid())
+        return false;
+    if (_interactionClassMap.find(interactionClass->getName()) != _interactionClassMap.end()) {
+        SG_LOG(SG_IO, SG_ALERT, "HLA: _insertInteractionClass: object instance with name \""
+               << interactionClass->getName() << "\" already known to federate!");
+        return false;
+    }
+    _interactionClassMap.insert(InteractionClassMap::value_type(interactionClass->getName(), interactionClass));
+    return true;
+}
+
+bool
+HLAFederate::_insertObjectClass(const SGSharedPtr<HLAObjectClass>& objectClass)
+{
+    if (!objectClass.valid())
+        return false;
+    if (_objectClassMap.find(objectClass->getName()) != _objectClassMap.end()) {
+        SG_LOG(SG_IO, SG_ALERT, "HLA: _insertObjectClass: object instance with name \""
+               << objectClass->getName() << "\" already known to federate!");
+        return false;
+    }
+    _objectClassMap.insert(ObjectClassMap::value_type(objectClass->getName(), objectClass));
+    return true;
+}
+
+bool
+HLAFederate::_insertObjectInstance(const SGSharedPtr<HLAObjectInstance>& objectInstance)
+{
+    if (!objectInstance.valid())
+        return false;
+    if (objectInstance->getName().empty()) {
+        SG_LOG(SG_IO, SG_ALERT, "HLA: _insertObjectInstance: trying to insert object instance with empty name!");
+        return false;
+    }
+    if (_objectInstanceMap.find(objectInstance->getName()) != _objectInstanceMap.end()) {
+        SG_LOG(SG_IO, SG_WARN, "HLA: _insertObjectInstance: object instance with name \""
+               << objectInstance->getName() << "\" already known to federate!");
+        return false;
+    }
+    _objectInstanceMap.insert(ObjectInstanceMap::value_type(objectInstance->getName(), objectInstance));
+    return true;
+}
+
+void
+HLAFederate::_eraseObjectInstance(const std::string& name)
+{
+    ObjectInstanceMap::iterator i = _objectInstanceMap.find(name);
+    if (i == _objectInstanceMap.end()) {
+        SG_LOG(SG_IO, SG_WARN, "HLA: _eraseObjectInstance: object instance with name \""
+               << name << "\" not known to federate!");
+        return;
+    }
+    _objectInstanceMap.erase(i);
+}
+
 } // namespace simgear