VR-Link API Documentation for HLA 1.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
2.9 - Basic VR-Link Examples

Table of Contents

This section lists and describes two simple VR-Link applications. The first is a listen-only application that observes an exercise without simulating any entity on the network. The second is a write-only program that does not process information about remote entities.

Note
The source code for both examples is included with VR-Link.

2.9.1 A Listen-Only Example

The Listen-Only is an application that just listens to the network. This application can be compiled for either DIS or HLA. The only protocol-specific code is contained in the #if statement that starts at line 27.

With each iteration of the loop, the program prints an entity's updated, dead-reckoned position in topographic coordinates. In addition, if a fire PDU or interaction is detected on the network, the program prints a message showing the entity ID of the attacker.

1 #include <vl/exerciseConn.h>
2 #include <vl/exerciseConnInitializer.h>
3 #include <vlutil/vlProcessControl.h>
4 #include <vl/reflectedEntityList.h>
5 #include <vl/entityStateRepository.h>
6 #include <vl/reflectedEntity.h>
7 #include <vl/fireInteraction.h>
8 #include <vl/topoView.h>
9 #include <iostream>
10
11 int keybrdTick(void);
12
13 // Define a callback to process fire interactions.
14 void fireCb(DtFireInteraction* fire, void* /*usr*/)
15 {
16 std::cout << "Fire Interaction from "
17 << fire->attackerId().string() << std::endl;
18 }
19
20 int main(int argc, char** argv)
21 {
22 try
23 {
24 // Create a connection to the exercise or federation execution.
25 DtVrlApplicationInitializer appInit(argc, argv, "VR-Link Listen");
26
27 #if DtDIS
28 appInit.setUseAsynchIO(true);
29 #endif
30
31 appInit.parseCmdLine();
32
33 DtExerciseConn exConn(appInit);
34
35 // Register a callback to handle fire interactions.
36 DtFireInteraction::addCallback(&exConn, fireCb, NULL);
37
38 // Create an object to manage entities that we hear about
39 // on the network.
40 DtReflectedEntityList rel(&exConn);
41
42 // Initialize VR-Link time.
43 DtClock* clock = exConn.clock();
44
45 int forever = 1;
46 while (forever)
47 {
48 // Check if user hit 'q' to quit.
49 if (keybrdTick() == -1)
50 break;
51
52 // Tell VR-Link the current value of simulation time.
53 clock->setSimTime(clock->elapsedRealTime());
54
55 // Process any incoming messages
56 exConn.drainInput();
57
58 // Find the first entity in the reflected entity list
59 DtReflectedEntity *first = rel.first();
60
61 if (first)
62 {
63 // Grab its state repository, where we can inspect its data.
65
66 // Create a topographic view on the state repository, so we
67 // can look at position information in topographic
68 // coordinates.
69 double refLatitude = DtDeg2Rad( 35.699760);
70 double refLongitude = DtDeg2Rad(-121.326577);
71 DtTopoView topoView(esr, refLatitude, refLongitude);
72
73 // Print the position.
74 // Since it returns a DtString, we need to force it to
75 // const char* with a cast.
76 std::cout << "Position of first entity: "
77 << topoView.location().string() << std::endl;
78 }
79
80 // Sleep till next iteration.
81 DtSleep(0.1);
82 }
83 return 0;
84 }
85 DtCATCH_AND_WARN(std::cout);
86 }
87
88 int keybrdTick()
89 {
90 char *keyPtr = DtPollBlockingInputLine();
91 if (keyPtr && (*keyPtr == 'q' || *keyPtr == 'Q'))
92 return -1;
93 else
94 return 0;
95 }

2.9.2.1 Connecting to An Exercise

In lines 22-25, 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.

If you want to specify initialization values in the DtExerciseConn, you would use code similar to the following:

