MAK RTIspy API Documentation for HLA 1.3
simpleDDM Example Code for HLA 1.3

simpleDDMSimple13.cxx and simpleDDMFedAmb13.cxx (simpleDDMFedAmb13.h) have the RTI calls and federate ambassador calls for the HLA 1.3 version of simpleDDM.

This page has the code for the following files:


simpleDDMSimple13.cxx

/******************************************************************************
** Copyright (c) 2006 MaK Technologies, Inc.
** All rights reserved.
******************************************************************************/
/******************************************************************************
** $RCSfile: simpleDDMSimple13.cxx,v $ $Revision: 1.3 $ $State: Exp $
******************************************************************************/

#ifdef DtHLA13

#ifdef WIN32
#pragma warning(disable: 4786)
#pragma warning(disable: 4290)
#include <winsock2.h>
#include <process.h>
#include <windows.h>

#else
#include <unistd.h>
#include <stdio.h>
#endif
#include "simpleDDMSimple13.h"
#include <cstdlib>

using namespace std;


const unsigned int simpleDDMFederate13::myNumAttributes = 1;
const unsigned long simpleDDMFederate13::myNumExtents = 1;

simpleDDMFederate13::simpleDDMFederate13()
:
   simpleDDMFederate(),
   myNumberOfDimensions(myNumExtents),
   myHourlyInteraction("hourlyChime"),
   myQuarterlyInteraction("quarterlyChime"),
   mySecondsDimensionName("seconds"),
   myUTCDimensionName("UTCn"),
   mySpaceName("WallClock"),
   myInterClassName("Chimes"),
   myClassName("BaseEntity"),
   myAttrName("clockPosition"),
   myRTIamb(0),
   myFedAmb(0)
{
   myFederationName = "MAKsimpleDDM";
   myFederationFile = "MAKsimpleDDM.fed";
   myFederateType = "rtisimple13";
}

simpleDDMFederate13::simpleDDMFederate13(simpleDDMFederate13& data)
:
   simpleDDMFederate(data),
   myNumberOfDimensions(data.myNumberOfDimensions),
   myHourlyInteraction(data.myHourlyInteraction),
   myQuarterlyInteraction(data.myQuarterlyInteraction),
   mySecondsDimensionName(data.mySecondsDimensionName),
   myUTCDimensionName(data.myUTCDimensionName),
   myInterClassName(data.myInterClassName),
   myClassName(data.myClassName),
   myAttrName(data.myAttrName)
{
}

simpleDDMFederate13::~simpleDDMFederate13()
{
   if(myRTIamb)
   {
      delete myRTIamb;
   }
   if(myFedAmb)
   {
      delete myFedAmb;
   }
}

void simpleDDMFederate13::initializeRTI()
{
   vector< string > args;

   myAttrHandlesArray = new RTI::AttributeHandle[myNumAttributes];

   // rti1516 and Federate Ambassadors
   myRTIamb = new RTI::RTIambassador();
   myFedAmb = new MyFederateAmbassador(myAmbData);

   // Construct an attribute handle set
   myAttrHandlesSet = RTI::AttributeHandleSetFactory::create(myNumAttributes);
}

// Create the federation execution
bool simpleDDMFederate13::createFedEx()
{
   cout << "createFederationExecution "
      << myFederationName << " "
      << myFederationFile << endl;
   try
   {
      myRTIamb->createFederationExecution(myFederationName.c_str(),
                                          myFederationFile.c_str());
   }
   catch(RTI::FederationExecutionAlreadyExists& ex)
   {
      cout  << "Could not create Federation Execution: "
         << "FederationExecutionAlreadyExists: "
         <<  ex._name << " "
         << ex._reason << endl;
      return false;
   }
   catch(RTI::Exception& ex)
   {
      cout  << "Could not create Federation Execution: " << endl
         << "RTI Exception: "
         << ex._name << " "
         << ex._reason << endl;
      exit(0);
   }
   myRTIamb->tick(0.1, 0.2);
   
   cout << "Federation Created" << endl;
   return true;

}

// Join the federation execution
bool simpleDDMFederate13::joinFedEx()
{
   bool joined=false;
   const int maxTry  = 10;
   int numTries = 0;
   cout  << "joinFederationExecution "
      << myFederateType.c_str() << " "
      << myFederationName.c_str() << endl;

   while (!joined && numTries++ < maxTry)
   {
      try
      {
         myRTIamb->joinFederationExecution(myFederateType.c_str(),
            myFederationName.c_str(), myFedAmb);
         joined = true;
      }
      catch(RTI::FederationExecutionDoesNotExist)
      {
         cout  << "FederationExecutionDoesNotExist, try "
            << numTries << "out of "
            << maxTry << endl;
         continue;
      }
      catch(RTI::Exception& ex)
      {
         cout  << "RTI Exception: "
            << ex._name << " "
            << ex._reason << endl;
         return false;
      }
      myRTIamb->tick(0.1, 0.2);
   }
   if (joined)
      cout << "Joined Federation." << endl;
   else
   {
      cout << "Giving up." << endl;
      myRTIamb->destroyFederationExecution(myFederationName.c_str());
      exit(0);
   }
   return true;
}

// Resign and destroy the federation execution
void simpleDDMFederate13::resignAndDestroy()
{
   myRegionValid = false;
   myRTIamb->resignFederationExecution(RTI::DELETE_OBJECTS);
   myRTIamb->destroyFederationExecution(myFederationName.c_str());
}

// Create the Region and initialize its bounds
bool simpleDDMFederate13::createAndInitializeRegions()
{
   // The space handle (to be retrieved from the RTI).
   RTI::SpaceHandle theSpaceHandle = 0;

   try
   {
      // Get the space and dimension handles
      theSpaceHandle = myRTIamb->getRoutingSpaceHandle( mySpaceName.c_str() );
      mySecondsDimHandle = myRTIamb->getDimensionHandle( mySecondsDimensionName.c_str(),
         theSpaceHandle );
      myUTCDimHandle = myRTIamb->getDimensionHandle( myUTCDimensionName.c_str(),
         theSpaceHandle );
   }
   catch (RTI::Exception& ex)
   {
      cout << "RTI Exception: "
         << ex._name << " "
         << ex._reason << endl
         << "Could not "
         << " get SpaceHandle or DimensionHandle " << endl;
      return false;           
   }

   try
   {
      // Create the region
     if ( myIsPublisher )
     {
         mySendRegion = myRTIamb->createRegion(theSpaceHandle,
            myNumberOfDimensions );
     }
     else
     {
         myListenRegion = myRTIamb->createRegion(theSpaceHandle,
            myNumberOfDimensions);
     }
   }
   catch (RTI::Exception& ex)
   {
      cout << "RTI Exception: " << ex._name << " "
         << ex._reason << endl  << "Could not "
         << " create Region" << endl;
      return false;           
   }

   if (myIsPublisher)
   {
      // Set the range bounds for a publisher
      mySendRegion->setRangeLowerBound(0,myUTCDimHandle, myUTCZone);
      mySendRegion->setRangeUpperBound(0,myUTCDimHandle, myUTCZone);
      mySendRegion->setRangeLowerBound(0,mySecondsDimHandle,mySendLowerBound);
      mySendRegion->setRangeUpperBound(0,mySecondsDimHandle,mySendUpperBound);
      try
      {
         myRTIamb->notifyAboutRegionModification(*mySendRegion);
         myAmbData.lowerSend = mySendLowerBound;
         myAmbData.upperSend = mySendUpperBound;
      }
      catch (RTI::Exception& ex)
      {
         cout << "RTI Exception: "
            << ex._name << " "
            << ex._reason << endl
            << "Could not "
            << " notify about region mods" << endl;
         return false;           
      }
   }
   else
   {
      // Set the range bounds for a subscriber
      myListenRegion->setRangeLowerBound(0, myUTCDimHandle, myUTCZone);
      myListenRegion->setRangeUpperBound(0, myUTCDimHandle, myUTCZone);
      myListenRegion->setRangeLowerBound(0, mySecondsDimHandle, myListenLowerBound);
      myListenRegion->setRangeUpperBound(0, mySecondsDimHandle, myListenUpperBound);
      try
      {
         myRTIamb->notifyAboutRegionModification(*myListenRegion);
         myAmbData.lowerListen = myListenLowerBound;
         myAmbData.upperListen = myListenUpperBound;
      }
      catch (RTI::Exception& ex)
      {
         cout << "RTI Exception: "
            << ex._name << " "
            << ex._reason << endl
            << "Could not "
            << " notify about region mods" << endl;
         return false;           
      }
   }
   myRegionValid = true;

   return true;
}

// Publish and subscribe the object class attributes.
// Register an object instance of the class.
bool simpleDDMFederate13::publishSubscribeAndRegisterObject()
{
   try
   {
      // Get the object class handle
      myClassHandle = myRTIamb->getObjectClassHandle(myClassName.c_str());
      myAmbData.objectClassMap[myClassHandle] = myClassName;
   }
   catch (RTI::Exception& ex)
   {
      cout  << "RTI Exception: "
         << ex._name << " "
         << ex._reason << endl
         << "Could not get object class handle: "
         << myClassName.c_str() << endl;
      return false;
   }

   try
   {
      // Get the attribute handles and construct the name-handle map.
      // A handle array is used in anticipation of using it in region association
      myAmbData.myPositionHandle =
      myAttrHandlesArray[0] =
         myRTIamb->getAttributeHandle(myAttrName.c_str(), myClassHandle);
      myAttrNameHandleMap.insert(make_pair(myAttrName, myAttrHandlesArray[0]));
      myAttrHandlesSet->add(myAttrHandlesArray[0]);
   }
   catch (RTI::Exception& ex)
   {
      cout  << "RTI Exception: "
            << ex._name << " "
            << ex._reason << endl
            << "Could not get attribute handle "
            << myAttrName.c_str() << endl;
      return false;
   }

   // Initialize attribute handle Value Map.
   string initialPosition("0");
   myAttrValues =  RTI::AttributeSetFactory::create(myAttrNameHandleMap.size());
   myAttrValues->add(myAttrHandlesArray[0],
                   initialPosition.c_str(),
                   initialPosition.length() + 1);
   myMapsInitialized = true;

   // Initialize the Region
   if ( !createAndInitializeRegions() )
   {
      return false;
   }

   try
   {
      // Publish or subscribe
      if (myIsPublisher)
      {
         myRTIamb->publishObjectClass(myClassHandle, *myAttrHandlesSet);
      }
      else
      {
         myRTIamb->subscribeObjectClassAttributesWithRegion(myClassHandle,
            *myListenRegion, *myAttrHandlesSet);
         cout  << "Subscribed to object: "
                  <<   myClassName.c_str() << " With region: ["
                  << myListenRegion->getRangeLowerBound(0, mySecondsDimHandle)
                  << " , " << myListenRegion->getRangeUpperBound(0, mySecondsDimHandle)
                  << ") in Time Zone " << myListenRegion->getRangeUpperBound(0, myUTCDimHandle)
                  << endl;
      }
      myRTIamb->tick(0.1, 0.2);
   }
   catch(RTI::Exception& ex)
   {
      cout  << "RTI Exception: "
         << ex._name << " "
         << ex._reason << endl;
      cout << "Could not "
         << (myIsPublisher ? L"publish" : L"subscribe") << endl;
      return false;
   }

   if (myIsPublisher)
   {
      const RTI::ULong numHandle = 5;
      RTI::Region* theRegions[numHandle];
      string objectName("UTC_publisher_");
      stringstream zoneID;

      theRegions[0] = mySendRegion;

      zoneID << myUTCZone;
      objectName += zoneID.str();

      // register object instance

      try
      {
#if 0
         // The following two lines are one way of registering an object
            // with no region and then ascribing region qualifiers to the
            // object.
         // It possible to associate an attribute with multiple regions
            // by invoking associateRegionsForUpdates for multiple times
            // i.e., these region associations are additive not substitutive.
         myObjectHandle = myRTIamb->registerObjectInstance(myClassHandle, objectName.c_str());
         myRTIamb->associateRegionForUpdates(
            *mySendRegion,
            myObjectHandle,
            *myAttrHandlesSet);
#endif

         // Alternatively, this registers the object with the region
            // qualifiers already specified. In this way, the object
            // will not be discovered if a subscriber does not overlap.
            // It is possible to pair the same attribute with multiple
            // regions by repeating it in the attribute array.
         myObjectHandle = myRTIamb->registerObjectInstanceWithRegion(
            myClassHandle, objectName.c_str(), myAttrHandlesArray, theRegions, 1);

         // Add object name-handle to map
         myAmbData.objectInstanceMap[myObjectHandle] = objectName;

         myRTIamb->tick(0.1, 0.2);

      }
      catch(RTI::Exception& ex)
      {
         cout  << "RTI Exception: "
            << ex._name << " "
            << ex._reason << endl
            << "Could not  Register Object "
            << " with class "
            << myClassName.c_str() << endl;
         return false;
      }
      cout  << "Registered object "
      << " with class name "
      <<  myClassName.c_str() << endl;
   }

   return true;
}

// Publish and Subscribe to an interaction class
bool simpleDDMFederate13::publishAndSubscribeInteraction()
{
   try
   {
      // Get the interaction class handle
      myInterClassHandle =
         myRTIamb->getInteractionClassHandle(myInterClassName.c_str());
      myAmbData.interactionClassMap[myInterClassHandle] = myInterClassName;
   }
   catch (RTI::Exception& ex)
   {
      cout  << "RTI Exception: "
         << ex._name << " "
         << ex._reason << endl
         << "Could not get interaction class handle: "
         << myInterClassName.c_str() << endl;
      return false;
   }

   string paramName;
   try
   {
      // Get the parameter handles and construct the name-handle map
      myHourlyHandle =
         myRTIamb->getParameterHandle(myHourlyInteraction.c_str(),
                                          myInterClassHandle);
      myParamNameHandleMap[myHourlyInteraction] = myHourlyHandle;
      myQuarterlyHandle =
         myRTIamb->getParameterHandle(myQuarterlyInteraction.c_str(),
                                          myInterClassHandle);
      myParamNameHandleMap[myQuarterlyInteraction] = myQuarterlyHandle;
      // Construct a parameter handle value pair set with the
      // values containing the parameter names
      myParamValues =
            RTI::ParameterSetFactory::create(myParamNameHandleMap.size());

   }
   catch (RTI::Exception& ex)
   {
      cout  << "RTI Exception: "
         << ex._name << " "
         << ex._reason << endl
         << "Could not get parameter handle "
         << paramName.c_str() << endl;
      return false;
   }

   try
   {
      // Publish and subscribe
      if ( myIsPublisher )
      {
         myRTIamb->publishInteractionClass(myInterClassHandle);
         myRTIamb->tick(0.1, 0.2);
      }
      else
      {
         myRTIamb->subscribeInteractionClassWithRegion(myInterClassHandle,
                                                   *myListenRegion);
         myRTIamb->tick(0.1, 0.2);
      }
   }
   catch (RTI::Exception& ex)
   {
      cout  << "RTI Exception: "
         << ex._name << " "
         << ex._reason << endl
         << "Could not "
         << (myIsPublisher ? "publish" : "subscribe")
         << " to interaction." << endl;
      return false;
   }
   if (!myIsPublisher)
   {
      cout  << "Subscribed to interaction class: "
            <<   myInterClassName.c_str()
            << " with handle: "
            <<  myInterClassHandle << endl;
   }
   return true;

}

