/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2012 Mudit Raj Gupta
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Authors: Mudit Raj Gupta <mudit.raaj.gupta@gmail.com>
*
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import hla.rti.AttributeHandleSet;
import hla.rti.FederatesCurrentlyJoined;
import hla.rti.FederationExecutionAlreadyExists;
import hla.rti.FederationExecutionDoesNotExist;
import hla.rti.LogicalTime;
import hla.rti.LogicalTimeInterval;
import hla.rti.RTIambassador;
import hla.rti.RTIexception;
import hla.rti.ResignAction;
import hla.rti.SuppliedAttributes;
import hla.rti.SuppliedParameters;
import hla.rti.jlc.EncodingHelpers;
import hla.rti.jlc.RtiFactoryFactory;
import org.portico.impl.hla13.types.DoubleTime;
import org.portico.impl.hla13.types.DoubleTimeInterval;
public class dummyFederate
{
//setting iterations
public static final int ITERATIONS = 20;
public static final String READY_TO_RUN = "ReadyToRun";
//communicating with other classes
private RTIambassador rtiamb;
private dummyFederateAmbassador fedamb;
int glo=0;
//simple logging function
private void log( String message )
{
System.out.println( "dummy : " + message );
}
//Wait for user to reply
private void waitForUser()
{
log( " >>>>>>>>>> Press Enter to Continue <<<<<<<<<<" );
BufferedReader reader = new BufferedReader( new InputStreamReader(System.in) );
try
{
reader.readLine();
}
catch( Exception e )
{
log( "Error while waiting for user input: " + e.getMessage() );
e.printStackTrace();
}
}
private LogicalTime convertTime( double time )
{
// PORTICO SPECIFIC!!
return new DoubleTime( time );
}
private LogicalTimeInterval convertInterval( double time )
{
// PORTICO SPECIFIC!!
return new DoubleTimeInterval( time );
}
// This is the main simulation loop. It can be thought of as the main method of
// the federate.
public void runFederate( String federateName ) throws RTIexception
{
// create the RTIambassador
rtiamb = RtiFactoryFactory.getRtiFactory().createRtiAmbassador();
// create the federation
// create
// NOTE: some other federate may have already created the federation,
// in that case, we'll just try and join it
try
{
File fom = new File( "testfom.fed" );
rtiamb.createFederationExecution( "ExampleFederation",
fom.toURI().toURL() );
log( "Created Federation" );
}
catch( FederationExecutionAlreadyExists exists )
{
log( "Didn't create federation, it already existed" );
}
catch( MalformedURLException urle )
{
log( "Exception processing fom: " + urle.getMessage() );
urle.printStackTrace();
return;
}
// join the federation
// create the federate ambassador and join the federation
log("Going To create a Federate Object");
fedamb = new dummyFederateAmbassador();
log("ObjectCreated");
rtiamb.joinFederationExecution( federateName, "ExampleFederation", fedamb );
log( "Joined Federation as " + federateName );
// announce the sync point
// announce a sync point to get everyone on the same page. if the point
// has already been registered, we'll get a callback saying it failed,
// but we don't care about that, as long as someone registered it
log("Registering Sync Point");
rtiamb.registerFederationSynchronizationPoint( READY_TO_RUN, null );
log("Registed Sync Point");
// wait until the point is announced
while( fedamb.isAnnounced == false )
{
rtiamb.tick();
}
// WAIT FOR USER TO KICK US OFF
// So that there is time to add other federates, we will wait until the
// user hits enter before proceeding. That was, you have time to start
// other federates.
waitForUser();
// achieve the point and wait for synchronization
// tell the RTI we are ready to move past the sync point and then wait
// until the federation has synchronized on
rtiamb.synchronizationPointAchieved( READY_TO_RUN );
log( "Achieved sync point: " +READY_TO_RUN+ ", waiting for federation..." );
while( fedamb.isReadyToRun == false )
{
rtiamb.tick();
}
// enable time policies
// in this section we enable/disable all time policies
// note that this step is optional!
enableTimePolicy();
log( "Time Policy Enabled" );
// publish and subscribe //
// in this section we tell the RTI of all the data we are going to
// produce, and all the data we want to know about
publishAndSubscribe();
log( "Published and Subscribed" );
//register an object to update
int objectHandle = registerObject();
log( "Registered Object, handle=" + objectHandle );
// do the main simulation loop
// here is where we do the meat of our work. in each iteration, we will
// update the attribute values of the object we registered, and will
// send an interaction.
for( int i = 0; i < ITERATIONS; i++ )
{
//update the attribute values of the instance //
glo++;
updateAttributeValues( objectHandle, i );
//request a time advance and wait until we get it
advanceTime( 1.0 );
log( "Time Advanced to " + fedamb.federateTime );
}
// delete the object we created
deleteObject( objectHandle );
log( "Deleted Object, handle=" + objectHandle );
// resign from the federation
rtiamb.resignFederationExecution( ResignAction.NO_ACTION );
log( "Resigned from Federation" );
// try and destroy the federation
// NOTE: we won't die if we can't do this because other federates
// remain. in that case we'll leave it for them to clean up
try
{
rtiamb.destroyFederationExecution( "ExampleFederation" );
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" );
}
}
// This method will attempt to enable the various time related properties for
// the federate
private void enableTimePolicy() throws RTIexception
{
LogicalTime currentTime = convertTime( fedamb.federateTime );
LogicalTimeInterval lookahead = convertInterval( fedamb.federateLookahead );
// enable time regulation
this.rtiamb.enableTimeRegulation( currentTime, lookahead );
// tick until we get the callback
while( fedamb.isRegulating == false )
{
rtiamb.tick();
}
// enable time constrained
this.rtiamb.enableTimeConstrained();
// tick until we get the callback
while( fedamb.isConstrained == false )
{
rtiamb.tick();
}
}
// This method will inform the RTI about the types of data that the federate will
// be creating, and the types of data we are interested in hearing about as other
// federates produce it.
private void publishAndSubscribe() throws RTIexception
{
// publish all attributes of ObjectRoot.PingPong
// before we can register instance of the object class ObjectRoot.PingPong and
// update the values of the various attributes, we need to tell the RTI
// that we intend to publish this information
// get all the handle information for the attributes of ObjectRoot.PingPong
int classHandle = rtiamb.getObjectClassHandle( "ObjectRoot.PingPong" );
int MsgTypeHandle = rtiamb.getAttributeHandle( "MsgType", classHandle );
int MsgHandle = rtiamb.getAttributeHandle( "Msg", classHandle );
AttributeHandleSet attributes =
RtiFactoryFactory.getRtiFactory().createAttributeHandleSet();
attributes.add( MsgTypeHandle );
attributes.add( MsgHandle );
// do the actual publication
rtiamb.publishObjectClass( classHandle, attributes );
// subscribe to all attributes of ObjectRoot.PingPong
// we also want to hear about the same sort of information as it is
// created and altered in other federates, so we need to subscribe to it
rtiamb.subscribeObjectClassAttributes( classHandle, attributes );
}
//This method will register an instance of the class ObjectRoot.PingPong and will
// return the federation-wide unique handle for that instance. Later in the
// simulation, we will update the attribute values for this instance
private int registerObject() throws RTIexception
{
int classHandle = rtiamb.getObjectClassHandle( "ObjectRoot.PingPong" );
return rtiamb.registerObjectInstance( classHandle );
}
// This method will update all the values of the given object instance.
private void updateAttributeValues( int objectHandle, int i ) throws RTIexception
{
// create the necessary container and values
// create the collection to store the values in, as you can see
// this is quite a lot of work
SuppliedAttributes attributes =
RtiFactoryFactory.getRtiFactory().createSuppliedAttributes();
byte[] MsgTypeValue,MsgValue;
// generate the new values
// we use EncodingHelpers to make things nice friendly for both Java and C++
if(i%2==0)
{
MsgTypeValue = EncodingHelpers.encodeString("ping" );
MsgValue = EncodingHelpers.encodeString("Client: Hello!!!");
}
else
{
MsgTypeValue = EncodingHelpers.encodeString("pong" );
MsgValue = EncodingHelpers.encodeString("Server: Hello!!!");
}
int classHandle = rtiamb.getObjectClass( objectHandle );
int MsgTypeHandle = rtiamb.getAttributeHandle( "MsgType", classHandle );
int MsgHandle = rtiamb.getAttributeHandle( "Msg", classHandle );
// put the values into the collection
attributes.add( MsgTypeHandle, MsgTypeValue );
attributes.add( MsgHandle, MsgValue );
System.out.println(EncodingHelpers.decodeString(attributes.getValue(0)));
// do the actual update
rtiamb.updateAttributeValues( objectHandle,attributes, generateTag() );
}
// This method will request a time advance to the current time, plus the given
// timestep. It will then wait until a notification of the time advance grant
// has been received.
private void advanceTime( double timestep ) throws RTIexception
{
// request the advance
fedamb.isAdvancing = true;
LogicalTime newTime = convertTime( fedamb.federateTime + timestep );
rtiamb.timeAdvanceRequest( newTime );
// wait for the time advance to be granted.
while( fedamb.isAdvancing )
{
rtiamb.tick();
}
}
//This method will attempt to delete the object instance of the given
// handle. We can only delete objects we created, or for which we own the
// privilegeToDelete attribute.
private void deleteObject( int handle ) throws RTIexception
{
rtiamb.deleteObjectInstance( handle, generateTag() );
}
private byte[] generateTag()
{
if(glo%2==0)
return (EncodingHelpers.encodeString("ping"));
else
return (EncodingHelpers.encodeString("pong"));
}
public static void main( String[] args )
{
// get a federate name
String federateName = "dummy";
if( args.length != 0 )
{
federateName = args[0];
}
try
{
// run the example federate
new dummyFederate().runFederate( federateName );
}
catch( RTIexception rtie )
{
// an exception occurred, just log the information and exit
rtie.printStackTrace();
}
}
}