-// 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"
_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
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
{
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
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!");
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
- _rtiFederate = 0;
+
+ _clearRTI();
return true;
}
}
while (!_rtiFederate->getTimeConstrainedEnabled()) {
- _rtiFederate->processMessage();
+ if (RTIFederate::ProcessMessageFatal == _rtiFederate->processMessage()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Fatal error on processing messages!");
+ return false;
+ }
}
return true;
}
while (!_rtiFederate->getTimeRegulationEnabled()) {
- _rtiFederate->processMessage();
+ if (RTIFederate::ProcessMessageFatal == _rtiFederate->processMessage()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Fatal error on processing messages!");
+ return false;
+ }
}
return true;
}
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();
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
- return _rtiFederate->processMessage();
+
+ if (RTIFederate::ProcessMessageFatal == _rtiFederate->processMessage()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Fatal error on processing messages!");
+ return false;
+ }
+ return true;
}
bool
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
- return _rtiFederate->processMessages(timeout.toSecs(), 0);
+
+ if (RTIFederate::ProcessMessageFatal == _rtiFederate->processMessages(timeout.toSecs(), 0)) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Fatal error on processing messages!");
+ return false;
+ }
+ return true;
}
bool
}
while (_rtiFederate->getTimeAdvancePending()) {
- _rtiFederate->processMessage();
+ if (RTIFederate::ProcessMessageFatal == _rtiFederate->processMessage()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Fatal error on processing messages!");
+ return false;
+ }
}
if (_timeConstrainedByLocalClock) {
double rest = (systemTime - SGTimeStamp::now()).toSecs();
if (rest < 0)
break;
- _rtiFederate->processMessages(rest, rest);
+ if (RTIFederate::ProcessMessageFatal == _rtiFederate->processMessages(rest, rest)) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Fatal error on processing messages!");
+ return false;
+ }
}
}
// Now flush just what is left
- while (_rtiFederate->processMessages(0, 0));
+ while (true) {
+ RTIFederate::ProcessMessageResult result = _rtiFederate->processMessages(0, 0);
+ if (RTIFederate::ProcessMessageLast == result)
+ break;
+ if (RTIFederate::ProcessMessageFatal == result) {
+ SG_LOG(SG_NETWORK, SG_WARN, "HLA: Fatal error on processing messages!");
+ return false;
+ }
+ }
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_WARN, "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;
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);
- SGSharedPtr<HLAObjectClass> hlaObjectClass = objectModelFactory.createObjectClass(objectClassName, *this);
- if (!hlaObjectClass.valid()) {
- SG_LOG(SG_IO, SG_INFO, "Ignoring object class \"" << objectClassName << "\".");
- continue;
- }
+ return resolveObjectModel();
+}
- bool publish = objectModelFactory.publishObjectClass(objectClassName, objectClass->getSharing());
- bool subscribe = objectModelFactory.subscribeObjectClass(objectClassName, objectClass->getSharing());
+bool
+HLAFederate::readRTI1516EObjectModelTemplate(const std::string& objectModel)
+{
+ SG_LOG(SG_IO, SG_WARN, "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;
+ }
- std::set<unsigned> subscriptions;
- std::set<unsigned> publications;
+ 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);
+ }
- // process the attributes
- for (unsigned j = 0; j < objectClass->getNumAttributes(); ++j) {
- const simgear::HLAOMTXmlVisitor::Attribute* attribute;
- attribute = objectClass->getAttribute(j);
+ 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);
+ }
- std::string attributeName = attribute->getName();
- unsigned index = hlaObjectClass->getAttributeIndex(attributeName);
+ return true;
+}
- if (index == ~0u) {
- SG_LOG(SG_IO, SG_WARN, "RTI does not know the \"" << attributeName << "\" attribute!");
- continue;
- }
+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();
+}
- 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);
+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);
+}
- if (publish)
- hlaObjectClass->publish(publications);
- if (subscribe)
- hlaObjectClass->subscribe(subscriptions, true);
+HLAInteractionClass*
+HLAFederate::getInteractionClass(const std::string& name)
+{
+ InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
+ if (i == _interactionClassMap.end())
+ return 0;
+ return i->second.get();
+}
- _objectClassMap[objectClassName] = hlaObjectClass;
- }
+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();
+}
- return true;
+HLAInteractionClass*
+HLAFederate::createInteractionClass(const std::string& name)
+{
+ return new HLAInteractionClass(name, this);
}
HLAObjectClass*
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)
{
bool
HLAFederate::readObjectModel()
{
- /// Currently empty, but is called at the right time so that
- /// the object model is present when it is needed
- return true;
+ // 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()
{
- /// Currently empty, but is called at the right time
+ 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()
{
- /// Currently empty, but is called at the right time
+ 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::update()
{
- return timeAdvanceBy(_timeIncrement);
+ if (_timeIncrement <= SGTimeStamp::fromSec(0))
+ return processMessages();
+ else
+ return timeAdvanceBy(_timeIncrement);
}
bool
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(HLAInteractionClass* interactionClass)
+{
+ if (!interactionClass)
+ 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(HLAObjectClass* objectClass)
+{
+ if (!objectClass)
+ 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(HLAObjectInstance* objectInstance)
+{
+ if (!objectInstance)
+ 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