hla: provide main loop capabilities for HLAFederate.

This commit is contained in:
Mathias Froehlich
2011-10-02 14:36:33 +02:00
parent f665431132
commit 5708ec5a89
5 changed files with 411 additions and 1 deletions

View File

@@ -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<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

View 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;

View File

@@ -701,6 +701,12 @@ RTI13Federate::resign()
}
}
bool
RTI13Federate::getJoined() const
{
return _joined;
}
bool
RTI13Federate::registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag)
{

View 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);

View 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;