Modular FOM and Class Hierarchy

It is recommended that you modularize your Federation. The OMT allows you to create several FOM files to separate its Federate. You can learn more about FOM Module in the document An Overview of the HLA Evolved Modular FOMs (Björn Möller, Björn Löfstrand ,Mikael Karlsson and Pitch Technologies).

In this tutorial, I’ll show it is not too hard to implement this using Portico. Let’s say you need to simulate military units. The basics you need to know about them is their position ( talking geographically ). You can have a name and a serial number too.

Now you decide to specialize your unit in tanks and aircraft. The tanks have a model number and the aircraft a maximum range identifier.

Class Hierarchy

Class Hierarchy

I put the position in a composition so that you understand better the HLAfixedRecord type that will show next.

We may have now 3 files with each definition. First, the basic unit.

<objects>
    <objectClass>
        <name>HLAobjectRoot</name>
  
        <objectClass>
            <name>BasicUnit</name>
            <sharing>PublishSubscribe</sharing>
            <semantics>A Basic Unit</semantics>
            <attribute>
                <name>Name</name>
                <dataType>HLAunicodeString</dataType>
                <updateType>Static</updateType>
                <updateCondition>NA</updateCondition>
                <ownership>NoTransfer</ownership>
                <sharing>PublishSubscribe</sharing>
                <dimensions/>
                <transportation>HLAreliable</transportation>
                <order>Receive</order>
                <semantics>Name of the Unit</semantics>
            </attribute>
            
            <attribute>
                <name>Serial</name>
                <dataType>HLAunicodeString</dataType>
                <updateType>Static</updateType>
                <updateCondition>NA</updateCondition>
                <ownership>NoTransfer</ownership>
                <sharing>PublishSubscribe</sharing>
                <dimensions/>
                <transportation>HLAreliable</transportation>
                <order>Receive</order>
                <semantics>Serial ID of the Unit</semantics>
            </attribute>                
            
            <attribute>
                <name>Position</name>
                <dataType>Position</dataType>
                <updateType>Conditional</updateType>
                <updateCondition>On Change</updateCondition>
                <ownership>NoTransfer</ownership>
                <sharing>PublishSubscribe</sharing>
                <transportation>HLAreliable</transportation>
                <order>Receive</order>
                <semantics>Coordinates of the Unit</semantics>
            </attribute>     

    
        </objectClass>
  
    </objectClass>
</objects>
  
<dataTypes>

    <fixedRecordDataTypes>
        <fixedRecordData>
            <name>Position</name>
            <encoding>HLAfixedRecord</encoding>
            <semantics>Position in geographic coordinates.</semantics>
            <field>
                <name>longitude</name>
                <dataType>HLAfloat64BE</dataType>
                <semantics>Longitude</semantics>
            </field>
            <field>
                <name>latitude</name>
                <dataType>HLAfloat64BE</dataType>
                <semantics>Latitude</semantics>
            </field>
        </fixedRecordData>
    </fixedRecordDataTypes>    


</dataTypes>	

Now, another file for the Tank ( I’ll not show the Aircraft file because it is very similar to this ):

<objects>
    <objectClass>
        <name>HLAobjectRoot</name>
        <objectClass>
            <name>BasicUnit</name>
            <objectClass>
                <name>Tank</name>
                <sharing>PublishSubscribe</sharing>
                <semantics>A Tank Implementation</semantics>
                <attribute>
                   <name>Model</name>
                   <dataType>HLAunicodeString</dataType>
                   <updateType>Static</updateType>
                   <updateCondition>NA</updateCondition>
                   <ownership>NoTransfer</ownership>
                   <sharing>PublishSubscribe</sharing>
                   <transportation>HLAreliable</transportation>
                   <order>Receive</order>
                   <semantics>The Tank Model</semantics>
                </attribute>  
            </objectClass>
        </objectClass>
    </objectClass>
</objects>

You can see in this file the BasicUnit definition without any attributes (just its name obviously). We call it a  scaffolding class ( a promess that this was defined in other file ). You can complement this information by reading the good High level architecture evolved modular federation object model ( WANG Wenguang,XU Yongping,CHEN Xin, LI Qun,WANG Weiping ).

Now, you must merge all the 3 files when creating the Federation or when join to it.

private void joinFederation( String federationName, String federateName ) throws Exception  {
  URL[] joinModules = new URL[]{
    (new File("foms/unit.xml")).toURI().toURL(),
    (new File("foms/tank.xml")).toURI().toURL(),
    (new File("foms/aircraft.xml")).toURI().toURL()
  };
  rtiamb.joinFederationExecution( federateName, "AnyTypeYouWant", federationName, joinModules );   
}

The good part is: if you subscribe to any attribute from main class ( the BasicUnit ) then you will receive updates from all its chidren ( Tanks and Aircraft )…

    this.unitHandle = rtiamb.getObjectClassHandle( "HLAobjectRoot.BasicUnit" );
    
    this.nameHandle = rtiamb.getAttributeHandle( unitHandle, "Name" );
    this.serialHandle = rtiamb.getAttributeHandle( unitHandle, "Serial" );
    this.positionHandle = rtiamb.getAttributeHandle( unitHandle, "Position" );

    this.attributes = rtiamb.getAttributeHandleSetFactory().create();
    attributes.add( nameHandle );
    attributes.add( serialHandle );
    attributes.add( positionHandle );
    rtiamb.subscribeObjectClassAttributes( unitHandle, attributes );

…but if you subscribe to attributes from any child then you will receive updates only from that class.

    this.tankHandle = rtiamb.getObjectClassHandle( "HLAobjectRoot.BasicUnit.Tank" );

    this.nameHandle = rtiamb.getAttributeHandle( tankHandle, "Name" );
    this.serialHandle = rtiamb.getAttributeHandle( tankHandle, "Serial" );
    this.positionHandle = rtiamb.getAttributeHandle( tankHandle, "Position" );
    this.modelHandle = rtiamb.getAttributeHandle( tankHandle, "Model" );

    this.attributes = rtiamb.getAttributeHandleSetFactory().create();
    attributes.add( nameHandle );
    attributes.add( serialHandle );
    attributes.add( positionHandle );
    attributes.add( modelHandle );
    rtiamb.subscribeObjectClassAttributes( tankHandle, attributes );


You must hold the class AND the “object” ID ( handle ) when the RTI rises the discoverObjectInstance event, so you will be able to know what class instance (I call object) the RTI is talking about.

public void discoverObjectInstance( ObjectInstanceHandle theObject,
                                    ObjectClassHandle theObjectClass,
                                    String objectName ) throws FederateInternalError {
  // Is the object we found a kind of Unit?
  if ( federate.getUnitClass().isClassOf( theObjectClass ) ) {
    try {
      // If so, create a new Unit object in our list.
      federate.getUnitClass().createNew( theObject );
      log("New Unit discovered");
    } catch ( Exception e ) {
      log( e.getMessage() );
    }
  }
  
}

This case, theObjectClass is the class ID you got by using

rtiamb.getObjectClassHandle( ... );

… and theObject is the instance of this class that some Federate ( or yourself ) created ( instantiated ) by using

rtiamb.registerObjectInstance( theObjectClass );

As you can see here, I like creating a Java class to control my objects. I think this is the simplest way to manage all the handles and to easy reuse code.

Basic Federation

Basic Federation

 

Add Comment