void simpleDDMFederate13::sendUpdate( int currentPosition )
{
   stringstream ss;
   ss << "13-" << myUpdateCount++;
   string tagForThisUpdate(ss.str());

   // myAttrHandleMap contains AttributeHandles indexed by attributeNames
   // attrValues contains values indexed by attributeHandles

   myAttrValues->remove(myAttrHandlesArray[0]);
   myAttrValues->add(myAttrHandlesArray[0],
                   tagForThisUpdate.c_str(),
                   tagForThisUpdate.length());

   setPosition(currentPosition);
   try
   {
      myRTIamb->updateAttributeValues(myObjectHandle,
                                      *myAttrValues,
                                      tagForThisUpdate.c_str());
   }
   catch (RTI::Exception& ex)
   {
      cout << "Caught Exception in update Attribute values\n"
         << ex._name << " " << ex._reason << endl;
   }
}

// Parameter values will be constructed when the sender generates an
   //   interaction and emptied after the interaction is sent.
void simpleDDMFederate13::sendInteraction_hourly()
{
   DtParamNameHandleMap::const_iterator iterAtHour =
      myParamNameHandleMap.find(myHourlyInteraction);
   stringstream ss;
   ss << "13-" << myUpdateCount++;
   string tagForThisUpdate(ss.str());

   try
   {
      myParamValues->add(iterAtHour->second,
                       iterAtHour->first.c_str(),
                       iterAtHour->first.length() + 1);
      myRTIamb->sendInteractionWithRegion(myInterClassHandle,
                                          *myParamValues,
                                          tagForThisUpdate.c_str(),
                                          *mySendRegion);
   }
   catch (RTI::Exception& ex)
   {
      cout << "Caught Exception in send Interaction with Regions\n"
         << ex._name << " " << ex._reason << endl;
   }
   myParamValues->remove(iterAtHour->second);

}

void simpleDDMFederate13::sendInteraction_quarterly()
{
   DtParamNameHandleMap::const_iterator iterAtQuarter =
      myParamNameHandleMap.find(myQuarterlyInteraction);
   stringstream ss;
   ss << "13-" << myUpdateCount++;
   string tagForThisUpdate(ss.str());

   try
   {
      myParamValues->add(iterAtQuarter->second,
                       iterAtQuarter->first.c_str(),
                       iterAtQuarter->first.length() + 1);
      myRTIamb->sendInteractionWithRegion(myInterClassHandle,
                                          *myParamValues,
                                          tagForThisUpdate.c_str(),
                                          *mySendRegion );
   }
   catch (RTI::Exception& ex)
   {
      cout << "Caught Exception in send Interaction with Regions\n"
         << ex._name << " " << ex._reason << endl;
   }
   myParamValues->remove(iterAtQuarter->second);
}

void simpleDDMFederate13::changeBounds(int lowerSeconds, int upperSeconds, int newUTC)
{
   if ( !myRegionValid )
   {
      // Region has not be created yet, just set up the bounds
      myUTCZone = newUTC;
      if (myIsPublisher)
      {
         mySendLowerBound = lowerSeconds;
         mySendUpperBound = upperSeconds;
      }
      else
      {
         myListenLowerBound = lowerSeconds;
         myListenUpperBound = upperSeconds;
      }
   }
   else if (myIsPublisher)
   {
      try
      {
         // Set the values in the region
         mySendRegion->setRangeUpperBound(0, myUTCDimHandle, newUTC + 1);
         mySendRegion->setRangeLowerBound(0, myUTCDimHandle, newUTC);
         mySendRegion->setRangeUpperBound(0, mySecondsDimHandle, upperSeconds);
         mySendRegion->setRangeLowerBound(0, mySecondsDimHandle, lowerSeconds);

         // Commit the changes
         myRTIamb->notifyAboutRegionModification(*mySendRegion);

         // Commit was successful, get the ranges back
         myUTCZone = mySendRegion->getRangeLowerBound(0, myUTCDimHandle);
         mySendLowerBound = mySendRegion->getRangeLowerBound(0, mySecondsDimHandle);
         mySendUpperBound = mySendRegion->getRangeUpperBound(0, mySecondsDimHandle);
         myAmbData.lowerSend = mySendLowerBound;
         myAmbData.upperSend = mySendUpperBound;
      }
      catch (RTI::Exception& ex)
      {
         cout << "Caught Exception when changing bounds\n"
              << ex._name
              << " "
              << ex._reason
              << " " << endl;
      }
   }
   else
   {
      try
      {
         // Set the values in the region
         myListenRegion->setRangeUpperBound(0, myUTCDimHandle, newUTC + 1);
         myListenRegion->setRangeLowerBound(0, myUTCDimHandle, newUTC);
         myListenRegion->setRangeLowerBound(0, mySecondsDimHandle, lowerSeconds);
         myListenRegion->setRangeUpperBound(0, mySecondsDimHandle, upperSeconds);

         // Commit the changes
         myRTIamb->notifyAboutRegionModification(*myListenRegion);

         // Commit was successful, get the ranges back
         myUTCZone = myListenRegion->getRangeLowerBound(0, myUTCDimHandle);
         myListenUpperBound =
            myListenRegion->getRangeUpperBound(0, mySecondsDimHandle);
         myListenLowerBound =
            myListenRegion->getRangeLowerBound(0, mySecondsDimHandle);
         myAmbData.lowerListen = myListenLowerBound;
         myAmbData.upperListen = myListenUpperBound;
      }
      catch (RTI::Exception& ex)
      {
         cout << "Caught Exception\n"
              << ex._name
              << " "
              << ex._reason
              << " " << endl;
      }
   }
}

void simpleDDMFederate13::tick(double atMost)
{
   try
   {
      myRTIamb->tick();
   }
   catch(RTI::Exception& ex)
   {
      cout << "rti13 Exception (during tick): "
         << ex._name << " " << ex._reason << endl;
   }
}

void simpleDDMFederate13::tick(double atLeast, double atMost)
{
   try
   {
      myRTIamb->tick(atLeast, atMost);
   }
   catch(RTI::Exception& ex)
   {
      cout << "rti13 Exception (during tick): "
         << ex._name << " " << ex._reason << endl;
   }
}

void simpleDDMFederate13::setPosition(int pos)
{
   // Attribute maps are initialized in publishSubscribeAndRegisterObject
      // which sets myMapsInitialized.
   if (myMapsInitialized)
   {
      // Attribute value will be the current position
      // represented as a string.
      string pos_string;
      ostringstream oss ;
      oss << pos;
      pos_string = oss.str();

      myAttrValues->remove(myAttrNameHandleMap[myAttrName]);
      myAttrValues->add(myAttrNameHandleMap[myAttrName],
         pos_string.c_str(), pos_string.length() + 1);
   }
   else
   {
      cout << "You must initialize the maps before calling this function.";
   }
}

#endif

simpleDDMFedAmb13.cxx

/******************************************************************************
** Copyright (c) 2006 MaK Technologies, Inc.
** All rights reserved.
******************************************************************************/
/******************************************************************************
** $RCSfile: simpleDDMFedAmb13.cxx,v $ $Revision: 1.1 $ $State: Exp $
******************************************************************************/

#ifdef WIN32
#pragma warning(disable: 4786)
#pragma warning(disable: 4290)
#endif

#include <stdio.h>
#include <iomanip>
#include <iostream>
#include <cstdlib>

#include "simpleDDMFedAmb13.h"
#include "simpleDDMStringUtil.h"

using namespace std;

void printAttributes(const RTI::AttributeHandleValuePairSet& attributes,
                     const DtTalkAmbData& data)
{
   for (unsigned int iloop = 0; iloop < attributes.size(); iloop++)
   {
      RTI::ULong length = attributes.getValueLength(iloop);
      cout  << attributes.getHandle(iloop) << " "
            << attributes.getValuePointer(iloop,length) << endl;
   }
}

void printParameters(const RTI::ParameterHandleValuePairSet& params)
{
   for (unsigned int iloop = 0; iloop < params.size(); iloop++)
   {
      RTI::ULong length = params.getValueLength(iloop);
      cout  << params.getHandle(iloop) << " "
            << params.getValuePointer(iloop,length) << endl;
   }
}

std::string timeToString(RTI::FedTime const& time)
{
   char* buff = new char[time.getPrintableLength()+1];
   ((RTI::FedTime &)time).getPrintableString(buff);
   std::string timeStr(buff);
   delete [] buff;
   return timeStr;
}

MyFederateAmbassador::MyFederateAmbassador(DtTalkAmbData & data) :
   NullFederateAmbassador(),
   myData(data)
{
}

MyFederateAmbassador::~MyFederateAmbassador()
   throw (RTI::FederateInternalError)
{
}

void MyFederateAmbassador::discoverObjectInstance (
   RTI::ObjectHandle theObject,
   RTI::ObjectClassHandle theObjectClass,
   const char* theObjectName)
   throw (
      RTI::CouldNotDiscover,
      RTI::ObjectClassNotKnown,
      RTI::FederateInternalError)
{
   cout  << "discoverObjectInstance: "
         << theObjectName << "("
         << theObject << ") of class "
         << myData.objectClassMap[theObjectClass].c_str() << "( "
         << theObjectClass << ")" << endl;

   // Map the handle to the name
   myData.objectInstanceMap[theObject] = theObjectName;
}

void MyFederateAmbassador::reflectAttributeValues (
        RTI::ObjectHandle                 theObject,
  const RTI::AttributeHandleValuePairSet& theAttributes,
  const RTI::FedTime&                     theTime,
  const char                             *theTag,
        RTI::EventRetractionHandle        theHandle)
throw (
  RTI::ObjectNotKnown,
  RTI::AttributeNotKnown,
  RTI::FederateOwnsAttributes,
  RTI::InvalidFederationTime,
  RTI::FederateInternalError)
{
   reflectAttributeValues (theObject, theAttributes, theTag);
}

void MyFederateAmbassador::reflectAttributeValues (
        RTI::ObjectHandle                 theObject,
  const RTI::AttributeHandleValuePairSet& theAttributes,
  const char                             *theTag)
throw (
  RTI::ObjectNotKnown,
  RTI::AttributeNotKnown,
  RTI::FederateOwnsAttributes,
  RTI::FederateInternalError)
{
   RTI::ULong length = theAttributes.getValueLength(0);
   char* dataPointer = theAttributes.getValuePointer(0,length);
   bool havePosition = false;

   for (unsigned int iloop = 0; !havePosition && iloop < theAttributes.size(); iloop++)
   {
      RTI::AttributeHandle handle = theAttributes.getHandle(iloop);

      if (handle == myData.myPositionHandle
         && theAttributes.getValueLength(iloop) > 0)
      {
         // Position is in the reflected attributes and it contains data
         // The data is a numeric string representation of the position
         myData.position = atoi(theAttributes.getValuePointer(iloop, length));
         havePosition = true;
      }
   }

   if (!havePosition)
   {
      cout << "Received reflect with no or NULL position\n";
   }
   else
   {
      cout << "Received Pos (" << myData.position;

      if ( myData.position < myData.lowerListen )
      {
         // Update region overlapped
         // but actual position less than subscribe region
         cout << ") less than subscribe Region [";
      }
      else if ( myData.position > myData.upperListen )
      {
         // Update region overlapped
         // but actual position greater than subscribe region
         cout << ") greater than subscribe Region [";
      }
      else
      {
         // Update region overlapped
         // and actual position inside subscribe region
         cout << ") inside subscribe Region [";
      }
      cout << myData.lowerListen << "," << myData.upperListen << ")\n";
   }
}

// 4.6
void MyFederateAmbassador::receiveInteraction (
        RTI::InteractionClassHandle       theInteraction,
  const RTI::ParameterHandleValuePairSet& theParameters,
  const RTI::FedTime&                     theTime,
  const char                             *theTag,
        RTI::EventRetractionHandle        theHandle)
throw (
  RTI::InteractionClassNotKnown,
  RTI::InteractionParameterNotKnown,
  RTI::InvalidFederationTime,
  RTI::FederateInternalError)
{
   cout  << "receiveInteraction: "
         << myData.interactionClassMap[theInteraction].c_str() << "( "
         << theInteraction << ") "
         << timeToString(theTime).c_str() << " "
         << (theTag ? theTag : "")  << " "
         << "#parameters: " << theParameters.size() << endl;
   printParameters(theParameters);
}

void MyFederateAmbassador::receiveInteraction (
        RTI::InteractionClassHandle       theInteraction,
  const RTI::ParameterHandleValuePairSet& theParameters,
  const char                             *theTag)
throw (
  RTI::InteractionClassNotKnown,
  RTI::InteractionParameterNotKnown,
  RTI::FederateInternalError)
{
   cout  << "receiveInteraction: "
         << myData.interactionClassMap[theInteraction].c_str() << "( "
         << theInteraction << ") "
         << (theTag ? theTag : "")  << " "
         << "#parameters: " << theParameters.size() << endl;
   printParameters(theParameters);
}

void MyFederateAmbassador::removeObjectInstance (
        RTI::ObjectHandle          theObject,
  const RTI::FedTime&              theTime,
  const char                      *theTag,
        RTI::EventRetractionHandle theHandle)
throw (
  RTI::ObjectNotKnown,
  RTI::InvalidFederationTime,
  RTI::FederateInternalError)
{
   cout  << "removeObjectInstance: "
         << myData.objectInstanceMap[theObject].c_str() << "("
         << theObject << ") "
         << timeToString(theTime).c_str() << " "
         << (theTag ? theTag : "") << endl;
}

void MyFederateAmbassador::removeObjectInstance (
        RTI::ObjectHandle          theObject,
  const char                      *theTag)
throw (
  RTI::ObjectNotKnown,
  RTI::FederateInternalError)
{
   cout  << "removeObjectInstance: "
         << myData.objectInstanceMap[theObject].c_str() << "("
         << theObject << ") "
         << (theTag ? theTag : "") << endl;
}



void MyFederateAmbassador::attributesInScope (
           RTI::ObjectHandle        theObject,
           const RTI::AttributeHandleSet& theAttributes)
         throw (
           RTI::ObjectNotKnown,
           RTI::AttributeNotKnown,
           RTI::FederateInternalError)
{
   if ( myData.enableScopeAdvisories )
   {
      cout<< "********************************\n"
          << "****Attributes entering scope***\n"
          << "********************************\n";
   }

}

