Ejemplo n.º 1
0
bool C4Network2IO::Connect(const C4NetIO::addr_t &addr, C4Network2IOProtocol eProt, const C4ClientCore &nCCore, const char *szPassword) // by main thread
{
    // get network class
    C4NetIO *pNetIO = getNetIO(eProt);
    if (!pNetIO) return false;
    // already connected/connecting?
    if (GetConnectionByConnAddr(addr, pNetIO)) return true;
    // assign new connection ID, peer address isn't known yet
    uint32_t iConnID = iNextConnID++;
    C4NetIO::addr_t paddr;
    ZeroMem(&paddr, sizeof paddr);
    // create connection object and add to list
    C4Network2IOConnection *pConn = new C4Network2IOConnection();
    pConn->Set(pNetIO, eProt, paddr, addr, CS_Connect, szPassword, iConnID);
    pConn->SetCCore(nCCore);
    AddConnection(pConn);
    // connect
    if (!pConn->Connect())
    {
        // show error
        LogF("Network: could not connect to %s:%d using %s: %s", inet_ntoa(addr.sin_addr), htons(addr.sin_port),
             getNetIOName(pNetIO), pNetIO->GetError() ? pNetIO->GetError() : "");
        pNetIO->ResetError();
        // remove class
        RemoveConnection(pConn);
        return false;
    }
    // ok, wait for connection
    return true;
}
//------------------------------------------------------------------------------
// entityStateManager() --  (Output support)
//    -- Update the entity object for this NIB(Player)
//------------------------------------------------------------------------------
bool Nib::entityStateManager(const double curExecTime)
{
   bool ok = true;
   if (getPlayer()->isMode(simulation::Player::ACTIVE) && isPlayerStateUpdateRequired(curExecTime)) {

      // Need to update this entity object ...

      NetIO* netIO = static_cast<NetIO*>(getNetIO());
      RTI::RTIambassador* rtiAmb = netIO->getRTIambassador();

      // ---
      // First, make sure this entity has been registered
      // ---
      if (!isRegistered()) {
         try {
            RTI::ObjectClassHandle theClassHandle = netIO->getObjectClassHandle( getClassIndex() );
            makeObjectName();
            setObjectHandle( rtiAmb->registerObjectInstance( theClassHandle, getObjectName() ) );
            netIO->addNibToObjectTables(this, simulation::NetIO::OUTPUT_NIB);
            std::cout << "rprfom::Nib::updateEntity(): Register entity: " << getObjectName() << " handle = " << getObjectHandle() << std::endl;
         }
         catch (RTI::Exception& e) {
            std::cerr << &e << std::endl;
            ok = false;
         }
      }

      // ---
      // Next, update the entity's attribute values ...
      // ---
      if ( ok && isRegistered()) {
         try {
            // Create the attribute-value pair set
            RTI::AttributeHandleValuePairSet* attrs = nullptr;
            attrs = RTI::AttributeSetFactory::create( NetIO::NUM_OBJECT_ATTRIBUTES );

            // Load the set with updated attribute values
            updateBasicEntity(attrs,curExecTime);
            updatePhysicalEntity(attrs,curExecTime);
            updatePlatform(attrs,curExecTime);

            // Send attributes to the RTI
            //std::cout << "RprFom::Nib::updateEntity(): Update entity: " << getObjectName() << " handle = " << getObjectHandle() << std::endl;
            ok = netIO->updateAttributeValues(getObjectHandle(), attrs);

            delete attrs;
         }

         catch (RTI::Exception& e) {
            std::cerr << &e << std::endl;
            ok = false;
         }
      }
   } // end -- if active player needs an update

   return ok;
}
Ejemplo n.º 3
0
void Ambassador::receiveInteraction (
        RTI::InteractionClassHandle       theInteraction,
  const RTI::ParameterHandleValuePairSet& theParameters,
  const char*)
throw (
   RTI::InteractionClassNotKnown,
   RTI::InteractionParameterNotKnown,
   RTI::FederateInternalError)
{
   std::cout << "Ambassador::receiveInteraction(): " << theInteraction << std::endl;
   NetIO* netIO = getNetIO();
   int idx = netIO->findInteractionClassIndex(theInteraction);
   if (idx != 0 && netIO->isInteractionClassSubscribed(idx)) {
      // It's an interaction that we subscribe to, so ...

      // just act as an interface to NetIO, which will handle this.
      getNetIO()->receiveInteraction(theInteraction, theParameters);
   }
}
Ejemplo n.º 4
0
void Ambassador::discoverObjectInstance (
   RTI::ObjectHandle          theObject,
   RTI::ObjectClassHandle     theObjectClass,
   const char *               theObjectName)
throw (
   RTI::CouldNotDiscover,
   RTI::ObjectClassNotKnown,
   RTI::FederateInternalError)
{
   std::cout << "Ambassador::discoverObjectInstance(): " << theObjectName << ", handle = " << theObject << std::endl;
   NetIO* netIO = getNetIO();
   int classIndex = netIO->findObjectClassIndex(theObjectClass);
   if (classIndex != 0 && netIO->isObjectClassSubscribed(classIndex)) {
      // It's an object class that we've subscribed to ...

      // just act as an interface to NetIO, which will handle this.
      getNetIO()->discoverObjectInstance(theObject, theObjectClass, theObjectName);
   }
}
Ejemplo n.º 5
0
//------------------------------------------------------------------------------
// setOutputPlayerType() -- sets the kind, country, ... variables
//------------------------------------------------------------------------------
bool Nib::setOutputPlayerType(const models::Player* const p)
{
   bool ok = false;

   if (getNetIO() != nullptr) {

      // Mark that we've been here.
      setEntityTypeChecked( true );

      // Find "by player" on the output list
      const Ntm* typeMapper = getNetIO()->findNetworkTypeMapper(p);

      // If we found a type mapper for this Player type,
      // then set the mapper and copy the unique type codes
      if (typeMapper != nullptr) {
         ok = typeMapper->copyEntityType(this);
         if (ok) setTypeMapper(typeMapper);
      }
   }

   return ok;
}
Ejemplo n.º 6
0
void Ambassador::turnInteractionsOff (
     RTI::InteractionClassHandle theInteraction)
   throw (
     RTI::InteractionClassNotPublished,
     RTI::FederateInternalError)
{
   std::cout << "Ambassador::turnInteractionsOff(): " ;
   NetIO* netIO = getNetIO();
   int idx = netIO->findInteractionClassIndex(theInteraction);
   if (idx != 0) {
      std::cout << idx;
      netIO->setInteractionEnabledFlag(idx,false);
   }
   std::cout << std::endl;
}
Ejemplo n.º 7
0
void Ambassador::stopRegistrationForObjectClass (
   RTI::ObjectClassHandle   theClass)
throw (
   RTI::ObjectClassNotPublished,
   RTI::FederateInternalError)
{
   //std::cout << "Ambassador::stopRegistrationForObjectClass(): ";
   NetIO* netIO = getNetIO();
   int classIndex = netIO->findObjectClassIndex(theClass);
   if (classIndex != 0 ) {
      //std::cout << classIndex;
      netIO->setObjectClassRegistrationFlag(classIndex,false);
   }
   //std::cout << std::endl;
}
Ejemplo n.º 8
0
void Ambassador::reflectAttributeValues (
        RTI::ObjectHandle                 theObject,
  const RTI::AttributeHandleValuePairSet& theAttrs,
  const char*                             theTag)
throw (
   RTI::ObjectNotKnown,
   RTI::AttributeNotKnown,
   RTI::FederateOwnsAttributes,
   RTI::FederateInternalError)
{
   //std::cout << "Ambassador::reflectAttributeValues(): object = " << theObject << ", theTag=" << theTag << std::endl;
   // find the input object
   NetIO* netIO = getNetIO();
   Nib* nib = static_cast<Nib*>( netIO->findNibByObjectHandle(theObject, NetIO::INPUT_NIB) );
   if (nib != nullptr) nib->reflectAttributeValues(theAttrs);
}
Ejemplo n.º 9
0
//------------------------------------------------------------------------------
// turnUpdatesOffForObjectInstance
//------------------------------------------------------------------------------
void Ambassador::turnUpdatesOffForObjectInstance (
        RTI::ObjectHandle        theObject,
  const RTI::AttributeHandleSet& theAttributes)
throw (
   RTI::ObjectNotKnown,
   RTI::AttributeNotOwned,
   RTI::FederateInternalError)
{
   //std::cout << "Ambassador:turnUpdatesOffForObjectInstance(): ";

   // Find the output object
   NetIO* netIO = getNetIO();
   Nib* nib = static_cast<Nib*>(netIO->findNibByObjectHandle(theObject, NetIO::OUTPUT_NIB));

   if (nib != 0) nib->turnUpdatesOff(theAttributes);
   //std::cout << std::endl;
}
Ejemplo n.º 10
0
void Ambassador::startRegistrationForObjectClass (
   RTI::ObjectClassHandle   theClass)
throw (
   RTI::ObjectClassNotPublished,
   RTI::FederateInternalError)
{
   //std::cout << "Ambassador::startRegistrationForObjectClass(): " ;
   NetIO* netIO = getNetIO();
   int classIndex = netIO->findObjectClassIndex(theClass);
   if (classIndex != 0 && netIO->isObjectClassPublished(classIndex)) {
      // It's an object class that we publish, so we can start to
      // register our objects ...
      //std::cout << classIndex;
      netIO->setObjectClassRegistrationFlag(classIndex,true);
   }
   //std::cout << std::endl;
}
Ejemplo n.º 11
0
void Ambassador::provideAttributeValueUpdate (
        RTI::ObjectHandle        theObject,
  const RTI::AttributeHandleSet& theAttrs)
throw (
   RTI::ObjectNotKnown,
   RTI::AttributeNotKnown,
   RTI::AttributeNotOwned,
   RTI::FederateInternalError)
{
   //std::cout << "Ambassador:provideAttributeValueUpdate(): ";
   // Find the output object
   NetIO* netIO = getNetIO();
   Nib* nib = static_cast<Nib*>( netIO->findNibByObjectHandle(theObject, NetIO::OUTPUT_NIB) );

   if (nib != nullptr) nib->provideAttributeValueUpdate(theAttrs);
   //std::cout << std::endl;
}
Ejemplo n.º 12
0
void Ambassador::turnInteractionsOn (
     RTI::InteractionClassHandle theInteraction)
   throw (
     RTI::InteractionClassNotPublished,
     RTI::FederateInternalError)
{
   std::cout << "Ambassador::turnInteractionsOn(): " ;
   NetIO* netIO = getNetIO();
   int idx = netIO->findInteractionClassIndex(theInteraction);
   if (idx != 0 && netIO->isInteractionClassPublished(idx)) {
      // It's an interaction that we publish, so we can start
      // send new interactions of this class ...
      std::cout << idx;
      netIO->setInteractionEnabledFlag(idx,true);
   }
   std::cout << std::endl;
}
Ejemplo n.º 13
0
void Ambassador::removeObjectInstance (
        RTI::ObjectHandle          theObject,
  const char*                      theTag)
