1 // Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Library General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 #include "HLAFederate.hxx"
20 #include "RTI13Federate.hxx"
21 #include "RTIFederate.hxx"
22 #include "RTIInteractionClass.hxx"
23 #include "RTIObjectClass.hxx"
24 #include "HLADataElement.hxx"
25 #include "HLADataType.hxx"
26 #include "HLAOMTXmlVisitor.hxx"
30 HLAFederate::HLAFederate() :
35 HLAFederate::~HLAFederate()
40 HLAFederate::getVersion() const
46 HLAFederate::setVersion(HLAFederate::Version version)
48 if (_rtiFederate.valid()) {
49 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
56 const std::list<std::string>&
57 HLAFederate::getConnectArguments() const
59 return _connectArguments;
63 HLAFederate::setConnectArguments(const std::list<std::string>& connectArguments)
65 if (_rtiFederate.valid()) {
66 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
69 _connectArguments = connectArguments;
74 HLAFederate::getFederationExecutionName() const
76 return _federationExecutionName;
80 HLAFederate::setFederationExecutionName(const std::string& federationExecutionName)
82 if (_rtiFederate.valid()) {
83 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
86 _federationExecutionName = federationExecutionName;
91 HLAFederate::getFederationObjectModel() const
93 return _federationObjectModel;
97 HLAFederate::setFederationObjectModel(const std::string& federationObjectModel)
99 if (_rtiFederate.valid()) {
100 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
103 _federationObjectModel = federationObjectModel;
108 HLAFederate::getFederateType() const
110 return _federateType;
114 HLAFederate::setFederateType(const std::string& federateType)
116 if (_rtiFederate.valid()) {
117 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
120 _federateType = federateType;
125 HLAFederate::getFederateName() const
127 return _federateName;
131 HLAFederate::setFederateName(const std::string& federateName)
133 if (_rtiFederate.valid()) {
134 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
137 _federateName = federateName;
142 HLAFederate::connect(Version version, const std::list<std::string>& stringList)
144 if (_rtiFederate.valid()) {
145 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Trying to connect to already connected federate!");
150 _rtiFederate = new RTI13Federate(stringList);
152 _connectArguments = stringList;
155 SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516 not yet(!?) supported.");
156 // _rtiFederate = new RTI1516Federate(stringList);
159 SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516E not yet(!?) supported.");
160 // _rtiFederate = new RTI1516eFederate(stringList);
163 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Unknown rti version in connect!");
165 return _rtiFederate.valid();
169 HLAFederate::connect()
171 if (_rtiFederate.valid()) {
172 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Trying to connect to already connected federate!");
177 _rtiFederate = new RTI13Federate(_connectArguments);
180 SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516 not yet(!?) supported.");
181 // _rtiFederate = new RTI1516Federate(_connectArguments);
184 SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516E not yet(!?) supported.");
185 // _rtiFederate = new RTI1516eFederate(_connectArguments);
188 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Unknown rti version in connect!");
190 return _rtiFederate.valid();
194 HLAFederate::disconnect()
196 if (!_rtiFederate.valid()) {
197 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
205 HLAFederate::createFederationExecution(const std::string& federation, const std::string& objectModel)
207 if (!_rtiFederate.valid()) {
208 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
212 RTIFederate::FederationManagementResult createResult;
213 createResult = _rtiFederate->createFederationExecution(federation, objectModel);
214 if (createResult == RTIFederate::FederationManagementFatal)
217 _federationExecutionName = federation;
218 _federationObjectModel = objectModel;
223 HLAFederate::destroyFederationExecution(const std::string& federation)
225 if (!_rtiFederate.valid()) {
226 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
230 RTIFederate::FederationManagementResult destroyResult;
231 destroyResult = _rtiFederate->destroyFederationExecution(federation);
232 if (destroyResult == RTIFederate::FederationManagementFatal)
239 HLAFederate::createFederationExecution()
241 if (!_rtiFederate.valid()) {
242 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
246 RTIFederate::FederationManagementResult createResult;
247 createResult = _rtiFederate->createFederationExecution(_federationExecutionName, _federationObjectModel);
248 if (createResult != RTIFederate::FederationManagementSuccess)
255 HLAFederate::destroyFederationExecution()
257 if (!_rtiFederate.valid()) {
258 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
262 RTIFederate::FederationManagementResult destroyResult;
263 destroyResult = _rtiFederate->destroyFederationExecution(_federationExecutionName);
264 if (destroyResult != RTIFederate::FederationManagementSuccess)
271 HLAFederate::join(const std::string& federateType, const std::string& federation)
273 if (!_rtiFederate.valid()) {
274 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
278 RTIFederate::FederationManagementResult joinResult;
279 joinResult = _rtiFederate->join(federateType, federation);
280 if (joinResult == RTIFederate::FederationManagementFatal)
289 if (!_rtiFederate.valid()) {
290 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
294 RTIFederate::FederationManagementResult joinResult;
295 joinResult = _rtiFederate->join(_federateType, _federationExecutionName);
296 if (joinResult != RTIFederate::FederationManagementSuccess)
303 HLAFederate::resign()
305 if (!_rtiFederate.valid()) {
306 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
309 return _rtiFederate->resign();
313 HLAFederate::createJoinFederationExecution()
315 if (!_rtiFederate.valid()) {
316 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
322 RTIFederate::FederationManagementResult joinResult;
323 joinResult = _rtiFederate->join(_federateType, _federationExecutionName);
324 switch (joinResult) {
325 case RTIFederate::FederationManagementSuccess:
326 // Fast return on success
328 case RTIFederate::FederationManagementFatal:
329 // Abort on fatal errors
335 // If not already joinable, try to create the requested federation
336 RTIFederate::FederationManagementResult createResult;
337 createResult = _rtiFederate->createFederationExecution(_federationExecutionName, _federationObjectModel);
338 switch (createResult) {
339 case RTIFederate::FederationManagementFatal:
340 // Abort on fatal errors
350 HLAFederate::resignDestroyFederationExecution()
352 if (!_rtiFederate.valid()) {
353 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
358 bool success = _rtiFederate->resign();
360 // and try to destroy, non fatal if still some federates joined
361 if (_rtiFederate->destroyFederationExecution(_federationExecutionName) == RTIFederate::FederationManagementFatal)
368 HLAFederate::enableTimeConstrained()
370 if (!_rtiFederate.valid()) {
371 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
375 if (!_rtiFederate->enableTimeConstrained()) {
376 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not enable time constrained!");
380 while (!_rtiFederate->getTimeConstrainedEnabled()) {
381 _rtiFederate->processMessage();
388 HLAFederate::disableTimeConstrained()
390 if (!_rtiFederate.valid()) {
391 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
394 return _rtiFederate->disableTimeConstrained();
398 HLAFederate::enableTimeRegulation(const SGTimeStamp& lookahead)
400 if (!_rtiFederate.valid()) {
401 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
405 if (!_rtiFederate->enableTimeRegulation(lookahead)) {
406 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not enable time regulation!");
410 while (!_rtiFederate->getTimeRegulationEnabled()) {
411 _rtiFederate->processMessage();
418 HLAFederate::disableTimeRegulation()
420 if (!_rtiFederate.valid()) {
421 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
424 return _rtiFederate->disableTimeRegulation();
428 HLAFederate::modifyLookahead(const SGTimeStamp& timeStamp)
430 if (!_rtiFederate.valid()) {
431 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
434 return _rtiFederate->modifyLookahead(timeStamp);
438 HLAFederate::timeAdvanceBy(const SGTimeStamp& timeIncrement)
440 if (!_rtiFederate.valid()) {
441 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
445 SGTimeStamp timeStamp;
446 if (!_rtiFederate->queryFederateTime(timeStamp)) {
447 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not query federate time!");
451 if (!_rtiFederate->timeAdvanceRequest(timeStamp + timeIncrement)) {
452 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
456 return processMessages();
460 HLAFederate::timeAdvance(const SGTimeStamp& timeStamp)
462 if (!_rtiFederate.valid()) {
463 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
467 if (!_rtiFederate->timeAdvanceRequest(timeStamp)) {
468 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
472 return processMessages();
476 HLAFederate::timeAdvanceAvailable()
478 if (!_rtiFederate.valid()) {
479 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
483 SGTimeStamp timeStamp;
484 if (!_rtiFederate->queryGALT(timeStamp)) {
485 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not query GALT!");
489 if (!_rtiFederate->timeAdvanceRequestAvailable(timeStamp)) {
490 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
494 return processMessages();
498 HLAFederate::queryFederateTime(SGTimeStamp& timeStamp)
500 if (!_rtiFederate.valid()) {
501 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
504 return _rtiFederate->queryFederateTime(timeStamp);
508 HLAFederate::queryLookahead(SGTimeStamp& timeStamp)
510 if (!_rtiFederate.valid()) {
511 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
514 return _rtiFederate->queryLookahead(timeStamp);
518 HLAFederate::processMessage()
520 if (!_rtiFederate.valid()) {
521 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
524 return _rtiFederate->processMessage();
528 HLAFederate::processMessage(const SGTimeStamp& timeout)
530 if (!_rtiFederate.valid()) {
531 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
534 return _rtiFederate->processMessages(timeout.toSecs(), 0);
538 HLAFederate::processMessages()
540 if (!_rtiFederate.valid()) {
541 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
545 while (_rtiFederate->getTimeAdvancePending()) {
546 _rtiFederate->processMessage();
549 // Now flush just what is left
550 while (!_rtiFederate->processMessages(0, 0));
556 HLAFederate::tick(const double& minimum, const double& maximum)
558 if (!_rtiFederate.valid()) {
559 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
562 return _rtiFederate->processMessages(minimum, maximum);
566 HLAFederate::readObjectModelTemplate(const std::string& objectModel,
567 HLAFederate::ObjectModelFactory& objectModelFactory)
569 if (!_rtiFederate.valid()) {
570 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
574 // The XML version of the federate object model.
575 // This one covers the generic attributes, parameters and data types.
576 HLAOMTXmlVisitor omtXmlVisitor;
578 readXML(objectModel, omtXmlVisitor);
579 } catch (const sg_throwable& e) {
580 SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file: "
584 SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file");
588 unsigned numObjectClasses = omtXmlVisitor.getNumObjectClasses();
589 for (unsigned i = 0; i < numObjectClasses; ++i) {
590 const HLAOMTXmlVisitor::ObjectClass* objectClass = omtXmlVisitor.getObjectClass(i);
591 std::string objectClassName = objectClass->getName();
593 SGSharedPtr<HLAObjectClass> hlaObjectClass = objectModelFactory.createObjectClass(objectClassName, *this);
594 if (!hlaObjectClass.valid()) {
595 SG_LOG(SG_IO, SG_INFO, "Ignoring object class \"" << objectClassName << "\".");
599 bool publish = objectModelFactory.publishObjectClass(objectClassName, objectClass->getSharing());
600 bool subscribe = objectModelFactory.subscribeObjectClass(objectClassName, objectClass->getSharing());
602 std::set<unsigned> subscriptions;
603 std::set<unsigned> publications;
605 // process the attributes
606 for (unsigned j = 0; j < objectClass->getNumAttributes(); ++j) {
607 const simgear::HLAOMTXmlVisitor::Attribute* attribute;
608 attribute = objectClass->getAttribute(j);
610 std::string attributeName = attribute->getName();
611 unsigned index = hlaObjectClass->getAttributeIndex(attributeName);
614 SG_LOG(SG_IO, SG_WARN, "RTI does not know the \"" << attributeName << "\" attribute!");
618 SGSharedPtr<HLADataType> dataType;
619 dataType = omtXmlVisitor.getAttributeDataType(objectClassName, attributeName);
620 if (!dataType.valid()) {
621 SG_LOG(SG_IO, SG_WARN, "Could not find data type for attribute \""
622 << attributeName << "\" in object class \"" << objectClassName << "\"!");
624 hlaObjectClass->setAttributeDataType(index, dataType);
626 HLAUpdateType updateType = HLAUndefinedUpdate;
627 if (attribute->_updateType == "Periodic")
628 updateType = HLAPeriodicUpdate;
629 else if (attribute->_updateType == "Static")
630 updateType = HLAStaticUpdate;
631 else if (attribute->_updateType == "Conditional")
632 updateType = HLAConditionalUpdate;
633 hlaObjectClass->setAttributeUpdateType(index, updateType);
635 if (subscribe && objectModelFactory.subscribeAttribute(objectClassName, attributeName, attribute->_sharing))
636 subscriptions.insert(index);
637 if (publish && objectModelFactory.publishAttribute(objectClassName, attributeName, attribute->_sharing))
638 publications.insert(index);
642 hlaObjectClass->publish(publications);
644 hlaObjectClass->subscribe(subscriptions, true);
646 _objectClassMap[objectClassName] = hlaObjectClass;
653 HLAFederate::getObjectClass(const std::string& name)
655 ObjectClassMap::const_iterator i = _objectClassMap.find(name);
656 if (i == _objectClassMap.end())
658 return i->second.get();
661 const HLAObjectClass*
662 HLAFederate::getObjectClass(const std::string& name) const
664 ObjectClassMap::const_iterator i = _objectClassMap.find(name);
665 if (i == _objectClassMap.end())
667 return i->second.get();
671 HLAFederate::getInteractionClass(const std::string& name)
673 InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
674 if (i == _interactionClassMap.end())
676 return i->second.get();
679 const HLAInteractionClass*
680 HLAFederate::getInteractionClass(const std::string& name) const
682 InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
683 if (i == _interactionClassMap.end())
685 return i->second.get();
688 } // namespace simgear