void MyFederateAmbassador::attributesOutOfScope (
           RTI::ObjectHandle        theObject,
           const RTI::AttributeHandleSet& theAttributes)
         throw (
           RTI::ObjectNotKnown,
           RTI::AttributeNotKnown,
           RTI::FederateInternalError)
{
   if ( myData.enableScopeAdvisories )
   {
      cout<< "********************************\n"
          << "****Attributes exiting scope****\n"
          << "********************************\n";
   }
}

moc_simpleDDMAclock.cxx

simpleDDMAclock.cxx

/****************************************************************************
**
** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved.
**
** This file is part of the example classes of the Qt Toolkit.
**
** Licensees holding a valid Qt License Agreement may use this file in
** accordance with the rights, responsibilities and obligations
** contained therein.  Please consult your licensing agreement or
** contact sales@trolltech.com if any conditions of this licensing
** agreement are not clear to you.
**
** Further information about Qt licensing is available at:
** http://www.trolltech.com/products/qt/licensing.html or by
** contacting info@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
/******************************************************************************
** $RCSfile: simpleDDMAclock.cxx,v $ $Revision: 1.2 $ $State: Exp $
******************************************************************************/

#ifdef SIMPLEDDMGUI

#include "simpleDDMAclock.h"
#include <qwidget.h>
#include <qdatetime.h>
#include <qpainter.h>
#include <qbitmap.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qsize.h>
#include <qsizepolicy.h>
#include <qlayout.h>
#include <qtimer.h> 
#include <qapplication.h>
#include <string>

//
// Constructs an analog clock widget that uses an internal QTimer.
//

const int analogClock::degreesInACircle = 360;
const int analogClock::numHoursOnOurClock = 12;
const int analogClock::numTicksPerDegree = 16;
const unsigned int analogClock::NUMSECONDSPERMINUTE = 60;
const unsigned int analogClock::NUMMINUTESPERHOUR = 60;
const unsigned int analogClock::NUMSECONDSPERHOUR = 
                  NUMSECONDSPERMINUTE * NUMMINUTESPERHOUR;

analogClock::analogClock(bool isPublisher, 
                         bool isClockWise, 
                         int zone,
                         bool displayRegion, 
                         QWidget *parent, 
                         const char *name )
: 
QWidget( parent ),
myMinSeconds(0),
myMinHour(0.0f),
myMinMinutes(0), 
myMaxSeconds(1),
myMaxMinutes(1),
myMaxHour(1.0f),
myHours(-1.0f),
myMinutes(0),
mySeconds(0),
myPublisher(isPublisher),
clockWise(isClockWise),
myDrawArc(displayRegion),
myUTCzone(zone),
initialized(false)
{
   internalTimer = new QTimer(this);
   connect(internalTimer, SIGNAL(timeout()), this, SLOT(update()));
   internalTimer->start(1000);
    
   resize(200, 200);   
   
   
   vLayout = new QVBoxLayout( this );   
   setLayout( vLayout );
   vSpacer = new QSpacerItem( 0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding );
   vLayout->addItem(vSpacer);   
   hLayout = new QHBoxLayout( this );
   vLayout->addLayout( hLayout );

   
   hSpacer = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Minimum );         
   clockwiseButton = new QPushButton(this);
   setUTCButton = new QPushButton(this);
   utcLineEdit = new QLineEdit(this);     
  
   initialize();   
}

void analogClock::closeEvent( QCloseEvent* arg)
{   
   if ( initialized )
   {    
      internalTimer->stop();      
   }
   initialized = false;
   QWidget::closeEvent(arg);
}

analogClock::~analogClock()
{

}

void analogClock::initialize()
{   
      
   hLayout->addItem(hSpacer);
   //hLayout->addItem(vSpacer);
   if ( myPublisher )
   {      
      utcLineEdit->hide();
      setUTCButton->hide();
      hLayout->addWidget(clockwiseButton);
   } 
   else
   {                  
      clockwiseButton->hide();
      utcLineEdit->setText(QString::number(myUTCzone));      
      utcLineEdit->setMaximumSize(25, 25);
      utcLineEdit->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);      
      hLayout->addWidget(utcLineEdit);    
      
      setUTCButton->setMaximumSize(115,25);
      //setUTCButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
      setUTCButton->setText("Set the Zone");      
      hLayout->addWidget( setUTCButton );            
   }


   if ( myPublisher )
   {
      connect(clockwiseButton, SIGNAL( clicked()), this,  SLOT(toggle()) );
   }
   else
   {
      connect(setUTCButton, SIGNAL( clicked()), this, SLOT(setUTC()) );
   }   
   internalTimer->start( 100 );     // emit signal every second
   
   if ( myPublisher )
   {
      if (clockWise)      
      {         
         clockwiseButton->setText(QString("Set CCW"));
      }
      else
      {
         clockwiseButton->setText(QString("Set CW"));
      }
   } 
   initialized = true;
}

 

void analogClock::toggle()
{
   if ( initialized ) 
   {
      clockWise = !clockWise;   
      // This should be unnecessary as the connect only happens when
      //myPublisher is true
      // but better safe than sorry!
      if ( myPublisher )
      {
         if (clockWise)
         {
            clockwiseButton->setText(QString("Set CCW"));
         }
      }
      else
      {
         clockwiseButton->setText(QString("Set CW"));
      }
   }
}

void analogClock::setUTC()
{
   if ( initialized ) 
      myUTCzone = utcLineEdit->text().toInt();   
}

void analogClock::paintEvent(QPaintEvent *)
{
   if ( initialized ) 
   {
      QPainter paint( this );
      //paint.setBrush( colorGroup().foreground() );
      drawClock( &paint );
   }
}

void analogClock::drawClock( QPainter* paint )
{
   const int widthOfWindow = 1000;
   const int heightOfWindow = 1300;
   const int diameterOfCircle = 1000;
   const int radiusOfCircle = (int)(diameterOfCircle / 2.0f);   
   const float timeLineWidthPercent = .88f;
   const float circleInUsePercentage = .9f;
   const int circleDiameterInUse = (int)((float)diameterOfCircle * circleInUsePercentage);   
   const int wOrigin = - ( circleDiameterInUse / 2 );      
   
   // Left hash is at leftmost extreme of timeLine.
   const int widthOfLeftHash = (int)(wOrigin * timeLineWidthPercent);
   const int widthOfRightHash = (int)(( wOrigin + circleDiameterInUse ) * timeLineWidthPercent);
   const int heightOfTopOfHash = (wOrigin + (int)(circleDiameterInUse * 1.15f));
   const int heightOfBottomOfHash = (wOrigin + (int)(circleDiameterInUse * 1.2f));
   const int heightOfTimeline = (int)((heightOfTopOfHash + heightOfBottomOfHash) / 2.0f);   
   const int heightOfCurrentPositionTick = heightOfTimeline + (int)( diameterOfCircle * .02f );
   const int numDegreesPerHour = 30;
   const int numDegreesPerMinute = numDegreesPerHour / 5;
   const int numDegreesPerSecond = numDegreesPerMinute;
   const int QT3oclockOffset = 90;
   
   const int lengthOfHourHand = (int) ( radiusOfCircle * .4f);
   const int lengthOfMinuteHand = (int) ( radiusOfCircle * .6f);
   const int lengthOfSecondHand = (int) (radiusOfCircle * .8f);
   const int widthOfHourHand = (int) (radiusOfCircle * .03f);
   const int widthOfMinuteHand = (int) (radiusOfCircle * .025f);
   const int widthOfSecondHand = (int) (radiusOfCircle * .016f);
   
   QColor minuteColor;
   QColor secondColor;
   QColor hourColor;
   QColor BlackColor = QColor(0,0,0);
   paint->save();   
   
   
   if (!myPublisher)
   {    
      minuteColor = QColor(150,0,40);
      secondColor = QColor(0,0,150);
      hourColor = QColor(150,40,170);
   }
   else
   {
      minuteColor = BlackColor;
      secondColor = BlackColor;
      hourColor = BlackColor;
   }
   
   
   QPen arcPenStyle;
   arcPenStyle.setWidth(4);   
   
   paint->setWindow( -radiusOfCircle, -radiusOfCircle, 
      widthOfWindow,
      heightOfWindow );          
   
   paint->setBrushOrigin(QPoint(0,0));
   
   // Set the Viewport to the square defined by the shorter side.
   //(i.e. don't let a non-square window distort image)
   QRect v = paint->viewport();
   int d = qMin( v.width(), v.height() );
   paint->setViewport( v.left() + (v.width()-d)/2,
      v.top() + (v.height()-d)/2, d, d );
   
   paint->save();
   arcPenStyle.setColor(hourColor);
   paint->setPen(arcPenStyle);
   
   if (myDrawArc)
   {
      // Qt places the origin at 3o'clock
      //float myShiftedMinHour = myMinHour + 3.0f;
      //float myMinHoursInDegrees = myShiftedMinHour * (360 / 12);
      //float myMinHoursinQT = myMinHoursInDegrees * 16;
      
      float myMinHoursinQT = (myMinHour - 3.0f) * 
         (degreesInACircle / numHoursOnOurClock) * 
         numTicksPerDegree; 
      
      //float lenInHours = (myMaxHour - myMinHour) ;
      //float lenInDegrees = lenInHours * (360 / 12);
      //float lenInQt = lenInDegrees * 16;
      float lenInQt = (myMaxHour - myMinHour) * 
         (degreesInACircle / numHoursOnOurClock) * 
         numTicksPerDegree;
      
      //the First 4 args describe a bounding box (x,y,w,h).  The arc is drawn on the 
      //circle defined by the box. (Largest circle that can fit in the box)
      //the 5th arg describes the starting point in degrees * 16 that the arc
      //should start at, relative to 3'oclock. Range: [0, 5760] 
      // The 6th arg defines the length of the arc in (16 * degrees) units.\
      // With +/- indicating direction.
      paint->drawArc( -radiusOfCircle,
            -radiusOfCircle,
            diameterOfCircle,
            diameterOfCircle,
            (int)(-myMinHoursinQT),
            (int)( -lenInQt) );        
      
      //We now draw a line to represent our current subscription.     
      arcPenStyle.setWidth(3);
      paint->setPen(arcPenStyle);      
      
      // (start of Timeline) + 
      // (percentage of numHoursOnClock) * (widthOfTimeline)
      int startingWidth = (int)(((float)wOrigin * timeLineWidthPercent) + 
               ((float)myMinHour / (float)numHoursOnOurClock) * 
               ((float)circleDiameterInUse * timeLineWidthPercent));
      
      // (start of Timeline ) +       
      // (percentage of numHoursOnClock) * (widthOfTimeline)      
      int endingWidth = (int)(((float)wOrigin * timeLineWidthPercent) + 
               ((float)myMaxHour / (float)numHoursOnOurClock) * 
               ((float)circleDiameterInUse * timeLineWidthPercent));
      
      paint->drawLine(
            QPoint(startingWidth,heightOfBottomOfHash),
            QPoint(endingWidth,heightOfBottomOfHash) ); 
   }
   
   arcPenStyle.setColor(BlackColor);
   arcPenStyle.setWidth(2);   
   paint->setPen(arcPenStyle);
   //Draw the left hash mark
   
   
   paint->drawLine(
         QPoint(widthOfLeftHash,heightOfTopOfHash), 
         QPoint(widthOfLeftHash,heightOfBottomOfHash ));   
   paint->drawLine(
         QPoint(widthOfRightHash,heightOfTopOfHash), 
         QPoint(widthOfRightHash,heightOfBottomOfHash ));  
   
   arcPenStyle.setWidth(2);
   paint->setPen(arcPenStyle);
   paint->drawLine( 
         QPoint(widthOfLeftHash,heightOfTimeline),
         QPoint(widthOfRightHash, heightOfTimeline) );
   
   
   
   
   arcPenStyle.setWidth(7);
   paint->setPen(arcPenStyle);  
   //the current position tick is just below the current subscription range.
   if (myHours > 0.0f)
   {   
      float centerOfCurrentPosition = ((wOrigin * timeLineWidthPercent) + 
                  (myHours / (float)numHoursOnOurClock)
                  * (circleDiameterInUse * timeLineWidthPercent));      
      paint->drawLine( 
            QPoint( (int)(centerOfCurrentPosition - 2.5f) , heightOfCurrentPositionTick) , 
            QPoint( (int)(centerOfCurrentPosition + 2.5f) , heightOfCurrentPositionTick) );    
   }
   
   paint->restore();
   
   // myHours is initially -1.0f.  Don't display hands if you haven't
   // discovered object!.
   if (myHours > 0.0f)
   {
      const int numPts = 4;
      QPointF pts[numPts];

      paint->save();    
      
      float numHoursInDegrees = (myHours * numDegreesPerHour) - QT3oclockOffset;  
      float numMinutesInDegrees = (myMinutes * numDegreesPerMinute) - QT3oclockOffset;
      float numSecondsInDegrees = (mySeconds * numDegreesPerSecond) - QT3oclockOffset;      
      
      paint->rotate( numHoursInDegrees ); 
      pts[0].setX( -widthOfHourHand );
      pts[0].setY( 0 );
      pts[1].setX( 0 );
      pts[1].setY( -widthOfHourHand );
      pts[2].setX( lengthOfHourHand );
      pts[2].setY( 0 );
      pts[3].setX( 0 );
      pts[3].setY( widthOfHourHand );
      paint->setPen(Qt::NoPen);
      paint->setBrush(hourColor);
      paint->drawConvexPolygon( pts, numPts );
      paint->setPen(Qt::SolidLine);    
      paint->restore();
      
      paint->save();
      paint->setPen(Qt::NoPen);
      paint->setBrush(minuteColor);    
      paint->rotate( numMinutesInDegrees );
      pts[0].setX( -widthOfMinuteHand );
      pts[0].setY( 0 );
      pts[1].setX( 0 );
      pts[1].setY( -widthOfMinuteHand );
      pts[2].setX( lengthOfMinuteHand );
      pts[2].setY( 0 );
      pts[3].setX( 0 );
      pts[3].setY( widthOfMinuteHand );
      paint->drawConvexPolygon( pts, numPts );
      
      paint->setPen(Qt::SolidLine);
      paint->setBrush(Qt::SolidPattern);
      paint->restore();
      
      paint->save();
      paint->setPen(Qt::NoPen);
      paint->setBrush(secondColor);
      paint->rotate( numSecondsInDegrees );
      pts[0].setX( -widthOfSecondHand );
      pts[0].setY( 0 );
      pts[1].setX( 0 );
      pts[1].setY( -widthOfSecondHand );
      pts[2].setX( lengthOfSecondHand );
      pts[2].setY( 0 );
      pts[3].setX( 0 );
      pts[3].setY( widthOfSecondHand );
      paint->drawConvexPolygon( pts, numPts );
      paint->setPen(Qt::SolidLine);
      paint->restore();
   }
   
   paint->setBrushOrigin(QPoint(50,50));
   
   for ( int i=0; i< numHoursOnOurClock; i++ ) 
   {
      paint->drawLine( (int)(radiusOfCircle *.93), 0, 
         (int)(radiusOfCircle * .95), 0 );
      paint->rotate( 30 );
   }
   
   
   paint->restore();
}


