VR-Link API Documentation for HLA Evolved
Listen Example

Listen is a simple listen-only VR-Link application which has been extended to take advantage of HLA Evolved Specific functionality.

The HLA Evolved functionality can be found inside the preprocessor #if DtHLA_1516_EVOLVED defines.

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.

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.


//********************************************************************
// Copyright (c) 2007 MaK Technologies, Inc.
// All rights reserved.
//********************************************************************
#include <vl/exConnInit.h>
#include <vl/reflEntList.h>
#include <vl/entitySR.h>
#include <vl/fireInter.h>
#include <vl/topoView.h>
#include <iostream>
int keybrdTick(void);
#if DtHLA
void reflectCb( const DtStateMsg& msg, DtHlaObject* obj, void* usr );
void removeObjectCb( DtHlaObject* obj, void* usr );
void discoverObjectCb( DtHlaObject* obj, void* usr );
#endif
unsigned int numUpdates = 0;
DtTime initialTime;
bool hasDiscovered = false;
DtString lastProducingFederate;
double updatesPerSecond = 0.0;
// Define a callback to process fire interactions.
void fireCb(DtFireInteraction* fire, void* /*usr*/)
{
std::cout << "Fire Interaction from "
<< fire->attackerId().string() ;
#if DtHLA_1516_EVOLVED
DtString producingFederate = fire->producingFederate();
if ( producingFederate.size() )
{
std::cout << " Federate Name " << producingFederate;
}
#endif
std::cout << std::endl;
}
int main(int argc, char** argv)
{
try
{
// Create an exercise conn initializer. This will parse the command
// line, as well as parse an mtl file with the same name as this application.
DtVrlApplicationInitializer appInit(argc, argv, "VR-Link Listen");
#if DtHLA_1516_EVOLVED
appInit.setFederateType("Listen Example");
#endif
// Process the command line. This will actually set values in the
// DtVrlApplicationInitializer class and should be called before
// creating the DtExerciseConn instance.
appInit.parseCmdLine();
#if DtHLA_1516_EVOLVED
appInit.setFedFileName("VR-Link_evolved.xml");
std::vector<DtString> joinModules;
joinModules.push_back("updateRate.xml");
appInit.setJoinFomModules(joinModules);
#endif
// The DtExerciseConn instance is perhaps the most important class
// in any VR-Link exercise. Think of it as the hub which holds
// everything else together. Technically this instance is what's
// responsible for connecting this federate to another federate via
// a network, or an RTI. After exConn is created, and if no error
// has occurred this simulator will be a live federate.
DtExerciseConn exConn(appInit);
// Register a callback to handle fire interactions.
DtFireInteraction::addCallback(&exConn, fireCb, NULL);
// Create an object to manage entities that we hear about
// on the network.
#if DtHLA_1516_EVOLVED
DtReflectedEntityList rel(&exConn, DtString("everyFiveSeconds") );
#else
DtReflectedEntityList rel(&exConn);
#endif
// Initialize VR-Link time.
DtClock* clock = exConn.clock();
#if DtHLA
#if DtHLA_1516
exConn.addDiscoverObjectCallback( RTI::ObjectClassHandle(), discoverObjectCb, 0 );
#else
exConn.addDiscoverObjectCallback( 0, discoverObjectCb, 0 );
#endif
#endif
int forever = 1;
while (forever)
{
// Check if user hit 'q' to quit.
if (keybrdTick() == -1)
break;
// Tell VR-Link the current value of simulation time.
clock->setSimTime(clock->elapsedRealTime());
// Process any incoming messages.
exConn.drainInput();
// Find the first entity in the reflected entity list.
DtReflectedEntity *first = rel.first();
if (first)
{
// Grab its state repository, where we can inspect its data.
// Create a topographic view on the state repository, so we
// can look at position information in topographic coordinates.
double refLatitude = DtDeg2Rad( 35.699760);
double refLongitude = DtDeg2Rad(-121.326577);
DtTopoView topoView(esr, refLatitude, refLongitude);
std::cout << " num updates / second = " << updatesPerSecond ;
#if DtHLA_1516_EVOLVED
lastProducingFederate = first->lastProducingFederate();
if ( lastProducingFederate.size() )
{
std::cout << ". Last Update from " << lastProducingFederate ;
}
#endif
std::cout << std::endl;
}
// Sleep till next iteration.
DtSleep(0.1);
}
}
DtCATCH_AND_WARN(std::cout);
return 0;
}
int keybrdTick()
{
char *keyPtr = DtPollBlockingInputLine();
if (keyPtr && (*keyPtr == 'q' || *keyPtr == 'Q'))
return -1;
else
return 0;
}
#if DtHLA
void reflectCb( const DtStateMsg& msg, DtHlaObject* obj, void* usr )
{
DtExerciseConn* exConn = obj->exerciseConn();
DtClock* clock = obj->exerciseConn()->clock();
DtTime curr = clock->elapsedRealTime();
++numUpdates;
if ( 0 == numUpdates )
{
initialTime = curr;
}
else
{
DtTime effectiveCurrTime = curr - initialTime;
updatesPerSecond = ((double)(numUpdates)) / ((double)(effectiveCurrTime));
}
}
void removeObjectCb( DtHlaObject* obj, void* usr )
{
obj->removeRemoveObjectCb( removeObjectCb, 0 );
obj->removePostReflectCb( reflectCb, 0 );
hasDiscovered = false;
}
void discoverObjectCb( DtHlaObject* obj, void* usr )
{
if ( !hasDiscovered )
{
obj->addPostReflectCb( reflectCb, 0 );
obj->addRemoveObjectCb( removeObjectCb, 0 );
}
hasDiscovered = true;
}
#endif

Document ID: Generated on Wed Aug 14 15:35:11 EDT 2013 from SVN revision 130445
Copyright © 2005-2013 VT MÄK. All Rights Reserved (www.mak.com)