The MapViewer Federate : Part 5

We’re almost done! I showed in the last post how to manage all simulation objects of a Federate, holding the class and attribute handles. To close our Map Viewer series I’ll show how to manage the object handle and the simulation attributes.

When you ask the RTI to create an “object” for you, you must tell  which class is the object you want. The class manager have a method to create objects:

From TankClass.

public ObjectInstanceHandle createNew(String name, String serial, Position position,int unitType) throws RTIexception {
    ObjectInstanceHandle coreObjectHandle = rtiamb.registerObjectInstance( tankHandle );
    TankObject to = new TankObject(coreObjectHandle, unitType);
    to.setName(name);
    to.setSerial(serial);
    to.setPosition(position);
    log("Tank " + to.getName() + " created.");
    instances.add( to );
    return coreObjectHandle;
}

The RTI will give us the object handle (ObjectInstanceHandle) of the new object. We need to keep this value to send attribute updates later ( and other things ). I decide to keep one java object to each RTI object handle. This java object will keep all the objects attributes too. The RTI doesn’t work in OOP. Each attribute is linked to its object by the object handle. It’s your responsibility to tell the RTI what object instance is the owner of the attribute you’re about to change and when the RTI notifies you about an attribute update, it will give you the owner’s object instance handle. You must search all your objects to discover what object the RTI is talking about. The only way to tell what attribute is from what object is by the object instance handle.

The class manager ( in this case the TankClass ) will keep the control of all its Tanks.

private List<TankObject> instances;

Our Tank objects is nothing more like a POJO, but you may want to do some particular simulations on each Tank.

public class TankObject {
    // To hold the RTI object handle for a specific Tank
    private ObjectInstanceHandle instance;
    // All attributes from the SOM must be here
    private String model;
    private Position position;
    private String name;
    private String serial;
    private String imageName = "military";
    
    ...
    
}

Now we have a place to store the object instance handle and all the attributes of this object. You must remember to start your object with default values because we will notify the Federation about the new object and this object must have a state. If you remember the last post, after receiving a new object notification, a Federate can invoke the RTI method requestAttributeValueUpdate() and you will be required to inform this by using  provideAttributeValueUpdate() .

The TankObject have a method to update its position, called by the TankClass ( for each known Tank )…

// Update the Tank state... just walk a little by Longitude axis.
public void update() {
    Random random = new Random();
    double rate = random.nextInt(9)+1;
    position.setLongitude( position.getLongitude() + ( rate / 10000 )  );
}

… and other to allow the TankClass query for a Tank given an object instance handle.

// Check if a given object handle is this Tank
public boolean isMe( ObjectInstanceHandle obj ) {
    return obj.equals( instance );
}

Used by the TankClass here ( isMe() )…

public void provideAttributeValueUpdate(ObjectInstanceHandle theObject, AttributeHandleSet theAttributes ) {
  log("Update attribute request for object " + theObject);
  for ( TankObject tank : instances ) {
    if( tank.isMe( theObject ) ) {
      try {
        updateAttributeValuesObject( tank );
      } catch ( Exception e ) {
        log("Error when send attributes updates");
      }
      return;
    }
  }
}

… and here ( update() ) …

public void updatePosition() throws Exception {
    for ( TankObject tank : instances ) {
        tank.update();
        AttributeHandleValueMap attributes = rtiamb.getAttributeHandleValueMapFactory().create(1);
        attributes.put( positionHandle, encoder.encodePosition( tank.getPosition() ) );
        rtiamb.updateAttributeValues( tank.getHandle(), attributes, "Tank Position".getBytes() );
    }
}

… comming from the Federate here:

@Override
public void whenIdle() {
    // Update only the position
    try {
        tankClass.updatePosition();
        rtiamb.evokeMultipleCallbacks(0.1, 0.3);
    } catch ( Exception e ) {
        //
    }
}

You can look the entire TankObject code from here ( GitHub ).

You can checkout the MapViewer repository from here.

 

 

Add Comment