#endif // SIMPLEDDMGUI

simpleDDMDisplay.cxx

/******************************************************************************
** Copyright (c) 2006 MaK Technologies, Inc.
** All rights reserved.
******************************************************************************/
/******************************************************************************
** $RCSfile: simpleDDMDisplay.cxx,v $ $Revision: 1.2 $ $State: Exp $
******************************************************************************/

#ifdef SIMPLEDDMGUI

#include "simpleDDMDisplay.h"
#include "simpleDDMAclock.h"
#include "qapplication.h"


#ifdef WIN32 
#include <winsock2.h>
#include <process.h> 
#include <windows.h> 

#else
#include <unistd.h> 
#include <pthread.h>
#endif 

#ifdef WIN32
DWORD WINAPI qtWindowThreadProc( LPVOID lpParam )
#else
  void* qtWindowThreadProc(void* lpParam)
#endif

{     
   clockDisplay* ourParent = (clockDisplay*) lpParam;        
   int numberOfArgs = 0;
   char** args = NULL;      
   
   QApplication ourQapp(numberOfArgs, args);  
   ourParent->a = &ourQapp;
   ourParent->ourAnalogClock = new analogClock( ourParent->isPublisher(),
                  ourParent->isClockWise(),
                  ourParent->zone(),
                  ourParent->areRegionsDisplayed() );
   
   ourParent->ourAnalogClock->resize( 300, 300 );
   ourParent->setHasAClock(true);   
   ourParent->ourAnalogClock->show();
   int result = ourParent->a->exec(); 
   ourParent->setHasAClock(false);
   ourParent->closed = true;       
#ifdef WIN32
   
   return 0;
#else
   //   pthread_exit(NULL); 
   return 0;
#endif
}

clockDisplay::clockDisplay(bool pub, bool cw, bool showReg, int zone)
:
mySeconds(0),
myMinutes(0),
myHours(0.0f),
myUpperBoundRegion(0),
myLowerBoundRegion(1),
myAreRegionsDisplayed(showReg),
myHaveAClock(false),
closed(false),
closing(false),
myIsPublisher(pub),
myIsClockWise(cw),
myUTCZone(zone)
{     
   initializeQTDisplay();      
}

clockDisplay::~clockDisplay()
{    

   setHasAClock(false);

}
void clockDisplay::initializeQTDisplay()
{ 
  
#ifdef WIN32      
   DWORD name;
   HANDLE qtThread; 
   qtThread = CreateThread(NULL, 0, qtWindowThreadProc, this, 0, &name );
   if (qtThread ==  NULL)
   {                  
      ExitProcess(0);
   }
   while ( false == hasAClock() )    
      Sleep(150);
   Sleep(300);
#else      
   pthread_t windowThread;
   pthread_create( &windowThread, NULL, qtWindowThreadProc, this); 
   while ( false == hasAClock() )
     {
      usleep(150);    
     }
#endif //ifdef Win32        
}

void clockDisplay::setTime(int seconds)
{   
   if ( hasAClock() )
   {
      ourAnalogClock->setTime(seconds);
      ourAnalogClock->update();
   }
}

void clockDisplay::setTime(float hour, float min, float sec)
{      
   if ( hasAClock() )
   {
      ourAnalogClock->setTime(hour, min, sec);
      ourAnalogClock->update();   
   }
}

void clockDisplay::setBoundsRegionInSeconds(int lower, int upper)
{
   if ( hasAClock() )
   {
      if ( myAreRegionsDisplayed )
      {
         ourAnalogClock->setRangeInSeconds(lower, upper);
         ourAnalogClock->update();        
      }
   }
}
   
// The owner of a clockDisplay Object instantiates a clockDisplay obj and
 // passes in a value for clockwise.
// clockDisplay::initilizeQTDisplay instantiates a QT display, passing it a 
 // pointer to this.
 // That QT display needs to know whether it is clockwise, and calls this
 //  function.  Then clockDisplay sets clockDisplay::initialized to true.
//The owner of the clockDisplay Object will periodically call isClockWise()
  // and expect that the answer comes from the QT object.
bool clockDisplay::isClockWise()
{
   if (hasAClock())
   {      
      return ourAnalogClock->getClockWise();
   }
   else
   {
      return myIsClockWise;
   }
}

void  clockDisplay::toggleClockWise()
{
   if (hasAClock())
   {      
      ourAnalogClock->toggle();
   }
   else
   {
      myIsClockWise = !myIsClockWise;
   }
}

int clockDisplay::zone()
{
   if (hasAClock())
   {
      return ourAnalogClock->zone();
   }
   else
   {
      return myUTCZone;
   }
}

void clockDisplay::setZone(int newZone)
{
   if ( hasAClock() )
   {
      ourAnalogClock->setZone(newZone);
      myUTCZone = newZone;
   }
   else
   {
      myUTCZone = newZone;
   }
}

#endif // SIMPLEDDMGUI

simpleDDMFederate.cxx

/******************************************************************************
** Copyright (c) 2006 MaK Technologies, Inc.
** All rights reserved.
******************************************************************************/
/******************************************************************************
** $RCSfile: simpleDDMFederate.cxx,v $ $Revision: 1.12 $ $State: Exp $
******************************************************************************/

#ifdef WIN32
#pragma warning(disable: 4786)
#pragma warning(disable: 4290)
#include <winsock2.h>
#include <process.h>
#include <windows.h>


#else
#include <unistd.h>
#include <stdio.h>
#endif

#include "simpleDDMFederate.h"

using namespace std;

const unsigned int simpleDDMFederate::NUMSECONDSPERMINUTE = 60;
const unsigned int simpleDDMFederate::NUMMINUTESPERHOUR = 60;
const unsigned int simpleDDMFederate::NUMSECONDSPERHOUR = NUMSECONDSPERMINUTE * NUMMINUTESPERHOUR;

// 0 seconds is the minimum.
const unsigned int simpleDDMFederate::LOWESTSecondsInRegion = 0;
//60 seconds * 60 minutes * 360 degrees.
const unsigned int simpleDDMFederate::GREATESTSecondsInRegion = NUMSECONDSPERHOUR * 12;
// 0 is the default UTC
const unsigned int simpleDDMFederate::LOWESTUTCInRegion = 0 ;
// We're pretending for this example that the World has only 24 distinct Time Zones. (GREATESTUTCInRegion = 23)
const unsigned int simpleDDMFederate::GREATESTUTCInRegion = 23;

simpleDDMFederate::simpleDDMFederate()
:
   myListenUpperBound(GREATESTSecondsInRegion),
   myListenLowerBound(LOWESTSecondsInRegion),
   mySendUpperBound(LOWESTSecondsInRegion+1),
   mySendLowerBound(LOWESTSecondsInRegion),
   myIsPublisher(false),
   myCurrentposition(0),
   myUpdateCount(0),
   mySizeToInc(1),
   mySendRangeSize(500.0f),
   myEnableScopeAdvisories(false),
   myInitialized(false),
   myClosed(false),
   myMapsInitialized(false),
   myRegionValid(false),
   myUTCZone(LOWESTUTCInRegion)
   {
   }


simpleDDMFederate::simpleDDMFederate(simpleDDMFederate& data)
:
   myListenUpperBound(data.myListenUpperBound),
   myListenLowerBound(data.myListenLowerBound),
   mySendUpperBound(data.mySendUpperBound),
   mySendLowerBound(data.mySendLowerBound),
   myIsPublisher(data.myIsPublisher),
   myCurrentposition(data.myCurrentposition),
   myUpdateCount(data.myUpdateCount),
   mySizeToInc(data.mySizeToInc),
   mySendRangeSize(data.mySendRangeSize),
   myEnableScopeAdvisories(data.myEnableScopeAdvisories),
   myInitialized(data.myInitialized),
   myClosed(data.myClosed),
   myMapsInitialized(data.myMapsInitialized),
   myRegionValid(data.myRegionValid),
   myUTCZone(LOWESTUTCInRegion)
{
}

simpleDDMFederate::~simpleDDMFederate()
{
}

simpleDDMKeyboard.cxx

/******************************************************************************
* Adapted from "Beginning Linux Programming", from Wrox Press -- www.wrox.com
******************************************************************************/
/******************************************************************************
** $RCSfile: simpleDDMKeyboard.cxx,v $ $Revision: 1.2 $ $State: Exp $
******************************************************************************/

#include "simpleDDMKeyboard.h"

#ifdef WIN32
#pragma warning(disable: 4786)
#pragma warning(disable: 4290)
#include <conio.h>
#else
#include <unistd.h>
#endif

keyboard::keyboard()
{
#ifndef WIN32
   tcgetattr(0,&initial_settings);
   new_settings = initial_settings;
   new_settings.c_lflag &= ~ICANON;
   new_settings.c_lflag &= ~ECHO;
   new_settings.c_lflag &= ~ISIG;
   new_settings.c_cc[VMIN] = 1;
   new_settings.c_cc[VTIME] = 0;
   tcsetattr(0, TCSANOW, &new_settings);
   peek_character=-1;
#endif
}

keyboard::~keyboard()
{
#ifndef WIN32
   tcsetattr(0, TCSANOW, &initial_settings);
#endif
}

int keyboard::kbhit()
{
#ifdef WIN32
   return _kbhit();
#else
   unsigned char ch;
   int nread;

   if (peek_character != -1) return 1;
   new_settings.c_cc[VMIN]=0;
   tcsetattr(0, TCSANOW, &new_settings);
   nread = read(0,&ch,1);
   new_settings.c_cc[VMIN]=1;
   tcsetattr(0, TCSANOW, &new_settings);

   if (nread == 1)
   {
      peek_character = ch;
      return 1;
   }
   return 0;
#endif
}

int keyboard::getkey()
{
   char ch;
#ifdef WIN32
   ch = _getch();
#else
   if (peek_character != -1)
   {
      ch = peek_character;
      peek_character = -1;
   }
   else
      read(0,&ch,1);

#endif
   return ch;
}

int keyboard::keybrdTick()
{
   char key = ' ';
   if (!kbhit())
      return 0;
   key = getkey();

   while (key != 'q' && key != 'Q' && key != upKey && key != downKey && kbhit())
      key = getkey();
   if (key == 'q' || key == 'Q')
   {
      return -1;
   }
   else if (key == upKey)
      return 1;
   else if (key == downKey)
      return 2;
   else if (key == leftKey)
      return 3;
   else if (key == rightKey)
      return 4;
   else if (key == 'p' || key == 'P')
      return 5;
   else
      return 6;
}


simpleDDMMain.cxx

/******************************************************************************
** Copyright (c) 2006 MaK Technologies, Inc.
** All rights reserved.
******************************************************************************/
/******************************************************************************
** $RCSfile: simpleDDMMain.cxx,v $ $Revision: 1.7 $ $State: Exp $
******************************************************************************/

// The simpleDDM example demonstrates the use of the Data Distribution Management services.
// It performs the typical federation calls required by most federates (join, create etc.)
// with the addition that when an object is registered or an interaction is sent,
// it is done so "with Region".
//
// The conceptual model of the example is a clock that updates its time.
// The time is represented as the number of seconds along a 12 hour time line.
// There are two dimensions used for routing updates and interactions.
// The dimension seconds designates the position of the clock.
// The dimension UTCn designated the time zone of the clock.
//
// The simpleDDM federate can be either a publisher or a subscriber.
//
// The publisher will register a single object and update its position attribute.
// The position attribute will be associated with a region having the seconds and UTCn dimensions.
// It will also send alarm interactions with this same region.
// The region extent will be maintained to encompass the clock's time zone
// and position. The range bounds for the UTCn dimension will be a single point containing
// the current zone. The range bounds for the seconds dimension will be extrapolated to
// contain future positions (at least the next update).
//
// The subscriber will subscribe to the clock position attribute and the alarm interactions
// with a region having the seconds and UTCn dimensions.  The region extent determines which
// clock is reflected and the time range where it will receive updates and interactions.

#ifdef WIN32
#pragma warning(disable: 4290)
#pragma warning(disable: 4786)
#include <winsock2.h> 
#include <process.h>
#include <windows.h>
#include <exception>
#include <string>
#else
#include <unistd.h>
#include <stdio.h>
#endif

#include <iterator>

#include "simpleDDMKeyboard.h"
#include "simpleDDMFederate.h"

#ifdef SIMPLEDDMGUI
#include "simpleDDMDisplay.h"
#endif //defined SIMPLEDDMGUI

#ifdef DtHLA13
#include "simpleDDMSimple13.h"
#elif DtHLA13DLC
#include "simpleDDMSimple13dlc.h"
#elif DtHLA1516E
#include "simpleDDMSimple1516e.h"
#else
#include "simpleDDMSimple1516.h"
#endif

using namespace std;

#ifndef SIMPLEDDMGUI
// Dummy display class when not linking GUI
class clockDisplay {};
#endif //defined SIMPLEDDMGUI

// Function Prototypes

// Convert command line parameters.
template< class T >
bool convert( const string& param,
             const string& value,
             T& dest );

// Parse command line parameters.
bool parseCmdLine( int argc, char* argv[], simpleDDMFederate* ourFed );

// Create the GUI Display
clockDisplay* createDisplay(simpleDDMFederate* aFederate);

// Change the region bounds
void changeBounds( int lower,
                   int upper,
                   int zone,
                   simpleDDMFederate* aFederate,
                   clockDisplay* aClock = 0);

// Set the time
void SetPosition( int seconds,
              simpleDDMFederate* aFederate,
              clockDisplay* aDisplay = 0 );

// Set the time and adjust the bounds
void SetPositionAndChangeBounds( int seconds,
              simpleDDMFederate* aFederate,
              clockDisplay* aDisplay = 0 );

// Check input for zone changes
bool syncOurZoneWithGui(simpleDDMFederate* aFederate,
   clockDisplay* aDisplay = 0);

// Check input for clockwise changes
bool checkForClockwiseChange(simpleDDMFederate* aFederate,
   clockDisplay* aDisplay = 0);

// Process keyboard input
// Returns -1 if quit command is given
int checkInput(simpleDDMFederate* aFederate,
               clockDisplay* aDisplay);

// Global Data

// Handles keyboard theInput without blocking
keyboard theInput;

// Indicate whether to use a GUI
bool theUseGui = true;

// Indicate whether to display region extents
bool theDisplayRegionExtents = true;

// This variable defines how close to the border of the extents
// (our sender's position can reach) before the sender's region should be
// re-calculated

// This is expressed as a percentage of sendRangeSize
// The default value is 20%, for the default sendRangeSize this indicates
//      that the sender will not update its send region until
//      its position is within 20% distance units of the edge of the Region
float theSendRangeTolerance(20.0f);

// This variable is just the calculation of the above variable multiplied
//    by the size of the send region.
float theSizeOfToleratedSendRange(1);

// The default time zone for publishing and subscribing
const int theDefaultZone = 0;

