From 5708ec5a89ff21868068a67815cd2771b96c11c4 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Sun, 2 Oct 2011 14:36:33 +0200 Subject: [PATCH] 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; -- 2.39.5