VR-Exchange 2.10 API Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Simple Broker Example

The SimpleBroker application is a complete VR-Exchange broker.

It demonstrates how to build a broker class as well as a broker application. The SimpleBroker receives and transmits DIS PDUs as part of the example. It does not do translations in any meaningful way, and is completely non functional as a DIS broker.

Three significant classes are created in this example. DtSimpleBroker, which subclasses DtBroker, connects to the Portal via DtBroker, and registers for callbacks for broker exit. It also processes the configuration file simpleBroker.xml. Two helper classes, DtEntityTranslator and DtFireTranslator, simulate translation of Entity State PDUs and Weapon Fire PDU's. These classes were designed to show how new objects can be created and updates can be processed for both objects and interactions.


simple.cxx

/****************************************************************************
* Copyright (c) 2014 MAK Technologies, Inc.
* All rights reserved.
****************************************************************************/
#include <simpleBroker.h>
#include <vlutil/vlExceptions.h>
#include <vlutil/vlMiniDumper.h>
#include <iostream>
using namespace MAKVrExchange;
int main( int argc, char* argv[] )
{
DtINIT_MINIDUMPER( "simple_broker" );
DtSimpleBroker* sb = 0;
try
{
const std::string version = "1.0";
// Load the configuration options
new DtBrokerInitializer( argc, argv, DtPortalConnection::version().c_str() );
init->parseCmdLine();
// There are no connection options for this simple broker, so just return
// without doing anything.
if ( init->showConnectionInfoDialog() )
{
return 0;
}
// Create a broker instance
sb = DtSimpleBroker::create( init );
// Tick the broker until we get the exit message
while ( ! sb->isTimeToQuit() )
{
DtSleep( sb->pollingInterval() );
}
}
DtCATCH_AND_WARN( std::cout );
DtDELETE( sb );
return 0;
}

simpleBroker.cxx

/****************************************************************************
* Copyright (c) 2016 MAK Technologies, Inc.
* All rights reserved.
****************************************************************************/
#include "simpleBroker.h"
#include <vl/exerciseConn.h>
#include <vl/exerciseConnInitializer.h>
using namespace MAKVrExchange;
{
DtSimpleBroker* broker = new DtSimpleBroker();
broker->initialize( init );
return broker;
}
, myDisExConn( 0 )
, myFireTranslator( 0 )
, myEntityTranslator( 0 )
{
}
{
DtBroker::initialize( init );
// Create a connection to the DIS Exercise with some default parameters
DtExerciseConnInitializer dInit;
dInit.setPort( 3005 );
dInit.setSiteId( 1 );
dInit.setApplicationNumber( 23 );
myDisExConn = new DtExerciseConn( dInit );
// Create a translator for all Fire Interactions
}
{
// Clean up resources
DtDELETE( myFireTranslator );
DtDELETE( myDisExConn );
}
DtExerciseConn* DtSimpleBroker::disExConn()
{
return myDisExConn;
}
{
try
{
myDisExConn->clock()->setSimTime( simTime() );
myDisExConn->drainInput();
}
DtCATCH_AND_WARN( DtWarn );
}

sFireTrans.cxx