// This represents the current position of the clock.
//  The valid range for this int is between
// [thePositionLowerBound, thePositionUpperBound)
int theCurrentPosition(0);

// This represents the last position of the clock.
int theLastPosition(0);

// This value represents the current zone of interest.
int theZone(theDefaultZone);

// This value represents the direction of the publisher.
bool theClockWise = true;

// Indicates that the clockwise direction should be changed
bool theChangeClockwiseDirection = false;

// Indicates that the clock movement should be paused
bool thePauseClock = false;

// The time to sleep each execution cycle in milliseconds
#ifdef WIN32
unsigned int theSleepInterval = 2;
#else
unsigned int theSleepInterval = 200;
#endif

// Print an dot for each update to better distinguish the bounds changes.
bool thePrintUpdate = true;

// This value is the default upper bound on legal positions
static int thePositionUpperBound(simpleDDMFederate::GREATESTSecondsInRegion);
// This value is the default lower bound on legal positions
static int thePositionLowerBound(simpleDDMFederate::LOWESTSecondsInRegion);
// The value is the default maximum range
static int theMaximumRange(simpleDDMFederate::GREATESTSecondsInRegion - simpleDDMFederate::LOWESTSecondsInRegion);


// The main routine

int main(int argc, char** argv)
{

   std::cout << "MAK simpleDDM " << std::endl;


   clockDisplay* ourDisplay = 0;
   simpleDDMFederate* ourFed;
#ifdef DtHLA1516   
   ourFed = new simpleDDMFederate1516();
#elif DtHLA1516E
   ourFed = new simpleDDMFederate1516e();
#else   
   ourFed = new simpleDDMFederate13();
#endif

   if (!parseCmdLine(argc, argv, ourFed))
      return 0;

   try
   {
      // Start up
      ourFed->initializeRTI();

      // Create the federation
      ourFed->createFedEx();

      // Join the federation
      ourFed->joinFedEx();

      if ( theUseGui )
      {
         ourDisplay = createDisplay(ourFed);
      }

      // Publish, subscribe and register and object with region
      if (!ourFed->publishSubscribeAndRegisterObject())
      {
         ourFed->resignAndDestroy();
         return 0;
      }

      // Publish and subscribe to the required interaction with Region
      if (!ourFed->publishAndSubscribeInteraction())
      {
         ourFed->resignAndDestroy();
         return 0;
      }

      // The subscriber has no initial position.  It only receives
         // positions updates from the publisher.
      if (ourFed->isPublisher())
      {
         // Initial position
         SetPosition(theCurrentPosition, ourFed);
      }
      

      ourFed->tick(0.0000001, 0.005);

      // Execution loop
      bool finished(false);
      while (!finished)
      {                 
         if (!ourFed->isPublisher())
         {
            // Process subscriber actions

            if (theUseGui)
            {            
               if (syncOurZoneWithGui(ourFed, ourDisplay)) 
               {
#ifdef SIMPLEDDMGUI
                  // Change the bounds to the new zone
                  changeBounds( ourFed->listenLowerBound(),
                                ourFed->listenUpperBound(), 
                                ourDisplay->zone(), 
                                ourFed, 
                                ourDisplay );
#endif
               }
            }
            if (ourFed->position() != theCurrentPosition )
            {
               // A new position has been reflected.
               // Update our local copy and the display.
               theCurrentPosition = ourFed->position();
               SetPosition(theCurrentPosition, ourFed, ourDisplay);
            }
         }
         else
         {
            // Process publisher actions

            checkForClockwiseChange(ourFed, ourDisplay);

            // Increment the position

            if( !thePauseClock )
            {
               if ( theClockWise )
               {
                  // Increment the position in clockwise direction
                  theLastPosition = theCurrentPosition;
                  theCurrentPosition += ourFed->sizeToInc();
                  if ( theCurrentPosition >= thePositionUpperBound )
                  {
                     // The position has reached the end; wrap around
                     theCurrentPosition = thePositionLowerBound
                        + (theCurrentPosition - thePositionUpperBound);
                  }
               }
               else
               {
                  // Increment the position in counter clockwise direction
                  theLastPosition = theCurrentPosition;
                  theCurrentPosition -= ourFed->sizeToInc();

                  if ( theCurrentPosition < thePositionLowerBound )
                  {
                     // The position has reached the beginning; wrap around
                     theCurrentPosition = thePositionUpperBound
                        - (thePositionLowerBound - theCurrentPosition);
                  }
               }

               // Now that the position has been incremented,
               // set it's attrValue in the Federate object and make an update

               SetPositionAndChangeBounds(theCurrentPosition, ourFed, ourDisplay);

               // send the update
               ourFed->sendUpdate(theCurrentPosition);

               // Send an interaction every 3 hours.
               if ( (theCurrentPosition % (60 * 60 * 3)) == 0 )
               {
                  ourFed->sendInteraction_quarterly();
               }

               else if ( (theCurrentPosition % ( 60 * 60 )) == 0 )
               {
                  ourFed->sendInteraction_hourly();
               }
            }
         }


         ourFed->tick(0.0000001, 0.005);

         // Check for input
         if (checkInput(ourFed, ourDisplay) < 0)
         {  
            finished = true;  
         }

#ifdef WIN32
         Sleep(theSleepInterval);
#else
         usleep(theSleepInterval);
#endif

      }
      // Resign and destroy federation
      ourFed->resignAndDestroy();

      if( ourFed )
      {
         delete ourFed;
         ourFed = 0;
      }
   }
#ifdef DtHLA13
   catch (RTI::Exception& ex)
   {
      cout << "RTI Exception (main loop): "
         << ex._name << " " << ex._reason << endl;

      if( ourFed )
      {
         delete ourFed;
      }
   }
#elif DtHLA13DLC
   catch (rti13::Exception& ex)
   {
      cout << "RTI Exception (main loop): "
         << ex._name << " " << ex._reason << endl;

      if( ourFed )
      {
         delete ourFed;
      }
   }
#elif DtHLA1516
   catch (rti1516::Exception& ex)
   {
      cout << "rti1516 Exception (main loop): "
         << DtToString(ex.what()) << endl;

      if( ourFed )
      {
         delete ourFed;
      }
   }
#elif DtHLA1516E
   catch (rti1516e::Exception& ex)
   {
       cout << "rti1516 Exception (main loop): "
           << DtToString(ex.what()) << endl;

       if( ourFed )
       {
           delete ourFed;
       }
   }
#endif
   catch ( ... )
   {
      cout << "Caught unknown exception "
         << endl;

      if( ourFed )
      {
         delete ourFed;
      }

      return 1;
   }
   return 0;

}

clockDisplay* createDisplay(simpleDDMFederate* ourFed)
{
   clockDisplay* tempDisplay = 0;

#ifdef SIMPLEDDMGUI
   // Create a clock GUI and set the initialize it
   tempDisplay = new clockDisplay(ourFed->isPublisher(),
      theClockWise,
      theDisplayRegionExtents,
      theZone != 0);

   if (ourFed->isPublisher())
   {
      changeBounds(ourFed->sendLowerBound(), ourFed->sendUpperBound(),
         theZone, ourFed, tempDisplay );
   }
   else
   {
      changeBounds(ourFed->listenLowerBound(),
         ourFed->listenUpperBound(),
         theZone, ourFed, tempDisplay );
   }
#endif
   return tempDisplay;
}

void SetPosition( int seconds,
              simpleDDMFederate* aFederate,
              clockDisplay* aDisplay )
{
   if (thePrintUpdate && !theUseGui && aFederate->isPublisher())
   {
      // Indicate each update versus range bound update
      cout << ".";
   }
   // Set the position in the federate object
   aFederate->setPosition(seconds);
#ifdef SIMPLEDDMGUI
   // Set the position in the display
   if (aDisplay)
   {
      aDisplay->setTime(seconds);
   }
#endif
}

void SetPositionAndChangeBounds( int seconds,
              simpleDDMFederate* aFederate,
              clockDisplay* aDisplay )
{
   int lowerPos(0);
   int upperPos(0);
   bool updated(false);

   // Set the position,
   // check the range bounds for the new position, and
   // change the bounds when the position is near the edge

   SetPosition(seconds, aFederate, aDisplay);


   if (aFederate->sendRangeSize() >= theMaximumRange)
   {
      // Bounds take up total range
      if (aFederate->sendLowerBound() != thePositionLowerBound
          || aFederate->sendUpperBound() != thePositionUpperBound)
      {
         changeBounds( thePositionLowerBound,
            thePositionUpperBound, theZone, aFederate, aDisplay);
      }
      return;
   }

   if ( theClockWise )
   {
      if ( theCurrentPosition < theLastPosition)
      {
         updated = true;
         // Must have wrapped around, update the bounds
         lowerPos = theCurrentPosition;
         upperPos = lowerPos + aFederate->sendRangeSize();
         if (upperPos > thePositionUpperBound)
         {
            // Don't exceed total range
            upperPos = thePositionUpperBound;
         }
      }
      else if ( (theCurrentPosition + theSizeOfToleratedSendRange) >= aFederate->sendUpperBound() )
      {
         // Position is nearing the end of the send range
         // Move the send range out
         if ( (theCurrentPosition + aFederate->sendRangeSize()) < thePositionUpperBound )
         {
            updated = true;
            // The new send range is within the total range
            lowerPos = theCurrentPosition;
            upperPos = theCurrentPosition + aFederate->sendRangeSize();
         }
         else if (aFederate->sendUpperBound() != thePositionUpperBound)
         {
            updated = true;
            // The new send range would be invalid.
            // However, the range bound cannot wrap around.
            // Set the upper bound to the maximum.
            // Once the upper bound is at the maximum,
            // bounds will remain unchanged until the position wraps
            lowerPos = theCurrentPosition;
            upperPos = thePositionUpperBound;

            // When the position wraps, the update will occur outside of
            // the previous range bound.
            // As an exercise, the federate could simply change clockwise
            // direction when reaching the maximum bound. How should the
            // range bounds be modified?
            // Alternatively, the federate could maintain two regions that
            // split the total range bounds. When the federate reaches
            // a border condition, it could set one range bound as above and
            // set the other range bound to where the federate
            // will be when it wraps.
         }
      }

      if (updated)
      {
         // The range bound needs to be changed.
         changeBounds( lowerPos, upperPos, theZone, aFederate, aDisplay);
      }
   }
   else
   {
      // Moving counter clockwise
      if ( theCurrentPosition > theLastPosition)
      {
         updated = true;
         // Must have wrapped around, update the bounds
         lowerPos = theCurrentPosition - aFederate->sendRangeSize();
         upperPos = theCurrentPosition;
         if (lowerPos < thePositionLowerBound)
         {
            updated = true;
            // Don't exceed total range
            lowerPos = thePositionLowerBound;
         }
      }
      else if ( (theCurrentPosition - theSizeOfToleratedSendRange) <= aFederate->sendLowerBound() )
      {
         // Position is nearing the end of the send range
         // Move the send range out
         if ( (theCurrentPosition - aFederate->sendRangeSize()) > thePositionLowerBound )
         {
            updated = true;
            // The new send range is within the total range
            lowerPos = theCurrentPosition - aFederate->sendRangeSize();
            upperPos = theCurrentPosition;
         }
         else if (aFederate->sendLowerBound() != thePositionLowerBound)
         {
            updated = true;
            // The new send range would be invalid.
            // However, the range bound cannot wrap around.
            // Set the lower bound to the minimum.
            // Once the lower bound is at the minimum,
            // bounds will remain unchanged until the position wraps.
            lowerPos = thePositionLowerBound;
            upperPos = theCurrentPosition;
         }
      }

      if (updated)
      {
         // The range bound needs to be changed.
         changeBounds(lowerPos, upperPos, theZone, aFederate, aDisplay);
      }
   }
}


void changeBounds( int lower,
                   int upper,
                   int zone,
                   simpleDDMFederate* aFederate,
                   clockDisplay* aDisplay)
{

   if ( (lower < (int)simpleDDMFederate::LOWESTSecondsInRegion) ||
      (upper > (int)simpleDDMFederate::GREATESTSecondsInRegion) )
   {
      // Seconds bounds outside limits
      cout << "The limits on seconds Subscriptions are ["  << simpleDDMFederate::LOWESTSecondsInRegion
           << " , " << simpleDDMFederate::GREATESTSecondsInRegion << ")\n";
   }
   else if (lower >= upper)
   {
      // Lower must be greater than upper
      cout << "You must set the Lowerbound to be < your Upper bound\n";
   }
   else if ( (zone < (int)simpleDDMFederate::LOWESTUTCInRegion) ||
         (zone >= (int)simpleDDMFederate::GREATESTUTCInRegion) )
   {
      // Zone bounds outside limits
      cout << "The limits on theZone are ["  << simpleDDMFederate::LOWESTUTCInRegion
           << " , " << simpleDDMFederate::GREATESTUTCInRegion << ")\n";

#ifdef SIMPLEDDMGUI
      if ( aDisplay)
      {
         // Reset display to what should be a good value
         aDisplay->setZone(theZone);
      }
#endif
   }
   else
   {
      // Bounds values are OK
      theZone = zone;

      if (thePrintUpdate && !aDisplay && aFederate->isPublisher())
      {
         // Start new line to break from updates
         cout << endl;
      }
      cout << "Setting Bounds to seconds Range ("
         << lower << "," << upper << ")" << " in zone " << zone << endl;

      aFederate->changeBounds( lower, upper, zone );
#ifdef SIMPLEDDMGUI
      if ( aDisplay )
      {
         // Adjust display
         aDisplay->setBoundsRegionInSeconds(lower, upper );
         aDisplay->setZone(zone);
      }
#endif
   }
}

bool syncOurZoneWithGui(simpleDDMFederate* aFederate,
   clockDisplay* aDisplay)
{
   bool zoneWasChanged = false;
#ifdef SIMPLEDDMGUI
   if ( theUseGui && aDisplay)
   {
      // Check to see if the user has changed the zone
      if ( aFederate->zone() != aDisplay->zone() )
      {         
         zoneWasChanged = true;
         //theZone = aDisplay->zone();
      }
   }
#endif
   return zoneWasChanged;
}

bool checkForClockwiseChange(simpleDDMFederate* aFederate,
   clockDisplay* aDisplay)
{
   bool directionWasChanged = false;
#ifndef SIMPLEDDMGUI
   if (theChangeClockwiseDirection)
   {
      theClockWise = !theClockWise;
      directionWasChanged = true;
      theChangeClockwiseDirection = false;
      cout << "Change direction to " << (theClockWise ? "ClockWise" : "CounterClockWise") << endl;
   }
#else
   if ( theUseGui && aDisplay)
   {
      if (theChangeClockwiseDirection)
      {
         // clockwise direction changed in console
         aDisplay->toggleClockWise();
         theClockWise = aDisplay->isClockWise();
         directionWasChanged = true;
         theChangeClockwiseDirection = false;
      }
      else
      if ( theClockWise != aDisplay->isClockWise() )
      {
         // clockwise direction change in GUI
         theClockWise = aDisplay->isClockWise();
         directionWasChanged = true;
      }
   }
#endif
   return directionWasChanged;
}

