A very basic Federation : Lesson 2

In this post I’ll explain the Main class of our basic Federation.

Please go to the previous post to refresh your memory and find where you can download important files.

Our main Federate class will declare this attributes:

public class Main {
  private RTIambassador rtiamb;
  private FederateAmbassador fedamb;  
  private TankClass tankClass;

        .....

}

And what is a main class without a main method?

public static void main( String[] args ) {
  try	{
    new Main( ).runFederate();
  } catch( Exception rtie ) {
    rtie.printStackTrace();
  }
}

This method is the runnable JAR entry point and just put our Federate in the game.

The “runFederate()” method will do all necessary stuff to run our Federation:

// Run the Federate.
public void runFederate() throws Exception	{
  String serial = UUID.randomUUID().toString().substring(1,5).toUpperCase();

  createRtiAmbassador();
  connect();
  createFederation("BasicFederation");
  joinFederation("BasicFederation", "TankFederate" + serial);
  
  // Start our objects managers.
  tankClass = new TankClass( rtiamb );
  
  // Publish and subscribe
  publishAndSubscribe();
  
  // Create and Register 5 Tanks.
  for ( int x=0; x<5; x++ ) {
    tankClass.createNew( );
  }
  
  // Send the Tank Model to the RTI
  // to notify all other Federates that subscribed to
  // this attribute.
  tankClass.updateAttributeValues();

  // Wait the user to press a key to exit; 
  System.out.println("Press a key to exit.");
  while ( System.in.available() == 0 ) {
    try {
      Thread.sleep(2000);
    } catch (Exception e) {
      // 
    }				
  }

  // Get out!
  exitFromFederation();
}

First, we need a unique ID for our Federate. It is not totally necessary, but if you want to run more than one instance of this Federate, it will avoid naming conflicts, but I did not anticipate this situation ( don’t subscribed the Tank for its own attribute changes ).

After this, we will do the basic stuff: get the RTI ambassador, connect to the RTI (LRC), create the Federation and join to it.  Then we instantiate our Tank object manager ( the “TankClass” class ). It will control all Tank objects operation: creation, update, publish and subscribe attributes and so on. This class have an important contructor that I’ll cover later.

Next step is to publish the Tank attribute. This will allow other Federates to subscribe to it and receive all changes. After this I just register 5 Tanks into the RTI. This will create 5 Tank “objects” inside the RTI and the RTI will give me back its handles, that I will store in each Java “TankObject” I just create. This process will be covered in details later.

Next, I send to the RTI an attribute update. Doing this I will make sure other Federates that found my Tanks have the correct attribute values. There is other way to do this, but I’ll keep it simple for now.

Then I just wait for the user to stop this madness and exit the Federation ( and eventually destroying it ). There is other way to do this, but this time I’ll keep it complex just for fun ( not entirely. inside this loop you may want to update attributes values that  change over the time, like the Tanks positions, so tankClass.updateAttributeValues() will be here ).

I’ll show now the basic RTI creation stuff. It is boring at this point, but I should be teaching. This will get the RTI Ambassador.

// Just get the RTI Ambassador
private void createRtiAmbassador() throws Exception {
  log( "Creating RTIambassador." );
  rtiamb = RtiFactoryFactory.getRtiFactory().getRtiAmbassador();
}

To connect your Federate Ambassador to the RTI. The CallbackModel.HLA_IMMEDIATE tells the RTI to immediately send all events to your RTI Ambassador. The other option is CallbackModel.HLA_EVOKED. Use this if you want to ask for events at your own time. I’ll cover this when I talk about time constrained Federations.

// Connect our FederateAmbassador to the RTI
private void connect() throws Exception {
  log( "Connecting..." );
  fedamb = new FederateAmbassador( this );
  rtiamb.connect( fedamb, CallbackModel.HLA_IMMEDIATE );
}

To create the Federation

// Create the Federation. Will raise an error if already created
// but you can ignore it.
// We must pass a FOM at this time. I will use the Standard MIM.
private void createFederation( String federationName ) throws Exception {
  log( "Creating Federation " + federationName );
  try	{
    URL[] modules = new URL[]{
      (new File("foms/HLAstandardMIM.xml")).toURI().toURL()
    };
    rtiamb.createFederationExecution( federationName, modules );
    log( "Created Federation." );
  } catch( FederationExecutionAlreadyExists exists ) {
    log( "Didn't create federation, it already existed." );
  } catch( MalformedURLException urle )	{
    log( "Exception loading one of the FOM modules from disk: " + urle.getMessage() );
    urle.printStackTrace();
    return;
  }
}

…to  join to the Federation…

// Join our Federate to the Federation.
// We must pass the SOM. Here we will use our SOM file.
// I recommend you to read this file.
private void joinFederation( String federationName, String federateName ) throws Exception  {
  URL[] joinModules = new URL[]{
    (new File("foms/tank_som.xml")).toURI().toURL()
  };
  rtiamb.joinFederationExecution( federateName, "TankFederateType", 
      federationName, joinModules );   
  log( "Joined Federation as " + federateName );
}

…to exit the Federation ( try to destroy the Federation – the last to get out turn off the lights )…

// Exit from Federation and try to destroy it.
// delete all objects owned by this Federate.
private void exitFromFederation() throws Exception {
  rtiamb.resignFederationExecution( ResignAction.DELETE_OBJECTS );
  log( "Resigned from Federation" );
  try	{
    rtiamb.destroyFederationExecution( "BasicFederation" );
    log( "Destroyed Federation" );
  } catch( FederationExecutionDoesNotExist dne ) {
    log( "No need to destroy federation, it doesn't exist" );
  } catch( FederatesCurrentlyJoined fcj ){
    log( "Didn't destroy federation, federates still joined" );
  }
}

… and to publish / subscribe to attributes ( we will just publish for now ).

// To publish our attributes and subscribe to interactions 
// and other Federates attributes
private void publishAndSubscribe() throws Exception	{
  
  tankClass.publish();
  log( "Published" );
  
  // Will not subscribe for nothing for now.
  // To subscribe, just create a class and call subscribe();
  // Ex: radarClass.subscribe();
  
}

 

Next post I’ll cover the “TankClass”.

 

Add Comment