VR-Forces 4.1.1 Class Documentation
2.4 - Customizing or Extending the Simulation Engine

Table of Contents

2.2 - Using the DtCgf Class described how to use the simulation engine in an application, through DtCgf's API.

This page explains how DtCgf is implemented, and describes how to extend or override various elements of its implementation.

DtCgf relies on a variety of managers and other classes to perform its job. We have already seen that it relies on DtExerciseConn for DIS and HLA connectivity. Some other classes that DtCgf relies on for various functions are:

These classes, in turn, rely on other lower-level classes to implement their functionality. For example, DtVrfObjectManager uses a DtVrfObject to represent each object that exists in the simulation. DtVrfObject relies on DtSimComponent, its subclasses DtActuatorComponent, and DtControllerComponent, and all of their numerous subclasses to help it implement a sensor-actuator-controller model of simulation. DtVrfObjectPlanManager (and some of the DtSimComponents) use DtPlan, DtSimStatement, DtSimTask, DtSimCondExpr, and their subclasses to represent plans that can be assigned to DtVrfObjects, as well as the tasks, statements, and conditional expressions that are used to build them. The figure illustrates this architecture.

If you customize the VR-Forces simulation engine, you will almost always derive a subclass from one or more of these classes to implement the desired functionality. Then you will register your subclasses with VR-Forces. To register custom subclasses with VR-Forces, you must understand the VR-Forces factory mechanism, and the DtVrfCreator class. They are described in the following sections.

vrforcesarchitecture.png
VR-Forces Architecture

2.4.1 VR-Forces Factories

VR-Forces uses factories to pick the components it needs to create an object. There are many places in the VR-Forces architecture where the simulation engine needs to choose among many subclasses of a particular base class to properly configure some object. For example, when the simulation engine initializes a new entity, it needs to create all of the components necessary to simulate it - the appropriate kind of actuator for vehicle dynamics, controllers to implement tasks, and so on. Since, for example, each kind of actuator is represented by its own subclass of the base DtActuatorComponent, VR-Forces needs a way to choose the right subclass to instantiate. It uses factories.

A typical factory maintains a list of associations between class identifiers (such as strings or enumerations identifying the various kinds of objects among which we are choosing), and creator functions that can be used to instantiate the various subclasses. (A creator function is a static function of a class that returns a new'ed instance of that class.) To tell VR-Forces about a new subclass that you have written, you must register the creator function for that class with the appropriate factory.

You can get a pointer to the appropriate factory through DtCgf's Factory Manager, which is a container for all of DtCgf's factories. DtCgf has an accessor function called factoryManager() that returns a pointer to its DtFactoryManager (factoryMgr.h). DtFactoryManager, in turn, provides accessors for all of the factories - taskFactory(), componentFactory(), and so on. Registering a creator function for a new subclass of DtActuatorComponent, for example, would look like this:

In this case, you are telling VR-Forces that an instance of your custom actuator component class (MyActuatorComponent) should be used when the simulation engine needs an "automotive actuator". 5 - Component Concepts, has more information about creating custom components, and registering them with the component factory. Details of deriving from other classes, such as DtSimTask and DtSimMessage, are in the chapters devoted to those classes.

You should register your subclasses with the appropriate factories immediately after DtCgf is initialized, to insure that the factory is configured correctly before it is used by the simulation engine to create anything.

2.4.2 The VR-Forces Creator

The previous section describes how VR-Forces uses factory classes during execution to create instances of various classes when it needs them. DtVrfCreator is a kind of factory class that DtCgf uses to create its top-level managers and other important classes during initialization (within init()). For example, when the DtCgf creates a DtVrfObjectManager, it calls DtVrfCreator's createVrfObjectManager() function to do so, rather than just calling new DtVrfObjectManager. This is to allow you to override the way VR-Forces objects are constructed. If you subclass DtVrfObjectManager, you can instruct DtCgf to use your subclass by configuring a DtVrfCreator so that createVrfObjectManager() returns a new'ed instance of your subclass. This is usually done by registering a creator function for your new subclass with a DtVrfCreator, before passing that creator to DtCgf's init() function, for example:

// Your subclass of DtVrfObjectManager
{
public
// You would probably override some virtual functions here to
// modify behavior, and so on.
...
// The creator function to be registered with DtVrfCreator
static DtVrfObjectManager* create(DtSimManager* simMgr)
{
return new MyObjManager(simMgr);
}
};

Now, when you create your DtCgf:

int main()
{
// Instantiate a default creator
// Register the creator for your MyObjManager class
creator.setVrfObjectManagerCreatorFcn(MyObjManager::create);
// Instantiate the DtCgf
DtCgf cgf(DtSimulationAddress(1, 3001));
DtExerciseConn exConn("VR-Link", "Minimal");
// Pass a pointer to your creator to DtCgfinit()
cgf.init(&exConn, &creator);
}

Notice that the creator that we instantiated is a DtDefaultVrfCreator, and not the base DtVrfCreator. This is because we do not want to have to manually register creator functions for all of the default managers, factories, and so on. The base DtVrfCreator starts empty - with no creator functions registered. But when you instantiate a DtDefaultVrfCreator, it already has self-registered creator functions for default managers, and so on. You only need to register creators for those classes for which you would like to provide alternate implementations.

Note
Another way of configuring a DtVrfCreator so that it returns an instance of your subclass is to subclass DtDefaultVrfCreator, and override functions like createVrfObjectManager(). But the creator registration method described in this section is usually preferable because it is a bit simpler and allows more modularity. (Several modules can register creators with DtVrfCreator without coordinating with each other.)

[<< Creating a Plugin] [Home] [Top of Page] [Customizing or Extending the vrfSim Application >>]


Document ID: Generated on Mon Apr 8 19:24:01 EDT 2013 from SVN revision 125877
Copyright © 2005-2013 VT MÄK. All Rights Reserved (www.mak.com)