From f665431132c2302cfd2acf7e294b4161da5b1448 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Sun, 2 Oct 2011 10:11:10 +0200 Subject: [PATCH 1/3] hla: lift the event loop logic from RTI to HLAFederate. --- simgear/hla/HLAFederate.cxx | 131 +++++++++++++++++++++----- simgear/hla/HLAFederate.hxx | 41 +++++++-- simgear/hla/RTI13Federate.cxx | 169 ++++++++++++++++++++-------------- simgear/hla/RTI13Federate.hxx | 22 ++--- simgear/hla/RTIFederate.hxx | 18 ++-- 5 files changed, 267 insertions(+), 114 deletions(-) diff --git a/simgear/hla/HLAFederate.cxx b/simgear/hla/HLAFederate.cxx index fa1cc576..05ba6f78 100644 --- a/simgear/hla/HLAFederate.cxx +++ b/simgear/hla/HLAFederate.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2011 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 @@ -27,7 +27,8 @@ namespace simgear { -HLAFederate::HLAFederate() +HLAFederate::HLAFederate() : + _version(RTI13) { } @@ -370,7 +371,17 @@ HLAFederate::enableTimeConstrained() SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); return false; } - return _rtiFederate->enableTimeConstrained(); + + 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 @@ -390,7 +401,17 @@ HLAFederate::enableTimeRegulation(const SGTimeStamp& lookahead) SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); return false; } - return _rtiFederate->enableTimeRegulation(lookahead); + + 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 @@ -404,23 +425,73 @@ HLAFederate::disableTimeRegulation() } bool -HLAFederate::timeAdvanceRequestBy(const SGTimeStamp& dt) +HLAFederate::modifyLookahead(const SGTimeStamp& timeStamp) { if (!_rtiFederate.valid()) { SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); return false; } - return _rtiFederate->timeAdvanceRequestBy(dt); + return _rtiFederate->modifyLookahead(timeStamp); } bool -HLAFederate::timeAdvanceRequest(const SGTimeStamp& dt) +HLAFederate::timeAdvanceBy(const SGTimeStamp& timeIncrement) { if (!_rtiFederate.valid()) { SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); return false; } - return _rtiFederate->timeAdvanceRequest(dt); + + 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)) { + 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; + } + + return processMessages(); } bool @@ -433,16 +504,6 @@ HLAFederate::queryFederateTime(SGTimeStamp& timeStamp) return _rtiFederate->queryFederateTime(timeStamp); } -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::queryLookahead(SGTimeStamp& timeStamp) { @@ -454,13 +515,41 @@ HLAFederate::queryLookahead(SGTimeStamp& timeStamp) } bool -HLAFederate::tick() +HLAFederate::processMessage() { if (!_rtiFederate.valid()) { SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); return false; } - return _rtiFederate->tick(); + 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(); + } + + // Now flush just what is left + while (!_rtiFederate->processMessages(0, 0)); + + return true; } bool @@ -470,7 +559,7 @@ HLAFederate::tick(const double& minimum, const double& maximum) SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); return false; } - return _rtiFederate->tick(minimum, maximum); + return _rtiFederate->processMessages(minimum, maximum); } bool diff --git a/simgear/hla/HLAFederate.hxx b/simgear/hla/HLAFederate.hxx index f3b84afe..4c82820c 100644 --- a/simgear/hla/HLAFederate.hxx +++ b/simgear/hla/HLAFederate.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2011 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 @@ -82,21 +82,42 @@ public: bool resignDestroyFederationExecution(); + /// Time management + bool enableTimeConstrained(); bool disableTimeConstrained(); bool enableTimeRegulation(const SGTimeStamp& lookahead); bool disableTimeRegulation(); + bool modifyLookahead(const SGTimeStamp& lookahead); - bool timeAdvanceRequestBy(const SGTimeStamp& dt); - bool timeAdvanceRequest(const SGTimeStamp& dt); + /// Advance the logical time by the given time increment. + /// Depending on the time constrained mode, this might + /// block until the time advance is granted. + bool timeAdvanceBy(const SGTimeStamp& timeIncrement); + /// Advance the logical time to the given time. + /// Depending on the time constrained mode, this might + /// block until the time advance is granted. + bool timeAdvance(const SGTimeStamp& timeStamp); + /// Advance the logical time as far as time advances are available. + /// This call should not block and advance the logical time + /// as far as currently possible. + bool timeAdvanceAvailable(); bool queryFederateTime(SGTimeStamp& timeStamp); - bool modifyLookahead(const SGTimeStamp& timeStamp); bool queryLookahead(SGTimeStamp& timeStamp); - /// Process messages - bool tick(); + /// Process one messsage + bool processMessage(); + /// Process one message but do not wait longer than the relative timeout. + bool processMessage(const SGTimeStamp& timeout); + /// Process messages until the federate can proceed with the + /// next simulation step. That is flush all pending messages and + /// depending on the time constrained mode process messages until + /// a pending time advance is granted. + bool processMessages(); + + /// Legacy tick call bool tick(const double& minimum, const double& maximum); class ObjectModelFactory { @@ -128,13 +149,21 @@ public: const HLAInteractionClass* getInteractionClass(const std::string& name) const; private: + HLAFederate(const HLAFederate&); + HLAFederate& operator=(const HLAFederate&); + + /// The underlying interface to the rti implementation SGSharedPtr _rtiFederate; + /// Parameters required to connect to an rti Version _version; std::list _connectArguments; + /// Parameters for the federation execution std::string _federationExecutionName; std::string _federationObjectModel; + + /// Parameters for the federate std::string _federateType; std::string _federateName; diff --git a/simgear/hla/RTI13Federate.cxx b/simgear/hla/RTI13Federate.cxx index bb86d12f..f7b8a407 100644 --- a/simgear/hla/RTI13Federate.cxx +++ b/simgear/hla/RTI13Federate.cxx @@ -579,7 +579,6 @@ private: RTI13Federate::RTI13Federate(const std::list& stringList) : _joined(false), - _tickTimeout(10), _ambassador(new RTI13Ambassador), _federateAmbassador(new FederateAmbassador) { @@ -728,13 +727,9 @@ RTI13Federate::registerFederationSynchronizationPoint(const std::string& label, } bool -RTI13Federate::waitForFederationSynchronizationPointAnnounced(const std::string& label) +RTI13Federate::getFederationSynchronizationPointAnnounced(const std::string& label) { - while (!_federateAmbassador->getFederationSynchronizationPointAnnounced(label)) { - _ambassador->tick(_tickTimeout, 0); - _federateAmbassador->processQueues(); - } - return true; + return _federateAmbassador->getFederationSynchronizationPointAnnounced(label); } bool @@ -766,13 +761,9 @@ RTI13Federate::synchronizationPointAchieved(const std::string& label) } bool -RTI13Federate::waitForFederationSynchronized(const std::string& label) +RTI13Federate::getFederationSynchronized(const std::string& label) { - while (!_federateAmbassador->getFederationSynchronized(label)) { - _ambassador->tick(_tickTimeout, 0); - _federateAmbassador->processQueues(); - } - return true; + return _federateAmbassador->getFederationSynchronized(label); } bool @@ -816,11 +807,6 @@ RTI13Federate::enableTimeConstrained() return false; } - while (!_federateAmbassador->_timeConstrainedEnabled) { - _ambassador->tick(_tickTimeout, 0); - _federateAmbassador->processQueues(); - } - return true; } @@ -863,6 +849,12 @@ RTI13Federate::disableTimeConstrained() return true; } +bool +RTI13Federate::getTimeConstrainedEnabled() +{ + return _federateAmbassador->_timeConstrainedEnabled; +} + bool RTI13Federate::enableTimeRegulation(const SGTimeStamp& lookahead) { @@ -910,11 +902,6 @@ RTI13Federate::enableTimeRegulation(const SGTimeStamp& lookahead) return false; } - while (!_federateAmbassador->_timeRegulationEnabled) { - _ambassador->tick(_tickTimeout, 0); - _federateAmbassador->processQueues(); - } - return true; } @@ -958,19 +945,44 @@ RTI13Federate::disableTimeRegulation() } bool -RTI13Federate::timeAdvanceRequestBy(const SGTimeStamp& dt) +RTI13Federate::modifyLookahead(const SGTimeStamp& timeStamp) { if (!_ambassador.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation at unconnected federate."); + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead."); return false; } - - SGTimeStamp fedTime = _federateAmbassador->_federateTime + dt; - return timeAdvanceRequest(fedTime); + try { + _ambassador->modifyLookahead(timeStamp); + } catch (RTI::InvalidLookahead& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason); + return false; + } + return true; } bool -RTI13Federate::timeAdvanceRequest(const SGTimeStamp& fedTime) +RTI13Federate::getTimeRegulationEnabled() +{ + return _federateAmbassador->_timeRegulationEnabled; +} + +bool +RTI13Federate::timeAdvanceRequest(const SGTimeStamp& timeStamp) { if (!_ambassador.valid()) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation at unconnected federate."); @@ -978,7 +990,7 @@ RTI13Federate::timeAdvanceRequest(const SGTimeStamp& fedTime) } try { - _ambassador->timeAdvanceRequest(fedTime); + _ambassador->timeAdvanceRequest(timeStamp); _federateAmbassador->_timeAdvancePending = true; } catch (RTI::InvalidFederationTime& e) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); @@ -1012,14 +1024,61 @@ RTI13Federate::timeAdvanceRequest(const SGTimeStamp& fedTime) return false; } - while (_federateAmbassador->_timeAdvancePending) { - _ambassador->tick(_tickTimeout, 0); - _federateAmbassador->processQueues(); + return true; +} + +bool +RTI13Federate::timeAdvanceRequestAvailable(const SGTimeStamp& timeStamp) +{ + if (!_ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation at unconnected federate."); + return false; + } + + try { + _ambassador->timeAdvanceRequestAvailable(timeStamp); + _federateAmbassador->_timeAdvancePending = true; + } catch (RTI::InvalidFederationTime& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederationTimeAlreadyPassed& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::TimeAdvanceAlreadyInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::EnableTimeRegulationPending& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::EnableTimeConstrainedPending& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; } return true; } +bool +RTI13Federate::getTimeAdvancePending() +{ + return _federateAmbassador->_timeAdvancePending; +} + bool RTI13Federate::queryFederateTime(SGTimeStamp& timeStamp) { @@ -1049,37 +1108,6 @@ RTI13Federate::queryFederateTime(SGTimeStamp& timeStamp) return true; } -bool -RTI13Federate::modifyLookahead(const SGTimeStamp& timeStamp) -{ - if (!_ambassador.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead."); - return false; - } - try { - _ambassador->modifyLookahead(timeStamp); - } catch (RTI::InvalidLookahead& e) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason); - return false; - } catch (RTI::FederateNotExecutionMember& e) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason); - return false; - } catch (RTI::ConcurrentAccessAttempted& e) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason); - return false; - } catch (RTI::SaveInProgress& e) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason); - return false; - } catch (RTI::RestoreInProgress& e) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason); - return false; - } catch (RTI::RTIinternalError& e) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason); - return false; - } - return true; -} - bool RTI13Federate::queryLookahead(SGTimeStamp& timeStamp) { @@ -1168,7 +1196,7 @@ RTI13Federate::queryLITS(SGTimeStamp& timeStamp) } bool -RTI13Federate::tick() +RTI13Federate::processMessage() { bool result = _ambassador->tick(); _federateAmbassador->processQueues(); @@ -1176,10 +1204,17 @@ RTI13Federate::tick() } bool -RTI13Federate::tick(const double& minimum, const double& maximum) +RTI13Federate::processMessages(const double& minimum, const double& maximum) { - bool result = _ambassador->tick(minimum, maximum); + bool result = _ambassador->tick(minimum, 0); _federateAmbassador->processQueues(); + if (!result) + return false; + SGTimeStamp timeStamp = SGTimeStamp::now() + SGTimeStamp::fromSec(maximum); + do { + result = _ambassador->tick(0, 0); + _federateAmbassador->processQueues(); + } while (result && SGTimeStamp::now() <= timeStamp); return result; } diff --git a/simgear/hla/RTI13Federate.hxx b/simgear/hla/RTI13Federate.hxx index 0a8cee4d..651756ed 100644 --- a/simgear/hla/RTI13Federate.hxx +++ b/simgear/hla/RTI13Federate.hxx @@ -48,30 +48,32 @@ public: /// Synchronization Point handling virtual bool registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag); - virtual bool waitForFederationSynchronizationPointAnnounced(const std::string& label); + virtual bool getFederationSynchronizationPointAnnounced(const std::string& label); virtual bool synchronizationPointAchieved(const std::string& label); - virtual bool waitForFederationSynchronized(const std::string& label); + virtual bool getFederationSynchronized(const std::string& label); /// Time management virtual bool enableTimeConstrained(); virtual bool disableTimeConstrained(); + virtual bool getTimeConstrainedEnabled(); virtual bool enableTimeRegulation(const SGTimeStamp& lookahead); virtual bool disableTimeRegulation(); + virtual bool modifyLookahead(const SGTimeStamp& timeStamp); + virtual bool getTimeRegulationEnabled(); - virtual bool timeAdvanceRequestBy(const SGTimeStamp& dt); - virtual bool timeAdvanceRequest(const SGTimeStamp& fedTime); + virtual bool timeAdvanceRequest(const SGTimeStamp& timeStamp); + virtual bool timeAdvanceRequestAvailable(const SGTimeStamp& timeStamp); + virtual bool getTimeAdvancePending(); virtual bool queryFederateTime(SGTimeStamp& timeStamp); - virtual bool modifyLookahead(const SGTimeStamp& timeStamp); virtual bool queryLookahead(SGTimeStamp& timeStamp); - virtual bool queryGALT(SGTimeStamp& timeStamp); virtual bool queryLITS(SGTimeStamp& timeStamp); /// Process messages - virtual bool tick(); - virtual bool tick(const double& minimum, const double& maximum); + virtual bool processMessage(); + virtual bool processMessages(const double& minimum, const double& maximum); virtual RTI13ObjectClass* createObjectClass(const std::string& name, HLAObjectClass* hlaObjectClass); @@ -86,10 +88,6 @@ private: RTI::FederateHandle _federateHandle; bool _joined; - /// The timeout for the single callback tick function in - /// syncronous operations that need to wait for a callback - double _tickTimeout; - /// RTI connection SGSharedPtr _ambassador; diff --git a/simgear/hla/RTIFederate.hxx b/simgear/hla/RTIFederate.hxx index b7aa8854..e922eff8 100644 --- a/simgear/hla/RTIFederate.hxx +++ b/simgear/hla/RTIFederate.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2011 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 @@ -49,30 +49,32 @@ public: /// Synchronization Point handling virtual bool registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag) = 0; - virtual bool waitForFederationSynchronizationPointAnnounced(const std::string& label) = 0; + virtual bool getFederationSynchronizationPointAnnounced(const std::string& label) = 0; virtual bool synchronizationPointAchieved(const std::string& label) = 0; - virtual bool waitForFederationSynchronized(const std::string& label) = 0; + virtual bool getFederationSynchronized(const std::string& label) = 0; /// Time management virtual bool enableTimeConstrained() = 0; virtual bool disableTimeConstrained() = 0; + virtual bool getTimeConstrainedEnabled() = 0; virtual bool enableTimeRegulation(const SGTimeStamp& lookahead) = 0; virtual bool disableTimeRegulation() = 0; + virtual bool modifyLookahead(const SGTimeStamp& timeStamp) = 0; + virtual bool getTimeRegulationEnabled() = 0; - virtual bool timeAdvanceRequestBy(const SGTimeStamp& dt) = 0; virtual bool timeAdvanceRequest(const SGTimeStamp& fedTime) = 0; + virtual bool timeAdvanceRequestAvailable(const SGTimeStamp& timeStamp) = 0; + virtual bool getTimeAdvancePending() = 0; virtual bool queryFederateTime(SGTimeStamp& timeStamp) = 0; - virtual bool modifyLookahead(const SGTimeStamp& timeStamp) = 0; virtual bool queryLookahead(SGTimeStamp& timeStamp) = 0; - virtual bool queryGALT(SGTimeStamp& timeStamp) = 0; virtual bool queryLITS(SGTimeStamp& timeStamp) = 0; /// Process messages - virtual bool tick() = 0; - virtual bool tick(const double& minimum, const double& maximum) = 0; + virtual bool processMessage() = 0; + virtual bool processMessages(const double& minimum, const double& maximum) = 0; virtual RTIObjectClass* createObjectClass(const std::string& name, HLAObjectClass* hlaObjectClass) = 0; // virtual RTIInteractionClass* createInteractionClass(const std::string& name) = 0; From 5708ec5a89ff21868068a67815cd2771b96c11c4 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Sun, 2 Oct 2011 14:36:33 +0200 Subject: [PATCH 2/3] hla: provide main loop capabilities for HLAFederate. --- simgear/hla/HLAFederate.cxx | 326 +++++++++++++++++++++++++++++++++- simgear/hla/HLAFederate.hxx | 78 ++++++++ simgear/hla/RTI13Federate.cxx | 6 + simgear/hla/RTI13Federate.hxx | 1 + simgear/hla/RTIFederate.hxx | 1 + 5 files changed, 411 insertions(+), 1 deletion(-) diff --git a/simgear/hla/HLAFederate.cxx b/simgear/hla/HLAFederate.cxx index 05ba6f78..003fd23a 100644 --- a/simgear/hla/HLAFederate.cxx +++ b/simgear/hla/HLAFederate.cxx @@ -28,7 +28,12 @@ namespace simgear { HLAFederate::HLAFederate() : - _version(RTI13) + _version(RTI13), + _createFederationExecution(true), + _timeConstrained(false), + _timeRegulating(false), + _timeConstrainedByLocalClock(false), + _done(false) { } @@ -70,6 +75,19 @@ HLAFederate::setConnectArguments(const std::list& connectArguments) return true; } +bool +HLAFederate::getCreateFederationExecution() const +{ + return _createFederationExecution; +} + +bool +HLAFederate::setCreateFederationExecution(bool createFederationExecution) +{ + _createFederationExecution = createFederationExecution; + return true; +} + const std::string& HLAFederate::getFederationExecutionName() const { @@ -364,6 +382,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 +534,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 +567,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() { @@ -546,6 +713,21 @@ 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)); @@ -685,4 +867,146 @@ HLAFederate::getInteractionClass(const std::string& name) const return i->second.get(); } +void +HLAFederate::setDone(bool done) +{ + _done = done; +} + +bool +HLAFederate::getDone() const +{ + return _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; +} + +bool +HLAFederate::subscribe() +{ + /// Currently empty, but is called at the right time + return true; +} + +bool +HLAFederate::publish() +{ + /// Currently empty, but is called at the right time + 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; +} + } // namespace simgear diff --git a/simgear/hla/HLAFederate.hxx b/simgear/hla/HLAFederate.hxx index 4c82820c..0775a566 100644 --- a/simgear/hla/HLAFederate.hxx +++ b/simgear/hla/HLAFederate.hxx @@ -41,21 +41,31 @@ public: RTI1516E }; + /// The rti version backend to connect Version getVersion() const; bool setVersion(HLAFederate::Version version); + /// The rti backends connect arguments, depends on the version const std::list& getConnectArguments() const; bool setConnectArguments(const std::list& connectArguments); + /// If true try to create on join and try to destroy on resign + bool getCreateFederationExecution() const; + bool setCreateFederationExecution(bool createFederationExecution); + + /// The federation execution name to use on create, join and destroy const std::string& getFederationExecutionName() const; bool setFederationExecutionName(const std::string& federationExecutionName); + /// The federation object model name to use on create and possibly join const std::string& getFederationObjectModel() const; bool setFederationObjectModel(const std::string& federationObjectModel); + /// The federate type used on join const std::string& getFederateType() const; bool setFederateType(const std::string& federateType); + /// The federate name possibly used on join const std::string& getFederateName() const; bool setFederateName(const std::string& federateName); @@ -84,11 +94,43 @@ public: /// Time management + /// If set to true, time constrained mode is entered on init + bool getTimeConstrained() const; + bool setTimeConstrained(bool timeConstrained); + + /// If set to true, time advance is constrained by the local system clock + bool getTimeConstrainedByLocalClock() const; + bool setTimeConstrainedByLocalClock(bool timeConstrainedByLocalClock); + + /// If set to true, time regulation mode is entered on init + bool getTimeRegulating() const; + bool setTimeRegulating(bool timeRegulating); + + /// If set to a non zero value, this federate leads the federations + /// locical time advance by this amount of time. + const SGTimeStamp& getLeadTime() const; + bool setLeadTime(const SGTimeStamp& leadTime); + + /// The time increment for use in the default update method. + const SGTimeStamp& getTimeIncrement() const; + bool setTimeIncrement(const SGTimeStamp& timeIncrement); + + /// Actually enable time constrained mode. + /// This method blocks until time constrained mode is enabled. bool enableTimeConstrained(); + /// Actually disable time constrained mode. bool disableTimeConstrained(); + /// Actually enable time constrained by local clock mode. + bool enableTimeConstrainedByLocalClock(); + + /// Actually enable time regulation mode. + /// This method blocks until time regulation mode is enabled. bool enableTimeRegulation(const SGTimeStamp& lookahead); + bool enableTimeRegulation(); + /// Actually disable time regulation mode. bool disableTimeRegulation(); + /// Actually modify the lookahead time. bool modifyLookahead(const SGTimeStamp& lookahead); /// Advance the logical time by the given time increment. @@ -104,7 +146,9 @@ public: /// as far as currently possible. bool timeAdvanceAvailable(); + /// Get the current federates time bool queryFederateTime(SGTimeStamp& timeStamp); + /// Get the current federates lookahead bool queryLookahead(SGTimeStamp& timeStamp); /// Process one messsage @@ -148,6 +192,21 @@ public: HLAInteractionClass* getInteractionClass(const std::string& name); const HLAInteractionClass* getInteractionClass(const std::string& name) const; + /// Tells the main exec loop to continue or not. + void setDone(bool done); + bool getDone() const; + + virtual bool readObjectModel(); + + virtual bool subscribe(); + virtual bool publish(); + + virtual bool init(); + virtual bool update(); + virtual bool shutdown(); + + virtual bool exec(); + private: HLAFederate(const HLAFederate&); HLAFederate& operator=(const HLAFederate&); @@ -162,11 +221,30 @@ private: /// Parameters for the federation execution std::string _federationExecutionName; std::string _federationObjectModel; + bool _createFederationExecution; /// Parameters for the federate std::string _federateType; std::string _federateName; + /// Time management related parameters + /// If true, the federate is expected to enter time constrained mode + bool _timeConstrained; + /// If true, the federate is expected to enter time regulating mode + bool _timeRegulating; + /// The amount of time this federate leads the others. + SGTimeStamp _leadTime; + /// The regular time increment we do on calling update() + SGTimeStamp _timeIncrement; + /// The reference system time at initialization time. + /// Is used to implement being time constrained on the + /// local system time. + bool _timeConstrainedByLocalClock; + SGTimeStamp _localClockOffset; + + /// If true the exec method returns. + bool _done; + typedef std::map > ObjectClassMap; ObjectClassMap _objectClassMap; diff --git a/simgear/hla/RTI13Federate.cxx b/simgear/hla/RTI13Federate.cxx index f7b8a407..a9953b93 100644 --- a/simgear/hla/RTI13Federate.cxx +++ b/simgear/hla/RTI13Federate.cxx @@ -701,6 +701,12 @@ RTI13Federate::resign() } } +bool +RTI13Federate::getJoined() const +{ + return _joined; +} + bool RTI13Federate::registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag) { diff --git a/simgear/hla/RTI13Federate.hxx b/simgear/hla/RTI13Federate.hxx index 651756ed..d3cf5ca6 100644 --- a/simgear/hla/RTI13Federate.hxx +++ b/simgear/hla/RTI13Federate.hxx @@ -45,6 +45,7 @@ public: /// Join with federateName the federation execution federation virtual FederationManagementResult join(const std::string& federateType, const std::string& federation); virtual bool resign(); + virtual bool getJoined() const; /// Synchronization Point handling virtual bool registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag); diff --git a/simgear/hla/RTIFederate.hxx b/simgear/hla/RTIFederate.hxx index e922eff8..94d692b0 100644 --- a/simgear/hla/RTIFederate.hxx +++ b/simgear/hla/RTIFederate.hxx @@ -46,6 +46,7 @@ public: /// Join with federateName the federation execution federation virtual FederationManagementResult join(const std::string& federateType, const std::string& federation) = 0; virtual bool resign() = 0; + virtual bool getJoined() const = 0; /// Synchronization Point handling virtual bool registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag) = 0; From 8e92c5d985f850bec1a028b582cafb9d52ca6185 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Sun, 2 Oct 2011 15:13:06 +0200 Subject: [PATCH 3/3] hla: fix typo resulting in an endless loop. --- simgear/hla/HLAFederate.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simgear/hla/HLAFederate.cxx b/simgear/hla/HLAFederate.cxx index 003fd23a..c5c70630 100644 --- a/simgear/hla/HLAFederate.cxx +++ b/simgear/hla/HLAFederate.cxx @@ -729,7 +729,7 @@ HLAFederate::processMessages() } // Now flush just what is left - while (!_rtiFederate->processMessages(0, 0)); + while (_rtiFederate->processMessages(0, 0)); return true; }