namespace simgear {
HLAFederate::HLAFederate() :
- _version(RTI13)
+ _version(RTI13),
+ _createFederationExecution(true),
+ _timeConstrained(false),
+ _timeRegulating(false),
+ _timeConstrainedByLocalClock(false),
+ _done(false)
{
}
return true;
}
+bool
+HLAFederate::getCreateFederationExecution() const
+{
+ return _createFederationExecution;
+}
+
+bool
+HLAFederate::setCreateFederationExecution(bool createFederationExecution)
+{
+ _createFederationExecution = createFederationExecution;
+ return true;
+}
+
const std::string&
HLAFederate::getFederationExecutionName() const
{
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()
{
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)
{
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()
{
_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));
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
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);
/// 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.
/// 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
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&);
/// 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;