/****************************************************************************
* Copyright (c) 2015 MAK Technologies, Inc.
* All rights reserved.
****************************************************************************/
#include "sFireTrans.h"
// VR-Link DIS Includes
#include <matrix/vlVector.h>
#include <vl/exerciseConn.h>
#include <vlpi/entityIdentifier.h>
// Portal Includes
using namespace MAKVrExchange;
DtFireTranslator::DtFireTranslator(DtExerciseConn& disConn, DtPortalConnection &pConn):
myDisConn(disConn),
myPortalConn(pConn)
{
DtFireInteraction::addCallback(
&myDisConn, receiveDisInteraction, this);
DtPortalFireInteraction::addCallback(
&myPortalConn, receivePortalInteraction, this);
}
{
DtFireInteraction::removeCallback(
DtPortalFireInteraction::removeCallback(
}
// -------------------------------------------------------------------
// -------- Translation Methods
// -------------------------------------------------------------------
{
DtFireInteraction out;
// In a real broker, some translation would need to happen here.
// The entity ID would need to be mapped from some string value. If there
// was no valid conversion a unique entity Id would need to be created.
out.setAttackerId(DtEntityIdentifier(1,3,4));
out.setTargetId(DtEntityIdentifier(2,4,2));
out.setMunitionId(DtEntityIdentifier(3,4,2));
out.setWarheadType((DtWarheadType)in.warheadType());
myDisConn.send(out);
}
void DtFireTranslator::createPortalInteraction( const DtFireInteraction& in )
{
// The Portal uses Strings for Ids. One translation scheme
// would be to use the DIS ID as a string. The decision regarding
// translation is significantly more complicated.
out.setAttackerId( in.attackerId().string() );
out.setTargetId( in.targetId().string() );
out.setMunitionId( in.munitionId().string() );
out.setWarheadType( (DtWarheadType)in.warheadType() );
}
// -------------------------------------------------------------------
// -------- Static Methods
// -------------------------------------------------------------------
void DtFireTranslator::receiveDisInteraction( DtFireInteraction* fire, void* usr )
{
trans->createPortalInteraction( *fire );
}
{
trans->createInteraction( fire );
}

sEntityTrans.cxx

/****************************************************************************
* Copyright (c) 2016 MAK Technologies, Inc.
* All rights reserved.
****************************************************************************/
#include "sEntityTrans.h"
// VR-Link DIS Includes
#include <matrix/vlVector.h>
#include <vl/exerciseConn.h>
#include <vl/entityPublisher.h>
#include <vl/reflectedEntityList.h>
#include <vl/baseEntityStateRepository.h>
// Portal Includes
#include <portal/pEntity.h>
using namespace MAKVrExchange;
: myDisConn( disConn )
, myPortalConn( pConn )
, myDisReflectedList( 0 )
, myPortalReflectedManager( 0 )
, myDisEntityPublisher( 0 )
, myPortalEntityPublisher( 0 )
{
// Create Reflected Lists to handle DIS Updates -- This is VR-Link DIS Code
myDisReflectedList = new DtReflectedEntityList(&disConn);
myDisReflectedList->addEntityRemovalCallback(DtEntityTranslator::disObjectDeletedCb, this);
myDisReflectedList->addEntityAdditionCallback(DtEntityTranslator::disObjectAddedCb, this);
// Create Reflected Manager for Portal Updates -- This is Portal Specific
myPortalReflectedManager = new DtPortalReflectedEntityManager(&pConn);
myPortalReflectedManager->addRemovalCallback(DtEntityTranslator::portalObjectDeletedCb, this);
myPortalReflectedManager->addAdditionCallback(DtEntityTranslator::portalObjectAddedCb, this);
myDisReflectedList->setDiscoveryCondition(disDiscoveryCriteria, this);
myPortalReflectedManager->setDiscoveryCondition(DtEntityTranslator::portalDiscoveryCriteria, this);
}
{
if (myDisEntityPublisher)
{
DtDELETE( myDisEntityPublisher );
}
if (myPortalEntityPublisher)
{
DtDELETE( myPortalEntityPublisher );
}
DtDELETE( myDisReflectedList );
DtDELETE( myPortalReflectedManager );
}
{
}
// -------------------------------------------------------------------
// -------- Translation Methods
// -------------------------------------------------------------------
void DtEntityTranslator::discoverDisObject(const DtReflectedEntity &reflectedObj)
{
if (!myPortalEntityPublisher)
{
myPortalEntityPublisher =
new DtPortalEntityPublisher(&myPortalConn);
// Call to update attributes - In DIS all attributes are available at discovery
receiveDisUpdate(reflectedObj);
}
}
{
// This example only translates the first entity
if (!myDisEntityPublisher)
{
// Create a DIS Publisher for this object. Most of the values for this
// publisher are bogus. Translation of a real object is beyond the scope of
// this example.
myDisEntityPublisher =
new DtEntityPublisher( DtEntityType(1,2,3,4,5,6,7),
&myDisConn,
DtEntityIdentifier(1,2,3));
// Call to update attributes - The Data Exchange makes all attributes
// available at discovery
receivePortalUpdate(reflectedObj);
}
}
void DtEntityTranslator::receiveDisUpdate( const DtReflectedEntity& reflectedObj )
{
if ( myPortalEntityPublisher )
{
DtPortalEntity* newSr = myPortalEntityPublisher->sr();
const DtEntityStateRepository* sr = reflectedObj.esr();
// Copy all values and do any translation required. In this case all DIS
// coords are the same as portal coords (Geocentric)
newSr->setLocation( sr->location() );
newSr->setVelocity( sr->velocity() );
newSr->setAcceleration( sr->acceleration() );
newSr->setOrientation( sr->orientation() );
newSr->setRotationalVelocity( sr->rotationalVelocity() );
newSr->setRelativeLocation( sr->relativeLocation() );
newSr->setRelativeVelocity( sr->relativeVelocity() );
newSr->setRelativeAcceleration( sr->relativeAcceleration() );
newSr->setRelativeOrientation( sr->relativeOrientation() );
newSr->setRelativeRotationalVelocity( sr->relativeRotationalVelocity() );
}
}
{
if (myDisEntityPublisher)
{
const DtPortalEntity *sr = reflectedObj.sr();
DtEntityStateRepository *newSr = myDisEntityPublisher->esr();
// Copy all values and do any translation required. In this case all DIS
// coords are the same as portal coords (Geocentric)
newSr->setLocation(sr->location());
newSr->setVelocity(sr->velocity());
newSr->setAcceleration(sr->acceleration());
newSr->setOrientation(sr->orientation());
newSr->setRotationalVelocity(sr->rotationalVelocity());
newSr->setRelativeLocation(sr->relativeLocation());
newSr->setRelativeVelocity(sr->relativeVelocity());
newSr->setRelativeAcceleration(sr->relativeAcceleration());
newSr->setRelativeOrientation(sr->relativeOrientation());
newSr->setRelativeRotationalVelocity(sr->relativeRotationalVelocity());
}
}
void DtEntityTranslator::processDisRemoval(const DtReflectedEntity &reflectedObj)
{
if (myPortalEntityPublisher)
{
DtDELETE( myPortalEntityPublisher );
}
}
{
// Any object removal will delete this entity publisher. It means this
// example will appear to work only when there is one entity available.
if (myDisEntityPublisher)
{
DtDELETE( myDisEntityPublisher );
}
}
// -------------------------------------------------------------------
// -------- Static Methods
// -------------------------------------------------------------------
DtReflectedEntity *reflectedObj, void *userData)
{
DtEntityTranslator *et = static_cast<DtEntityTranslator*>(userData);
et->discoverDisObject(*reflectedObj);
// Register for updates on this object
reflectedObj->addPostUpdateCallback(DtEntityTranslator::disObjectUpdatedCb, userData);
}
DtReflectedEntity *reflectedObj, void *userData)
{
DtEntityTranslator *et = static_cast<DtEntityTranslator*>(userData);
et->receiveDisUpdate(*reflectedObj);
}
DtReflectedEntity *reflectedObj, void *userData)
{
DtEntityTranslator *et = static_cast<DtEntityTranslator*>(userData);
et->processDisRemoval(*reflectedObj);
}
const DtPortalReflectedEntity& reflectedObj, void *userData)
{
DtEntityTranslator *et = static_cast<DtEntityTranslator*>(userData);
et->discoverPortalObject(reflectedObj);
// Register for updates on this object
}
const DtPortalReflectedEntity& reflectedObj, void *userData)
{
DtEntityTranslator *et = static_cast<DtEntityTranslator*>(userData);
et->receivePortalUpdate(reflectedObj);
}
const DtPortalReflectedEntity& reflectedObj, void *userData)
{
DtEntityTranslator *et = static_cast<DtEntityTranslator*>(userData);
et->processProtalRemoval(reflectedObj);
}
DtReflectedObject* ro, void *object)
{
// HLA Object is always discoverable for this example
return true;
}
const DtPortalReflectedObject *ro, void *object)
{
// Portal Object is always discoverable for this example
return true;
}

Document ID: Generated on Mon May 25 18:45:12 EDT 2026 from SVN revision 289111
Copyright © 2005-2026 MAK Technologies. All Rights Reserved (www.mak.com)