![]() |
VR-Vantage 1.4.1 API Class Documentation
|
Project 3C in the Distributed Simulation tutorial takes a look at how to add both an add and a remove reflected entity callback to the simulation connection using VR-Link, which will inform the driver as to the entry and exit of an entity into and from the scene. Entities that are added to the scene can be agents added at scenario load and removed at scenario unload. Note that added entities can also be introduced during the run of a scenario, such as the introduction of a missile by another agent, the detonation of which will result in that missile entity's removal from the scene.
For this project, we will again use project 2A as the base, and no more class files will need to be added. All changes will be made in the DistributedSimulationDriver class as before.
Adding Reflected Entity Callbacks
To add callbacks, we will need to add two static callback functions, one for entity addition and the other for entity removal. We will also need instance functions for these callbacks to invoke in order for the actual instance of the driver to receive and respond to received entity data.
The first thing we need to do is to add declarations for both callback functions and both instance functions to the driver header file. All functions will need to take a pointer to a DtReflectedEntity object. The callbacks will also need to receive a void pointer to the object which owns the associated local instance function that the callback function will need to invoke.
static void processReflectedEntityAdditionCb(DtReflectedEntity *reflectedObj, void *usr); static void processReflectedEntityRemovalCb(DtReflectedEntity *reflectedObj, void *usr); virtual void processReflectedEntityAdd(DtReflectedEntity *reflectedObj) const; virtual void processReflectedEntityRemove(DtReflectedEntity *reflectedObj) const;
The new onStart() function looks as follows:
bool DistributedSimulationDriver::onStart() { std::cout << "DistributedSimulationDriver::onStart(): " << std::endl; DtExerciseConnInitializer init; init.setPort(3152); init.setExerciseId(1); init.setSiteId(2); init.setApplicationNumber(1); // VR-Link default buffer is to small for this application; set it to 1 MB. init.setReceiveBufferSize(0x100000); DtExerciseConn::InitializationStatus status = DtExerciseConn::DtINIT_SUCCESS; try { myConnection = new DtExerciseConn(init, &status); } catch(...) { return false; } myConnectionState = (status == DtExerciseConn::DtINIT_SUCCESS); // Add a reflected entity list callback myConnection->clock()->setSimTime(0); myReflectedEntityList = new DtReflectedEntityList(myConnection); myReflectedEntityList->addEntityAdditionCallback(&processReflectedEntityAdditionCb, this); myReflectedEntityList->addEntityRemovalCallback(&processReflectedEntityRemovalCb, this); return myConnectionState; }
The difference between this version and the version in Project 3A is that, instead of directly adding a callback for detonation interactions, we add a code block for instantiating a DtReflectedEntityList object, passing it our connection object. We then add to the entity list object references to our callback functions. It is important that the clock sim time should be reset.
// Add a reflected entity list callback myConnection->clock()->setSimTime(0); myReflectedEntityList = new DtReflectedEntityList(myConnection); myReflectedEntityList->addEntityAdditionCallback(&processReflectedEntityAdditionCb, this); myReflectedEntityList->addEntityRemovalCallback(&processReflectedEntityRemovalCb, this);
The callback functions, as noted, both take pointers of the type DtReflectedEntity, as well as void pointers to the object that owns the instance function that will be called from within both callbacks.
void DistributedSimulationDriver::processReflectedEntityAdditionCb(DtReflectedEntity *reflectedObj, void *usr) { ((DistributedSimulationDriver*)usr)->processReflectedEntityAdd(reflectedObj); } void DistributedSimulationDriver::processReflectedEntityRemovalCb(DtReflectedEntity *reflectedObj, void *usr) { ((DistributedSimulationDriver*)usr)->processReflectedEntityRemove(reflectedObj); }
Both callback functions will make calls to the instance functions shown here. These instance functions receive a DtReflectedEntity each, and print out arbitrary values regarding the associated entity.
void DistributedSimulationDriver::processReflectedEntityAdd(DtReflectedEntity *reflectedObj) const { std::cout << "A(" << reflectedObj->entityId().entityNum() << "," << reflectedObj->id().entityNum() << "," << reflectedObj->idString() << ")"; } void DistributedSimulationDriver::processReflectedEntityRemove(DtReflectedEntity *reflectedObj) const { std::cout << "R(" << reflectedObj->entityId().entityNum() << "," << reflectedObj->id().entityNum() << "," << reflectedObj->idString() << ")"; }
Invoke either the tutorialDistributedSimulation3Cd.bat or tutorialDistributedSimulation3C.sh script file to start the VR-Vantage Stealth application. Follow these instructions to test the plugin:
[<< Add a Detonation Listener] [Add an Entity Existence Listener >>]
/****************************************************************************** ** Copyright (c) 2011 MAK Technologies, Inc. ** All rights reserved. ******************************************************************************/ #pragma once #include <vrvCore/DtDriver.h> class DtExerciseConn; class DtReflectedEntity; class DtReflectedEntityList; namespace makVrv { namespace tutorialDistributedSimulation3C { class DistributedSimulationDriver : public DtDriver { public: DistributedSimulationDriver(DtAgentManager& agentManager, const std::string& instanceName); virtual ~DistributedSimulationDriver(); virtual const std::string& className() const; protected: virtual bool onStart(); virtual bool onStop(); virtual bool onTick(); static void processReflectedEntityAdditionCb(DtReflectedEntity *reflectedObj, void *usr); static void processReflectedEntityRemovalCb(DtReflectedEntity *reflectedObj, void *usr); virtual void processReflectedEntityAdd(DtReflectedEntity *reflectedObj) const; virtual void processReflectedEntityRemove(DtReflectedEntity *reflectedObj) const; protected: DtExerciseConn* myConnection; bool myConnectionState; DtReflectedEntityList* myReflectedEntityList; }; } }
/****************************************************************************** ** Copyright (c) 2011 MAK Technologies, Inc. ** All rights reserved. ******************************************************************************/ #define DtDIS 1 #include "DistributedSimulationDriver3C.h" #include <vrvCore/DtDe.h> #include <vl/exConnInit.h> #include <vl/exerciseConn.h> #include <vl/dReflEntList.h> #include <iostream> namespace makVrv { namespace tutorialDistributedSimulation3C { DistributedSimulationDriver::DistributedSimulationDriver( DtAgentManager& agentManager, const std::string& instanceName) : DtDriver(agentManager, instanceName) , myConnection(0) , myConnectionState(0) { } DistributedSimulationDriver::~DistributedSimulationDriver(void) { } const std::string& DistributedSimulationDriver::className() const { // name must be static, since it's returned by reference static std::string name("DistributedSimulationDriver"); return name; } bool DistributedSimulationDriver::onStart() { std::cout << "DistributedSimulationDriver::onStart(): " << std::endl; DtExerciseConnInitializer init; init.setPort(3152); init.setExerciseId(1); init.setSiteId(2); init.setApplicationNumber(1); // VR-Link default buffer is to small for this application; set it to 1 MB. init.setReceiveBufferSize(0x100000); DtExerciseConn::InitializationStatus status = DtExerciseConn::DtINIT_SUCCESS; try { myConnection = new DtExerciseConn(init, &status); } catch(...) { return false; } myConnectionState = (status == DtExerciseConn::DtINIT_SUCCESS); // Add a reflected entity list callback myConnection->clock()->setSimTime(0); myReflectedEntityList = new DtReflectedEntityList(myConnection); myReflectedEntityList->addEntityAdditionCallback(&processReflectedEntityAdditionCb, this); myReflectedEntityList->addEntityRemovalCallback(&processReflectedEntityRemovalCb, this); return myConnectionState; } bool DistributedSimulationDriver::onStop() { // NOTE: breakdown code goes here. Return false on bad status. std::cout << "DistributedSimulationDriver::onStop(): " << std::endl; delete myConnection; myConnection = 0; return true; } bool DistributedSimulationDriver::onTick() { // printout to show whether or not connected at the tick level if (myConnectionState) { int numread = myConnection->drainInput(); std::cout << "." << numread; } else std::cout << "x"; return myConnectionState; } void DistributedSimulationDriver::processReflectedEntityAdditionCb(DtReflectedEntity *reflectedObj, void *usr) { ((DistributedSimulationDriver*)usr)->processReflectedEntityAdd(reflectedObj); } void DistributedSimulationDriver::processReflectedEntityRemovalCb(DtReflectedEntity *reflectedObj, void *usr) { ((DistributedSimulationDriver*)usr)->processReflectedEntityRemove(reflectedObj); } void DistributedSimulationDriver::processReflectedEntityAdd(DtReflectedEntity *reflectedObj) const { std::cout << "A(" << reflectedObj->entityId().entityNum() << "," << reflectedObj->id().entityNum() << "," << reflectedObj->idString() << ")"; } void DistributedSimulationDriver::processReflectedEntityRemove(DtReflectedEntity *reflectedObj) const { std::cout << "R(" << reflectedObj->entityId().entityNum() << "," << reflectedObj->id().entityNum() << "," << reflectedObj->idString() << ")"; } } }
/****************************************************************************** ** Copyright (c) 2011 MAK Technologies, Inc. ** All rights reserved. ******************************************************************************/ #pragma once // Setup proper plugin export symbol #ifdef WIN32 #define DT_DE_PLUGIN_EXPORT_MACRO __declspec ( dllexport ) #else #define DT_DE_PLUGIN_EXPORT_MACRO #endif // Declare & export the plugin initialization function (bool initDeModule(DtDe* de)) #include <vrvCore/exportPlugin.h> namespace makVrv { class DtDe; } // Work function for the plugin initialization void init(makVrv::DtDe& de); // Callback to create the stateViewDriver void createDistributedSimDriver(makVrv::DtDe* de);
/****************************************************************************** ** Copyright (c) 2011 MAK Technologies, Inc. ** All rights reserved. ******************************************************************************/ #include "DistributedSimulationPlugin3C.h" #include "DistributedSimulationDriver3C.h" #include <vrvCore/DtDe.h> #include <vrvCore/DtDriverManager.h> #include <boost/bind.hpp> using namespace makVrv; using namespace makVrv::tutorialDistributedSimulation3C; void createDistributedSimDriver(DtDe* de) { // We're done with the signal, so disconnect from it de->signal_postInitialize.disconnect(boost::bind( &createDistributedSimDriver, de)); // Create the driver that will implement a distributed simulation DistributedSimulationDriver* driver = new DistributedSimulationDriver( de->agentManager(), "DistributedSimulationDriver3C"); // After the driver is added to the display engine below, the DE will manage // its memory. This driver will add itself to the connection list. Start // it from the connection panel. de->driverManager().addDriver(driver); } void init(DtDe& de) { // Ensure that init only gets called once // (not strictly necessary here, but this is good practice in general) DT_DE_INIT_ONCE(de); // We only want to create the driver if we're running in master mode: if (de.isInMasterMode()) { // The driver must be created after the DE's initialization is // finished, to make sure all the objects it uses exist. de.signal_postInitialize.connect(boost::bind( &createDistributedSimDriver, &de)); } } bool initDeModule(makVrv::DtDe* de) { // Setup the plugin. Normally, the init function and functionality // should be in its own library. init(*de); return true; }