throw (
   RTI::ObjectNotKnown,
   RTI::FederateInternalError)
{
   std::cout << "Ambassador::removeObjectInstance(): remove object = " << theObject << ", theTag=" << theTag << std::endl;

   // find the input object
   NetIO* netIO = getNetIO();
   Nib* nib = netIO->findNibByObjectHandle(theObject, NetIO::INPUT_NIB);
   if (nib != nullptr) {
      // set NIB delete request (Simulation::NetIO::cleanupInputList() should handle this)
      nib->setMode(simulation::Player::DELETE_REQUEST);
   }
}
Ejemplo n.º 14
0
//------------------------------------------------------------------------------
// updatePhysicalEntity() -- (Output support)
//    -- sets the PhysicalEntity attribute values that need to be updated
//
//    -- We send all published PhysicalEntity attributes every time.
//       The function isPlayerStateUpdateRequired() check if the player's state
//       needs to be re-sent.  Therefore, we're not checking the individual update
//       required flags with isAttributeUpdateRequired(), but we do clear them
//       with setAttributeUpdateRequiredFlag().
//
//   (Also handles the host to network byte swapping)
//------------------------------------------------------------------------------
void Nib::updatePhysicalEntity(
         RTI::AttributeHandleValuePairSet* attrs, 
         const double)
{
   // PhysicalEntity??
   PhysicalEntity* physicalEntity =  dynamic_cast<PhysicalEntity*>(baseEntity);
   if (physicalEntity != nullptr) {
      // Our handler 
      NetIO* netIO = static_cast<NetIO*>(getNetIO());

      // Force Identifier
      if (isAttributeUpdateEnabled(NetIO::FORCE_IDENTIFIER_AI)) {

         // Force ID: When mapping Player side to force IDs ...
         if (getSide() == simulation::Player::BLUE) {
            // blue's are friendly, ...
            physicalEntity->forceIdentifier = FRIENDLY;     
         }
         else if (getSide() == simulation::Player::RED) {
            // red's are not, ...
            physicalEntity->forceIdentifier = OPPOSING;
         }
         else if (getSide() == simulation::Player::WHITE) {
            // white is neutral, ...
            physicalEntity->forceIdentifier = NEUTRAL;
         }
         else {
            // and everyone else is type OTHER.
            physicalEntity->forceIdentifier = OTHER;
         }

         //std::cout << "Send force: " << physicalEntity->forceIdentifier << std::endl;;

         unsigned char netBuffer = static_cast<unsigned char>(physicalEntity->forceIdentifier);  // 8 bits enum type (ForceIdentifierEnum8)
         attrs->add(netIO->getObjectAttributeHandle(
               NetIO::FORCE_IDENTIFIER_AI),
               reinterpret_cast<char*>(&netBuffer),
               sizeof(netBuffer)
            );

         setAttributeUpdateRequiredFlag(NetIO::FORCE_IDENTIFIER_AI, false);
      }
   }
}
Ejemplo n.º 15
0
//------------------------------------------------------------------------------
// emitterBeamsManager()
//    -- (Output) Manages the emitter beam for this NIB(Player)
//------------------------------------------------------------------------------
bool Nib::emitterBeamsManager(const LCreal curExecTime)
{
   // ---
   // First, find all of our player's RfSensor systems and setup their handlers
   // ---
   if ( numEmissionSystems == 0 ) {

      // Check for the single-beam RADAR
      {
         // (DPG -- #### only a simple, single-beam Radar)
         const Basic::Pair * pair = getPlayer()->getSensorByType(typeid(Simulation::Radar));
         if (pair != nullptr) {
            Simulation::RfSensor* rs = (Simulation::RfSensor*) pair->object();

            // When we have a R/F sensor, create a handler for it
            EmissionPduHandler* handler = nullptr;

            // First, try to find an Emission PDU handler for this type system.
            // If we find one, then clone it for our use.
            NetIO* const disIO = static_cast<NetIO*>(getNetIO());
            const EmissionPduHandler* tmp = disIO->findEmissionPduHandler(rs);
            if (tmp != nullptr) {
               handler = tmp->clone();
            }

            // Handler wasn't found? Then just create a simple, default emission handler
            if (handler == nullptr) {
               handler = new EmissionPduHandler();
            }

            handler->setSensor( rs );
            handler->setEmitterIdNumber( numEmissionSystems + 1 );
            emitterSysHandler[numEmissionSystems] = handler;
            numEmissionSystems++;
         }
      } // end radar check

      // Check for a Jammer
      {
         const Basic::Pair * pair = getPlayer()->getSensorByType(typeid(Simulation::Jammer));
         if (pair != nullptr) {
            Simulation::RfSensor* js = (Simulation::RfSensor*) pair->object();

            bool singleBeam = true;
            Basic::PairStream* subcomponents = js->getComponents();
            if (subcomponents != nullptr) {

               // Check for multi-beam jammer (each beam is a subcomponent Jammer)
               Basic::List::Item* item = subcomponents->getFirstItem();
               while (item != nullptr && numEmissionSystems < MAX_EM_SYSTEMS) {

                  Basic::Pair* pair = static_cast<Basic::Pair*>( item->getValue() );
                  Simulation::Jammer* jam = dynamic_cast<Simulation::Jammer*>( pair->object() );
                  if (jam != nullptr) {
                     singleBeam = false;

                     // When we have a R/F sensor, create a handler for it
                     EmissionPduHandler* handler = nullptr;

                     // First, try to find an Emission PDU handler for this type system.
                     // If we find one, then clone it for our use.
                     NetIO* const disIO = static_cast<NetIO*>(getNetIO());
                     const EmissionPduHandler* tmp = disIO->findEmissionPduHandler(jam);
                     if (tmp != nullptr) {
                        handler = tmp->clone();
                     }

                     // Handler wasn't found? Then just create a simple, default handler
                     if (handler == nullptr) {
                        handler = new EmissionPduHandler();
                        handler->setEmitterFunction(EmissionPduHandler::ESF_JAMMING);
                     }

                     handler->setSensor( jam );
                     handler->setEmitterIdNumber( numEmissionSystems + 1 );
                     emitterSysHandler[numEmissionSystems] = handler;
                     numEmissionSystems++;

                  }
                  item = item->getNext();
               }

               subcomponents->unref();
               subcomponents = nullptr;
            }

            // Single beam jammer
            if (singleBeam && numEmissionSystems < MAX_EM_SYSTEMS) {

               // When we have a R/F sensor, create a handler for it
               EmissionPduHandler* handler = nullptr;

               // First, try to find an Emission PDU handler for this type system.
               // If we find one, then clone it for our use.
               NetIO* const disIO = static_cast<NetIO*>(getNetIO());
               const EmissionPduHandler* tmp = disIO->findEmissionPduHandler(js);
               if (tmp != nullptr) {
                  handler = tmp->clone();
               }

               // Handler wasn't found? Then just create a simple, default jammer handler
               if (handler == nullptr) {
                  handler = new EmissionPduHandler();
                  handler->setEmitterFunction(EmissionPduHandler::ESF_JAMMING);
               }

               handler->setSensor( js );
               handler->setEmitterIdNumber( numEmissionSystems + 1 );
               emitterSysHandler[numEmissionSystems] = handler;
               numEmissionSystems++;

            }

         }

      }  // end jammer check

   }  // end (numEmissionSystems == 0)

   // ---
   // Have the handlers check their electromagnetic emission systems
   // and generate the PDUs as needed.
   // ---
   for (emissionSystemsIndex = 0; emissionSystemsIndex < numEmissionSystems; emissionSystemsIndex++) {
      if (emitterSysHandler[emissionSystemsIndex] != nullptr) {
         emitterSysHandler[emissionSystemsIndex]->updateOutgoing(curExecTime, this);
      }
   }

   return true;
}
Ejemplo n.º 16
0
//------------------------------------------------------------------------------
// (Input) processElectromagneticEmissionPDU()
//------------------------------------------------------------------------------
bool Nib::processElectromagneticEmissionPDU(const ElectromagneticEmissionPDU* const pdu)
{
   bool ok = false;

   // ---
   // Loop through the Emission Systems in the PDU
   // ---
   for (unsigned char is = 0; is < pdu->numberOfSystems && is < MAX_EM_SYSTEMS; is++) {
      const EmissionSystem* es = pdu->getEmissionSystem(is);
      if (es != nullptr) {

         unsigned char idNum = es->emitterSystem.emitterIdentificationNumber;
         EmissionPduHandler* handler = nullptr;

         // ---
         // Does a handler for this system already exist in our list?
         // ---
         for (unsigned char i = 0; i < numEmissionSystems && handler == nullptr; i++) {
            if (idNum == emitterSysHandler[i]->getEmitterIdNumber()) {
               // Yes it does!
               handler = emitterSysHandler[i];
            }
         }

         // ---
         // Create a handler if one doesn't already exist
         // ---
         if (handler == nullptr && numEmissionSystems < MAX_EM_SYSTEMS) {

            // First, try to find an Emission PDU handler for this type system.
            // If we find one, then clone it for our use.
            NetIO* const disIO = static_cast<NetIO*>(getNetIO());
            const EmissionPduHandler* tmp = disIO->findEmissionPduHandler(es);
            if (tmp != nullptr) {
               handler = tmp->clone();
            }

            if (handler != nullptr) {
               // Handler found!
               handler->setEmitterIdNumber( idNum );
               handler->setEmitterFunction( es->emitterSystem.function );
               emitterSysHandler[numEmissionSystems] = handler;
               numEmissionSystems++;
            }
            else {
               // Handler wasn't found?
               std::cerr << "Dis::Nib::processElectromagneticEmissionPDU() warning: ";
               std::cerr << "EmissionPduHandler not found for emitterName: " << es->emitterSystem.emitterName;
               std::cerr << std::endl;
            }

         }

         // ---
         // Ok, pass the location of the EmissionSystem (and beam data) to the handler
         // ---
         if (handler != nullptr) {
            ok = handler->updateIncoming(pdu, es, this);
         }

      }
   } // End: for all systems

   return ok;
}
Ejemplo n.º 17
0
//------------------------------------------------------------------------------
// reflectAttributeValues() -- (Input support)
//  Called by our FederateAmbassador to update the attribute values for
//  this object instance.  (Also handles the network to host byte swapping)
//------------------------------------------------------------------------------
void Nib::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& theAttrs)
{
   NetIO* netIO = static_cast<NetIO*>(getNetIO());
   if (netIO != nullptr && baseEntity != nullptr) {

      // PhysicalEntity pointer
      PhysicalEntity* physicalEntity = dynamic_cast<PhysicalEntity*>(baseEntity);

      RTI::ULong length;
      char netBuffer[1000];
      for (RTI::ULong j = 0; j < theAttrs.size(); j++ ) {

         // get the attribute's handle and data (network byte order)
         RTI::AttributeHandle theAttr = theAttrs.getHandle(j);
         theAttrs.getValue(j, netBuffer, length);

         // Process the attribute
         switch ( netIO->findAttributeIndex(theAttr) ) {

            // Update Federate ID
            case NetIO::ENTITY_IDENTIFIER_AI : {
               EntityIdentifierStruct* net = reinterpret_cast<EntityIdentifierStruct*>(&netBuffer);

               base::NetHandler::fromNetOrder(&baseEntity->entityIdentifier.federateIdentifier.applicationID, net->federateIdentifier.applicationID );
               base::NetHandler::fromNetOrder(&baseEntity->entityIdentifier.federateIdentifier.siteID, net->federateIdentifier.siteID );
               base::NetHandler::fromNetOrder(&baseEntity->entityIdentifier.entityNumber, net->entityNumber );

               setAttributeUpdateRequiredFlag(NetIO::ENTITY_IDENTIFIER_AI, true);
            }
            break;

            // Update Entity Type
            case NetIO::ENTITY_TYPE_AI : {
               EntityTypeStruct* net = reinterpret_cast<EntityTypeStruct*>(&netBuffer);

               // All bytes except for country
               baseEntity->entityType = *net;
               base::NetHandler::fromNetOrder(&baseEntity->entityType.countryCode, net->countryCode );

               setAttributeUpdateRequiredFlag(NetIO::ENTITY_TYPE_AI, true);
            }
            break;

            // Update Spatial
            case NetIO::SPATIAL_AI : {

               // NIB's base entity structure pointers
               SpatialStruct* spatial = &(baseEntity->spatial);
               SpatialRVStruct* spatialRvw = &(baseEntity->spatialRvw);
               WorldLocationStruct* worldLocation = &spatialRvw->worldLocation;
               OrientationStruct* orientation = &spatialRvw->orientation;
               VelocityVectorStruct* velocityVector = &spatialRvw->velocityVector;
               AccelerationVectorStruct* accelerationVector = &spatialRvw->accelerationVector;
               AngularVelocityVectorStruct* angularVelocity = &spatialRvw->angularVelocity;

               // Net buffer component pointers 
               SpatialStruct* netSpatial = reinterpret_cast<SpatialStruct*>(&netBuffer[0]);
               WorldLocationStruct* netWorldLocation = nullptr;
               OrientationStruct* netOrientation = nullptr;
               VelocityVectorStruct* netVelocityVector = nullptr;
               AccelerationVectorStruct* netAccelerationVector = nullptr;
               AngularVelocityVectorStruct* netAngularVelocity = nullptr;

               // Dead reckoning 
               spatial->deadReckoningAlgorithm = netSpatial->deadReckoningAlgorithm;

               // find network components based on dead reckoning algorithm
               // (and set the isFrozen flag)
               switch (spatial->deadReckoningAlgorithm) {

                  case DRM_STATIC : {
                     SpatialStaticStruct* netSpatialStatic = reinterpret_cast<SpatialStaticStruct*>(&netBuffer[sizeof(SpatialStruct)]);
                     spatialRvw->isFrozen = netSpatialStatic->isFrozen;
                     netWorldLocation = &netSpatialStatic->worldLocation;
                     netOrientation = &netSpatialStatic->orientation;
                  }
                  break;

                  case DRM_FPW : {
                     SpatialFPStruct* netSpatialFpw = reinterpret_cast<SpatialFPStruct*>(&netBuffer[sizeof(SpatialStruct)]);
                     spatialRvw->isFrozen = netSpatialFpw->isFrozen;
                     netWorldLocation = &netSpatialFpw->worldLocation;
                     netOrientation = &netSpatialFpw->orientation;
                     netVelocityVector = &netSpatialFpw->velocityVector;
                  }
                  break;

                  case DRM_RPW : {
                     SpatialRPStruct* netSpatialRpw = reinterpret_cast<SpatialRPStruct*>(&netBuffer[sizeof(SpatialStruct)]);
                     spatialRvw->isFrozen = netSpatialRpw->isFrozen;
                     netWorldLocation = &netSpatialRpw->worldLocation;
                     netOrientation = &netSpatialRpw->orientation;
                     netVelocityVector = &netSpatialRpw->velocityVector;
                     netAngularVelocity = &netSpatialRpw->angularVelocity;
                  }
                  break;

                  case DRM_RVW : {
                     SpatialRVStruct* netSpatialRvw = reinterpret_cast<SpatialRVStruct*>(&netBuffer[sizeof(SpatialStruct)]);
                     spatialRvw->isFrozen = netSpatialRvw->isFrozen;
                     netWorldLocation = &netSpatialRvw->worldLocation;
                     netOrientation = &netSpatialRvw->orientation;
                     netVelocityVector = &netSpatialRvw->velocityVector;
                     netAccelerationVector = &netSpatialRvw->accelerationVector;
                     netAngularVelocity = &netSpatialRvw->angularVelocity;
                  }
                  break;

                  case DRM_FVW : {
                     SpatialFVStruct* netSpatialFvw = reinterpret_cast<SpatialFVStruct*>(&netBuffer[sizeof(SpatialStruct)]);
                     spatialRvw->isFrozen = netSpatialFvw->isFrozen;
                     netWorldLocation = &netSpatialFvw->worldLocation;
                     netOrientation = &netSpatialFvw->orientation;
                     netVelocityVector = &netSpatialFvw->velocityVector;
                     netAccelerationVector = &netSpatialFvw->accelerationVector;
                  }
                  break;
               }  // end dead rec switch

               if (netWorldLocation != nullptr) {
                  base::NetHandler::fromNetOrder(&worldLocation->x, netWorldLocation->x);
                  base::NetHandler::fromNetOrder(&worldLocation->y, netWorldLocation->y);
                  base::NetHandler::fromNetOrder(&worldLocation->z, netWorldLocation->z);
               }
               else {
                  worldLocation->x = 0;
                  worldLocation->y = 0;
                  worldLocation->z = 0;
               }

               if (netOrientation != nullptr) {
                  base::NetHandler::fromNetOrder(&orientation->phi, netOrientation->phi);
                  base::NetHandler::fromNetOrder(&orientation->theta, netOrientation->theta);
                  base::NetHandler::fromNetOrder(&orientation->psi, netOrientation->psi);
               }
               else {
                  orientation->phi = 0;
                  orientation->theta = 0;
                  orientation->psi = 0;
               }

               if (netVelocityVector != nullptr) {
                  base::NetHandler::fromNetOrder(&velocityVector->xVelocity, netVelocityVector->xVelocity);
                  base::NetHandler::fromNetOrder(&velocityVector->yVelocity, netVelocityVector->yVelocity);
                  base::NetHandler::fromNetOrder(&velocityVector->zVelocity, netVelocityVector->zVelocity);
               }
               else {
                  velocityVector->xVelocity = 0;
                  velocityVector->yVelocity = 0;
                  velocityVector->zVelocity = 0;
               }

               if (netAccelerationVector != nullptr) {
                  base::NetHandler::fromNetOrder(&accelerationVector->xAcceleration, netAccelerationVector->xAcceleration);
                  base::NetHandler::fromNetOrder(&accelerationVector->yAcceleration, netAccelerationVector->yAcceleration);
                  base::NetHandler::fromNetOrder(&accelerationVector->zAcceleration, netAccelerationVector->zAcceleration);
               }
               else {
                  accelerationVector->xAcceleration = 0;
                  accelerationVector->yAcceleration = 0;
                  accelerationVector->zAcceleration = 0;
               }

               if (netAngularVelocity != nullptr) {
                  base::NetHandler::fromNetOrder(&angularVelocity->xAngularVelocity, netAngularVelocity->xAngularVelocity);
                  base::NetHandler::fromNetOrder(&angularVelocity->yAngularVelocity, netAngularVelocity->yAngularVelocity);
                  base::NetHandler::fromNetOrder(&angularVelocity->zAngularVelocity, netAngularVelocity->zAngularVelocity);
               }
               else {
                  angularVelocity->xAngularVelocity = 0;
                  angularVelocity->yAngularVelocity = 0;
                  angularVelocity->zAngularVelocity = 0;
               }

               setAttributeUpdateRequiredFlag(NetIO::SPATIAL_AI, true);
            }
            break;

            case NetIO::FORCE_IDENTIFIER_AI : {
               unsigned char* net = reinterpret_cast<unsigned char*>(&netBuffer);
               physicalEntity->forceIdentifier = ForceIdentifierEnum8( *net );
               //std::cout << "Recv force: " << physicalEntity->forceIdentifier << std::endl;;
               setAttributeUpdateRequiredFlag(NetIO::FORCE_IDENTIFIER_AI, true);
            }
            break;

         } // end -- process attribute switch
      } // end -- for each attribute pair

      // Update the basic NIB state data with this new data
      entityState2Nib();
   }
}
Ejemplo n.º 18
0
//------------------------------------------------------------------------------
// updateBasicEntity() -- (Output support)
//    -- sets the BasicEntity attribute values that need to be updated
//
//    -- We send all published BasicEntity attributes every time.
//
//       The function isPlayerStateUpdateRequired() checking if the player's state
//       needs to be resent.  Therefore, we're not check the individual update
//       required flags with isAttributeUpdateRequired(), but we do clear them
//       with setAttributeUpdateRequiredFlag().
//
//   (Also handles the host to network byte swapping)
//------------------------------------------------------------------------------
void Nib::updateBasicEntity(
         RTI::AttributeHandleValuePairSet* attrs, 
         const double)
{
   if (baseEntity != nullptr) {
      // Our handler 
      NetIO* netIO = static_cast<NetIO*>(getNetIO());

      // Our simulation
      simulation::Simulation* ourSim = netIO->getSimulation();

      // Get the player data
      playerState2Nib();

      // Entity ID
      if (isAttributeUpdateEnabled(NetIO::ENTITY_IDENTIFIER_AI)) {
         EntityIdentifierStruct* entityId = &baseEntity->entityIdentifier;
         entityId->federateIdentifier.siteID = getSiteID();
         entityId->federateIdentifier.applicationID = getApplicationID();
         entityId->entityNumber = getPlayerID();
         //std::cout << "Send Federate ID: (" << entityId->entityNumber << "," << entityId->federateIdentifier.applicationID << "," << entityId->federateIdentifier.siteID << ")" << std::endl;

         EntityIdentifierStruct netBuffer;
         base::NetHandler::toNetOrder(&netBuffer.federateIdentifier.applicationID, entityId->federateIdentifier.applicationID );
         base::NetHandler::toNetOrder(&netBuffer.federateIdentifier.siteID, entityId->federateIdentifier.siteID );
         base::NetHandler::toNetOrder(&netBuffer.entityNumber, entityId->entityNumber );
         attrs->add(netIO->getObjectAttributeHandle(
               NetIO::ENTITY_IDENTIFIER_AI),
               reinterpret_cast<char*>(&netBuffer),
               sizeof(EntityIdentifierStruct)
            );

         setAttributeUpdateRequiredFlag(NetIO::ENTITY_IDENTIFIER_AI, false);
      }

      // Entity Type
      if (isAttributeUpdateEnabled(NetIO::ENTITY_TYPE_AI)) {

         EntityTypeStruct* entityType = &baseEntity->entityType;
         entityType->entityKind   = getEntityKind();
         entityType->domain       = getEntityDomain();
         entityType->countryCode  = getEntityCountry();
         entityType->category     = getEntityCategory();
         entityType->subcategory  = getEntitySubcategory();
         entityType->specific     = getEntitySpecific();
         entityType->extra        = getEntityExtra();

         // Network byte order: all bytes except country code which is unsigned short.
         EntityTypeStruct netBuffer = *entityType;
         base::NetHandler::toNetOrder(&netBuffer.countryCode, entityType->countryCode );
         attrs->add(netIO->getObjectAttributeHandle(
               NetIO::ENTITY_TYPE_AI),
               reinterpret_cast<char*>(&netBuffer),
               sizeof(EntityTypeStruct)
            );

         setAttributeUpdateRequiredFlag(NetIO::ENTITY_TYPE_AI, false);
      }

      // Spatial Structure
      if (isAttributeUpdateEnabled(NetIO::SPATIAL_AI)) {

         osg::Vec3d pos = getDrPosition();
         osg::Vec3d vel = getDrVelocity();
         osg::Vec3d accel = getDrAcceleration();
         osg::Vec3d angles = getDrEulerAngles();
         osg::Vec3d arates = getDrAngularVelocities();

         // NIB's base entity structures
         SpatialStruct* spatial = &(baseEntity->spatial);
         SpatialRVStruct* spatialRvw = &(baseEntity->spatialRvw);

         // Net order buffer (used to send the attribute to the RTI)
         const unsigned int SPATIAL_NET_BUFFER_SIZE = sizeof(SpatialStruct) + sizeof(SpatialRVStruct);
         unsigned char netBuffer[SPATIAL_NET_BUFFER_SIZE];

         SpatialStruct* netSpatial = reinterpret_cast<SpatialStruct*>(&netBuffer[0]);
         SpatialRVStruct* netSpatialRvw = reinterpret_cast<SpatialRVStruct*>(&netBuffer[sizeof(SpatialStruct)]);

         // Ref Position 
         double refLat = 0.0;
         double refLon = 0.0;
         if (ourSim != nullptr) {
            refLat = ourSim->getRefLatitude();
            refLon = ourSim->getRefLongitude();
         }

         // Convert position vector to Lat/Lon/Alt
         double alt = 0.0;
         double simCoord[3] = { 0.0, 0.0, 0.0 };
         base::Nav::convertPosVec2LL(
               refLat, refLon, 
               pos,
               &simCoord[base::Nav::ILAT], &simCoord[base::Nav::ILON], &alt
            );
         simCoord[base::Nav::IALT] = alt;

         //std::cout << "RprFom::Nib::entityState2Nib(): simCoord(" << simCoord[Basic::Nav::ILAT] << "," << simCoord[Basic::Nav::ILON] << "," << simCoord[Basic::Nav::IALT] << ")"  << std::endl;

         // Convert to geocentric coordinates
         double geocPos[3] = { 0.0, 0.0, 0.0 };
         double geocVel[3] = { 0.0, 0.0, 0.0 };
         double geocAcc[3] = { 0.0, 0.0, 0.0 };
         base::Nav::getWorldPosAccVel(simCoord, vel.ptr(), accel.ptr(), geocPos, geocVel, geocAcc);

         // Dead reckoning algorithm
         {
            spatial->deadReckoningAlgorithm = DRM_RVW;

            netSpatial->deadReckoningAlgorithm = spatial->deadReckoningAlgorithm;
         }

         // Is Frozen?
         {
            bool simFrz = false;
            if (ourSim != nullptr) simFrz = ourSim->isFrozen();
            if (isFrozen() || simFrz) spatialRvw->isFrozen = RTI::RTI_TRUE;  // Is this object or the simulation frozen?
            else spatialRvw->isFrozen = RTI::RTI_FALSE;

            netSpatialRvw->isFrozen = spatialRvw->isFrozen;
         }

         // World Location
         {
            WorldLocationStruct* worldLocation = &spatialRvw->worldLocation;
            WorldLocationStruct* netWorldLocation = &netSpatialRvw->worldLocation;

            worldLocation->x = geocPos[base::Nav::IX];
            worldLocation->y = geocPos[base::Nav::IY];
            worldLocation->z = geocPos[base::Nav::IZ];

            base::NetHandler::toNetOrder(&netWorldLocation->x, worldLocation->x);
            base::NetHandler::toNetOrder(&netWorldLocation->y, worldLocation->y);
            base::NetHandler::toNetOrder(&netWorldLocation->z, worldLocation->z);
         }

         // Velocity vector
         {
            VelocityVectorStruct* velocityVector = &spatialRvw->velocityVector;
            VelocityVectorStruct* netVelocityVector = &netSpatialRvw->velocityVector;

            velocityVector->xVelocity = static_cast<RTI::Float>(geocVel[base::Nav::IX]);
            velocityVector->yVelocity = static_cast<RTI::Float>(geocVel[base::Nav::IY]);
            velocityVector->zVelocity = static_cast<RTI::Float>(geocVel[base::Nav::IZ]);

            base::NetHandler::toNetOrder(&netVelocityVector->xVelocity, velocityVector->xVelocity);
            base::NetHandler::toNetOrder(&netVelocityVector->yVelocity, velocityVector->yVelocity);
            base::NetHandler::toNetOrder(&netVelocityVector->zVelocity, velocityVector->zVelocity);
         }

         // Acceleration vector
         {
            AccelerationVectorStruct* accelerationVector = &spatialRvw->accelerationVector;
            AccelerationVectorStruct* netAccelerationVector = &netSpatialRvw->accelerationVector;

            accelerationVector->xAcceleration = static_cast<RTI::Float>(geocAcc[base::Nav::IX]);
            accelerationVector->yAcceleration = static_cast<RTI::Float>(geocAcc[base::Nav::IY]);
            accelerationVector->zAcceleration = static_cast<RTI::Float>(geocAcc[base::Nav::IZ]);

            base::NetHandler::toNetOrder(&netAccelerationVector->xAcceleration, accelerationVector->xAcceleration);
            base::NetHandler::toNetOrder(&netAccelerationVector->yAcceleration, accelerationVector->yAcceleration);
            base::NetHandler::toNetOrder(&netAccelerationVector->zAcceleration, accelerationVector->zAcceleration);
         }

         // Orientation
         {
            OrientationStruct* orientation = &spatialRvw->orientation;
            OrientationStruct* netOrientation = &netSpatialRvw->orientation;

            // Convert Euler angles to geocentric angles
            double geocAngles[3] = { 0.0, 0.0, 0.0 };
            base::Nav::getGeocAngle(simCoord, angles.ptr(), geocAngles);

            orientation->phi   = static_cast<RTI::Float>(geocAngles[base::Nav::IPHI]);
            orientation->theta = static_cast<RTI::Float>(geocAngles[base::Nav::ITHETA]);
            orientation->psi   = static_cast<RTI::Float>(geocAngles[base::Nav::IPSI]);

            base::NetHandler::toNetOrder(&netOrientation->phi, orientation->phi);
            base::NetHandler::toNetOrder(&netOrientation->theta, orientation->theta);
            base::NetHandler::toNetOrder(&netOrientation->psi, orientation->psi);
         }

         // Angular velocity vector (all zeros for now)
         {
            AngularVelocityVectorStruct* angularVelocityVector = &spatialRvw->angularVelocity;
            AngularVelocityVectorStruct* netAngularVelocityVector = &netSpatialRvw->angularVelocity;

            angularVelocityVector->xAngularVelocity = 0;
            angularVelocityVector->yAngularVelocity = 0;
            angularVelocityVector->zAngularVelocity = 0;

            base::NetHandler::toNetOrder(&netAngularVelocityVector->xAngularVelocity, angularVelocityVector->xAngularVelocity);
            base::NetHandler::toNetOrder(&netAngularVelocityVector->yAngularVelocity, angularVelocityVector->yAngularVelocity);
            base::NetHandler::toNetOrder(&netAngularVelocityVector->zAngularVelocity, angularVelocityVector->zAngularVelocity);
         }

         attrs->add(
               netIO->getObjectAttributeHandle(NetIO::SPATIAL_AI),
               reinterpret_cast<char*>(&netBuffer),
               SPATIAL_NET_BUFFER_SIZE
            );

         setAttributeUpdateRequiredFlag(NetIO::SPATIAL_AI, false);
      }
   }
}
Ejemplo n.º 19
0
//------------------------------------------------------------------------------
// entityStateManager() --  (Output support)
//    -- Update the entity object for this NIB(Player)
//------------------------------------------------------------------------------
bool Nib::entityStateManager(const LCreal curExecTime)
{
   bool ok = false;

   // Get the player pointer
   const Simulation::Player* player = getPlayer();
   if (player == nullptr) return ok;

   // Dummy weapon?
   const Simulation::Weapon* ww = dynamic_cast<const Simulation::Weapon*>( player );
   if (ww != nullptr) {
      if (ww->isDummy()) return ok;
   }

   if (isPlayerStateUpdateRequired(curExecTime)) {

      //
      // Send an entity state PDU
      //   1) create buffer
      //   2) set state information
      //   3) send data
      //

      // Get our NetIO and the main simulation
      NetIO* disIO = static_cast<NetIO*>(getNetIO());
      Simulation::Simulation* sim = disIO->getSimulation();

      // Capture the player data, reset the dead reckoning and
      // mark the current time.
      playerState2Nib();

      // ---
      // Create buffer and cast it as an entity state PDU
      // ---
      char pduBuffer[NetIO::MAX_PDU_SIZE];
      EntityStatePDU* pdu = (EntityStatePDU*) &pduBuffer[0];

      //
      // Entity state PDU structure
      // =========================================================
      // PDUHeader            header;
      // EntityIdentifierDIS  entityID;
      // uint8_t              forceID;
      // uint8_t              numberOfArticulationParameters;
      // EntityType           entityType;
      // EntityType           alternativeType;
      // VectorDIS            entityLinearVelocity;
      // WorldCoordinates     entityLocation;
      // EulerAngles          entityOrientation;
      // uint32_t             appearance;
      // uint8_t              deadReckoningAlgorithm;
      // uint8_t              otherParameters[15];
      // VectorDIS            DRentityLinearAcceleration;
      // AngularVelocityVectorDIS DRentityAngularVelocity;
      // EntityMarking        entityMarking;
      // uint32_t             capabilities;
      // =========================================================
      //

      // ---
      // Standard header (PDUHeader)
      // ---
      pdu->header.protocolVersion = disIO->getVersion();
      pdu->header.exerciseIdentifier = disIO->getExerciseID();
      pdu->header.PDUType = NetIO::PDU_ENTITY_STATE;
      pdu->header.protocolFamily = NetIO::PDU_FAMILY_ENTITY_INFO;
      //
      if (disIO->getTimeline() == Simulation::NetIO::UTC)
         pdu->header.timeStamp = disIO->makeTimeStamp( getTimeUtc(), true );
      else
         pdu->header.timeStamp = disIO->makeTimeStamp( getTimeExec(), false );
      //
      pdu->header.status = 0;
      pdu->header.padding = 0;

      // ---
      // Entity ID (EntityIdentifierID)
      // ---
      pdu->entityID.simulationID.siteIdentification = getSiteID();
      pdu->entityID.simulationID.applicationIdentification = getApplicationID();
      pdu->entityID.ID = getPlayerID();

      // ---
      // Force ID: When mapping Player side to force IDs ...
      // ---
      if (getSide() == Simulation::Player::BLUE) {
         // blue's are friendly, ...
         pdu->forceID = NetIO::FRIENDLY_FORCE;
      }
      else if (getSide() == Simulation::Player::RED) {
         // red's are not, ...
         pdu->forceID = NetIO::OPPOSING_FORCE;
      }
      else if (getSide() == Simulation::Player::WHITE) {
         // white is neutral, ...
         pdu->forceID = NetIO::NEUTRAL_FORCE;
      }
      else {
         // and everyone else is type OTHER.
         pdu->forceID = NetIO::OTHER_FORCE;
      }

      // ---
      // Entity type (EntityType)
      // ---
      pdu->entityType.kind                 = getEntityKind();
      pdu->entityType.domain               = getEntityDomain();
      pdu->entityType.country              = getEntityCountry();
      pdu->entityType.category             = getEntityCategory();
      pdu->entityType.subcategory          = getEntitySubcategory();
      pdu->entityType.specific             = getEntitySpecific();
      pdu->entityType.extra                = getEntityExtra();
      // ---
      // Alternative type (EntityType)
      // ---
      pdu->alternativeType.kind            = getEntityKind();
      pdu->alternativeType.domain          = getEntityDomain();
      pdu->alternativeType.country         = getEntityCountry();
      pdu->alternativeType.category        = getEntityCategory();
      pdu->alternativeType.subcategory     = getEntitySubcategory();
      pdu->alternativeType.specific        = getEntitySpecific();
      pdu->alternativeType.extra           = getEntityExtra();

      // ---
      // Player position and orientation state data data
      // 1) All data is geocentric (ECEF)
      // 2) The playerState2Nib() function, which was called above, captures
      //    the state data and passed the state data to the dead reckoning
      //    system, and we're using this DR captured data.
      // ---
      {
         // ---
         // Entity linear velocity (VectorDIS)
         // ---
         osg::Vec3d geocVel = getDrVelocity();
         pdu->entityLinearVelocity.component[0] = static_cast<float>(geocVel[0]);
         pdu->entityLinearVelocity.component[1] = static_cast<float>(geocVel[1]);
         pdu->entityLinearVelocity.component[2] = static_cast<float>(geocVel[2]);

         // ---
         // Entity location (WorldCoordinates)
         // ---
         osg::Vec3d geocPos = getDrPosition();
         pdu->entityLocation.X_coord = geocPos[Basic::Nav::IX];
         pdu->entityLocation.Y_coord = geocPos[Basic::Nav::IY];
         pdu->entityLocation.Z_coord = geocPos[Basic::Nav::IZ];

         // ---
         // Entity orientation (EulerAngles)
         // ---
         osg::Vec3d geocAngles = getDrEulerAngles();
         pdu->entityOrientation.phi   = static_cast<float>(geocAngles[Basic::Nav::IPHI]);
         pdu->entityOrientation.theta = static_cast<float>(geocAngles[Basic::Nav::ITHETA]);
         pdu->entityOrientation.psi   = static_cast<float>(geocAngles[Basic::Nav::IPSI]);
      }

      // ---
      // Appearance bits generic to all domains (except munitions)
      // ---
      {
         pdu->appearance = 0x0;

         // ---
         // Frozen?
         // ---
         if ( isFrozen() || sim->isFrozen() ) {
            pdu->appearance |= FROZEN_BIT;
         }

         // Deactive this entity?
         {
            if (isMode(Simulation::Player::DELETE_REQUEST) || player->isDead() )
               pdu->appearance |= DEACTIVATE_BIT;
         }


         // Damage or health?  (Bits 3-4)
         {
            unsigned int bits = 0;
            if (getDamage() > 0.9f) bits = 3;       // Destroyed or Fatality
            else if (getDamage() > 0.5) bits = 2;   // Moderate
            else if (getDamage() > 0.0) bits = 1;   // Slight
            else bits = 0;                          // None
            pdu->appearance |= (bits << 3);
         }


         // Camouflage type
         // Note: air platform appearance bits 17 and 18 are not used, but we're using them the same as land platforms
         {
            unsigned int bits = getCamouflageType();
            if (bits > 0 && bits <= 4) {
               pdu->appearance |= CAMOUFLAGE_BIT;

               // Land based camouflage bits
               if (player->isMajorType(Simulation::Player::GROUND_VEHICLE)) {
                  // Subtract one to match DIS camouflage bits.
                  // Our camouflage type for DIS is the camouflage appearance bits
                  // plus one because our camouflage type of zero is no camouflage.
                  bits--;
                  pdu->appearance |= (bits << 17);
               }
            }
         }

         // Life forms appearance bits
         if (player->isMajorType(Simulation::Player::LIFE_FORM)) {
            const Simulation::LifeForm* lf = dynamic_cast<const Simulation::LifeForm*>(player);
            if (lf != nullptr) {
               // Health (aka damaged for other domains) same bits (3-4) - this is from the NIB, because it IS
               // updated
               // bits 5-8 compliance (not implemented)
               // bits 9 - 11 unused
               // bit 12 flashlight (not implemented)
               // bits 13-15 unused
               // bits 16 - 19 life form state
               // data is from the player, because NIB doesn't have actions associated with it
               {
                  unsigned int bits = 1;      // upright, standing still
                  if (lf->getActionState() == Simulation::LifeForm::UPRIGHT_STANDING) bits = 1;       // standing
                  else if (lf->getActionState() == Simulation::LifeForm::UPRIGHT_WALKING) bits = 2;   // walking
                  else if (lf->getActionState() == Simulation::LifeForm::UPRIGHT_RUNNING) bits = 3;   // running
                  else if (lf->getActionState() == Simulation::LifeForm::KNEELING) bits = 4;          // kneeling
                  else if (lf->getActionState() == Simulation::LifeForm::PRONE) bits = 5;             // prone
                  else if (lf->getActionState() == Simulation::LifeForm::CRAWLING) bits = 6;          // crawling
                  else if (lf->getActionState() == Simulation::LifeForm::SWIMMING) bits = 7;          // swimming
                  else if (lf->getActionState() == Simulation::LifeForm::PARACHUTING) bits = 8;       // parachuting
                  else if (lf->getActionState() == Simulation::LifeForm::JUMPING) bits = 9;           // jumping
                  else if (lf->getActionState() == Simulation::LifeForm::SITTING) bits = 10;          // sitting
                  else if (lf->getActionState() == Simulation::LifeForm::SQUATTING) bits = 11;        // squatting
                  else if (lf->getActionState() == Simulation::LifeForm::CROUCHING) bits = 12;        // crouching
                  else if (lf->getActionState() == Simulation::LifeForm::WADING) bits = 13;           // wading
                  else if (lf->getActionState() == Simulation::LifeForm::SURRENDER) bits = 14;        // surrender
                  else if (lf->getActionState() == Simulation::LifeForm::DETAINED) bits = 15;         // detained
                  else bits = 1;
                  pdu->appearance |= (bits << 16);
               }
               // bit 20 unused
               // bit 21 frozen status (taken care of above)
               // bits 24 - 25 weapon 1 (not implemented)
               // bits 26-27 weapon 2 (N/I)
               // bits 28-29
            }
         }

         // Common Non-life form appearance bits
         else {

            // Smoking?  (Bits 5-6) Standard (IST-CF-03-01, May 5, 2003)
            {
               unsigned int bits = 0;
               if (getSmoke() > 0.9f) bits = 3;
               else if (getSmoke() > 0.5) bits = 2;
               else if (getSmoke() > 0.0) bits = 1;
               else bits = 0;
               pdu->appearance |= (bits << 5);
            }

            // Flames? (Bit 15) Standard (IST-CF-03-01, May 5, 2003)
            {
               if (getFlames() > 0.5f)
                  pdu->appearance |= FLAMES_BIT;
            }

            // Power plant status bit (just leave ON for now)
            pdu->appearance |= POWER_PLANT_BIT;
         }


      }

      // ---
      // Dead reckoning algorithm
      // ---
      pdu->deadReckoningAlgorithm = static_cast<unsigned char>(getDeadReckoning());

      // ---
      // Other parameters
      // ---
      for (unsigned int i=0; i<15; i++) {
          pdu->otherParameters[i] = 0;
      }

      // ---
      // Dead reckoning information
      // ---
      {
         // ---
         // Dead reckoning linear acceleration (VectorDIS)
         // ---
         osg::Vec3d geocAcc = getDrAcceleration();
         pdu->DRentityLinearAcceleration.component[0] = static_cast<float>(geocAcc[0]);
         pdu->DRentityLinearAcceleration.component[1] = static_cast<float>(geocAcc[1]);
         pdu->DRentityLinearAcceleration.component[2] = static_cast<float>(geocAcc[2]);

         // ---
         // Dead reckoning angular velocity (AngularVelocityVectorDIS)
         // ---
         osg::Vec3d geocAngVel = getDrAngularVelocities();
         pdu->DRentityAngularVelocity.x_axis = static_cast<float>(geocAngVel[Basic::Nav::IX]);
         pdu->DRentityAngularVelocity.y_axis = static_cast<float>(geocAngVel[Basic::Nav::IY]);
         pdu->DRentityAngularVelocity.z_axis = static_cast<float>(geocAngVel[Basic::Nav::IZ]);
      }

      // ---
      // Entity marking (EntityMarking)
      // ---
      {
         const char* const pName = getPlayerName();
         size_t nameLen = std::strlen(pName);
         for (unsigned int i = 0; i < EntityMarking::BUFF_SIZE; i++) {
            if (i < nameLen) {
               pdu->entityMarking.marking[i] = pName[i];
            }
            else {
               pdu->entityMarking.marking[i] = '\0';
            }
         }
         pdu->entityMarking.characterSet = 1;
      }

      // ---
      // Capabilities
      // ---
      pdu->capabilites = 0x0;

      // ---
      // Articulation parameters
      // ---
      pdu->numberOfArticulationParameters = manageArticulationParameters(pdu);

      // Size of the PDU package
      unsigned short length = sizeof(EntityStatePDU) + (pdu->numberOfArticulationParameters * sizeof(VpArticulatedPart));
      pdu->header.length = length;

      if (Basic::NetHandler::isNotNetworkByteOrder()) pdu->swapBytes();
      ok = disIO->sendData( reinterpret_cast<char*>(pdu), length );
   }
   return ok;
}
//------------------------------------------------------------------------------
// munitionDetonationMsgFactory() -- (Output) Munition detonation message factory
//------------------------------------------------------------------------------
bool Nib::munitionDetonationMsgFactory(const LCreal)
{
   // Dummy weapon?
   const Simulation::Weapon* ww = dynamic_cast<const Simulation::Weapon*>( getPlayer() );
   if (ww != 0) {
      if (ww->isDummy()) return true;
   }

    bool ok = true;
    //std::cout << "NetIO::munitionDetonationMsgFactory() HERE!!" << std::endl;

    // Get our NetIO
    NetIO* disIO = (NetIO*)(getNetIO());

    // If our NIB's player just detonated, then it must be a weapon!
    Simulation::Weapon* mPlayer = dynamic_cast<Simulation::Weapon*>(getPlayer());
    if (mPlayer == 0) return false;

    // Ok, we have the weapon, now get the firing and target players
    Simulation::Player* tPlayer = mPlayer->getTargetPlayer();
    Simulation::Player* fPlayer = mPlayer->getLaunchVehicle();
    if (fPlayer == 0) return false;

    // ---
    // PDU header
    // ---
    DetonationPDU pdu;
    pdu.header.protocolVersion = disIO->getVersion();
    pdu.header.PDUType = NetIO::PDU_DETONATION;
    pdu.header.protocolFamily = NetIO::PDU_FAMILY_WARFARE;
    pdu.header.length = sizeof(DetonationPDU);
    pdu.header.exerciseIdentifier = disIO->getExerciseID();
    pdu.header.timeStamp = disIO->timeStamp();
    pdu.header.status = 0;
    pdu.header.padding = 0;

    // ---
    // Set the PDU data with the firing (launcher) player's id
    // ---
    pdu.firingEntityID.ID = fPlayer->getID();
    pdu.firingEntityID.simulationID.siteIdentification = getSiteID();
    pdu.firingEntityID.simulationID.applicationIdentification = getApplicationID();

    // ---
    // Set the PDU data with the munition's ID
    // ---
    pdu.munitionID.ID = mPlayer->getID();
    pdu.munitionID.simulationID.siteIdentification = getSiteID();
    pdu.munitionID.simulationID.applicationIdentification = getApplicationID();

    // ---
    // Set the PDU data with the target's ID
    // ---
    {
         bool tOk = false;
         if (tPlayer != 0) {
            pdu.targetEntityID.ID = tPlayer->getID();
            if (tPlayer->isLocalPlayer()) {
               // Local player, use our site/app/exerc IDs
               pdu.targetEntityID.simulationID.siteIdentification = getSiteID();
               pdu.targetEntityID.simulationID.applicationIdentification = getApplicationID();
               tOk = true;
            }
            else {
               // Networked player, use its NIB's IDs
               const Nib* fNIB = dynamic_cast<const Nib*>( tPlayer->getNib() );
               if (fNIB != 0) {
                  pdu.targetEntityID.simulationID.siteIdentification = fNIB->getSiteID();
                  pdu.targetEntityID.simulationID.applicationIdentification = fNIB->getApplicationID();
                  tOk = true;
               }
            }
         }
         if (!tOk) {
            pdu.targetEntityID.ID = 0;
            pdu.targetEntityID.simulationID.siteIdentification = 0;
            pdu.targetEntityID.simulationID.applicationIdentification = 0;
         }
    }

    // ---
    // Event ID
    // ---
    pdu.eventID.simulationID.siteIdentification = getSiteID();
    pdu.eventID.simulationID.applicationIdentification = getApplicationID();
    pdu.eventID.eventNumber = mPlayer->getReleaseEventID();

    // ---
    // Location & Velocity
    // ---

    // World Coordinates
    osg::Vec3d geocPos = mPlayer->getGeocPosition();
    pdu.location.X_coord = geocPos[Basic::Nav::IX];
    pdu.location.Y_coord = geocPos[Basic::Nav::IY];
    pdu.location.Z_coord = geocPos[Basic::Nav::IZ];

    // Velocity
    osg::Vec3d geocVel = mPlayer->getGeocVelocity();
    pdu.velocity.component[0] = (float)geocVel[Basic::Nav::IX];
    pdu.velocity.component[1] = (float)geocVel[Basic::Nav::IY];
    pdu.velocity.component[2] = (float)geocVel[Basic::Nav::IZ];

    // ---
    // Burst
    // ---
    pdu.burst.munition.kind         = getEntityKind();
    pdu.burst.munition.domain       = getEntityDomain();
    pdu.burst.munition.country      = getEntityCountry();
    pdu.burst.munition.category     = getEntityCategory();
    pdu.burst.munition.subcategory  = getEntitySubcategory();
    pdu.burst.munition.specific     = getEntitySpecific();
    pdu.burst.munition.extra        = getEntityExtra();
    pdu.burst.warhead = 0;
    pdu.burst.fuse = 0;;
    pdu.burst.quantity = 1;
    pdu.burst.rate = 0;

    // ---
    // Location
    // ---
    osg::Vec3 lpos = mPlayer->getDetonationLocation();
    pdu.locationInEntityCoordinates.component[0] = (float) lpos[0];
    pdu.locationInEntityCoordinates.component[1] = (float) lpos[1];
    pdu.locationInEntityCoordinates.component[2] = (float) lpos[2];

    // ---
    // Results
    // ---
    pdu.detonationResult = (unsigned char)( mPlayer->getDetonationResults() );
    pdu.numberOfArticulationParameters = 0;

    //std::cout << "NetIO::munitionDetonationMsgFactory() results: " << int(pdu.detonationResult) << std::endl;
    //pdu.dumpData();

    // ---
    // Send the PDU
    // ---
    if (Basic::NetHandler::isNotNetworkByteOrder()) pdu.swapBytes();
    ok = disIO->sendData((char*)&pdu,sizeof(pdu));

    // Set the detonation message sent flag so that we don't do this again.
    setDetonationMessageSent(true);

    return ok;
}
Ejemplo n.º 21
0
//------------------------------------------------------------------------------
// entityState2Nib() -- (Input support)
//  Transfers data from the incoming entity attributes to the basic
//  NIB class variables.
//------------------------------------------------------------------------------
void Nib::entityState2Nib()
{    
   if (isAttributeUpdateRequired(NetIO::ENTITY_IDENTIFIER_AI)) {
      setPlayerID(baseEntity->entityIdentifier.entityNumber);
      setSiteID(baseEntity->entityIdentifier.federateIdentifier.siteID);
      setApplicationID(baseEntity->entityIdentifier.federateIdentifier.applicationID);
      setAttributeUpdateRequiredFlag(NetIO::ENTITY_IDENTIFIER_AI, false);
      haveEntityIdFlg = true;
   }

   if (isAttributeUpdateRequired(NetIO::ENTITY_TYPE_AI)) {
      setEntityType(
            baseEntity->entityType.entityKind,
            baseEntity->entityType.domain,
            baseEntity->entityType.countryCode,
            baseEntity->entityType.category,
            baseEntity->entityType.subcategory,
            baseEntity->entityType.specific,
            baseEntity->entityType.extra
         );
      setAttributeUpdateRequiredFlag(NetIO::ENTITY_TYPE_AI, false);
      haveEntityTypeFlg = true;
   }

   if (isAttributeUpdateRequired(NetIO::SPATIAL_AI)) {

      // NIB's base entity structures
      //SpatialStruct* spatial = &(baseEntity->spatial);
      SpatialRVStruct* spatialRvw = &(baseEntity->spatialRvw);

      // Set the freeze flag
      freeze(spatialRvw->isFrozen != 0);

      // Get the geocentric position, velocity and acceleration
      osg::Vec3d geocPos;
      geocPos[base::Nav::IX] = spatialRvw->worldLocation.x;
      geocPos[base::Nav::IY] = spatialRvw->worldLocation.y;
      geocPos[base::Nav::IZ] = spatialRvw->worldLocation.z;

      osg::Vec3d geocVel;
      geocVel[base::Nav::IX] = spatialRvw->velocityVector.xVelocity;
      geocVel[base::Nav::IY] = spatialRvw->velocityVector.yVelocity;
      geocVel[base::Nav::IZ] = spatialRvw->velocityVector.zVelocity;

      osg::Vec3d geocAcc;
      geocAcc[base::Nav::IX] = spatialRvw->accelerationVector.xAcceleration;
      geocAcc[base::Nav::IY] = spatialRvw->accelerationVector.yAcceleration;
      geocAcc[base::Nav::IZ] = spatialRvw->accelerationVector.zAcceleration;

      // Get orientation orientation and rates
      osg::Vec3d geocAngles;
      geocAngles[base::Nav::IPHI] = spatialRvw->orientation.phi;
      geocAngles[base::Nav::ITHETA] = spatialRvw->orientation.theta;
      geocAngles[base::Nav::IPSI] = spatialRvw->orientation.psi; 

      osg::Vec3d arates(0.0, 0.0, 0.0);

      // (re)initialize the dead reckoning function
      double diffTime(0.0);
      resetDeadReckoning(
         RVW_DRM,
         geocPos,
         geocVel,
         geocAcc,
         geocAngles,
         arates,
         diffTime);

      haveWorldLocationFlg = true;
      haveOrientationFlg = true;

      setAttributeUpdateRequiredFlag(NetIO::SPATIAL_AI, false);
   }
    
   // PhysicalEntity pointer
   PhysicalEntity* physicalEntity = dynamic_cast<PhysicalEntity*>(baseEntity);
   if (physicalEntity != nullptr) {

      if (isAttributeUpdateRequired(NetIO::FORCE_IDENTIFIER_AI)) {
         // Side: When mapping Force ID to Player Side ...
         if (physicalEntity->forceIdentifier == FRIENDLY) {
            // Friendly's are blue, ...
            setSide(simulation::Player::BLUE);
         }
         else if (physicalEntity->forceIdentifier == OPPOSING) {
            // opposing side is red, ...
            setSide(simulation::Player::RED);
         }
         else if (physicalEntity->forceIdentifier == NEUTRAL) {
            // Neutrals are white, ...
            setSide(simulation::Player::WHITE);
         }
         else  {
            // and everyone else is gray.
            setSide(simulation::Player::GRAY);
         }
         setAttributeUpdateRequiredFlag(NetIO::FORCE_IDENTIFIER_AI, false);
      }

   }

   setMode(simulation::Player::ACTIVE);    
   setTimeExec( (double) getNetIO()->getCurrentTime() );
}
Ejemplo n.º 22
0
//------------------------------------------------------------------------------
// weaponFireMsgFactory() -- (Output support) Weapon fire message factory
//------------------------------------------------------------------------------
bool Nib::weaponFireMsgFactory(const LCreal)
{
    bool ok = true;
    //std::cout << "NetIO::weaponFireMsgFactory() HERE!!" << std::endl;

    // Get our NetIO
    NetIO* disIO = (NetIO*)(getNetIO());
    //Simulation* sim = disIO->getSimulation();

    // Set the NIB mode so that we don't do this again.
    setMode(Simulation::Player::ACTIVE);
    
    // Our NIB's player is a weapon that just became active
    Simulation::Weapon* mPlayer = (Simulation::Weapon*)(getPlayer());

    // Ok, we have the weapon, now get the firing and target players
    Simulation::Player* tPlayer = mPlayer->getTargetPlayer();
    Simulation::Player* fPlayer = mPlayer->getLaunchVehicle();
    if (fPlayer == 0) return false;

    // ---
    // PDU header 
    // ---
    FirePDU pdu;
    pdu.header.protocolVersion = disIO->getVersion();
    pdu.header.exerciseIdentifier = disIO->getExerciseID();
    pdu.header.PDUType = NetIO::PDU_FIRE;
    pdu.header.protocolFamily = NetIO::PDU_FAMILY_WARFARE;
    pdu.header.timeStamp = disIO->timeStamp();
    pdu.header.length = sizeof(FirePDU);
    
    // ---
    // Set the PDU data with the firing (launcher) player's id
    // ---
    pdu.firingEntityID.ID = fPlayer->getID();
    pdu.firingEntityID.simulationID.siteIdentification = disIO->getSiteID();
    pdu.firingEntityID.simulationID.applicationIdentification = disIO->getApplicationID();
    
    // ---
    // Set the PDU data with the munition's ID
    // ---
    pdu.munitionID.ID = mPlayer->getID();
    pdu.munitionID.simulationID.siteIdentification = disIO->getSiteID();
    pdu.munitionID.simulationID.applicationIdentification = disIO->getApplicationID();
    
    // ---
    // Set the PDU data with the target's ID
    // ---
    {
      bool tOk = false;
      if (tPlayer != 0) {
         pdu.targetEntityID.ID = tPlayer->getID();
         if (tPlayer->isLocalPlayer()) {
            // Local player, use our site/app/exerc IDs
            pdu.targetEntityID.simulationID.siteIdentification = disIO->getSiteID();
            pdu.targetEntityID.simulationID.applicationIdentification = disIO->getApplicationID();
            tOk = true;
         }
         else {
            const Nib* fNIB = dynamic_cast<const Nib*>( tPlayer->getNib() );
            if (fNIB != 0) {
               // Networked player, use it's NIB's IDs
               pdu.targetEntityID.simulationID.siteIdentification = fNIB->getSiteID();
               pdu.targetEntityID.simulationID.applicationIdentification = fNIB->getApplicationID();
               tOk = true;
            }
         }
      }
      if (!tOk) {
         // Networked player, use it's NIB's IDs
         pdu.targetEntityID.ID = 0;
         pdu.targetEntityID.simulationID.siteIdentification = 0;
         pdu.targetEntityID.simulationID.applicationIdentification = 0;
      }
    }
    
    // ---
    // Event ID
    // ---
    pdu.eventID.simulationID.siteIdentification = disIO->getSiteID();
    pdu.eventID.simulationID.applicationIdentification = disIO->getApplicationID();
    pdu.eventID.eventNumber = mPlayer->getReleaseEventID();

    // ---
    // Location & Velociy
    // ---

    // World Coordinates
    osg::Vec3d geocPos = mPlayer->getGeocPosition();
    pdu.location.X_coord = geocPos[Basic::Nav::IX];
    pdu.location.Y_coord = geocPos[Basic::Nav::IY];
    pdu.location.Z_coord = geocPos[Basic::Nav::IZ];

    // Velocity
    osg::Vec3d geocVel = mPlayer->getGeocVelocity();
    pdu.velocity.component[0] = (float)geocVel[Basic::Nav::IX];
    pdu.velocity.component[1] = (float)geocVel[Basic::Nav::IY];
    pdu.velocity.component[2] = (float)geocVel[Basic::Nav::IZ];

    // ---
    // Burst
    // ---
    pdu.burst.munision.kind         = getEntityKind();
    pdu.burst.munision.domain       = getEntityDomain();
    pdu.burst.munision.country      = getEntityCountry();
    pdu.burst.munision.category     = getEntityCategory();
    pdu.burst.munision.subcategory  = getEntitySubcategory();
    pdu.burst.munision.specific     = getEntitySpecific();
    pdu.burst.munision.extra        = getEntityExtra();
    pdu.burst.warhead = 0;
    pdu.burst.fuse = 0;;
    pdu.burst.quantity = 1;
    pdu.burst.rate = 0;

    // ---
    // Range and fire index
    // ---
    pdu.fireMissionIndex = 0;
    pdu.range = 0.0;

    //pdu.dumpData();
    //std::cout << "NetIO::weaponFireMsgFactory() fired:";
    //std::cout << "(" << pdu.firingEntityID.ID;
    //std::cout << "," << pdu.firingEntityID.simulationID.applicationIdentification ;
    //std::cout << "," << pdu.firingEntityID.simulationID.siteIdentification;
    //std::cout << ")   munision:";
    //std::cout << "(" << pdu.munitionID.ID;
    //std::cout << "," << pdu.munitionID.simulationID.applicationIdentification ;
    //std::cout << "," << pdu.munitionID.simulationID.siteIdentification;
    //std::cout << ")" << std::endl;

    if (Basic::NetHandler::isNotNetworkByteOrder()) pdu.swapBytes();
    ok = disIO->sendData((char*)&pdu,sizeof(pdu));

    return ok;
}    
Ejemplo n.º 23
0
//------------------------------------------------------------------------------
// Manage the articulated parameters and attached parts
//------------------------------------------------------------------------------
unsigned char Nib::manageArticulationParameters(EntityStatePDU* const pdu)
{
   unsigned char cnt = 0;
   NetIO* const disIO = static_cast<NetIO*>(getNetIO());

   // First articulation parameter is just after the main PDU
   unsigned char *p = (reinterpret_cast<unsigned char *>(pdu)) + sizeof(*pdu);
   VpArticulatedPart* ap = reinterpret_cast<VpArticulatedPart*>(p);

   // ---
   // Air Vehicle articulated parts and attachments
   // ---
   if ( getPlayer()->isMajorType(Simulation::Player::AIR_VEHICLE) ) {

      // Check wing sweep angle.
      if (getAPartWingSweepCnt() > 0) {
         // fill the articulation parameter structure
         ap->parameterTypeDesignator = VpArticulatedPart::ARTICULATED_PART;
         ap->changeIndicator = static_cast<unsigned char>(getAPartWingSweepCnt() & 0xff);
         ap->id = 0;
         ap->parameterType = (VpArticulatedPart::WING_SWEEP + VpArticulatedPart::AZIMUTH);
         ap->parameterValue.value[0] = static_cast<float>(getAPartWingSweep());  // radians
         ap->parameterValue.value[1] = 0;
         // Update part count & pointer
         cnt++;
         ap++;
      }

      // Check landing gear position.
      if (getAPartGearPosCnt() > 0) {
         // fill the articulation parameter structure
         ap->parameterTypeDesignator = VpArticulatedPart::ARTICULATED_PART;
         ap->changeIndicator = static_cast<unsigned char>(getAPartGearPosCnt() & 0xff);
         ap->id = 0;
         ap->parameterType = (VpArticulatedPart::LANDING_GEAR + VpArticulatedPart::POSITION);
         ap->parameterValue.value[0] = static_cast<float>(getAPartPartGearPos())/100.0f;
         ap->parameterValue.value[1] = 0;
         // Update part count & pointer
         cnt++;
         ap++;
      }

      // Check weapon bay door position (send out both doors)
      if (getAPartBayDoorCnt() > 0) {

         // Left door
         ap->parameterTypeDesignator = VpArticulatedPart::ARTICULATED_PART;
         ap->changeIndicator = static_cast<unsigned char>(getAPartBayDoorCnt() & 0xff);
         ap->id = 0;
         ap->parameterType = (VpArticulatedPart::LEFT_WEAPON_BAY_DOOR + VpArticulatedPart::POSITION);
         ap->parameterValue.value[0] = static_cast<float>(getAPartBayDoorPos())/100.0f;
         ap->parameterValue.value[1] = 0;

         // Update part count & pointer
         cnt++;
         ap++;

         // Right door
         ap->parameterTypeDesignator = VpArticulatedPart::ARTICULATED_PART;
         ap->changeIndicator = static_cast<unsigned char>(getAPartBayDoorCnt() & 0xff);
         ap->id = 0;
         ap->parameterType = (VpArticulatedPart::RIGHT_WEAPON_BAY_DOOR + VpArticulatedPart::POSITION);
         ap->parameterValue.value[0] = static_cast<float>(getAPartBayDoorPos())/100.0f;
         ap->parameterValue.value[1] = 0;

         // Update part count & pointer
         cnt++;
         ap++;

      }

   }

   // ---
   // Ground Vehicle articulated parts and attachments
   // ---
   else if ( getPlayer()->isMajorType(Simulation::Player::GROUND_VEHICLE) ) {

      // Check launcher elevation angle
      if (getAPartLauncherElevationCnt() > 0) {
         // fill the articulation parameter structure
         ap->parameterTypeDesignator = VpArticulatedPart::ARTICULATED_PART;
         ap->changeIndicator = static_cast<unsigned char>(getAPartLauncherElevationCnt() & 0xff);
         ap->id = 0;
         ap->parameterType = (VpArticulatedPart::PRIMARY_LAUNCHER_1 + VpArticulatedPart::ELEVATION);
         ap->parameterValue.value[0] = static_cast<float>( getAPartLauncherElevation() );
         ap->parameterValue.value[1] = 0;
         // Update part count & pointer
         cnt++;
         ap++;
      }

      // Check attached missiles
      unsigned int n = getAPartNumberAttachedNumMissiles();
      for (unsigned int i = 0; i < n; i++) {

         const Simulation::Missile* msl = getAPartAttachedMissile(i+1);

         // Find the missile's entity type
         if (apartMslTypes[i] == nullptr) {

            const Ntm* ntm = dynamic_cast<const Ntm*>( disIO->findNetworkTypeMapper(msl) );
            if (ntm != nullptr) {

               // found the NTM for the missile -- and it must be a DIS NTM
               apartMslTypes[i] = dynamic_cast<const Ntm*>(ntm);
               if (apartMslTypes[i] != nullptr) apartMslTypes[i]->ref();
            }

         }

         // We must have the missile's entity type to send the attached part ...
         if (apartMslTypes[i] != nullptr) {

            // fill the articulation parameter structure
            ap->parameterTypeDesignator = VpArticulatedPart::ATTACHED_PART;
            ap->changeIndicator = static_cast<unsigned char>(getAPartAttacheMissileChangeCnt(i+1) & 0xff);
            ap->id = 1;                   // ATTACHED to LAUNCHER (above)
            ap->parameterType = (i+1);    // Station number
            if (msl->isMode(Simulation::Player::LAUNCHED)) {
               ap->parameterValue.entityType.kind = 0;
               ap->parameterValue.entityType.domain = 0;
               ap->parameterValue.entityType.country = 0;
               ap->parameterValue.entityType.category = 0;
               ap->parameterValue.entityType.subcategory = 0;
               ap->parameterValue.entityType.specific = 0;
               ap->parameterValue.entityType.extra = 0;
            }
            else {
               ap->parameterValue.entityType.kind = apartMslTypes[i]->getEntityKind();
               ap->parameterValue.entityType.domain = apartMslTypes[i]->getEntityDomain();
               ap->parameterValue.entityType.country = apartMslTypes[i]->getEntityCountry();
               ap->parameterValue.entityType.category = apartMslTypes[i]->getEntityCategory();
               ap->parameterValue.entityType.subcategory = apartMslTypes[i]->getEntitySubcategory();
               ap->parameterValue.entityType.specific = apartMslTypes[i]->getEntitySpecific();
               ap->parameterValue.entityType.extra = apartMslTypes[i]->getEntityExtra();
            }

            // Update part count & pointer
            cnt++;
            ap++;
         }
      }
   }

   return cnt;
}
Ejemplo n.º 24
0
//------------------------------------------------------------------------------
// IffManager() -- (Output support) IFF manager
//------------------------------------------------------------------------------
bool Nib::IffManager(const double curExecTime)
{
   NetIO* disIO = static_cast<NetIO*>(getNetIO());
   const base::Pair* pair = getPlayer()->getRadioByType(typeid(models::Iff));

   // OK if the player has an IFF transponder and we're the correct version.
   bool ok = (disIO->getVersion() >= NetIO::VERSION_1278_1A) && (pair != nullptr);

   if (ok) {
      const models::Iff* iffSystem = static_cast<const models::Iff*>(pair->object());

      if (isIffUpdateRequired(curExecTime, iffSystem)) {


         // Standard header stuff
         IffAtcNavaidsPDU pdu;
         pdu.header.protocolVersion = disIO->getVersion();
         pdu.header.exerciseIdentifier = disIO->getExerciseID();
         pdu.header.PDUType = NetIO::PDU_IFF_ATC_NAVAIDS;
         pdu.header.protocolFamily = NetIO::PDU_FAMILY_DIS_EMISSION_REG;
         pdu.header.timeStamp = disIO->timeStamp();
         pdu.header.length = sizeof(IffAtcNavaidsPDU);

         // Entity ID
         pdu.emittingEntityID.simulationID.siteIdentification = getSiteID();
         pdu.emittingEntityID.simulationID.applicationIdentification = getApplicationID();
         pdu.emittingEntityID.ID = getPlayerID();

         // Location (default is center of parent entity)
         pdu.location.component[0] = 0;
         pdu.location.component[1] = 0;
         pdu.location.component[2] = 0;

         // System ID (for now just use a standard Mark X11; upgrade to type from IFF later)
         pdu.systemID.systemType = 1;        // Mark X11
         pdu.systemID.systemName = 2;        // Mark X11
         pdu.systemID.systemMode = 0;        // Other
         pdu.systemID.options = iffOptions;  // Option bits

         // Functional operational data
         pdu.operationalData.systemStatus = iffFunOpData->systemStatus;
         pdu.operationalData.alternateParam4 = iffFunOpData->alternateParam4;
         pdu.operationalData.informationLayers = iffFunOpData->informationLayers;
         pdu.operationalData.modifier = iffFunOpData->modifier;
         pdu.operationalData.param1 = iffFunOpData->param1;
         pdu.operationalData.param2 = iffFunOpData->param2;
         pdu.operationalData.param3 = iffFunOpData->param3;
         pdu.operationalData.param4 = iffFunOpData->param4;
         pdu.operationalData.param5 = iffFunOpData->param5;
         pdu.operationalData.param6 = iffFunOpData->param6;

         // Event ID
         pdu.eventID.simulationID.siteIdentification = disIO->getSiteID();
         pdu.eventID.simulationID.applicationIdentification = disIO->getApplicationID();
         pdu.eventID.eventNumber = disIO->getNewIffEventID();

         //pdu.dumpData();
         if (base::NetHandler::isNotNetworkByteOrder()) pdu.swapBytes();
         ok = disIO->sendData(reinterpret_cast<char*>(&pdu), sizeof(pdu));

         iffLastExecTime = curExecTime;

      }

   }

   return ok;
}
//------------------------------------------------------------------------------
// munitionDetonationMsgFactory() -- (Output) Munition detonation message factory
//------------------------------------------------------------------------------
bool Nib::munitionDetonationMsgFactory(const double)
{
   std::cout << "rprfom::Nib::sendMunitionDetonation() HERE!!" << std::endl;

   // Early out -- we must be registered
   if (!isRegistered()) return false;

   NetIO* netIO = static_cast<NetIO*>(getNetIO());

   // Create the parameter/value set
   RTI::ParameterHandleValuePairSet* pParams =
      RTI::ParameterSetFactory::create( NetIO::NUM_INTERACTION_PARAMETER );

   // Set our mode so that we don't do this again.
   setMode(simulation::Player::DETONATED);

   // If our player just detonated, then it must be a weapon!
   simulation::Weapon* mPlayer = dynamic_cast<simulation::Weapon*>(getPlayer());
   if (mPlayer == nullptr) return false;   // Early out -- it wasn't a weapon

   // ---
   // Event ID
   // ---
   unsigned short fireEvent = getWeaponFireEvent();
   EventIdentifierStruct eventIdentifier;
   base::NetHandler::toNetOrder(&eventIdentifier.eventCount, fireEvent);
   base::utStrncpy(
      reinterpret_cast<char*>(&eventIdentifier.issuingObjectIdentifier.id[0]),
      sizeof(eventIdentifier.issuingObjectIdentifier.id),
      getObjectName(),
      RTIObjectIdStruct::ID_SIZE );    
   pParams->add(
      netIO->getInteractionParameterHandle(NetIO::EVENT_IDENTIFIER_MD_PI),
      reinterpret_cast<char*>(&eventIdentifier),
      sizeof(EventIdentifierStruct) );

   // ---
   // Location & Velocity
   // ---
   {
      osg::Vec3d geocPos = getDrPosition();
      osg::Vec3d geocVel = getDrVelocity();
      osg::Vec3d geocAcc = getDrAcceleration();

      // World Coordinates
      WorldLocationStruct detonationLocation;
      base::NetHandler::toNetOrder(&detonationLocation.x, geocPos[base::Nav::IX]);
      base::NetHandler::toNetOrder(&detonationLocation.y, geocPos[base::Nav::IY]);
      base::NetHandler::toNetOrder(&detonationLocation.z, geocPos[base::Nav::IZ]);
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::DETONATION_LOCATION_MD_PI), 
         reinterpret_cast<char*>(&detonationLocation), 
         sizeof(WorldLocationStruct) );

      // Velocity
      VelocityVectorStruct finalVelocityVector; 
      base::NetHandler::toNetOrder(&finalVelocityVector.xVelocity, static_cast<float>(geocVel[base::Nav::IX]));
      base::NetHandler::toNetOrder(&finalVelocityVector.yVelocity, static_cast<float>(geocVel[base::Nav::IY]));
      base::NetHandler::toNetOrder(&finalVelocityVector.zVelocity, static_cast<float>(geocVel[base::Nav::IZ]));
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::FINAL_VELOCITY_VECTOR_MD_PI), 
         reinterpret_cast<char*>(&finalVelocityVector), 
         sizeof(VelocityVectorStruct) );
   }

   // ---
   // Munition Object identifiers:
   // ---
   {
      RTIObjectIdStruct munitionObjectIdentifier;
      base::utStrncpy(
         reinterpret_cast<char*>(&munitionObjectIdentifier.id[0]),
         sizeof(munitionObjectIdentifier.id),
         getObjectName(),
         RTIObjectIdStruct::ID_SIZE );    
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::MUNITION_OBJECT_IDENTIFIER_MD_PI),
         reinterpret_cast<char*>(&munitionObjectIdentifier),
         sizeof(RTIObjectIdStruct) );
   }

   // ---
   // Firing Object identifier:
   //
   // Get the firing player and its NIB.
   //   First check to see if it's an IPlayer from an HLA network.
   //   If it's not, then check our output list.
   // ---
   {
      Nib* fNib = nullptr;
      simulation::Player* fPlayer = mPlayer->getLaunchVehicle();
      if (fPlayer != nullptr) {
         if (fPlayer->isNetworkedPlayer()) {
            fNib = dynamic_cast<Nib*>( fPlayer->getNib() );
         }
         else {
            fNib = dynamic_cast<Nib*>( netIO->findNib(fPlayer, simulation::NetIO::OUTPUT_NIB) );
         }
      }

      if (fNib != nullptr) {
         RTIObjectIdStruct firingObjectIdentifier;
         base::utStrncpy(
            reinterpret_cast<char*>(&firingObjectIdentifier.id[0]),
            sizeof(firingObjectIdentifier.id),
            fNib->getObjectName(),
            RTIObjectIdStruct::ID_SIZE );    
         pParams->add(
            netIO->getInteractionParameterHandle(NetIO::FIRING_OBJECT_IDENTIFIER_MD_PI),
            reinterpret_cast<char*>(&firingObjectIdentifier),
            sizeof(RTIObjectIdStruct) );
      }
   }

   // ---
   // Target Object identifier:
   //
   // Get the target player and its NIB.
   //   First check to see if it's an IPlayer from an HLA network.
   //   If it's not, then check our output list.
   // ---
   {
      Nib* tNib = nullptr;
      simulation::Player* tPlayer = mPlayer->getTargetPlayer();
      if (tPlayer != nullptr) {
         tNib = dynamic_cast<Nib*>( tPlayer->getNib() );
         if (tNib == nullptr)
            tNib = dynamic_cast<Nib*>( netIO->findNib(tPlayer, simulation::NetIO::OUTPUT_NIB) );
      }

      if (tNib != nullptr) {
         RTIObjectIdStruct targetObjectIdentifier;
         base::utStrncpy(
            reinterpret_cast<char*>(&targetObjectIdentifier.id[0]),
            sizeof(targetObjectIdentifier.id),
            tNib->getObjectName(),
            RTIObjectIdStruct::ID_SIZE );    
         pParams->add(
            netIO->getInteractionParameterHandle(NetIO::TARGET_OBJECT_IDENTIFIER_MD_PI),
            reinterpret_cast<char*>(&targetObjectIdentifier),
            sizeof(RTIObjectIdStruct) );
      }
   }

   // ---
   // Munition Type
   // ---
   {
      EntityTypeStruct munitionType;
      munitionType.entityKind = getEntityKind();
      munitionType.domain = getEntityDomain();
      base::NetHandler::toNetOrder(&munitionType.countryCode, getEntityCountry() );
      munitionType.category  = getEntityCategory();
      munitionType.subcategory = getEntitySubcategory();
      munitionType.specific   = getEntitySpecific();
      munitionType.extra  = getEntityExtra();
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::MUNITION_TYPE_MD_PI),
         reinterpret_cast<char*>(&munitionType),
         sizeof(EntityTypeStruct) );
   }

   // ---
   // Fuse Type (16 bit enum)
   // ---
   {
      FuseTypeEnum16 fuseType = FuseTypeOther;
      unsigned short netBuffer;
      base::NetHandler::toNetOrder(&netBuffer, static_cast<unsigned short>(fuseType) );
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::FUSE_TYPE_MD_PI),
         reinterpret_cast<char*>(&netBuffer),
         sizeof(unsigned short) );
   }

   // ---
   // Quantity fired
   // ---
   {
      unsigned short quantityFired = 1;
      unsigned short netBuffer;
      base::NetHandler::toNetOrder(&netBuffer, quantityFired );
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::QUANTITY_FIRED_MD_PI),
         reinterpret_cast<char*>(&netBuffer),
         sizeof(unsigned short) );
   }

   // ---
   // Rate Of Fire
   // ---
   {
      unsigned short rateOfFire = 0;
      unsigned short netBuffer;
      base::NetHandler::toNetOrder(&netBuffer, rateOfFire );
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::RATE_OF_FIRE_MD_PI),
         reinterpret_cast<char*>(&netBuffer),
         sizeof(unsigned short) );
   }

   // ---
   // Warhead type
   // ---
   {
      WarheadTypeEnum16 warheadType = WarheadTypeOther;
      unsigned short netBuffer;
      base::NetHandler::toNetOrder(&netBuffer, static_cast<unsigned short>(warheadType) );
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::WARHEAD_TYPE_MD_PI),
         reinterpret_cast<char*>(&netBuffer),
         sizeof(unsigned short) );
   }

   // ---
   // Relative detonation location
   // ---
   {
      RelativePositionStruct relativeDetonationLocation;
      relativeDetonationLocation.bodyXDistance = 0;
      relativeDetonationLocation.bodyYDistance = 0;
      relativeDetonationLocation.bodyZDistance = 0;

      RelativePositionStruct netBuffer;
      base::NetHandler::toNetOrder(&netBuffer.bodyXDistance, relativeDetonationLocation.bodyXDistance );
      base::NetHandler::toNetOrder(&netBuffer.bodyYDistance, relativeDetonationLocation.bodyYDistance );
      base::NetHandler::toNetOrder(&netBuffer.bodyZDistance, relativeDetonationLocation.bodyZDistance );
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::RELATIVE_DETONATION_LOCATION_MD_PI),
         reinterpret_cast<char*>(&netBuffer),
         sizeof(RelativePositionStruct) );
   }

   // ---
   // Detonation result code
   // ---
   {
      DetonationResultCodeEnum8 detonationResultCode;
      switch ( mPlayer->getDetonationResults() ) {
         case simulation::Weapon::DETONATE_OTHER :
            detonationResultCode = DetonationResultCodeOther;
            break;
         case simulation::Weapon::DETONATE_ENTITY_IMPACT :
            detonationResultCode = EntityImpact;
            break;
         case simulation::Weapon::DETONATE_ENTITY_PROXIMATE_DETONATION :
            detonationResultCode = EntityProximateDetonation;
            break;
         case simulation::Weapon::DETONATE_GROUND_IMPACT :
            detonationResultCode = GroundImpact;
            break;
         case simulation::Weapon::DETONATE_GROUND_PROXIMATE_DETONATION :
            detonationResultCode = GroundProximateDetonation;
            break;
         case simulation::Weapon::DETONATE_DETONATION :
            detonationResultCode = Detonation;
            break;
         case simulation::Weapon::DETONATE_NONE :
            detonationResultCode = None;
            break;
         default :
            detonationResultCode = DetonationResultCodeOther;
            break;
      };

      unsigned char netBuffer = static_cast<unsigned char>(detonationResultCode);
      pParams->add(
         netIO->getInteractionParameterHandle(NetIO::DETONATION_RESULT_CODE_MD_PI),
         reinterpret_cast<char*>(&netBuffer),
         sizeof(unsigned char) );
   }

   // ---
   // Send the interaction
   // ---
   bool ok = netIO->sendInteraction(
      netIO->getInteractionClassHandle(NetIO::MUNITION_DETONATION_INTERACTION), pParams );

   // don't need this anymore
   delete pParams;

   return ok;
}
Ejemplo n.º 26
0
//------------------------------------------------------------------------------
// isPlayerStateUpdateRequired() -- check to see if an update is required
//------------------------------------------------------------------------------
bool Nib::isPlayerStateUpdateRequired(const double curExecTime)
{
   enum { NO, YES, UNSURE } result = UNSURE;

   // ---
   // 1) Make sure that we have a valid player and entity type
   // ---
   const models::Player* player = getPlayer();
   if (player == nullptr || isEntityTypeInvalid()) result = NO;

   // ---
   // 2) Mode changes
   // ---
   if ( (result == UNSURE) && isNotMode( player->getMode()) ) result = YES;

   // 2-a) NIB is being deleted, send one more update to deactivate the entity
   if ( (result == UNSURE) && isMode( models::Player::DELETE_REQUEST ) ) result = YES;

   // ---
   // 3) When we're a local player, check for one of the following ...
   // ---
   if ( (result == UNSURE) && player->isLocalPlayer()) {

      //double drTime = curExecTime - getTimeExec();
      models::SynchronizedState playerState = player->getSynchronizedState();
      const double drTime = static_cast<double>(playerState.getTimeExec()) - getTimeExec();

      // 3-a) Freeze flag has changed
      if ( (player->isFrozen() && isNotFrozen()) || (!player->isFrozen() && isFrozen()) ) {
         result = YES;
      }

      // 3-b) Max DR timeout
      if (result == UNSURE) {
         if ( drTime >= getNetIO()->getMaxTimeDR(this) ) {
            result = YES;
         }
      }

      // 3-c) Appearance has changed
      if (result == UNSURE &&
         (player->getDamage() != getDamage() ||
         player->getSmoke()  != getSmoke()   ||
         player->getFlames() != getFlames() ||
         player->getCamouflageType() != getCamouflageType() )
         ) {
            result = YES;
      }

      // 3-d) Check dead reckoning errors
      if (result == UNSURE && isNotFrozen()) {

         // Compute our dead reckoned position and angles, which are
         // based on our last packet sent.
         base::Vec3d drPos;
         base::Vec3d drAngles;
         mainDeadReckoning(drTime, &drPos, &drAngles);

         // 3-d-1) Position error
         if (!player->isPositionFrozen() && !player->isAltitudeFrozen()) {

            // max position error (meters)
            const double maxPosErr = getNetIO()->getMaxPositionErr(this);
            const double maxPosErr2 = maxPosErr*maxPosErr;  // squared

            // Check if the length of the position error (squared) is greater
            // than the max error (squared)
            //base::Vec3d ppos = player->getGeocPosition();
            const base::Vec3d ppos = playerState.getGeocPosition();
            const base::Vec3d errPos = drPos - ppos;
            if (errPos.length2() >= maxPosErr2) {
               result = YES;
            }
         }

         // 3-d-2) Orientation error
         if (result == UNSURE && !player->isAttitudeFrozen()) {

            // max angle error (radians)
            const double maxAngleErr = getNetIO()->getMaxOrientationErr(this);

            // Compute angular error
            //base::Vec3 errAngles = drAngles - player->getGeocEulerAngles();
            base::Vec3d errAngles = drAngles - playerState.getGeocEulerAngles();

            // Check if any angle error is greater than the max error
            errAngles[0] = std::fabs( base::angle::aepcdDeg(errAngles[0]) );
            if (errAngles[0] >= maxAngleErr) result = YES;

            errAngles[1] = std::fabs( base::angle::aepcdDeg(errAngles[1]) );
            if (errAngles[1] >= maxAngleErr) result = YES;

            errAngles[2] = std::fabs( base::angle::aepcdDeg(errAngles[2]) );
            if (errAngles[2] >= maxAngleErr) result = YES;
         }
      }
   }

   // ---
   // 4) Check for air vehicle articulated and attached parts (always check this)
   // ---
   if ( player != nullptr && player->isMajorType(models::Player::AIR_VEHICLE) ) {

      const models::AirVehicle* av = static_cast<const models::AirVehicle*>(player);

      // (4-a) Check wing sweep angle.  We only send out wing sweep as
      // an part if the position is greater than zero or if we've previously been
      // sending the wing sweep (count > 0).
      {
         const double angle = av->getWingSweepAngle();  //  radians
         if (angle > 0 || apartWingSweepCnt > 0) {
            // Check if the angle has changed.
            if (angle != apartWingSweep) {
               apartWingSweep = angle;
               apartWingSweepCnt++;
               result = YES;
            }
         }
      }

      // (4-b) Check landing gear position.  We only send out gear position as
      // an part if the gear is not up (pos != 0) or if we've previously been
      // sending the gear position (count > 0).
      {
         const double pos = av->getLandingGearPosition(); // (0% up; 100% down)
         if (pos > 0 || apartGearPosCnt > 0) {
            // Check if the pos has changed.
            if (pos != apartLandingGear) {
               apartLandingGear = pos;
               apartGearPosCnt++;
               result = YES;
            }
         }
      }

      // (4-c) Check bay door position.  We only send out bay door posiiton as
      // an part if the door is not closed (pos != 0) or if we've previously been
      // sending the door position (count > 0).
      {
         const double pos = av->getWeaponBayDoorPosition(); // % (0% closed; 100% open)
         if (pos > 0 || apartBayDoorCnt > 0) {
            // Check if the pos has changed.
            if (pos != apartBayDoor) {
               apartBayDoor = pos;
               apartBayDoorCnt++;
               result = YES;
            }
         }
      }

   }

   // ---
   // 5) Check for ground vehicle articulated and attached parts (always check this)
   // ---
   if ( player != nullptr && player->isMajorType(models::Player::GROUND_VEHICLE) ) {

      const models::GroundVehicle* gv = static_cast<const models::GroundVehicle*>(player);

      // (5-a) Send launcher elevation angle and for an attached missile
      //       (on SamVehicles and Artillery only)
      if ( gv->isClassType(typeid(models::SamVehicle)) || gv->isClassType(typeid(models::Artillery)) ) {

         const double angle = gv->getLauncherPosition();  //  (radians)

         // First pass --
         if (apartLnchrElevCnt == 0) {

            // find all missiles missiles
            const models::StoresMgr* sm = gv->getStoresManagement();
            if (sm != nullptr) {
               const base::PairStream* stores = sm->getStores();
               if (stores != nullptr) {
                  const base::List::Item* item = stores->getFirstItem();
                  while (item != nullptr && apartNumMissiles < MAX_AMSL) {
                     const auto pair = static_cast<const base::Pair*>(item->getValue());
                     if (pair != nullptr) {
                        const auto msl = dynamic_cast<const models::Missile*>( pair->object() );
                        if (msl != nullptr) {
                           // Save the pointer to the missile, set the missile's change count to 1,
                           // and up the missile count
                           msl->ref();
                           apartMsl[apartNumMissiles] = msl;
                           apartMslAttached[apartNumMissiles] = !(msl->isMode(models::Player::LAUNCHED));
                           apartMslCnt[apartNumMissiles] = 1;
                           apartNumMissiles++;
                        }
                     }
                     item = item->getNext();
                  }
                  stores->unref();
                  stores = nullptr;
               }

            }

            // If we have missile then set the launcher angle
            if (apartNumMissiles > 0) {
               apartLnchrElev = angle;
               apartLnchrElevCnt++;
            }
         }

         // If we have the launcher angle and missiles then check for changes
         if (apartLnchrElevCnt != 0) {

            // Check if the pos has changed
            if (angle != apartLnchrElev) {
               apartLnchrElev = angle;
               apartLnchrElevCnt++;
               result = YES;
            }

            // Check all missiles for change in launched status
            for (unsigned int i = 0; i < apartNumMissiles; i++) {
               bool attached = !(apartMsl[i]->isMode(models::Player::LAUNCHED));
               if (attached != apartMslAttached[i]) {
                  // There's been a change in status
                  apartMslAttached[i] = attached;
                  apartMslCnt[i]++;
               }
            }

         }

      }

   }

   // ---
   // 6) When we're a network player -- Update when the exec time of the
   //    last input (player's NIB) is different that our exec time.
   // ---
   if ( (result == UNSURE) && player->isNetworkedPlayer() ) {
      const auto playerNib = dynamic_cast<const Nib*>(player->getNib());
      if (playerNib->getTimeExec() != getTimeExec()) {
         result = YES;
      }
   }

   return (result == YES);
}