![]() |
VR-Link API Documentation for DIS
|
VR-Link supports HLA ownership management services, which allow you to transfer the responsibility for sending updates for particular object attributes from one federate to another.
Most ownership management functionality is accessed through the DtHlaObject class. Recall that both DtObjectPublishers and DtReflectedObjects have member functions called hlaObject() that return the DtHlaObject that is being published or reflected. DtHlaObject encapsulates the HLA details of an object.
One conceptual change necessitated by support for ownership management is that the line between a locally simulated object and a reflected object is blurred. It is possible to have both a DtObjectPublisher and a DtReflectedObject associated with the same HLA object. That is, they share a DtHlaObject.
The publisher is still responsible for sending out updates for owned attributes. If you want to own and update any attributes of a particular object, you must create a publisher for that object, even if you are not the federate that registers the object with the RTI. DtObjectPublisher and its subclasses have a constructor that allows you to create a publisher for an existing DtHlaObject.
The reflected object is still responsible for collecting attribute updates sent by the owners of the various attributes, and presenting the reflected view of the object's current state through its state repository. However, now there may not be a single federate sending all of the attribute updates for an object, and some of the updates may even be coming from the local federate.
When a publisher's destructor is called, VR-Link will, by default, delete the corresponding HLA object if and only if the local federate owns the privilegeToDelete attribute. (And of course, because the HLA object gets deleted, the corresponding DtReflectedObject will be deleted and removed from your reflected object lists.) You can use DtObjectPublisher's setDeleteObjInDtorFlag() to change this behavior so that VR-Link does not delete the HLA object even if the local application owns the privilegeToDelete attribute. Use deleteObjInDtorFlag() to check the current status of the flag.
Because you can have a publisher for an object for which you do not own the privilege to delete, it is possible for your publisher's underlying HLA object to be deleted by a remote federate. When this occurs, your publisher's DtHlaObject pointer is set to NULL, and subsequent ticks will effectively be no-ops. To be notified when a
DtHlaObject is deleted so that you can delete the corresponding publisher (which is now useless), you can register a removeObject() callback with the DtHlaObject using its addRemoveObjectCb() function. Alternatively, you can register an objectRemoval() callback for the corresponding DtReflectedObject with your DtReflectedObjectList. For more information, please see Learning when Entities Join or Leave an Exercise.
To maintain backward compatibility with older releases for federates that do not use ownership management, creating a publisher and updating attributes does NOT, by default, result in the creation of a corresponding reflected object in the reflected object list, and the reflection of locally generated attribute updates.
DtHlaObject has the following member functions that wrap the RTI's federate-initiated ownership management services:
In general, you should use VR-Link's ownership-related functions rather than calling the RTI's functions directly, to insure that VR-Link can keep its ownership information consistent with the RTI's.
VR-Link keeps track of the locally-owned attributes of each object, and its publishers send attribute updates only for owned attributes. The current set of owned attributes for a particular DtHlaObject is obtained using its ownedAttributes() member function.
RTI-initiated ownership management services (the RTI-callbacks) are intercepted by VR-Link (again to keep VR-Link's ownership information current), and then passed along to application code through a class called DtOwnershipHandler (defined in ownerHandler.h). (Remember, all RTI-initiated callbacks, including these ownership management calls, are called from within the RTI's tick function, which is called by DtExerciseConn::drainInput().)
To receive ownership-related callbacks, such as notification that you have successfully acquired or divested ownership of a set of attributes, you must subclass DtOwnershipHandler, overriding VR-Link's virtual functions with versions that you want to have called when these events occur. You then register an instance of your subclass with a particular DtHlaObject, using DtHlaObject's setOwnershipHandler() member function. By doing so, you are saying to VR-Link: "This is the object I want you to use to handle incoming ownership information for this particular HLA object."
Most DtOwnershipHandler functions that you may want to override have the same names as their corresponding RTI services:
In addition, gainOwnership and loseOwnership are called whenever the federate actually gains or loses attributes, regardless of which ownership management mechanisms were used to effect the transfer.
HLA allows a transfer of ownership to be initiated by either the potential acquirer or divestor. On the following pages, we describe a few examples that use the various mechanisms.
You register an object, and then want to give up some attributes:
If you want to be notified when another federate assumes ownership, you need to subclass DtOwnershipHandler, and override the virtual function attributeOwnershipDivestitureNotification().
// Your subclass of DtOwnershipHandler class MyOwnershipHandler : public DtOwnershipHandler { public: virtual void attributeOwnershipDivestitureNotification( const RTI::AttributeHandleSet& attributes) { // Do something } }; // Create the publisher, and grab its DtHlaObject DtEntityPublisher pub(classHandle, conn); DtHlaObjectWithStateRep* obj = pub.hlaObject(); // Instantiate your handler class, and tell the DtHlaObject to use the // instance. MyOwnershipHandler handler; obj->setOwnershipHandler(&handler); // Initiate the divest // ******************** RTI 1.3 only ********************* // The rest of this example is for RTI 1.3 only RTI::AttributeHandleSet* hSet = RTI::AttributeHandleSetFactory::create(3); hSet->add(1); hSet->add(2); hSet->add(3); obj->negotiatedDivest(*hSet); delete hSet;
You discover an object, and want to acquire some attributes:
If you want your application code to be notified when the acquisition succeeds (so that you know, for example, to start actually simulating the relevant parts of the object), subclass DtOwnershipHandler. In this case, override attributeOwnershipAcquisitionNotification().
// Your subclass of DtOwnershipHandler class MyOwnershipHandler : public DtOwnershipHandler { public: virtual void attributeOwnershipAcquisitionNotification( const RTI::AttributeHandleSet& attributes) { // Do something } }; // Create the reflected entity list DtReflectedEntityList rel(...); ... // Find the entity you are interested in, and grab its DtHlaObject DtReflectedEntity* ent = rel.lookup(...); DtHlaObjectWithStateRep* obj = ent->hlaObject(); // Instantiate your handler class, and tell the DtHlaObject to use the // instance. MyOwnershipHandler handler; obj->setOwnershipHandler(&handler); // Create a publisher for the object DtEntityPublisher pub(obj, obj->exerciseConn()); // Initiate the acquisition. // ******************** RTI 1.3 only ********************* // The rest of this example is for RTI 1.3 only RTI::AttributeHandleSet* hSet = RTI::AttributeHandleSetFactory::create(3); hSet->add(1); hSet->add(2); hSet->add(3); obj->acquireAttributes(*hSet);
You do not want to initiate a divestiture, but you want to give up attributes of an object if another federate requests them:
In your subclass, override the function requestAttributeOwnershipRelease() with an implementation that calls unconditionalDivest() on the requested attributes. When a remote federate attempts to acquire attributes that you own, your function is called, which allows the transaction to complete.
// Your subclass of DtOwnershipHandler class MyOwnershipHandler : public DtOwnershipHandler { public: virtual void requestAttributeOwnershipRelease( const RTI::AttributeHandleSet& attributes, const char* tag) { // As a result of being asked to release some attributes, // go ahead and release them. hlaObject()->unconditionalDivest(attributes); } }; // Create the publisher, and grab its DtHlaObject DtEntityPublisher pub(classHandle, conn); DtHlaObjectWithStateRep* obj = pub.hlaObject(); // Instantiate your handler class, and tell the DtHlaObject to use the // instance. MyOwnershipHandler handler; obj->setOwnershipHandler(&handler);
You do not want to initiate an acquisition, but you want to acquire attributes of an object if another federate initiates a divest:
At some point, create a publisher for the object, passing the DtHlaObject in question to the publisher's constructor. You can either do this before acquiring the attributes, or once you know that you have secured the attributes.
class MyOwnershipHandler : public DtOwnershipHandler { public: virtual void requestAttributeOwnershipAssumption( const RTI::AttributeHandleSet& attributes, const char* tag) { // As a result of being asked to acquire some attributes, // go ahead and acquire them. hlaObject()->acquireAttributes(releasedAttributes); } virtual void attributeOwnershipAcquisitionNotification( const RTI::AttributeHandleSet& attributes) { // You might want to create the publisher here, now that you // know you will actually need it. pub = new DtEntityPublisher( hlaObject(), hlaObject()->exerciseConn()); } }; // Create the reflected entity list, DtReflectedEntityList rel(...); ... // Find the entity you're interested in, and grab its DtHlaObject DtReflectedEntity* ent = rel.lookup(...); DtHlaObjectWithStateRep* obj = ent->hlaObject(); // Instantiate your handler class, and tell the DtHlaObject to use the // instance. MyOwnershipHandler handler; obj->setOwnershipHandler(&handler);
[<< Managing HLA Objects] [Home] [Top of Page] [Using DDM >>]