]> git.mxchange.org Git - simgear.git/commitdiff
hla: provide main loop capabilities for HLAFederate.
authorMathias Froehlich <Mathias.Froehlich@web.de>
Sun, 2 Oct 2011 12:36:33 +0000 (14:36 +0200)
committerMathias Froehlich <Mathias.Froehlich@web.de>
Sun, 2 Oct 2011 12:36:33 +0000 (14:36 +0200)
simgear/hla/HLAFederate.cxx
simgear/hla/HLAFederate.hxx
simgear/hla/RTI13Federate.cxx
simgear/hla/RTI13Federate.hxx
simgear/hla/RTIFederate.hxx

index 05ba6f782299de4da38be487faae6f45803ed80b..003fd23ad2224fcac568318cdddf5155914d2a63 100644 (file)
 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<std::string>& 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
index 4c82820cb13c9183a3fe813ea75856c6c4aff6f0..0775a566ca04d49e8c3467568f4151e4f6506555 100644 (file)
@@ -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<std::string>& getConnectArguments() const;
     bool setConnectArguments(const std::list<std::string>& 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<std::string, SGSharedPtr<HLAObjectClass> > ObjectClassMap;
     ObjectClassMap _objectClassMap;
 
index f7b8a407fbb4f058e1389fb87aea9f0ebeea75d9..a9953b9381496c5962f61af16642956eddc6050c 100644 (file)
@@ -701,6 +701,12 @@ RTI13Federate::resign()
     }
 }
 
+bool
+RTI13Federate::getJoined() const
+{
+    return _joined;
+}
+
 bool
 RTI13Federate::registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag)
 {
index 651756edb36e9ff4902df0bdb3241d2c3e80e7d7..d3cf5ca61d3c65973df99cbba3b8fdeb2918aa49 100644 (file)
@@ -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);
index e922eff873bc8b11ae14ff86a9e48e2da229b753..94d692b0d87917c714613e8b4639e6f17abe3f53 100644 (file)
@@ -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;