int checkInput(simpleDDMFederate* aFederate,
               clockDisplay* aDisplay)
{
   int result = 1;

   // Process keyboard input

   int keyboardReturnCode = theInput.keybrdTick();
   if (keyboardReturnCode < 0)
   {  
      result = -1;
   }
   else if (keyboardReturnCode == 1)
   {
      // keybrdTick returns one if the up arrow was pushed
      // only the subscriber can change timezone.
      if (false == aFederate->isPublisher())
      {         
         changeBounds(
               aFederate->listenLowerBound(),
               aFederate->listenUpperBound(),
               (aFederate->zone() + 1),
               aFederate,
               aDisplay);
      }
   }
   else if (keyboardReturnCode == 2)
   {
      // keybrdTick returns two if the down arrow was pushed
      // only the subscriber can change timezone.
      if (false == aFederate->isPublisher())
      {
         theZone = aFederate->zone();
         changeBounds(
               aFederate->listenLowerBound(),
               aFederate->listenUpperBound(),
               (aFederate->zone() - 1),
               aFederate,
               aDisplay);
      }
   }
   else if (keyboardReturnCode == 3)
   {
      // keybrdTick returns three if the left arrow was pushed
      // only the publisher can change clockwise.
      if (aFederate->isPublisher())
      {
         theChangeClockwiseDirection = theClockWise;
      }
   }
   else if (keyboardReturnCode == 4)
   {
      // keybrdTick returns four if the right arrow was pushed
      // only the publisher can change clockwise.
      if (aFederate->isPublisher())
      {
         theChangeClockwiseDirection = !theClockWise;
      }
   }
   else if (keyboardReturnCode == 5)
   {
      // keybrdTick returns five if 'p' was pressed to pause the rotation
      // only the publisher can pause
      if (aFederate->isPublisher())
      {
         thePauseClock = !thePauseClock;
      }
   }
   else if (keyboardReturnCode != 0)
   {
      if (aFederate->isPublisher())
      {
         cout  << "Left Arrow  - counter clockwise\n"
               << "Right Arrow - clockwise\n"
               << "P,p         - pause/unpause\n"
               << "Q,q         - quit\n";
      }
      else
      {
         cout  << "Up Arrow   - increase listen zone\n"
               << "Down Arrow - decrease listen zone\n"
               << "Q,q        - quit\n";
      }
   }

   return result;
}

bool parseCmdLine( int argc, char* argv[], simpleDDMFederate* ourFed )
{
   // Process commandline input

   // This local variable is used in calculating sendRangeSize
   // The sendRangeSize is calculated by the size of the Range in units of
   // Updates multiplied by sizeToInc in units of Distance / Update.
   // In this example Distance is a measure of time along the Clock.
   float pertinentRange = 500.0f;
   int maxSecondsSubscribe(simpleDDMFederate::GREATESTSecondsInRegion);
   int minSecondsSubscribe(simpleDDMFederate::LOWESTSecondsInRegion);


   vector< string > cmdArgs;
   // Skip the first arg - program name
   copy( argv + 1, argv + argc, back_inserter( cmdArgs ));

   vector< string >::const_iterator cur = cmdArgs.begin();
   vector< string >::const_iterator last = cmdArgs.end();
   int mult(1);


   while ( cur != last )
   {
      vector< string >::const_iterator next = cur + 1;
      if ( *cur == "-h" )
      {
         cerr << usage();
         return false;
      }
      else if (*cur == "-fedFile" )
      {
         ourFed->setFedFileName( next->c_str() );
         ++cur;
      }
      else if (*cur == "-maxSubscribe" )
      {
         if ( !convert<int> (*cur, *next, maxSecondsSubscribe ) )
            return false;
         ++cur;
      }
      else if (*cur == "-minSubscribe" )
      {
         if ( !convert<int> (*cur, *next, minSecondsSubscribe ) )
            return false;

         ++cur;
      }
      else if (*cur == "-maxSubscribeH" )
      {
         float maxSecondsSubscribeH;
         if ( !convert<float> (*cur, *next, maxSecondsSubscribeH ) )
            return false;
         ++cur;
         // convert maxSubscribeH (in Hours) to maxSubscribe (in seconds)
         maxSecondsSubscribe = ((int)(maxSecondsSubscribeH * 60.0f * 60.0f));
      }
      else if (*cur == "-minSubscribeH" )
      {
         float minSecondsSubscribeH;
         if ( !convert<float> (*cur, *next, minSecondsSubscribeH ) )
            return false;
         ++cur;
         // convert minSubscribeH (in Hours) to minSubscribe (in seconds)
         minSecondsSubscribe = ((int)(minSecondsSubscribeH * 60.0f * 60.0f));
      }
      else if (*cur == "-scopeAdvisories" )
      {
         int tmpscopeAdvisory(-1);
         if ( !convert<int> (*cur, *next, tmpscopeAdvisory ) )
            return false;
         if ( tmpscopeAdvisory == 0 || tmpscopeAdvisory == 1 )
            ourFed->setEnableScopeAdvisories(tmpscopeAdvisory != 0);
         else
            return false;
         ++cur;
      }
      else if (*cur == "-isPublisher" )
      {
         int intisPub(0);
         if (!convert<int>(*cur, *next, intisPub))
            return false;
         ourFed->setIsPublisher(intisPub != 0);
         ++cur;
      }
      else if (*cur == "-clockWise" )
      {
         int intCW(0);
         if (!convert<int>(*cur, *next, intCW))
            return false;
         theClockWise = intCW != 0;
         ++cur;
      }
      else if (*cur == "-increment" )
      {
         int inc;
         if (!convert<int> (*cur, *next, inc) )
            return false;
         if (inc < 0)
         {
            ourFed->setSizeToInc(-1 * (1 / inc));
         }
         else if ( inc == 0 )
         {
            cout << " The publisher has to increment > 0\nTo set your increment to be a fraction"
                 << " negative numbers are assigned as follows: (-1 * (1 / input))\n";
            return false;
         }
         else
            ourFed->setSizeToInc(inc);
         ++cur;
      }
      else if (*cur == "-multiplier" )
      {
         if (!convert<int> (*cur, *next, mult))
            return 0;
         ++cur;
      }
      else if (*cur == "-wait" )
      {
         int waitTime = 2;
         if (!convert<int> (*cur, *next, waitTime) || waitTime < 0)
            return false;
#ifdef WIN32
         theSleepInterval = waitTime;
#else
         theSleepInterval = waitTime * 100;
#endif
         ++cur;
      }
      else if (*cur == "-range" )
      {
         if (!convert<float> (*cur, *next, pertinentRange) )
            return false;
         ++cur;
      }
      else if (*cur == "-sendRangeTolerance")
      {
         if (!convert<float> (*cur, *next, theSendRangeTolerance ))
            return false;
         ++cur;
      }
      else if (*cur == "-timeZone" )
      {
         if ( !convert<int> (*cur, *next, theZone ) )
            return false;
         if ( theZone > (int)simpleDDMFederate::GREATESTUTCInRegion
            || theZone < (int)simpleDDMFederate::LOWESTUTCInRegion )
         {
            return false;
         }
         ++cur;
      }
      else if (*cur == "-printUpdate" )
      {
         int printUpdateSwitch(-1);
         if ( !convert<int> (*cur, *next, printUpdateSwitch ) )
            return false;
         if ( printUpdateSwitch == 0 || printUpdateSwitch == 1 )
            thePrintUpdate = printUpdateSwitch == 1;
         else
            return false;
         ++cur;
      }     
      
      else if (*cur == "-displayRegion")
      {
         int tmpdisplayRegion(-1);
         if (!convert<int> (*cur, *next, tmpdisplayRegion ))
            return false;
         if ( tmpdisplayRegion == 0 || tmpdisplayRegion == 1 )
            theDisplayRegionExtents = tmpdisplayRegion == 1;
         else
            return false;
         ++cur;
      }      
      else if (*cur == "-useGUI" )
      {
#ifdef SIMPLEDDMGUI
         int intUseGUI(0);
         if (!convert<int>(*cur, *next, intUseGUI ))
            return false;
         if ( theUseGui == 0 || theUseGui == 1 )
            theUseGui = intUseGUI == 1;
         else
            return false;
         ++cur;
#else
         cerr << "Cannot use -useGUI. The GUI is not available in this version of the example.\n"
            << usage();
         return false;
#endif
      }      
      else
      {
         cerr << "Unrecognized command line option: "
            << *cur << "\n"
            << usage();
         return false;
      }
      ++cur;    
   }

   //******************************************//
   // Check sanity of input parameters         //
   //******************************************//


   if ( (minSecondsSubscribe < (int)simpleDDMFederate::LOWESTSecondsInRegion) ||
      (maxSecondsSubscribe > (int)simpleDDMFederate::GREATESTSecondsInRegion) )
   {
      cout << "The limits on seconds Subscriptions are ["  << simpleDDMFederate::LOWESTSecondsInRegion
           << " , " << simpleDDMFederate::GREATESTSecondsInRegion << ")\nExiting...";
      return false;
   }

   if (minSecondsSubscribe >= maxSecondsSubscribe)
   {
      cout << "You cannot set the Lowerbound to be < your Upper bound\nExiting...\n";
      return false;
   }

   if ( mult < 1 )
   {
      cout << "You cannot set a multiplier to less than unity\nExiting...\n";
      return false;
   }

   if ( pertinentRange < 0 )
   {
      cout << "You must have a non-Zero sized range \nExiting...\n";
      return false;
   }

   if ( (theZone < (int)simpleDDMFederate::LOWESTUTCInRegion) ||
         (theZone >= (int)simpleDDMFederate::GREATESTUTCInRegion) )
   {
      cout << "The limits on theZone are ["  << simpleDDMFederate::LOWESTUTCInRegion
           << " , " << simpleDDMFederate::GREATESTUTCInRegion << ")\nExiting...";
      return false;
   }

   if ( theSendRangeTolerance > 100 || theSendRangeTolerance < 0 )
   {
      cout << "The tolerance parameter is expressed as a percentage of your Range\n"
           << " it must be between [1,100]\n";
      return false;
   }

   //******************************************//
   // Update dependencies of variables that may//
   //   have been set in parseCmdLine          //
   //******************************************//

   //Initial conditions are defined for the subscriber federate,
   // but not for the publishing federate.
   if ( !ourFed->isPublisher() )
   {
      ourFed->changeBounds(minSecondsSubscribe, maxSecondsSubscribe, theZone);
      cout << "Setting initial Bounds to seconds Range ("
         << minSecondsSubscribe << "," << maxSecondsSubscribe << ")"
         << " in zone " << theZone << endl;
   }
   else
   {
      ourFed->changeBounds(0, 1, theZone);
      cout << "No initial bounds specifed, setting to seconds Range ("
         << 0 << "," << 1 << ")" << " in zone " << theZone << endl;
   }

   // Set the initial current position to be with our publishing range
   theCurrentPosition = (0);

   ourFed->setSizeToInc(mult * ourFed->sizeToInc() );

   //******************************************//
   // For the publisher, the size of the region//
   //   shall be determined by the             //
   //pertinentRange * the size of the increment//
   //******************************************//

   ourFed->setSendRangeSize((int)(pertinentRange * ourFed->sizeToInc()));

   //******************************************//
   // For the publisher, the size of the buffer//
   //  between the current position and the    //
   //  edge of the region being advanced upon: //
   //   theSizeOfToleratedSendRange             //
   //pertinentRange * the size of the increment//
   //******************************************//

   theSizeOfToleratedSendRange =
      ((float)ourFed->sendRangeSize() * (theSendRangeTolerance / 100.0f));
   return true;
}

template< class T >
bool convert( const string& param,
             const string& value,
             T& dest )
{
   istringstream convert( value );
   convert >> dest;
   if ( convert.fail() )
   {
      cerr << "Bad Parameter Value\n"
         << "Param: " << param
         << "\tValue: " << value << endl;
      return false;
   }
   return true;
}

simpleDDMAclock.h

/****************************************************************************
**
** Copyright (C) 2004-2007 Trolltech ASA. All rights reserved.
**
** This file is part of the example classes of the Qt Toolkit.
**
** Licensees holding a valid Qt License Agreement may use this file in
** accordance with the rights, responsibilities and obligations
** contained therein.  Please consult your licensing agreement or
** contact sales@trolltech.com if any conditions of this licensing
** agreement are not clear to you.
**
** Further information about Qt licensing is available at:
** http://www.trolltech.com/products/qt/licensing.html or by
** contacting info@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
/******************************************************************************
** $RCSfile: simpleDDMAclock.h,v $ $Revision: 1.2 $ $State: Exp $
******************************************************************************/

#ifndef ANALOGCLOCK_H
#define ANALOGCLOCK_H

#include <qwidget.h>
#include <math.h>
#include <qlineedit.h>

class QPushButton;
class QVBoxLayout;
class QHBoxLayout;
class QSpacerItem;

class analogClock : public QWidget
{
    Q_OBJECT

public:
    analogClock( bool isPublisher, bool isClockWise, int zone, bool displayRegions, 
        QWidget *parent=0, const char *name=0 );
    
    ~analogClock();
    void setAutoMask(bool b);    
    inline void setRangeInHours(float minimum, float maximum);
    inline void setRangeInSeconds(int minimum, int maximum);
    inline void setTime(int seconds);
    inline void setTime(float hour = 12.0f, float minute = 0, float second = 0);
    inline bool getClockWise();
    inline int  zone();
    inline void setZone(int newZone);

    static const int degreesInACircle;
    static const int numHoursOnOurClock;
    static const int numTicksPerDegree;
    bool initialized;
    
protected:
    void paintEvent(QPaintEvent *event);
    void closeEvent( QCloseEvent* );
    void drawClock( QPainter* paint );
        
private:
   float myMinHour;
   float myMaxHour;
   int myMinSeconds;
   int myMinMinutes;
   int myMaxSeconds;
   int myMaxMinutes;
   float myMinutes;
   float mySeconds;
   float myHours;
   bool myPublisher;
   bool clockWise;
   bool myDrawArc;
   int myUTCzone;

private slots:
    void initialize();

public slots:
   void toggle();
   void setUTC();
   

private:
    QPoint clickPos;
    QPushButton* clockwiseButton;
    QPushButton* setUTCButton;    
    QLineEdit*   utcLineEdit;
    
    QTimer* internalTimer;       
    QVBoxLayout* vLayout;
    QHBoxLayout* hLayout;
    
    QSpacerItem* hSpacer;
    QSpacerItem* vSpacer;
    
    
   static const unsigned int NUMSECONDSPERMINUTE;
   static const unsigned int NUMMINUTESPERHOUR;
   static const unsigned int NUMSECONDSPERHOUR;
};



