Listen is a simple listen-only VR-Link application.
This application can be compiled for either DIS or HLA. The only protocol-specific code is contained in the #if statement (#if DtDIS).
With each iteration of the loop, the program prints an entity's updated, dead-reckoned position in topographic coordinates. If a fire PDU or interaction is detected on the network, the program prints a message showing the entity ID of the attacker.
To exit, press the 'q' key. This example works with the Talk example.
Connecting to An Exercise
The program creates an exercise connection (DtExerciseConn.) This connection serves as the program's interface to an exercise. DtExerciseConn has several constructors. In this example, we create a DtVrlApplicationInitializer and pass it to the DtExerciseConn. Use of a DtVrlApplicationInitializer provides support for command line arguments. The default protocol-specific initialization values are set in the DtVrlApplicationInitializer and its base class, DtExerciseConnInitializer. This is the only protocol-specific part of the code.
Managing State and Interaction Information
Applications based on VR-Link typically use callbacks to handle incoming interactions such as fire, detonations, and collisions. For example, a callback named fireCb is registered with the DtFireInteraction class. This callback prints a message containing the attacker ID. It executes whenever the exercise connection receives a Fire PDU or interaction during a call to drainInput().
Tracking Entities
We create a reflected entity list to keep track of entities found on the network. The entity list tracks the arrival and departure of entities, performs dead reckoning, manages time outs, and performs other entity-tracking tasks.
Time Managing Time
We obtain a pointer to the simulation clock from the exercise connection.
Listening to the Network
At the start of each iteration, the program sets VR-Link simulation time to provide a common time value for use by time-related operations that occur within an iteration of the loop (such as the dead-reckoning of multiple entities.) The drainInput() call reads and processes any messages arriving through the exercise connection. This call triggers the execution, if needed, of any callbacks you have registered for that exercise connection.
The program finds the first entity in the entity list, then it retrieves the pointer to the entity's entity state repository. It creates a topographic view of that entity state repository, allowing us to retrieve its position data in topographic coordinates rather than geocentric. (The coordinates for this example are hard-coded.) The application obtains and prints the dead-reckoned entity location.
Example Code
#include <iostream>
int theReceivedUpdateCount = 0;
void DtRtiShutdownHandler(const char * label, void* finished)
{
int* finishedInt = (int*)finished;
if (*finishedInt)
{
DtWarn <<
"Shutting down: " << label << std::endl;
}
*finishedInt = 0;
}
{
theReceivedUpdateCount++;
}
{
}
{
theReceivedUpdateCount++;
}
{
}
{
{
return false;
}
return true;
}
{
std::cout <<
"Fire Interaction from " << fire->
attackerId().
string() << std::endl;
}
{
}
int main(int argc, char** argv)
{
try
{
#if DtDIS
appInit.setUseAsynchIO( true );
appInit.setDisVersionToSend( 7 );
#else
appInit.setExecName( "MAK-One-2024" );
appInit.setRprFomVersion( 2.0 );
appInit.setRprFomRevision( 2 );
#ifdef DtHLA_1516_EVOLVED
std::vector<DtString> fomModules;
std::vector<DtString> fomModuleFromCommandLine;
appInit.fomModules(fomModuleFromCommandLine);
fomModules.push_back("NETN-BASE.xml");
fomModules.push_back("NETN-Physical.xml");
fomModules.push_back("NETN-METOC.xml");
fomModules.push_back("NETN-MRM.xml");
fomModules.push_back("MAK-Physical-2_evolved.xml");
fomModules.push_back("MAK-Aerodrome-1_evolved.xml");
fomModules.push_back("MAK-METOC-1_evolved.xml");
fomModules.push_back("MAK-VRFExt-9_evolved.xml");
fomModules.push_back("MAK-DIGuy-7_evolved.xml");
fomModules.push_back("MAK-LgrControl-2_evolved.xml");
fomModules.push_back("MAK-VRFAggregate-6_evolved.xml");
fomModules.push_back("MAK-DynamicTerrain-2_evolved.xml");
fomModules.push_back("MAK-VRLExt-3_evolved.xml");
fomModules.push_back("MAK-DER-1_evolved.xml");
fomModules.push_back("RPR-Enumerations_Experimental_IFF.xml");
fomModules.push_back("RPR-MAK_Experimental_IFF-3.xml");
fomModules.insert(fomModules.end(), fomModuleFromCommandLine.begin(), fomModuleFromCommandLine.end());
appInit.setFomModules(fomModules);
#endif
#endif
appInit.parseCmdLine();
#ifdef DtHLA
std::cout <<
"[" << clock->
simTime() <<
", " <<
" 0] Initializing" << std::endl;
#endif
if (status != 0)
{
std::cout << "Error creating exercise connection." << std::endl;
return -1;
}
relEnv.addEnvironmentProcessAdditionCallback(envProcAddedCb, NULL);
#ifdef DtHLA
std::cout <<
"[" << clock->
simTime() <<
", " <<
" 0] Executing" << std::endl;
#endif
int forever = 1;
#ifdef DtHLA
#endif
unsigned long loopCount = 0;
double outputInterval = appInit.outputInterval();
double frameTime = 0.1;
std::cout << std::fixed << std::setprecision(2);
while (forever)
{
loopCount++;
break;
if (first && (outputInterval <= 0.0 || outputTime < clock->absRealTime()))
{
#if DtDIS
const char* entityId = first->entityId().string();
#else
#endif
double refLongitude =
DtDeg2Rad(-121.326577);
DtTopoView topoView(esr, refLatitude, refLongitude);
std::cout <<
"[" << clock->
simTime() <<
", " << loopCount <<
"] #entities: " << rel.
count()
<< " #updates received: " << theReceivedUpdateCount << ", "
<< "First entity: \"" << entityId << "\" " << " position: "
<< "(" << topoView.location().x() << ", " << topoView.location().y() << ", " << topoView.location().z() << ")" << std::endl;
theReceivedUpdateCount = 0;
}
#ifdef DtDIS
if (duration < frameTime)
{
}
#else
exConn.
drainInput(frameTime - duration, frameTime - duration);
#endif
}
}
return 0;
}