Introduction to Project 2A
Project 2A in the Distributed Simulation tutorial takes a look at how to create a non-threaded connection to the distributed simulation using VR-Link. A connection can be made using any of the following protocols: DIS, HLA 1.3, or HLA 1516. For this project, and for project 2B, we are going to look at creating a DIS connection. We will use that protocol for all subsequent projects.
Examining the files that make up the project
For this project, all files created for Project 1 will be reused. No new files will be needed. All changes, other than filenames, will be made in the DistributedSimulationDriver class files.
Creating a non-threaded VR-Link connection
To create a non-threaded VR-Link connection, we will need to add a DtExerciseConn pointer as a member in the DistributedSimulationDriver class. It is also useful to have a member boolean to keep the current state of the connection. Once these are added to the header file, we can instantiate the connection in the OnStart() function, and make use of it in onTick().
First we want to make a decision as to which protocol we mean to use. Since DIS is the simplest choice, we will add the following at the top of the .cxx file.
Then we will need to include the necessary VR-Link header files. The exConnInit.h header file routes off to declarations of a DIS, HLA 1.3, or HLA 1516 version of the DtExerciseConnInitializer class which is used for initializing a connection. The DtDIS macro that we defined above will cause the following header to route to the correct version of the exerciseConn.h file for the DIS protocol.
The new onStart() function looks as follows:
{
std::cout << "DistributedSimulationDriver::onStart(): " << std::endl;
init.setPort(3152);
init.setExerciseId(1);
init.setSiteId(2);
init.setApplicationNumber(1);
init.setReceiveBufferSize(0x100000);
DtExerciseConn::InitializationStatus status = DtExerciseConn::DtINIT_SUCCESS;
try
{
myConnection = new DtExerciseConn(init, &status);
}
return myConnectionState;
}
Let's look at this new function. First we instantiate and initialize a connection initializer object which will be passed as the first parameter to the connection constructor. Always make sure that you set the default buffer size to be at least 1MB:
init.setPort(3152);
init.setExerciseId(1);
init.setSiteId(2);
init.setApplicationNumber(1);
init.setReceiveBufferSize(0x100000);
The second input parameter for the connection constructor is an enumeration used for returning the connection status after the connection object has been constructed:
DtExerciseConn::InitializationStatus status = DtExerciseConn::DtINIT_SUCCESS;
Since the connection constructor can throw an exception, we wrap the instantiation of the connection object inside a try block.
try
{
myConnection = new DtExerciseConn(init, &status);
}
catch(...)
{
return false;
}
myConnectionState = (status == DtExerciseConn::DtINIT_SUCCESS);
And then we return the connection state as a boolean.
return myConnectionState;
}
The new onTick() function has also been changed to contain one new call wrapped in an if statement. If the connection state is good, then we want to drain whatever simulation input is waiting for us on the connection. The return value for the drainInput() function is the number of PDUs processed. Again the connection state is returned as the result of the onTick() call.
{
if (myConnectionState)
{
int numread = myConnection->drainInput();
std::cout << "." << numread;
}
else
{
std::cout << "x";
}
The new onStop() function looks as follows:
{
std::cout << "DistributedSimulationDriver::onStop(): " << std::endl;
delete myConnection;
myConnection = 0;
return true;
}
The files changed to add this functionality are as follows:
Testing the plugin
Invoke either the tutorialDistributedSimulation2Ad.bat or tutorialDistributedSimulation2A.sh script file to start the VR-Vantage Stealth application. Follow these instructions to test the plugin:
-
Choose File > View > Drivers Panel.
-
Select the driver named "DistributedSimulationDriver2A".
-
Click on the Start button.
-
You will see in the console window that the text "DistributedSimulationDriver::onStart():" has printed, and on the subsequent line, a series of dots is now continually being printed. Each dot is followed by the number of PDUs read in from the simulation connection. At this point these will mostly be 0, but can be a small positive integer.
-
If you start up a VR-Forces application using DIS as the protocol, open a scenario, and then start the scenario, the number of PDUs read will increase notably, showing that a connection to the simulation has in fact been established by the driver.
-
Go back to Stealth, make sure the same driver is selected in the Drivers Panel, and click the Stop button.
-
You will see in the console window that the dots and byte counts are no longer being printed, and that the text "DistributedSimulationDriver::onStop():" has been printed on the subsequent line.
-
Continually clicking the Start and Stop button will keep starting and stopping the driver, giving these same results in the console window.
[<< Introduction] [Create a Threaded Connection >>]
Project Files
DistributedSimulationDriver2A.h
#pragma once
class DtExerciseConn;
namespace makVrv
{
namespace tutorialDistributedSimulation2A
{
class DistributedSimulationDriver : public DtDriver
{
public:
protected:
protected:
};
}
}
DistributedSimulationDriver2A.cxx
#define DtDIS 1
#include <vl/exerciseConnInitializer.h>
#include <vl/exerciseConn.h>
#include <iostream>
namespace makVrv
{
namespace tutorialDistributedSimulation2A
{
DtAgentManager& agentManager,
const std::string& instanceName)
: DtDriver(agentManager, instanceName)
, myConnection(0)
, myConnectionState(0)
{
}
DistributedSimulationDriver::~DistributedSimulationDriver(void)
{
}
const std::string& DistributedSimulationDriver::className()
const
{
}
bool DistributedSimulationDriver::onStart()
{
std::cout << "DistributedSimulationDriver::onStart(): " << std::endl;
init.setPort(3152);
init.setExerciseId(1);
init.setSiteId(2);
init.setApplicationNumber(1);
init.setReceiveBufferSize(0x100000);
DtExerciseConn::InitializationStatus status = DtExerciseConn::DtINIT_SUCCESS;
try
{
myConnection = new DtExerciseConn(init, &status);
}
catch(...)
{
return false;
}
myConnectionState = (status == DtExerciseConn::DtINIT_SUCCESS);
return myConnectionState;
}
bool DistributedSimulationDriver::onStop()
{
std::cout << "DistributedSimulationDriver::onStop(): " << std::endl;
delete myConnection;
myConnection = 0;
return true;
}
bool DistributedSimulationDriver::onTick()
{
if (myConnectionState)
{
int numread = myConnection->drainInput();
std::cout << "." << numread;
}
else
{
std::cout << "x";
}
return myConnectionState;
}
}
}
DistributedSimulationPlugin2A.h
#pragma once
#ifdef WIN32
#define DT_DE_PLUGIN_EXPORT_MACRO __declspec ( dllexport )
#else
#define DT_DE_PLUGIN_EXPORT_MACRO
#endif
namespace makVrv { class DtDe; }
DistributedSimulationPlugin2A.cxx
#include <boost/bind.hpp>
using namespace makVrv;
using namespace tutorialDistributedSimulation2A;
{
DistributedSimulationDriver* driver = new DistributedSimulationDriver(
}
{
{
}
}
{
return true;
}