inline void analogClock::setTime(int seconds)
{   
   
   float hour = seconds / (float)NUMSECONDSPERHOUR;
   seconds -= ( (int)floor(hour) * NUMSECONDSPERHOUR);
   float minute = seconds / (float)NUMSECONDSPERMINUTE;
   seconds -= ( (int)floor(minute) * NUMSECONDSPERMINUTE);
   float second = seconds;
   
   setTime(hour, minute, second);

}

inline void analogClock::setTime(float hour, float minute, float second)
{   
   myHours = hour;
   myMinutes = minute;
   mySeconds = second;
}


inline void analogClock::setRangeInSeconds(int minimum, int maximum )
{
   myMinHour = (float)minimum / (float)NUMSECONDSPERHOUR;
   myMaxHour = (float)maximum / (float)NUMSECONDSPERHOUR;
}

inline void analogClock::setRangeInHours(float minimum, float maximum)
{
   myMinHour = minimum;
   myMaxHour = maximum;
}

inline bool analogClock::getClockWise()
{
   return clockWise;
}

inline int analogClock::zone()
{
   return myUTCzone;
}

inline void analogClock::setZone(int newZone)
{
   myUTCzone = newZone;
   utcLineEdit->setText(QString::number(newZone));

}

#endif // ACLOCK_H

simpleDDMDisplay.h

/******************************************************************************
** Copyright (c) 2006 MaK Technologies, Inc.
** All rights reserved.
******************************************************************************/
/******************************************************************************
** $RCSfile: simpleDDMDisplay.h,v $ $Revision: 1.2 $ $State: Exp $
******************************************************************************/

#ifndef DISPLAYFORREGIONEXAMPLE_H_
#define DISPLAYFORREGIONEXAMPLE_H_

#ifdef SIMPLEDDMGUI

#include <vector>
#include <string>

class analogClock;
class QApplication;
 

class clockDisplay
{
public:
   clockDisplay( bool pub = false, bool cw = true,                               
                            bool showReg = true, int zone = 0 );
   ~clockDisplay();
   clockDisplay(clockDisplay& data);

protected:
   void initializeQTDisplay();


public:
   float upperBoundRegion();
   float lowerBoundRegion();
   bool  areRegionsDisplayed();
   bool  isPublisher();
   bool  isClockWise();
   void  toggleClockWise();
   bool  hasAClock();
   void  setHasAClock(bool newVal);
   int   zone();
   void  setZone(int newZone);
   
   // In Seconds
   void setBoundsRegionInSeconds(int lower, int upper);

   void setTime(int seconds);
   void setTime(float hour, float min, float sec);

   bool myHaveAClock;
   bool closed;  
   bool closing;   

   analogClock* ourAnalogClock;   
   QApplication* a;

private:
   float mySeconds;
   float myMinutes;
   float myHours;
   float myUpperBoundRegion;
   float myLowerBoundRegion;
   bool  myAreRegionsDisplayed;
   bool  myIsPublisher;   
   bool  myIsClockWise;
   int   myUTCZone;

};


inline float clockDisplay::upperBoundRegion()
{
   return myUpperBoundRegion;
}

inline float clockDisplay::lowerBoundRegion()
{
   return myLowerBoundRegion;
}

inline bool clockDisplay::areRegionsDisplayed()
{
   return myAreRegionsDisplayed;
}

inline bool clockDisplay::isPublisher() 
{
   return myIsPublisher;
}

inline bool clockDisplay::hasAClock()
{
  return myHaveAClock;
}

inline void clockDisplay::setHasAClock(bool newVal)
{
   myHaveAClock = newVal;
}

#endif // SIMPLEDDMGUI

#endif // DISPLAYFORREGIONEXAMPLE_H_

simpleDDMFedAmb13.h

/******************************************************************************
** Copyright (c) 2006 MaK Technologies, Inc.
** All rights reserved.
******************************************************************************/
/******************************************************************************
** $RCSfile: simpleDDMFedAmb13.h,v $ $Revision: 1.1 $ $State: Exp $
******************************************************************************/

// The Federate Ambassador discovers and remove objects and
// processes object reflects and recieve interactions. It also notes
// attribute scope advisories

#ifndef MyFederateAmbassador_H_
#define MyFederateAmbassador_H_

#include "NullFederateAmbassador.hh"

#include <map>
#include <string>


// Data exchanged between federate and Federate Ambassador
class DtTalkAmbData
{
public:
   std::map<RTI::ObjectClassHandle, std::string> objectClassMap;
   std::map<RTI::ObjectHandle, std::string> objectInstanceMap;
   std::map<RTI::InteractionClassHandle, std::string> interactionClassMap;
   RTI::AttributeHandle myPositionHandle;
   int position;
   int lowerListen;
   int upperListen;
   int lowerSend;
   int upperSend;
   bool enableScopeAdvisories;
   bool isPublisher;

};

class MyFederateAmbassador : public NullFederateAmbassador
{
public:

   MyFederateAmbassador(DtTalkAmbData & data);

   virtual ~MyFederateAmbassador()
     throw (RTI::FederateInternalError);


   // Object Management Services //

   virtual void discoverObjectInstance (
           RTI::ObjectHandle          theObject,      // supplied C1
           RTI::ObjectClassHandle     theObjectClass, // supplied C1
     const char*                      theObjectName)  // supplied C4
   throw (
     RTI::CouldNotDiscover,
     RTI::ObjectClassNotKnown,
     RTI::FederateInternalError);

   virtual void reflectAttributeValues (
           RTI::ObjectHandle                 theObject,     // supplied C1
     const RTI::AttributeHandleValuePairSet& theAttributes, // supplied C4
     const RTI::FedTime&                     theTime,       // supplied C1
     const char                             *theTag,        // supplied C4
           RTI::EventRetractionHandle        theHandle)     // supplied C1
   throw (
     RTI::ObjectNotKnown,
     RTI::AttributeNotKnown,
     RTI::FederateOwnsAttributes,
     RTI::InvalidFederationTime,
     RTI::FederateInternalError);

   virtual void reflectAttributeValues (
           RTI::ObjectHandle                 theObject,     // supplied C1
     const RTI::AttributeHandleValuePairSet& theAttributes, // supplied C4
     const char                             *theTag)        // supplied C4
   throw (
     RTI::ObjectNotKnown,
     RTI::AttributeNotKnown,
     RTI::FederateOwnsAttributes,
     RTI::FederateInternalError);

   // 4.6
   virtual void receiveInteraction (
           RTI::InteractionClassHandle       theInteraction, // supplied C1
     const RTI::ParameterHandleValuePairSet& theParameters,  // supplied C4
     const RTI::FedTime&                     theTime,        // supplied C4
     const char                             *theTag,         // supplied C4
           RTI::EventRetractionHandle        theHandle)      // supplied C1
   throw (
     RTI::InteractionClassNotKnown,
     RTI::InteractionParameterNotKnown,
     RTI::InvalidFederationTime,
     RTI::FederateInternalError);

   virtual void receiveInteraction (
           RTI::InteractionClassHandle       theInteraction, // supplied C1
     const RTI::ParameterHandleValuePairSet& theParameters,  // supplied C4
     const char                             *theTag)         // supplied C4
   throw (
     RTI::InteractionClassNotKnown,
     RTI::InteractionParameterNotKnown,
     RTI::FederateInternalError);

   virtual void removeObjectInstance (
           RTI::ObjectHandle          theObject, // supplied C1
     const RTI::FedTime&              theTime,   // supplied C4
     const char                      *theTag,    // supplied C4
           RTI::EventRetractionHandle theHandle) // supplied C1
   throw (
     RTI::ObjectNotKnown,
     RTI::InvalidFederationTime,
     RTI::FederateInternalError);

   virtual void removeObjectInstance (
           RTI::ObjectHandle          theObject, // supplied C1
     const char                      *theTag)    // supplied C4
   throw (
     RTI::ObjectNotKnown,
     RTI::FederateInternalError);

   virtual void attributesInScope (
           RTI::ObjectHandle        theObject,     // supplied C1
           const RTI::AttributeHandleSet& theAttributes) // supplied C4
         throw (
           RTI::ObjectNotKnown,
           RTI::AttributeNotKnown,
           RTI::FederateInternalError) ;

   virtual void attributesOutOfScope (
           RTI::ObjectHandle        theObject,     // supplied C1
           const RTI::AttributeHandleSet& theAttributes) // supplied C4
         throw (
           RTI::ObjectNotKnown,
           RTI::AttributeNotKnown,
           RTI::FederateInternalError) ;


public:
   DtTalkAmbData & myData;
};



#endif

simpleDDMFederate.h

/******************************************************************************
** Copyright (c) 2006 MaK Technologies, Inc.
** All rights reserved.
******************************************************************************/
/******************************************************************************
** $RCSfile: simpleDDMFederate.h,v $ $Revision: 1.17 $ $State: Exp $
******************************************************************************/

#ifndef REGIONEXAMPLE_H_
#define REGIONEXAMPLE_H_

// Base class for wrappers around the RTI Ambassador calls.

#include <sstream>
#include <string>
#include <iostream>
#include <iomanip>
#include <vector>


#include "simpleDDMStringUtil.h"



class simpleDDMFederate
{
public:
// Default Constructor
   simpleDDMFederate();

// Constructor
   simpleDDMFederate(simpleDDMFederate& data);

// Destructor
   virtual ~simpleDDMFederate();

// RTI Wrappers

// Initialize the RTI
   virtual void initializeRTI() = 0;

// Create a federation execution
   virtual bool createFedEx() = 0;

// Join a federation execution
   virtual bool joinFedEx() = 0;

// Resign from the federation execution and destroy it
   virtual void resignAndDestroy() = 0;

// Create the Region and initialize its bounds
   virtual bool createAndInitializeRegions() = 0;

// Publish and subscribe the object class attributes.
// Register an object instance of the class.
   virtual bool publishSubscribeAndRegisterObject() = 0;

// Publish and Subscribe to an interaction class
   virtual bool publishAndSubscribeInteraction() = 0;

// Send the default update with Region.  A less simple federate would have to
// specify which attributes need be updated.  This on merely passes in the
// position which is sent with Region as the object update.
   virtual void sendUpdate(int currentPosition ) = 0;

// Send Interactions with Region.  The following two interactions are meant to
// emulate a cuckoo clock with both an hourly chime, and a quarterly chime.

// Send the hourly interaction with Region. This is an interaction that in this
// example occurs for each hour that is passed on the clock that is not
// {12,3,6,9}.
   virtual void sendInteraction_hourly() = 0;

// Send the quarterly interaction with Region.  This is an interaction that in
// this example occurs for each hour that is passed on the clock that is in the
// following set {12,3,6,9}
   virtual void sendInteraction_quarterly() = 0;

// changeBounds sets the subscription of publication bounds of this federate.
   virtual void changeBounds(int lower, int upper, int UTCZone) = 0;

// Set the RTI's enable advisory switch
   virtual void setEnableScopeAdvisories(bool yesNo) = 0;

// Get scope advisory setting
   bool enableScopeAdvisories() const ;

// Perform the tick or evokeCallback method.
   virtual void tick(double atMost=0.0f) = 0;

// Perform the tick or evokeCallback method.
   virtual void tick(double atLeast, double atMost) = 0;

   // Simulation Methods

// Set federate as publisher (true) or subscriber (false)
   virtual void setIsPublisher(bool yesNo) = 0;

// Return true if this federate is publishing
   bool isPublisher() const ;

// Set the position (number of seconds)
   virtual void setPosition(int data) = 0;

// Get the position (number of seconds)
   virtual int position() = 0;

// Set the number of seconds to increment each cycle
   void setSizeToInc(int data);

// Get the number of seconds to increment each cycle
   int sizeToInc() const ;

// Get the zone used to send or listen
   int zone() const ;

   // Region Range Bound Methods

// Set the update range (number of seconds ahead of current position)
// This value should be at least large enough to have the next update fall
// within the range.
   void setSendRangeSize(int data);

// Get the update range (number of seconds ahead of current position)
   int sendRangeSize() const ;

// Get this listen upper bound
   int listenUpperBound() const ;

// Get this listen lower bound
   int listenLowerBound() const ;

// Get the send upper bound
   int sendUpperBound() const ;

// Get the send lower bound
   int sendLowerBound() const;


// Set the Fed File Name
virtual void setFedFileName(const wchar_t* newFedName) = 0;

// Set the Fed File Name with a std::string.
virtual void setFedFileName(const char* newFedName) = 0;

// Get the Fed File Name
virtual char* getFedFileName() const = 0;

   // Constants used in calculations
   static const unsigned int NUMSECONDSPERMINUTE;
   static const unsigned int NUMMINUTESPERHOUR;
   static const unsigned int NUMSECONDSPERHOUR;

   // 0 seconds is the minimum.
   static const unsigned int LOWESTSecondsInRegion;
   //60 seconds * 60 minutes * 360 degrees.
   static const unsigned int GREATESTSecondsInRegion;
   // 0 is the default UTC
   static const unsigned int LOWESTUTCInRegion;
   // For this example, the World has only 24 distinct Time Zones. (GREATESTUTCInRegion = 23)
   static const unsigned int GREATESTUTCInRegion;

   enum simpleAttributeHandleIndex
   {
      simplePositionIndex = 0,
      simpleMaxIndex
   };

protected:

   // Our upper bound is the number of seconds in a circle.
   // This is our default upper bound of interest extent in our region.
   int myListenUpperBound;

   // This is our default lower bound of interest extent in our region.
   int myListenLowerBound;

   // Is this instance the publisher.  The Simple DDM example has one federate
   // publishing and the other federate publishing no information,
   // simply subscribing.
   bool myIsPublisher;

   //******************************************//
   // The following are publisher specific data
   //******************************************//
   // This is our default upper area of interest extent in our region.
   int mySendUpperBound;
   // This is our default lower area of interest extent in our region.
   int mySendLowerBound;
   // This is the default time increment between ticks (seconds)
   int mySizeToInc;
   // This is the calculated range of the sender
   float mySendRangeSize;
   // This represents the current position of the executing federate.
   //  The valid range for this int is between
   //                     [positionLowerBound, positionUpperBound)
   int myCurrentposition;

   // The number of updates sent
   int myUpdateCount;

   int myUTCZone;

   //******************************************//
   // The following is subscriber specific data
   //******************************************//
   // This boolean enables the scope Advisory callback from the rti1516.
   // The scoping callback is issued when an object that is subscribed with
   // region changes visibility to the federate.  i.e. When the subscribed and
   // published region start to instersect and cease to intersect.
   bool myEnableScopeAdvisories;

   //initialized represents whether or not the QT process has Initialized,
   // After main launches a QT thread,
   //  main waits for QT to set initialized before proceeding
   bool myInitialized;
   // closed is a global representing whether the main loop has exited for any
   // reason including the user closing the dialog.
   // The main loop sets it prior to exiting and the QT thread
   // exits when it detects the main loop has closed.
   bool myClosed;

   bool myRegionValid;
   bool myMapsInitialized;

private:
   // Assignment Operator not implemented: Copy not allowed
   simpleDDMFederate &operator=(const simpleDDMFederate&);
};


