X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fhla%2FHLAFederate.cxx;h=c5c70630f8297c2b3222019fe20811ae99324590;hb=85e58b4a49d3c3b74afed3c766b47b65a6a95a66;hp=59a5f4b0cd56b9afc4375d9178b6bf09ddd2b7b9;hpb=becea84955bf1d553f0bb6b721ace64b9880fa93;p=simgear.git diff --git a/simgear/hla/HLAFederate.cxx b/simgear/hla/HLAFederate.cxx index 59a5f4b0..c5c70630 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,13 @@ namespace simgear { -HLAFederate::HLAFederate() +HLAFederate::HLAFederate() : + _version(RTI13), + _createFederationExecution(true), + _timeConstrained(false), + _timeRegulating(false), + _timeConstrainedByLocalClock(false), + _done(false) { } @@ -35,24 +41,119 @@ HLAFederate::~HLAFederate() { } -std::string +HLAFederate::Version +HLAFederate::getVersion() const +{ + return _version; +} + +bool +HLAFederate::setVersion(HLAFederate::Version version) +{ + if (_rtiFederate.valid()) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!"); + return false; + } + _version = version; + return true; +} + +const std::list& +HLAFederate::getConnectArguments() const +{ + return _connectArguments; +} + +bool +HLAFederate::setConnectArguments(const std::list& connectArguments) +{ + if (_rtiFederate.valid()) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!"); + return false; + } + _connectArguments = connectArguments; + return true; +} + +bool +HLAFederate::getCreateFederationExecution() const +{ + return _createFederationExecution; +} + +bool +HLAFederate::setCreateFederationExecution(bool createFederationExecution) +{ + _createFederationExecution = createFederationExecution; + return true; +} + +const std::string& +HLAFederate::getFederationExecutionName() const +{ + return _federationExecutionName; +} + +bool +HLAFederate::setFederationExecutionName(const std::string& federationExecutionName) +{ + if (_rtiFederate.valid()) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!"); + return false; + } + _federationExecutionName = federationExecutionName; + return true; +} + +const std::string& +HLAFederate::getFederationObjectModel() const +{ + return _federationObjectModel; +} + +bool +HLAFederate::setFederationObjectModel(const std::string& federationObjectModel) +{ + if (_rtiFederate.valid()) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!"); + return false; + } + _federationObjectModel = federationObjectModel; + return true; +} + +const std::string& HLAFederate::getFederateType() const { - if (!_rtiFederate.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); - return std::string(); + return _federateType; +} + +bool +HLAFederate::setFederateType(const std::string& federateType) +{ + if (_rtiFederate.valid()) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!"); + return false; } - return _rtiFederate->getFederateType(); + _federateType = federateType; + return true; } -std::string -HLAFederate::getFederationName() const +const std::string& +HLAFederate::getFederateName() const { - if (!_rtiFederate.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); - return std::string(); + return _federateName; +} + +bool +HLAFederate::setFederateName(const std::string& federateName) +{ + if (_rtiFederate.valid()) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!"); + return false; } - return _rtiFederate->getFederationName(); + _federateName = federateName; + return true; } bool @@ -65,6 +166,8 @@ HLAFederate::connect(Version version, const std::list& stringList) switch (version) { case RTI13: _rtiFederate = new RTI13Federate(stringList); + _version = version; + _connectArguments = stringList; break; case RTI1516: SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516 not yet(!?) supported."); @@ -80,6 +183,31 @@ HLAFederate::connect(Version version, const std::list& stringList) return _rtiFederate.valid(); } +bool +HLAFederate::connect() +{ + if (_rtiFederate.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLA: Trying to connect to already connected federate!"); + return false; + } + switch (_version) { + case RTI13: + _rtiFederate = new RTI13Federate(_connectArguments); + break; + case RTI1516: + SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516 not yet(!?) supported."); + // _rtiFederate = new RTI1516Federate(_connectArguments); + break; + case RTI1516E: + SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516E not yet(!?) supported."); + // _rtiFederate = new RTI1516eFederate(_connectArguments); + break; + default: + SG_LOG(SG_NETWORK, SG_WARN, "HLA: Unknown rti version in connect!"); + } + return _rtiFederate.valid(); +} + bool HLAFederate::disconnect() { @@ -98,7 +226,15 @@ HLAFederate::createFederationExecution(const std::string& federation, const std: SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); return false; } - return _rtiFederate->createFederationExecution(federation, objectModel); + + RTIFederate::FederationManagementResult createResult; + createResult = _rtiFederate->createFederationExecution(federation, objectModel); + if (createResult == RTIFederate::FederationManagementFatal) + return false; + + _federationExecutionName = federation; + _federationObjectModel = objectModel; + return true; } bool @@ -108,7 +244,45 @@ HLAFederate::destroyFederationExecution(const std::string& federation) SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); return false; } - return _rtiFederate->destroyFederationExecution(federation); + + RTIFederate::FederationManagementResult destroyResult; + destroyResult = _rtiFederate->destroyFederationExecution(federation); + if (destroyResult == RTIFederate::FederationManagementFatal) + return false; + + return true; +} + +bool +HLAFederate::createFederationExecution() +{ + if (!_rtiFederate.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); + return false; + } + + RTIFederate::FederationManagementResult createResult; + createResult = _rtiFederate->createFederationExecution(_federationExecutionName, _federationObjectModel); + if (createResult != RTIFederate::FederationManagementSuccess) + return false; + + return true; +} + +bool +HLAFederate::destroyFederationExecution() +{ + if (!_rtiFederate.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); + return false; + } + + RTIFederate::FederationManagementResult destroyResult; + destroyResult = _rtiFederate->destroyFederationExecution(_federationExecutionName); + if (destroyResult != RTIFederate::FederationManagementSuccess) + return false; + + return true; } bool @@ -118,7 +292,29 @@ HLAFederate::join(const std::string& federateType, const std::string& federation SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); return false; } - return _rtiFederate->join(federateType, federation); + + RTIFederate::FederationManagementResult joinResult; + joinResult = _rtiFederate->join(federateType, federation); + if (joinResult == RTIFederate::FederationManagementFatal) + return false; + + return true; +} + +bool +HLAFederate::join() +{ + if (!_rtiFederate.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); + return false; + } + + RTIFederate::FederationManagementResult joinResult; + joinResult = _rtiFederate->join(_federateType, _federationExecutionName); + if (joinResult != RTIFederate::FederationManagementSuccess) + return false; + + return true; } bool @@ -131,6 +327,183 @@ HLAFederate::resign() return _rtiFederate->resign(); } +bool +HLAFederate::createJoinFederationExecution() +{ + if (!_rtiFederate.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); + return false; + } + + for (;;) { + // Try to join. + RTIFederate::FederationManagementResult joinResult; + joinResult = _rtiFederate->join(_federateType, _federationExecutionName); + switch (joinResult) { + case RTIFederate::FederationManagementSuccess: + // Fast return on success + return true; + case RTIFederate::FederationManagementFatal: + // Abort on fatal errors + return false; + default: + break; + }; + + // If not already joinable, try to create the requested federation + RTIFederate::FederationManagementResult createResult; + createResult = _rtiFederate->createFederationExecution(_federationExecutionName, _federationObjectModel); + switch (createResult) { + case RTIFederate::FederationManagementFatal: + // Abort on fatal errors + return false; + default: + // Try again to join + break; + } + } +} + +bool +HLAFederate::resignDestroyFederationExecution() +{ + if (!_rtiFederate.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); + return false; + } + + // Resign ourselves + bool success = _rtiFederate->resign(); + + // and try to destroy, non fatal if still some federates joined + if (_rtiFederate->destroyFederationExecution(_federationExecutionName) == RTIFederate::FederationManagementFatal) + success = false; + + 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() { @@ -138,7 +511,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 @@ -151,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) { @@ -158,7 +554,31 @@ 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 +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 @@ -172,43 +592,83 @@ 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::queryFederateTime(SGTimeStamp& timeStamp) +HLAFederate::timeAdvance(const SGTimeStamp& timeStamp) { if (!_rtiFederate.valid()) { SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); return false; } - return _rtiFederate->queryFederateTime(timeStamp); + + if (!_rtiFederate->timeAdvanceRequest(timeStamp)) { + SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!"); + return false; + } + + return processMessages(); } bool -HLAFederate::modifyLookahead(const SGTimeStamp& timeStamp) +HLAFederate::timeAdvanceAvailable() { if (!_rtiFederate.valid()) { SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); return false; } - return _rtiFederate->modifyLookahead(timeStamp); + + 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 +HLAFederate::queryFederateTime(SGTimeStamp& timeStamp) +{ + if (!_rtiFederate.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); + return false; + } + return _rtiFederate->queryFederateTime(timeStamp); } bool @@ -222,13 +682,56 @@ 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->processMessage(); +} + +bool +HLAFederate::processMessage(const SGTimeStamp& timeout) { if (!_rtiFederate.valid()) { SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); return false; } - return _rtiFederate->tick(); + 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(); + } + + 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 true; } bool @@ -238,7 +741,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 @@ -364,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