int main()
{
// Create a connection to the exercise or federation execution
#if DtHLA
DtString execName("VR-Link");
DtString fedName("VR-Link listen");
DtExerciseConn exConn(execName, fedName, new DtSimpleRprFomMapper);
#elif DtDIS
int port = 3000;
int exerciseId = 1;
int siteId = 1;
int applicationNum = 15;
DtExerciseConn exConn(port, exerciseId, siteId, applicationNum,
0, // No Status, any error will be fatal
true); // use Async IO
#endif

2.9.1.2 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 at line 36. This callback (defined at line 14) prints a message containing the attacker ID. It executes whenever the exercise connection receives a Fire PDU or interaction during a call to drainInput().

2.9.1.3 Tracking Entities

We create a reflected entity list in line 40 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.

2.9.1.4 Managing Time

On line 43 we obtain a pointer to the simulation clock from the exercise connection.

2.9.1.5 Listening to the Network

At the start of each iteration, the program sets VR-Link simulation time (line 53) 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 (line 56) 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.

In line 59, the program finds the first entity in the entity list, then in line 64, retrieves the pointer to the entity's entity state repository. Line 71 creates a topographic view of that entity state repository, allowing us to retrieve its position data in topographic coordinates rather than geocentric. (Lines 69 and 70 hard code the coordinates for this example.)

Line 76 obtains and prints the dead-reckoned entity location.

2.9.2 A Send-Only Example

The Send-Only application simulates the flight of an F18 aircraft. The program begins by sending a fire PDU or HLA fire interaction. Thereafter, the F18 flies north for 10 seconds, updating its position by sending DIS entity state PDUs or HLA attribute updates.

1 #include <vl/exerciseConn.h>
2 #include <vl/exerciseConnInitializer.h>
3 #include <vl/topoView.h>
4 #include <vl/entityPublisher.h>
5 #include <vl/entityStateRepository.h>
6 #include <vl/fireInteraction.h>
7 #include <vl/iffPublisher.h>
8 #include <vlpi/EntityTypes.h>
9 #include <vlutil/vlProcessControl.h>
10 #include <iostream>
11
12 int main(int argc, char** argv)
13 {
14
15 try
16 {
17 // Create a connection to the exercise or federation execution.
18 DtVrlApplicationInitializer appInit(argc, argv "VR-Link talk");
19
20 // Change some defaults
21 #if DtDIS
22 appInit.setUseAsynchIO(true);
23 #endif
24
25 appInit.parseCmdLine();
26
27 DtExerciseConn exConn(appInit);
28
31
32 // Create an entity publisher for the entity we are simulating.
33 DtEntityPublisher entityPub(f18Type, &exConn, DtDrDrmRvw,
35
36 // Hold on to the entity's state repository, where we can set data.
38
39 // Create a topographic view on the state repository, so we
40 // can set position information in topographic coordinates.
41 double refLatitude = DtDeg2Rad( 35.699760);
42 double refLongitude = DtDeg2Rad(-121.326577);
43 DtTopoView topoView(esr, refLatitude, refLongitude);
44
45 // We can use the ESR to set state.
46 esr->setMarkingText("VR-Link");
47 topoView.setOrientation(DtTaitBryan(0.0, 0.0, 0.0));
48
49 // Initialize VR-Link time.
50 DtClock* clock = exConn.clock();
51
52 DtVector position(0, 0, -100);
53 DtVector velocity(20, 0, 0);
54
55 // Send a Fire Interaction.
57 fire.setAttackerId(entityPub.globalId());
58 exConn.sendStamped(fire);
59
60 // Main loop
61 DtTime dt = 0.05;
62 DtTime simTime = 0;
63 while (simTime <= 10.0)
64 {
65 // Tell VR-Link the current value of simulation time.
66 clock->setSimTime(simTime);
67
68 // Process any incoming messages.
69 exConn.drainInput();
70
71 // Set the current position information.
72 topoView.setLocation(position);
73 topoView.setVelocity(velocity);
74
75 // Call tick, which insures that any data that needs to be
76 // updated is sent.
77 entityPub.tick();
78
79 // Set up for next iteration.
80 position[0] += velocity[0] * dt;
81 simTime += dt;
82
83 // Wait till real time equals simulation time of next step
84 DtSleep(simTime - clock->elapsedRealTime());
85 }
86
87 }
88 DtCATCH_AND_WARN(std::cout);
89 return 0;
90 }

2.9.2.1 Connecting to An Exercise

Like the listen-only example, this program creates a DtExerciseConn to provide an interface to the RTI or DIS network (lines 17 through 27).

2.9.2.2 Managing Entities

Line 29 defines the entity type the F18 will use.

To be visible to other applications in the exercise, each locally-simulated entity requires a DtEntityPublisher, created in line 33. The entity publisher manages the generation of messages for this particular entity. It provides an entity state repository where you can set state values, and a tick() function, which causes state information to be sent to the network if necessary.

Line 37 sets up a pointer to the entity state repository, then line 43 creates a topographic view on that repository. This lets us set the entity's positional data using topographic coordinates, rather than the default geocentric coordinates. (Lines 41 and 42 hard code the coordinates for this example.) Line 46 shows an example of storing a non-positional state value in the repository.

2.9.2.3 Sending Interactions

An example of sending an interaction appears in lines 56-58. You can send the interaction using the exercise connection's sendStamped() function.

Note
You can use sendStamped() to send state updates, but it is preferable to let the entity publisher send state updates for you, using data in the entity state repository, as shown in lines 72 through 77.

2.9.2.4 Sending State Messages

The main loop executes twenty times per second for ten seconds. As in the listen-only example, this program sets simulation time at the start of each iteration (line 66).

Note
While this program's main purpose is to demonstrate the sending of data to the network, it is not a true send-only application. Incoming data is also processed with the drainInput() call on line 69. This call is required for HLA, because this is where we tick the RTI.

The program updates the F18's positional data in its entity state repository in lines 72 and 73, and ticks the entity publisher in line 77 to send the updated data onto the network. Lines 72 and 73 set topographic coordinates through a view, which VR-Link converts to geocentric coordinates.

Thereafter, the only remaining tasks are to increment the F18's position, increment the simulation time, and sleep until it is time to begin the next iteration.

[<< Big and Little Endian Wire Formats] [Home] [Top of Page]


Document ID: Generated on Fri Dec 2 02:42:08 EST 2016 from SVN revision 171416
Copyright © 2005-2016 VT MÄK. All Rights Reserved (www.mak.com)