inline void simpleDDMFederate::setSizeToInc(int data)
{
   mySizeToInc = data;
}
inline void simpleDDMFederate::setSendRangeSize(int data)
{
   if ( data < (int)(GREATESTSecondsInRegion - LOWESTSecondsInRegion) )
   {
      mySendRangeSize = (float)data;
   }
   else
   {
      mySendRangeSize = (float)(GREATESTSecondsInRegion - LOWESTSecondsInRegion);
   }
}

inline int simpleDDMFederate::listenUpperBound() const
{
   return myListenUpperBound;
}

inline int simpleDDMFederate::listenLowerBound() const
{
   return myListenLowerBound;
}

inline bool simpleDDMFederate::isPublisher() const
{
   return myIsPublisher;
}

inline int simpleDDMFederate::sendUpperBound() const
{
   return mySendUpperBound;
}

inline int simpleDDMFederate::sendLowerBound() const
{
   return mySendLowerBound;
}

inline int simpleDDMFederate::sizeToInc() const
{
   return mySizeToInc;
}

inline int simpleDDMFederate::sendRangeSize() const
{
   return (int)mySendRangeSize;
}

inline bool simpleDDMFederate::enableScopeAdvisories() const
{
   return myEnableScopeAdvisories;
}

inline int simpleDDMFederate::zone() const
{
   return myUTCZone;
}

#endif

simpleDDMKeyboard.h

/******************************************************************************
* Adapted from "Beginning Linux Programming", from Wrox Press -- www.wrox.com
******************************************************************************/
/******************************************************************************
** $RCSfile: simpleDDMKeyboard.h,v $ $Revision: 1.1 $ $State: Exp $
******************************************************************************/

// Utility to allow keyboard input without blocking

#ifndef MYKBHIT_H_
#define MYKBHIT_H_

#ifndef WIN32
#include <termios.h>
#endif

class keyboard
{
public:

   // Special Extended Key Definitions
   enum
   {
#ifdef WIN32
       upKey            = '\110',
       downKey          = '\120',
       leftKey          = '\113',
       rightKey         = '\115'
#else
       // Fix incorrect keybindings in *nix.
       // we're still using the keypad.
       upKey            = 'A',
       downKey          = 'B',
       leftKey          = 'D',
       rightKey         = 'C'
#endif
   };

   keyboard();

   ~keyboard();

   // Returns 1 if keyboard input is ready; otherwise, 0
   int kbhit();

   // Returns character from keyboard if avaialable; otherwise, 0
   int keybrdTick();

protected:

   // Return character from keyboard input
   int getkey();

private:

#ifndef WIN32
   struct termios initial_settings, new_settings;
   int peek_character;
#endif

};


#endif

simpleDDMSimple13.h

/******************************************************************************
** Copyright (c) 2006 MaK Technologies, Inc.
** All rights reserved.
******************************************************************************/
/******************************************************************************
** $RCSfile: simpleDDMSimple13.h,v $ $Revision: 1.2 $ $State: Exp $
******************************************************************************/

#ifndef REGIONEXAMPLE13_H_
#define REGIONEXAMPLE13_H_

// A wrapper around the RTI Ambassador calls that incorporates
// Data Distribution Management (DDM).
// The typical calls are supported such as create/destroy, join/resign,
// publish/subscribe, register/delete object, update object, and send interaction.
// The DDM calls to create and maintain regions are also supported and regions
// are used with the other services where appropriate.

#include "simpleDDMFederate.h"
#include <string.h>
#include "RTI.hh"
#include "simpleDDMFedAmb13.h"

// Map between strings and attribute handles
typedef std::map<std::string, RTI::AttributeHandle>  DtAttrNameHandleMap;
// Map between strings and parameter handles
typedef std::map<std::string, RTI::ParameterHandle>  DtParamNameHandleMap;


class simpleDDMFederate13 : public simpleDDMFederate
{
public:

// Default Constructor
   simpleDDMFederate13();

// Constructor
   simpleDDMFederate13(simpleDDMFederate13& data);

// Destructor
   ~simpleDDMFederate13();

// RTI Wrappers

// Initialize the RTI
   void initializeRTI();

// Create a federation execution
   bool createFedEx();

// Join a federation execution
   bool joinFedEx();

// Resign from the federation execution and destroy it
   void resignAndDestroy();

// Create the Region and initialize its bounds
   bool createAndInitializeRegions();

// Publish and subscribe the object class attributes.
// Register an object instance of the class.
   bool publishSubscribeAndRegisterObject();

// Publish and Subscribe to an interaction class
   bool publishAndSubscribeInteraction();

// Send the default update with Region.  A less simple federate would have to
// specify which attributes need be updated.  This on merely passes in the
// position which is sent with Region as the object update.
   void sendUpdate(int currentPosition );

// Send Interactions with Region.  The following two interactions are meant to
// emulate a cuckoo clock with both an hourly chime, and a quarterly chime.

// Send the hourly interaction with Region. This is an interaction that in this
// example occurs for each hour that is passed on the clock that is not
// {12,3,6,9}.
   void sendInteraction_hourly();

// Send the quarterly interaction with Region.  This is an interaction that in
// this example occurs for each hour that is passed on the clock that is in the
// following set {12,3,6,9}
   void sendInteraction_quarterly();

// Perform the tick or evokeCallback method.
   void tick(double atMost=0.0f);

// Perform the tick or evokeCallback method.
   void tick(double atLeast, double atMost);

// changeBounds sets the subscription of publication bounds of this federate.
   void changeBounds(int lower, int upper, int UTCZone) ;

// Set the RTI's enable advisory switch
   void setEnableScopeAdvisories(bool yesNo);

   // Simulation Methods

// Set federate as publisher (true) or subscriber (false)
   void setIsPublisher(bool yesNo);

// Get the position (number of seconds)
   int  position();

// Set the position (number of seconds)   
   void setPosition(int data);
   
// Set the Fed File Name
   void setFedFileName(const char* newFedName);

// Set the Fed File Name
void setFedFileName(const wchar_t* newFedName);
   
// Get the Fed File Name
char* getFedFileName() const;

   
protected:

   // Map between strings and attribute handles
   DtAttrNameHandleMap myAttrNameHandleMap;

   // Map between strings and parameter handles
   DtParamNameHandleMap myParamNameHandleMap;

   static const unsigned int myNumAttributes;
   static const unsigned long myNumExtents;

   // Array of attributeHandles.
   RTI::AttributeHandle* myAttrHandlesArray;

   RTI::AttributeHandleSet* myAttrHandlesSet;

   RTI::AttributeHandleValuePairSet *myAttrValues;

   // Data shared between federate and federate ambassador
   DtTalkAmbData myAmbData;

private:
   // Federate and Federation info
   std::string myFederationName;
   std::string myFederationFile;
   std::string myFederateType;

   // An interaction published at {1, 2, 4, 5, 7, 8, 10 , 11}
   std::string myHourlyInteraction;

   // An interaction published at {3,6,9,12}
   std::string myQuarterlyInteraction;

   // The interaction class name
   std::string myInterClassName;

   // The object class name
   std::string myClassName;

   // The attribute name
   std::string myAttrName;

   // The number of dimensions
   unsigned int myNumberOfDimensions;

   // The RTI Ambassador
   RTI::RTIambassador* myRTIamb;

   // The Federate Ambassador
   MyFederateAmbassador* myFedAmb;

   // the Handle for the hourlyInteraction, (to be retrieved from RTI).
   RTI::ParameterHandle myHourlyHandle;

   // the Handle for the quarterlyInteraction, (to be retrieved from RTI).
   RTI::ParameterHandle myQuarterlyHandle;


   // Construct a parameter handle value pair set with the
   // values containing the parameter names
   RTI::ParameterHandleValuePairSet* myParamValues;

   // The name of the dimension is specified in your FED file.
   std::string mySecondsDimensionName;

   // The time zone dimension name
   std::string myUTCDimensionName;

   // The routing space name
   std::string mySpaceName;

   // The object class handle (to be retrieved from RTI).
   RTI::ObjectClassHandle myClassHandle;

   //The object instance handle ( to be retrieved from the rti).
   RTI::ObjectHandle myObjectHandle;

   // The interaction class handle (to be retrieved from RTI).
   RTI::InteractionClassHandle myInterClassHandle;

   // The Seconds dimension handle (to be retrieved from the RTI).
   RTI::DimensionHandle mySecondsDimHandle;

   // The UTC dimension handle (to be retrieved from the RTI).
   RTI::DimensionHandle myUTCDimHandle;

   // The listen region
   RTI::Region* myListenRegion;

   // The publish region
   RTI::Region* mySendRegion;


};

inline void simpleDDMFederate13::setIsPublisher(bool yesNo)
{
   myIsPublisher = yesNo;
   myAmbData.isPublisher = yesNo;
}

inline void simpleDDMFederate13::setEnableScopeAdvisories(bool yesNo)
{
   myEnableScopeAdvisories = yesNo;
   myAmbData.enableScopeAdvisories = yesNo;
}

inline int simpleDDMFederate13::position()
{
   if (!isPublisher())
      myCurrentposition = myAmbData.position;
   return myCurrentposition;
}

inline void simpleDDMFederate13::setFedFileName(const char* newFedName)
{
   myFederationFile = std::string(newFedName);
}

inline void simpleDDMFederate13::setFedFileName(const wchar_t* newFedName)
{
   myFederationFile = DtToString(std::wstring(newFedName));
}

inline char* simpleDDMFederate13::getFedFileName() const 
{
   return strdup(myFederationFile.c_str());
}



#endif

simpleDDMStringUtil.h

/******************************************************************************
** Copyright (c) 2006 MaK Technologies, Inc.
** All rights reserved.
******************************************************************************/
/******************************************************************************
** $RCSfile: simpleDDMStringUtil.h,v $ $Revision: 1.1 $ $State: Exp $
******************************************************************************/

#ifndef stringUtil_H_
#define stringUtil_H_

// Utility for converting strings between narrow and wide formats

#include <string>
#include <sstream>

std::wstring DtToWString(const char* in_val);
std::string DtToString(const std::wstring &in_val);
std::string usage();


// Convert narrow C string to wide string
inline std::wstring DtToWString(const char* in_val)
{
   std::wstring temp;
   while (*in_val != '\0')
   temp += *in_val++;
   return temp;
}

// Convert narrow string to wide string
inline std::string DtToString(const std::wstring &in_val)
{
   std::string temp;
   std::wstring::const_iterator b = in_val.begin();
   const std::wstring::const_iterator e = in_val.end();
   while (b != e)
   {
      temp += static_cast<char>(*b);
      ++b;
   }
   return temp;
}



inline std::string usage()
{
   std::ostringstream ostr;
   ostr << "Usage:\n"

      << std::setw( 20 ) << " -fedFile "
      << "specify the Fed file name \n"
      << std::setw ( 32 ) << " " << "1.3  Default: (MAKSimpleDDM.fed) \n"
      << std::setw ( 32 ) << " " << "1516 Default: (MAKSimpleDDM.xml) \n"
      << "\nSubscriber parameters\n"
      
      << std::setw( 20 ) << " -maxSubscribe "
      << "Simple DDM uses just one extent and dimension, \n"
      << std::setw( 32 ) << " " << "this is the subscribers upper range \n"
      << std::setw( 32 ) << " " << "(in seconds)\n"

      << std::setw( 20 ) << " -minSubscribe "
      << "Simple DDM uses just one extent and dimension, \n"
      << std::setw( 32 ) << " " << "this is the subscriber's lower range \n"
      << std::setw( 32 ) << " " << "(in seconds)\n"

      << std::setw( 20 ) << " -maxSubscribeH "
      << "Simple DDM uses just one extent and dimension, \n"
      << std::setw( 32 ) << " " << "this is the subscribers upper range\n"
      << std::setw( 32 ) << " " << "(in hours)\n"
      
      << std::setw( 20 ) << " -minSubscribeH "
      << "Simple DDM uses just one extent and dimension, \n"
      << std::setw( 32 ) << " " << "this the subscriber's lower range  \n"
      << std::setw( 32 ) << " " << "(in hours)\n"
      
      << std::setw( 20 ) << " -scopeAdvisories "
      << "Whether or not the user wants to receive       \n"
      << std::setw( 32 ) << " " << "scoping advisory notices (0 || 1)\n"


      << "\nPublisher parameters\n"

      << std::setw( 20 ) << " -isPublisher "
      << "Whether the application should as publisher or \n"
      << std::setw( 32 ) << " " << "subscriber. (default 0)\n"

      << std::setw( 20 ) << " -clockWise "
      << "Whether the object moves in CW or CCW direction \n"
      << std::setw( 32 ) << " " << "1 = CW (default)\n"

      << std::setw( 20 ) << " -increment "
      << "Increment that the publisher will advance by in seconds\n"
      << std::setw( 32 ) << " " << "modified by multiplier\n"

      << std::setw( 20 ) << " -multiplier "
      << "Multiplier for both advancement upon the extent\n"
      << std::setw( 32 ) << " " << "and lookahead on the extent\n"

      << std::setw( 20 ) << " -wait "
      << "Time interval (in milliseconds) to wait inbetween each update cycle.\n"

      << std::setw( 20 ) << " -range "
      << "Lookahead multiplier that the listening range  \n"
      << std::setw( 32 ) << " " << "will subscribe to\n"

      << std::setw( 20 ) << " -sendRangeTolerance "
      << " Describes a percentage of the sending range,  \n"
      << std::setw( 32 ) << " " << "how close the sender can get to the \n"
      << std::setw( 32 ) << " " << "extents of the sending range before \n"
      << std::setw( 32 ) << " " << "the Lower and Upper Bound of the \n"
      << std::setw( 32 ) << " " << "sender are re-sent\n"

      << std::setw( 20 ) << " -timeZone"
      << " Sets the UTC zone of the publisher  \n"
      << std::setw( 32 ) << " " << "Acceptable Values are from 0 .. 23 \n"
      << std::setw( 32 ) << " " << " Default value is 0, representing GMT\n"

      << std::setw( 20 ) << " -printUpdate "
      << "When GUI is disabled, prints a dot for each update to better\n"
      << std::setw( 32 ) << " " << "distinguish bounds changes\n"


      << "\nDisplay Options \n"
      << std::setw( 20 ) << " -displayRegion "
      << "Whether or not there is distinction in shading \n"
      << std::setw( 32 ) << " " << "in extent of a region and the entire \n"
      << std::setw( 32 ) << " " << "dimension (0 || 1)\n"

#ifdef SIMPLEDDMGUI
      << std::setw( 20 ) << " -useGUI "
      << "Whether the application should run in GUI or \n"
      << std::setw( 32 ) << " " << "console mode. \n"
#endif
      << std::endl;

   return ostr.str();
}

#endif




Document ID: Generated on Thu Jun 14 14:15:04 EDT 2012 from SVN revision 116116
Copyright © 2005-2012 VT MÄK Inc. All Rights Reserved (www.mak.com)