MAK RTIspy API Documentation for HLA 1.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
simpleTime Example Code for HLA 1.3

simpleTime13.cxx and simpleTimeFedAmb13.cxx (simpleTimeFedAmb13.h) have the RTI calls and federate ambassador calls for the HLA 1.3 version of simpleTime.

This page has the code for the following files:


simpleTime13.cxx

/*******************************************************************************
** Copyright (c) 1992-2018 VT MAK
** All rights reserved.
*******************************************************************************/
// A simple federate that updates an object with attributes whose values
// are the name of the attribute. Objects from other simple federates
// are discovered and reflected. The string values are byte encoded to allow
// compatibility between 1.3 and 1516
#ifdef WIN32
#pragma warning(disable: 4251)
#pragma warning(disable: 4786)
#pragma warning(disable: 4290)
#include <winsock2.h>
#include <process.h>
#else
#include <unistd.h>
#include <stdlib.h>
#include <sched.h>
#include <netdb.h>
#endif
#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <sstream>
#include <iterator>
#include "RTI.hh"
#include "fedtime.hh"
using namespace std;
bool parseCmdLine( int argc, char* argv[] );
// Handles keyboard input without blocking
keyboard input;
// Data shared between federate and federate ambassador
DtTalkAmbData theAmbData;
// The object class name
string theClassName = "BaseEntity";
// The interaction class name
string fireInteractionName = "WeaponFire";
string detonateInteractionName = "MunitionDetonation";
// The object class handle (to be retrieved from RTI).
RTI::ObjectClassHandle theClassHandle;
// The interaction class handles (to be retrieved from RTI).
RTI::InteractionClassHandle fireInteractionHandle;
RTI::InteractionClassHandle detonateInteractionHandle;
// The object instance handle (to be retrieved from the RTI).
RTI::ObjectHandle theObjectHandle;
// This federation of simple objects has a single master object, (determined by command line arguments)
// The master federate will keep the other federates from entering their main loop of execution until
// all of numFederates have joined.
bool Master(false);
// numFederates is the number of federates (including the master) that the master should wait to join the
// federation before it allows any federate to enter its main loop.
// This variable is only used by the master federate.
int numFederates(0);
// dedicatedMachine indicates that this federate will be as greedy as possible with the processor.
// this is helpful for users who have two federates on separate machines and want them to time-step
// as quickly as possible.
// If each federate is not on a dedicated machine, this may actually slow federates.
bool dedicatedMachine(false);
// unManaged Federate will allow you to see the operation of a time regulating and constrained federate
// when the federate does not wait for the "begin" synchronization before executing.
bool unManagedFederate(false);
// sleepTime (indicated in milliseconds, defaults to 850ms), is the time that a federate will sleep between
// iterations of the main loop. This value is invalidated if (above) dedicatedMachine is set.
// 850 ms is selected to allow the user to see the time advances progressing at a very slow pace.
// There is no need to set this to a value > 50ms or so other than allowing the user to watch the text scroll.
int sleepTime(850);
// the name of the fed file this federate will use. Can be overridden with cmd line parameter fedFile
string fedFileName("MAKsimpletime.fed");
// the name of the federation we'll create.
string federationName("MAKsimpletime");
// The name of the initialization synchronization point that the master and other federates use to establish a
// synchronized starting point for the federation.
string initSyncPointLabel("begin");
// The lookahead
double theLookAhead = 1.0;
// The time advance increment
double theTimeAdvance = 5.0;
enum TimeAdvanceService
{
tasUnknown,
tasTimeAdvanceRequest,
tasNextEventRequest,
tasFlushQueue
};
// The time advance service
TimeAdvanceService theTimeAdvanceService = tasTimeAdvanceRequest;
// Indicates if available option of service is used
bool theAdvanceUsesAvailable = false;
// Create the federation execution
void createFedEx(RTI::RTIambassador* rtiAmb,
string const& fedName,
string const& fedFile)
{
std::cout << "createFederationExecution " << fedName.c_str() << " " << fedFile.c_str() << endl;
try
{
rtiAmb->createFederationExecution(fedName.c_str(), fedFile.c_str());
}
catch(RTI::FederationExecutionAlreadyExists& ex)
{
std::cout << "Could not create Federation Execution: "
<< "FederationExecutionAlreadyExists: "
<< ex._name << " "
<< ex._reason << endl;
}
catch(RTI::Exception& ex)
{
std::cout << "Could not create Federation Execution: " << endl
<< "RTI Exception: "
<< ex._name << " "
<< ex._reason << endl;
exit(0);
}
rtiAmb->tick(0.1, 0.2);
std::cout << "Federation Created" << endl;
}
// Join the federation execution
void joinFedEx(
RTI::RTIambassador* rtiAmb, MyFederateAmbassador* fedAmb,
string const& federateType)
{
bool joined=false;
const int maxTry = 10;
int numTries = 0;
std::cout << "joinFederationExecution " << federateType.c_str() << " " << federationName.c_str() << endl;
while (!joined && numTries++ < maxTry)
{
try
{
rtiAmb->joinFederationExecution(federateType.c_str(), federationName.c_str(), fedAmb);
joined = true;
}
catch(RTI::FederationExecutionDoesNotExist)
{
std::cout << "FederationExecutionDoesNotExist, try " << numTries << "out of " << maxTry << endl;
continue;
}
catch(RTI::Exception& ex)
{
std::cout << "RTI Exception: " << ex._name << " " << ex._reason << endl;
return;
}
rtiAmb->tick(0.1, 0.2);
}
if (joined)
{
std::cout << "Joined Federation." << endl;
}
else
{
std::cout << "Giving up." << endl;
rtiAmb->destroyFederationExecution(federationName.c_str());
exit(0);
}
}
// Resign and destroy the federation execution
void resignAndDestroy( RTI::RTIambassador* rtiAmb )
{
try
{
rtiAmb->resignFederationExecution(RTI::DELETE_OBJECTS);
rtiAmb->destroyFederationExecution(federationName.c_str());
}
catch (RTI::Exception& ex)
{
std::cout << "RTI Exception: "
<< ex._name << " "
<< ex._reason << endl
<< "During resign and destroy. " << endl;
}
}
// Publish and subscribe the object class attributes.
// Register an object instance of the class.
bool publishSubscribeAndRegisterObject(RTI::RTIambassador* rtiAmb)
{
// Declare the attributes that we will be publishing.
theAmbData.ourAttrs.insert(string("AccelerationVector"));
theAmbData.ourAttrs.insert(string("DeadReckoningAlgorithm"));
theAmbData.ourAttrs.insert(string("Orientation"));
theAmbData.ourAttrs.insert(string("WorldLocation"));
theAmbData.ourAttrs.insert(string("VelocityVector"));
theAmbData.ourAttrs.insert(string("DamageState"));
// Get the object class handle
try
{
theClassHandle = rtiAmb->getObjectClassHandle(theClassName.c_str());
theAmbData.objectClassMap[theClassHandle] = theClassName;
}
catch (RTI::Exception& ex)
{
std::cout << "RTI Exception: "
<< ex._name << " "
<< ex._reason << endl
<< "Could not get object class handle: "
<< theClassName.c_str() << endl;
return false;
}
// Construct an attribute handle set
string attrName;
RTI::AttributeHandleSet* hSet = RTI::AttributeHandleSetFactory::create(theAmbData.ourAttrs.size());
// Create an appropriately sized Attribute Handle Value Pair Set
theAmbData.attrValues = RTI::AttributeSetFactory::create(theAmbData.ourAttrs.size());
set<string>::iterator attributeSetIterator = theAmbData.ourAttrs.begin();
set<string>::iterator attributeSetEnd = theAmbData.ourAttrs.end();
string currentAttribute("");
RTI::AttributeHandle retrievedHandle;
for ( ; attributeSetIterator != attributeSetEnd; ++attributeSetIterator )
{
currentAttribute = *attributeSetIterator;
try
{
retrievedHandle = rtiAmb->getAttributeHandle(currentAttribute.c_str(), theClassHandle);
}
catch (RTI::Exception& ex)
{
std::cout << "RTI Exception: "
<< ex._name << " "
<< ex._reason << endl
<< "Could not get attribute handle "
<< attrName.c_str() << endl;
return false;
}
// Populate the AttributeHandleSet
hSet->add(retrievedHandle);
// Populate the attribute handle value pair set with the
// values containing the attribute names
// Attribute values will be just the name of the attribute.
theAmbData.attrValues->add(retrievedHandle, currentAttribute.c_str(), currentAttribute.length()+1);
theAmbData.theAttrNameHandleMap.insert( std::make_pair(currentAttribute, retrievedHandle));
}
// Publish and subscribe
int cnt=0;
try
{
rtiAmb->publishObjectClass(theClassHandle, *hSet);
rtiAmb->tick(0.1, 0.2);
cnt=1;
rtiAmb->subscribeObjectClassAttributes(theClassHandle, *hSet);
rtiAmb->tick(0.1, 0.2);
}
catch (RTI::Exception& ex)
{
std::cout << "RTI Exception: "
<< ex._name << " "
<< ex._reason << endl
<< "Could not "
<< (cnt ? "publish" : "subscribe") << endl;
delete hSet;
return false;
}
string objectName("Talk");
// Register the object instance
try
{
unsigned int objId = abs(getpid());
stringstream pid;
pid << objId;
objectName += pid.str();
theObjectHandle = rtiAmb->registerObjectInstance(theClassHandle, objectName.c_str());
// Add name-handle to map
theAmbData.objectInstanceMap[theObjectHandle] = rtiAmb->getObjectInstanceName(theObjectHandle);
rtiAmb->tick(0.1, 0.2);
}
catch (RTI::Exception& ex)
{
std::cout << "RTI Exception: "
<< ex._name << " "
<< ex._reason << endl
<< "Could not Register Object "
<< objectName.c_str()
<< " with class "
<< theClassName.c_str() << endl;
delete hSet;
return false;
}
std::cout << "Registered object "
<< objectName.c_str()
<< " with class name "
<< theClassName.c_str() << endl;
delete hSet;
return true;
}
// Publish and Subscribe to an interaction class
bool publishAndSubscribeInteraction(RTI::RTIambassador* rtiAmb)
{
theAmbData.ourParms.insert("EventIdentifier");
theAmbData.ourParms.insert("FiringLocation");
theAmbData.ourParms.insert("FiringObjectIdentifier");
theAmbData.ourParms.insert("MunitionObjectIdentifier");
theAmbData.ourParms.insert("TargetObjectIdentifier");
// Get the interaction class handle
try
{
fireInteractionHandle = rtiAmb->getInteractionClassHandle(fireInteractionName.c_str());
theAmbData.interactionClassMap[fireInteractionHandle] = fireInteractionName;
detonateInteractionHandle = rtiAmb->getInteractionClassHandle(detonateInteractionName.c_str());
theAmbData.interactionClassMap[detonateInteractionHandle] = detonateInteractionName;
}
catch (RTI::Exception& ex)
{
std::cout << "RTI Exception: "
<< ex._name << " "
<< ex._reason << endl
<< "Could not get interaction class handle: "
<< theClassName.c_str() << endl;
return false;
}
// Construct a parameter handle value pair set with the
// values containing the parameter names
theAmbData.paramValues = RTI::ParameterSetFactory::create(theAmbData.ourParms.size());
// Get the parameter handles and construct the name-handle map
string paramName;
set<string>::const_iterator parameterIter = theAmbData.ourParms.begin();
set<string>::const_iterator parameterEnd = theAmbData.ourParms.end();
RTI::ParameterHandle retrievedHandle;
for ( ; parameterIter != parameterEnd; ++parameterIter )
{
paramName = *parameterIter;
try
{
retrievedHandle = rtiAmb->getParameterHandle(paramName.c_str(), fireInteractionHandle);
}
catch (RTI::Exception& ex)
{
std::cout << "RTI Exception: "
<< ex._name << " "
<< ex._reason << endl
<< "Could not get parameter handle "
<< paramName.c_str() << endl;
return false;
}
// Parameter values will be just the name of the attribute.
theAmbData.paramValues->add(retrievedHandle, paramName.c_str(), paramName.length()+1);
theAmbData.theParamNameHandleMap.insert( std::make_pair(paramName, retrievedHandle));
}
// Publish and subscribe
int cnt=0;
try
{
rtiAmb->publishInteractionClass(fireInteractionHandle);
rtiAmb->tick(0.1, 0.2);
rtiAmb->publishInteractionClass(detonateInteractionHandle);
rtiAmb->tick(0.1, 0.2);
cnt=1;
rtiAmb->subscribeInteractionClass(fireInteractionHandle);
rtiAmb->tick(0.1, 0.2);
rtiAmb->subscribeInteractionClass(detonateInteractionHandle);
rtiAmb->tick(0.1, 0.2);
}
catch (RTI::Exception& ex)
{
std::cout << "RTI Exception: "
<< ex._name << " "
<< ex._reason << endl
<< "Could not "
<< (cnt ? "publish" : "subscribe")
<< " to interaction." << endl;
return false;
}
std::cout << "Subscribed to interaction class: "
<< fireInteractionName.c_str()
<< " with handle: "
<< fireInteractionHandle << endl
<< " and interaction class "
<< detonateInteractionName.c_str()
<< " with handle: "
<< detonateInteractionHandle << endl;
return true;
}
// This function will exit the program after resigning the federation.
void cleanUpProgram(RTI::RTIambassador* rtiAmb)
{
try
{
if ( theAmbData.isRegulating )
{
rtiAmb->disableTimeRegulation();
}
// Resign and destroy federation
resignAndDestroy(rtiAmb);
delete rtiAmb;
}
catch (RTI::Exception& ex)
{
std::cout << "RTI Exception (during exit): " << ex._name << " " << ex._reason << endl;
}
#ifdef WIN32
WSACleanup();
#endif
exit(0);
}
// This is a simple function to output a FedTime object.
// Helpful for debugging and general diagnostics.
void printOutFedTime(RTI::FedTime& time)
{
char* buff = new char[time.getPrintableLength()];
time.getPrintableString(buff);
std::cout << atof(buff) ;
delete [] buff;
}
// platform independent sleep function.
void sleepFunction()
{
// On a dedicated machine we do not sleep, making this function a nop
if ( ! dedicatedMachine )
{
#ifdef WIN32
Sleep(sleepTime);
#else
// Uses microseconds, multiple milliseconds by 1000
usleep(sleepTime * 1000);
#endif
}
}
// platform independent sleep, for a predetermined small time. (10 ms)
void minimalSleepFunction()
{
#ifdef WIN32
Sleep(10);
#else
usleep(10 * 1000);
#endif
}
// simply yields the current thread independent of the platform
void yieldFunction()
{
// On a dedicated machine we do not yield the processor, making this function a nop
if ( ! dedicatedMachine )
{
#ifdef _WIN32
Sleep( 0 );
#elif __solaris__
yield();
#else
sched_yield();
#endif
}
}
// This function causes the federate to become time constrained and regulating.
// If the user presses q while the federate is waiting for the callback from the RTI
// making it time constrained, the federate will quit.
void becomeConstrainedAndRegulating(RTI::RTIambassador* rtiAmb,
RTI::FedTime& currentTime,
RTI::FedTime& lookAhead )
{
try
{
rtiAmb->enableTimeRegulation(currentTime, lookAhead);
std::cout << "Waiting to become Time Regulating \n";
rtiAmb->tick(.1, 1);
while ( ! theAmbData.isRegulating )
{
std::cout << ".";
if (input.keybrdTick() < 0)
{
cleanUpProgram(rtiAmb);
}
minimalSleepFunction();
rtiAmb->tick(.1, 1);
}
std::cout << endl;
rtiAmb->enableTimeConstrained();
std::cout << "Waiting to become Time Constrained \n";
rtiAmb->tick(.1, 1);
while ( ! theAmbData.isConstrained )
{
std::cout << ".";
if (input.keybrdTick() < 0 )
{
cleanUpProgram(rtiAmb);
}
rtiAmb->tick(.1, 1);
if ( ! theAmbData.isConstrained )
{
yieldFunction();
}
}
std::cout << endl;
}
catch (RTI::Exception& )
{
std::cout << " unable to become regulating and constrained\n" << " Exiting ...\n";
cleanUpProgram(rtiAmb);
}
}
// This function will not exit until numFederates (as indicated to the master
// of this federation execution) have been made known to the master federate.
// The master then waits to have discovered numFederates - 1,
// (i.e. all federates but itself), then accomplished by the master registering
// a sync point. From this point the master behaves exactly as the other federates.
// The non-master federates wait for the announceSyncPoint callback, indicating that
// the master federate has discovered all necessary federates. They each non-master federate
// will call synchPointAchieved, indicating to the RTI that they are prepared to start.
// Then both master and non-master simply wait for the RTI federationSynchronized callback.
// Note: An alternative to waiting for object discovery callbacks to indicate a joined federate
// is to use MOM interactions. The master can subscribe to a MOM interaction and have a joined
// federate send that interaction prior to entering the synchronizeFederation function.
void synchronizeFederation(RTI::RTIambassador* rtiAmb)
{
if ( !theAmbData.isMaster )
{
rtiAmb->tick(0.1, 0.2);
std::cout << " Ordinary federate is waiting for synchPoint message\n";
while (!theAmbData.announceSyncReceived)
{
if (input.keybrdTick() < 0)
{
cleanUpProgram(rtiAmb);
}
yieldFunction();
rtiAmb->tick(0.1, 0.2);
}
std::cout << "sync Point message received\n";
}
else
{
std::string synchPointTag("");
int maximumSize(256);
char* hostName = new char[maximumSize];
if ( -1 == gethostname(hostName, maximumSize) )
{
unsigned int objId = abs(getpid());
std::stringstream pid;
pid.str(std::string(""));
pid << "unknownHostName" << "_" << objId;
synchPointTag = pid.str();
}
else
{
unsigned int objId = abs(getpid());
std::stringstream pid;
pid.str(std::string(""));
pid << hostName << "_" << objId;
synchPointTag = pid.str();
}
delete hostName;
// Wait until other federates have joined.
rtiAmb->tick(0.1, 0.2);
std::cout << " Master waiting for all federates to Join.\n";
while ( theAmbData.otherFederatesReady < (theAmbData.numFederates - 1) )
{
if (input.keybrdTick() < 0 )
{
cleanUpProgram(rtiAmb);
}
yieldFunction();
rtiAmb->tick(0.1, 0.2);
}
// Now that all required federates have joined, register a sync point.
std::cout << " Master federate has discovered the required number of other federates.\n\n";
rtiAmb->registerFederationSynchronizationPoint(initSyncPointLabel.c_str(), synchPointTag.c_str());
rtiAmb->tick(0.1, 0.2);
while ( !theAmbData.registerFailed && !theAmbData.registerSucceeded )
{
if (input.keybrdTick() < 0 )
{
cleanUpProgram(rtiAmb);
}
yieldFunction();
rtiAmb->tick(0.1, 0.2);
}
if ( theAmbData.registerFailed )
{
std::cout << " We failed to register synch point " << initSyncPointLabel << std::endl
<< " with tag " << synchPointTag << std::endl;
cleanUpProgram(rtiAmb);
}
std::cout << "Master successfully registered\n";
}
// At this time, any kind of federate announces to the RTI that they have reached their
// synchronization.
try
{
rtiAmb->synchronizationPointAchieved(initSyncPointLabel.c_str());
}
catch (RTI::Exception& )
{
std::cout << " Synch point achieved failed\n" << " Exiting....\n";
cleanUpProgram(rtiAmb);
}
//Then they will wait for the RTI to announce to all federates that all federates are synchronized.
rtiAmb->tick(0.1, 0.2);
while ( !theAmbData.federationIsSynchronized )
{
if (input.keybrdTick() < 0 )
{
cleanUpProgram(rtiAmb);
}
minimalSleepFunction();
rtiAmb->tick(0.1, 0.2);
}
}
int main(int argc, char** argv)
{
std::cout << "MAK simpleTime version 1.3" << std::endl;
try
{
// Federate and Federation info
string federateType("simpletime13");
if (argc > 1)
{
if (!parseCmdLine(argc, argv))
{
exit(0);
}
}
// RTI and Federate Ambassadors
RTI::RTIambassador* rtiAmb = new RTI::RTIambassador;
MyFederateAmbassador fedAmb(theAmbData);
// Create the federation
createFedEx(rtiAmb, federationName, fedFileName);
// Join the federation
joinFedEx(rtiAmb, &fedAmb, federateType);
#ifdef WIN32
WSADATA data;
WSAStartup(MAKEWORD(1,1), &data);
#endif
rtiAmb->tick(0.1, 0.2);
long count=0;
RTIfedTime oneTimeStep = RTIfedTime(theTimeAdvance);
RTIfedTime lookAhead = RTIfedTime(theLookAhead);
RTIfedTime updateTime = RTIfedTime(0.0);
RTIfedTime interactionTime = RTIfedTime(0.0);
RTIfedTime epsilon;
theAmbData.time = RTI::FedTimeFactory::makeZero();
RTI::FedTime& currentTime = *theAmbData.time;
epsilon.setEpsilon();
//Become Time managed and regulating in this federation.
becomeConstrainedAndRegulating(rtiAmb, *theAmbData.time, lookAhead);
// Publish, subscribe and register and object
if (!publishSubscribeAndRegisterObject(rtiAmb))
{
resignAndDestroy(rtiAmb);
delete rtiAmb;
return 0;
}
// By using synchronization points, ensure that all expected federates
// have joined prior to commencing. This function requires that
// other federates have registered an object as it utilizes discovery
// callbacks to count the number of federates that have joined as yet.
if ( !unManagedFederate )
{
synchronizeFederation(rtiAmb);
}
// Publish and subscribe to the required interaction
if (!publishAndSubscribeInteraction(rtiAmb))
{
resignAndDestroy(rtiAmb);
delete rtiAmb;
return 0;
}
// This is the main loop of the application. In it, the federate ticks the RTI, updates
// its published attributes and if indicated, fires and detonates, this continues
// until this federate has been detonated.
bool hasDetonated = false;
while (!hasDetonated && !theAmbData.timeManagedObject.isDetonated())
{
try
{
string tag;
if (*theAmbData.time < updateTime)
{
theAmbData.timeManagedObject.tick();
}
else
{
// Move update time to next step
updateTime += oneTimeStep;
std::cout << "===================================================================\n";
std::cout << "Current time (";
printOutFedTime(currentTime);
std::cout << "), Lookahead (";
printOutFedTime(lookAhead);
std::cout << ") update time (";
printOutFedTime(updateTime);
std::cout << ")" << std::endl;
std::cout << endl;
stringstream ss;
ss << "1.3-" << count++;
tag = ss.str();
theAmbData.timeManagedObject.tick();
theAmbData.timeManagedObject.incPosition(theTimeAdvance);
// Update the object
rtiAmb->updateAttributeValues(theObjectHandle, *(theAmbData.attrValues), updateTime, tag.c_str());
rtiAmb->tick(0.001, 0.5);
}
// Send the interaction if appropriate.
if ( theAmbData.timeManagedObject.shouldDetonate() )
{
string munitionString = "MunitionObjectIdentifier";
// Find the Parameter Handle that the RTI associated with this Parameter Name.
RTI::ParameterHandle munitionHandle = theAmbData.theParamNameHandleMap.find(munitionString)->second;
interactionTime = currentTime;
interactionTime += lookAhead;
// Add epsilon in case of 0 lookahead
interactionTime += epsilon;
// By adding a munitions parameter with nothing for the data,
// we communicate that this interaction is a munitions interaction.
theAmbData.paramValues->remove( munitionHandle );
theAmbData.paramValues->add(munitionHandle, "\0", 1);
rtiAmb->sendInteraction(detonateInteractionHandle, *theAmbData.paramValues, interactionTime, tag.c_str());
// Restore the munitions parameter data.
theAmbData.paramValues->remove( munitionHandle );
theAmbData.paramValues->add(munitionHandle,
munitionString.c_str(), munitionString.length() + 1);
hasDetonated = true;
}
if ( theAmbData.timeManagedObject.shouldFire() )
{
string fireString = "FiringObjectIdentifier";
// Find the Parameter Handle that the RTI associated with the Fire Parameter.
RTI::ParameterHandle fireHandle = theAmbData.theParamNameHandleMap.find(fireString)->second;
interactionTime = currentTime;
interactionTime += lookAhead;
// Add epsilon in case of 0 lookahead
interactionTime += epsilon;
// By replacing the existing fire parameter with one that has null data,
// we indicate that this interaction is a fire interaction.
theAmbData.paramValues->remove(fireHandle);
theAmbData.paramValues->add(fireHandle, "\0", 1);
rtiAmb->sendInteraction(fireInteractionHandle, *theAmbData.paramValues, interactionTime, tag.c_str());
// Restore the fire parameter's data.
theAmbData.paramValues->remove(fireHandle);
theAmbData.paramValues->add(fireHandle, fireString.c_str(), fireString.length() + 1);
}
}
catch (RTI::InvalidFederationTime& ex)
{
std::cout << " caught an Invalid Federation Time !!\n";
std::cout << ex._name << " " << ex._reason << endl;
// A federate can easily rectify a difference in current time with the RTI's time.
// This federate is synchronized before it advances time, this should never be reached.
cleanUpProgram(rtiAmb);
}
int kb(0);
try
{
if ( theAmbData.isRegulating )
{
// Advance time to the last sent update
if (theTimeAdvanceService == tasTimeAdvanceRequest)
{
if (theAdvanceUsesAvailable)
{
rtiAmb->timeAdvanceRequestAvailable(updateTime);
}
else
{
rtiAmb->timeAdvanceRequest(updateTime);
}
}
else if (theTimeAdvanceService == tasNextEventRequest)
{
if (theAdvanceUsesAvailable)
{
rtiAmb->nextEventRequestAvailable(updateTime);
}
else
{
rtiAmb->nextEventRequest(updateTime);
}
}
else if (theTimeAdvanceService == tasFlushQueue)
{
rtiAmb->flushQueueRequest(updateTime);
}
else
{
// Default to time advance request
rtiAmb->timeAdvanceRequest(updateTime);
}
theAmbData.timeAdvanced = false;
rtiAmb->tick(0.001, 0.2);
while ( ! theAmbData.timeAdvanced )
{
kb = input.keybrdTick();
if (kb < 0)
{
break;
}
else if ( kb == 1 )
{
theAmbData.timeManagedObject.firePressed();
std::cout << "********** Fire pressed at time ";
printOutFedTime(updateTime);
std::cout << " *************\n";
}
else if ( !theAmbData.timeAdvanced )
{
yieldFunction();
rtiAmb->tick(0.001, 0.2);
}
}
}
}
catch( RTI::Exception& ex )
{
std::cout << "RTI Exception" << endl
<< ex._name << " " << ex._reason << endl
<< " Could not advance time" << endl;
}
rtiAmb->tick(0.001, 0.2);
if ( kb == 0 )
{
kb = input.keybrdTick();
}
if ( kb < 0 )
{
break;
}
else if ( kb == 1 )
{
theAmbData.timeManagedObject.firePressed();
std::cout << "********** Firing at Time ";
printOutFedTime(updateTime);
std::cout << " *************\n";
}
std::cout << "===================================================================\n\n";
sleepFunction();
}
delete theAmbData.time;
delete theAmbData.paramValues;
delete theAmbData.attrValues;
if ( theAmbData.isRegulating )
{
rtiAmb->disableTimeRegulation();
}
// Resign and destroy federation
resignAndDestroy(rtiAmb);
delete rtiAmb;
}
catch (RTI::Exception& ex)
{
std::cout << "RTI Exception (main loop): " << ex._name << " " << ex._reason << endl;
}
#ifdef WIN32
WSACleanup();
#endif
return 0;
}
bool parseCmdLine(int argc, char* argv[])
{
// Process command line input.
vector < std::string > cmdArgs;
copy(argv + 1, argv + argc, back_inserter(cmdArgs));
vector<std::string>::const_iterator cur = cmdArgs.begin();
vector<std::string>::const_iterator last = cmdArgs.end();
while (cur != last)
{
vector<std::string>::const_iterator next = cur + 1;
if (*cur == "-h")
{
std::cerr << usage();
return false;
}
else if (*cur == "-fedFile")
{
if (next == last || !convert<string>(*cur, *next, fedFileName))
{
std::cerr << usage();
return false;
}
++cur;
}
else if (*cur == "-m")
{
if (next == last || !convert<int>(*cur, *next, theAmbData.numFederates))
{
std::cerr << usage();
return false;
}
theAmbData.isMaster = true;
++cur;
}
else if (*cur == "-phaseLine")
{
double phaseLine(0);
if (next == last || !convert<double>(*cur, *next, phaseLine))
{
std::cerr << usage();
return false;
}
theAmbData.timeManagedObject.setPhaseLine(phaseLine);
++cur;
}
else if (*cur == "-sleepTime")
{
if (next == last || !convert<int>(*cur, *next, sleepTime))
{
std::cerr << usage();
return false;
}
++cur;
}
else if (*cur == "-dedicated")
{
dedicatedMachine = true;
}
else if (*cur == "-unManaged")
{
unManagedFederate = true;
}
else if (*cur == "-lookAhead")
{
if (next == last || !convert<double>(*cur, *next, theLookAhead))
{
std::cerr << usage();
return false;
}
++cur;
}
else if (*cur == "-timeIncrement")
{
if (next == last || !convert<double>(*cur, *next, theTimeAdvance))
{
std::cerr << usage();
return false;
}
++cur;
}
else if (*cur == "-available")
{
theAdvanceUsesAvailable = true;
}
else if (*cur == "-advanceTimeWith")
{
std::string timeAdvanceService;
if (next == last || !convert<string>(*cur, *next, timeAdvanceService))
{
std::cerr << usage();
return false;
}
++cur;
if (timeAdvanceService == "timeAdvanceRequest")
{
theTimeAdvanceService = tasTimeAdvanceRequest;
}
else if (timeAdvanceService == "nextMessageRequest")
{
theTimeAdvanceService = tasNextEventRequest;
}
else if (timeAdvanceService == "flushQueue")
{
theTimeAdvanceService = tasFlushQueue;
}
else
{
std::cerr << usage();
return false;
}
}
else
{
std::cerr << usage();
return false;
}
++cur;
}
return true;
}

