+ 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()
+{
+ if (!_rtiFederate.valid()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+ return false;
+ }
+
+ if (!_rtiFederate->enableTimeConstrained()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not enable time constrained!");
+ return false;
+ }
+
+ while (!_rtiFederate->getTimeConstrainedEnabled()) {
+ _rtiFederate->processMessage();
+ }
+
+ return true;
+}
+
+bool
+HLAFederate::disableTimeConstrained()
+{
+ if (!_rtiFederate.valid()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+ return false;
+ }
+ 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)
+{
+ if (!_rtiFederate.valid()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+ return false;
+ }
+
+ if (!_rtiFederate->enableTimeRegulation(lookahead)) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not enable time regulation!");
+ return false;
+ }
+
+ while (!_rtiFederate->getTimeRegulationEnabled()) {
+ _rtiFederate->processMessage();
+ }
+
+ 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()
+{
+ if (!_rtiFederate.valid()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+ return false;
+ }
+ return _rtiFederate->disableTimeRegulation();
+}
+
+bool
+HLAFederate::modifyLookahead(const SGTimeStamp& timeStamp)
+{
+ if (!_rtiFederate.valid()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+ return false;
+ }
+ return _rtiFederate->modifyLookahead(timeStamp);
+}
+
+bool
+HLAFederate::timeAdvanceBy(const SGTimeStamp& timeIncrement)
+{
+ if (!_rtiFederate.valid()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+ return false;
+ }
+
+ SGTimeStamp timeStamp;
+ if (!_rtiFederate->queryFederateTime(timeStamp)) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not query federate time!");
+ return false;
+ }
+
+ if (!_rtiFederate->timeAdvanceRequest(timeStamp + timeIncrement)) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
+ return false;
+ }
+
+ return processMessages();
+}
+
+bool
+HLAFederate::timeAdvance(const SGTimeStamp& timeStamp)
+{
+ if (!_rtiFederate.valid()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+ return false;
+ }
+
+ if (!_rtiFederate->timeAdvanceRequest(timeStamp)) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
+ return false;
+ }
+
+ return processMessages();
+}
+
+bool
+HLAFederate::timeAdvanceAvailable()
+{
+ if (!_rtiFederate.valid()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+ return false;
+ }
+
+ SGTimeStamp timeStamp;
+ if (_rtiFederate->queryGALT(timeStamp)) {
+ if (!_rtiFederate->timeAdvanceRequestAvailable(timeStamp)) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
+ return false;
+ }
+ }
+
+ return processMessages();
+}
+
+bool
+HLAFederate::queryFederateTime(SGTimeStamp& timeStamp)
+{
+ if (!_rtiFederate.valid()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+ return false;
+ }
+ return _rtiFederate->queryFederateTime(timeStamp);
+}
+
+bool
+HLAFederate::queryLookahead(SGTimeStamp& timeStamp)
+{
+ if (!_rtiFederate.valid()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+ return false;
+ }
+ return _rtiFederate->queryLookahead(timeStamp);
+}
+
+bool
+HLAFederate::processMessage()
+{
+ if (!_rtiFederate.valid()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+ return false;
+ }
+ return _rtiFederate->processMessage();
+}
+
+bool
+HLAFederate::processMessage(const SGTimeStamp& timeout)
+{
+ if (!_rtiFederate.valid()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+ return false;
+ }
+ return _rtiFederate->processMessages(timeout.toSecs(), 0);
+}
+
+bool
+HLAFederate::processMessages()
+{
+ if (!_rtiFederate.valid()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
+ return false;
+ }
+
+ while (_rtiFederate->getTimeAdvancePending()) {
+ _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));
+
+ return true;
+}
+
+bool
+HLAFederate::readRTI13ObjectModelTemplate(const std::string& objectModel)
+{
+ SG_LOG(SG_IO, SG_ALERT, "HLA version RTI13 not yet(!?) supported.");
+ return false;
+}
+
+bool
+HLAFederate::readRTI1516ObjectModelTemplate(const std::string& objectModel)
+{
+ // The XML version of the federate object model.
+ // This one covers the generic attributes, parameters and data types.
+ HLAOMTXmlVisitor omtXmlVisitor;
+ try {
+ readXML(objectModel, omtXmlVisitor);
+ } catch (const sg_throwable& e) {
+ SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file: "
+ << e.getMessage());
+ return false;
+ } catch (...) {
+ SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file");
+ return false;
+ }
+
+ 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;
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ return true;
+}
+
+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)
+{
+ ObjectClassMap::const_iterator i = _objectClassMap.find(name);
+ if (i == _objectClassMap.end())
+ return 0;
+ return i->second.get();
+}
+
+const HLAObjectClass*
+HLAFederate::getObjectClass(const std::string& name) const
+{
+ ObjectClassMap::const_iterator i = _objectClassMap.find(name);
+ if (i == _objectClassMap.end())
+ return 0;
+ return i->second.get();
+}
+
+HLAObjectClass*
+HLAFederate::createObjectClass(const std::string& name)
+{
+ 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 HLAObjectInstance*
+HLAFederate::getObjectInstance(const std::string& name) const
+{
+ 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);