simpleTimeFedAmb13.cxx

/*******************************************************************************
** Copyright (c) 2018 MaK Technologies, Inc.
** All rights reserved.
*******************************************************************************/
/*******************************************************************************
** $RCSfile: simpleTimeFedAmb13.cxx,v $ $Revision: 1.3 $ $State: Exp $
*******************************************************************************/
#ifdef WIN32
#pragma warning(disable: 4786)
#pragma warning(disable: 4290)
#else
#include <stdio.h>
#endif
#include <cstdlib>
#include <iostream>
using namespace std;
isConstrained(false),
isRegulating(false),
timeAdvanced(false),
time(0),
otherFederatesReady(0),
isMaster(false),
numFederates(0),
registerSucceeded(false),
registerFailed(false),
announceSyncReceived(false),
federationIsSynchronized(false)
{ }
{
}
NullFederateAmbassador(), myData(data)
{ }
throw (RTI::FederateInternalError)
{
}
RTI::ObjectHandle theObject,
RTI::ObjectClassHandle theObjectClass,
const char* theObjectName)
throw (
RTI::CouldNotDiscover,
RTI::ObjectClassNotKnown,
RTI::FederateInternalError)
{
// This is an over simplification of the initialization of a federation.
// In our case we simply wait until there are the requisite # of known federates
// before starting.
++myData.otherFederatesReady;
if ( myData.isMaster)
{
std::cout << " Master federate is aware of "
<< myData.otherFederatesReady + 1
<< " federates, including itself\n";
}
// Now that we've discovered an object we should request an Attribute
// update for all of the attributes that we're subscribed for.
// Construct an attribute handle set
RTI::AttributeHandleSet* hSet =
RTI::AttributeHandleSetFactory::create(myData.ourParms.size());
for (DtAttrNameHandleMap::iterator iter = myData.theAttrNameHandleMap.begin();
iter != myData.theAttrNameHandleMap.end();
iter++)
{
hSet->add(iter->second);
}
// In order to avoid making RTI calls from within an RTI callback,
// we'll add this attrRequest to a shared Object, allowing the
// call to be made from outside this callback.
myData.updateRequestMap.insert(make_pair(theObject,hSet));
delete hSet;
myData.objectInstanceMap[theObject] = theObjectName;
}
// To keep callbacks expedient and simple, we simply save all pertinent information
// from this reflect in our timeManagedObject, allowing the main thread of execution
// to process the update when it chooses.
// The same can be said of the other reflectAttributeValues calls
RTI::ObjectHandle theObject,
const RTI::AttributeHandleValuePairSet& theAttributes,
const RTI::FedTime& theTime,
const char *theTag,
throw (
RTI::ObjectNotKnown,
RTI::AttributeNotKnown,
RTI::FederateOwnsAttributes,
RTI::InvalidFederationTime,
RTI::FederateInternalError)
{
myData.timeManagedObject.addAttrUpdateEvent(new attributeUpdateEvent(
theAttributes,
theTime,
theTag,
theHandle));
}
RTI::ObjectHandle theObject,
const RTI::AttributeHandleValuePairSet& theAttributes,
const char *theTag)
throw (
RTI::ObjectNotKnown,
RTI::AttributeNotKnown,
RTI::FederateOwnsAttributes,
RTI::FederateInternalError)
{
myData.timeManagedObject.addAttrUpdateEvent(new attributeUpdateEvent(
theAttributes,
theTag ));
}
// Similar to the reflectAttributeValues implementations, here we do some minimal
// interpretation of the received Interaction (whether it is a fire or detonation
// interaction), and add the interaction event to our timeManagedObject, allowing
// the main thread of execution to process it as appropriate.
const RTI::ParameterHandleValuePairSet& theParameters,
const RTI::FedTime& theTime,
const char *theTag,
throw (
RTI::InteractionClassNotKnown,
RTI::InteractionParameterNotKnown,
RTI::InvalidFederationTime,
RTI::FederateInternalError)
{
string munitionString("MunitionObjectIdentifier");
string fireString("FiringObjectIdentifier");
RTI::ParameterHandle munitionHandle =
myData.theParamNameHandleMap.find(munitionString)->second;
RTI::ParameterHandle fireHandle =
myData.theParamNameHandleMap.find(fireString)->second;
for ( unsigned int i(0);
(interactionType == interactionEvent::Unknown) && i < theParameters.size();
++i )
{
if ( theParameters.getHandle(i) == munitionHandle )
{
RTI::ULong length = theParameters.getValueLength(i);
if ( length == 1 )
{
}
}
if ( theParameters.getHandle(i) == fireHandle )
{
RTI::ULong length = theParameters.getValueLength(i);
if ( length == 1 )
{
interactionType = interactionEvent::FireType;
}
}
}
myData.timeManagedObject.addInteractionEvent(new interactionEvent ( theInteraction,
theParameters,
theTime,
theTag,
interactionType ));
}
const RTI::ParameterHandleValuePairSet& theParameters,
const char *theTag)
throw (
RTI::InteractionClassNotKnown,
RTI::InteractionParameterNotKnown,
RTI::FederateInternalError)
{
myData.timeManagedObject.addInteractionEvent(
new interactionEvent( theInteraction,
theParameters,
theTag) );
}
// remove the object instance from our map of object instances.
RTI::ObjectHandle theObject,
const RTI::FedTime& theTime,
const char *theTag,
throw (
RTI::ObjectNotKnown,
RTI::InvalidFederationTime,
RTI::FederateInternalError)
{
if ( myData.objectInstanceMap.find(theObject) != myData.objectInstanceMap.end())
myData.objectInstanceMap.erase(theObject);
myData.timeManagedObject.reset();
}
RTI::ObjectHandle theObject,
const char *theTag)
throw (
RTI::ObjectNotKnown,
RTI::FederateInternalError)
{
if ( myData.objectInstanceMap.find(theObject) != myData.objectInstanceMap.end())
myData.objectInstanceMap.erase(theObject);
myData.timeManagedObject.reset();
}
// A request was made for an attribute update from this update, add the request
// to our updateRequestMap.
RTI::ObjectHandle theObject,
const RTI::AttributeHandleSet& theAttributes)
throw (
RTI::ObjectNotKnown,
RTI::AttributeNotKnown,
RTI::AttributeNotOwned,
RTI::FederateInternalError)
{
RTI::AttributeHandleSet* hSet =
RTI::AttributeHandleSetFactory::create(myData.ourAttrs.size());
for (DtAttrNameHandleMap::iterator iter = myData.theAttrNameHandleMap.begin();
iter != myData.theAttrNameHandleMap.end();
iter++)
{
hSet->add(iter->second);