simulationhigh-level-architecture

Do I use provided time or user supplied tag when handling a reflect on a receive order attribute from a time managed federate?


In a simulation using RPR-FOM, if I get a reflectAttributeValues with a LogicalTime time stamp (simulation time) and the OrderType receive order in my FederateAmbassador. For dead reckoning algorithms do I use the time stamp supplied by the RTI or the time stamp encoded in the userSuppliedTag? Using the userSuppliedTag would be decoded value if absolute and system clock if relative.

To clarify, I get attributes reflected specified receive order from a time managed federate in this call in FederateAmbassador from the RTI:

void reflectAttributeValues(ObjectInstanceHandle theObject,
                               AttributeHandleValueMap theAttributes,
                               byte[] userSuppliedTag,
                               OrderType sentOrdering,
                               TransportationTypeHandle theTransport,
                               LogicalTime theTime,
                               OrderType receivedOrdering,
                               MessageRetractionHandle retractionHandle,
                               SupplementalReflectInfo reflectInfo)

Solution

  • For attributes that were updated Time Stamp Order, I used the time parameter to know when the attribute last had been updated and simulation time to dead reckon.

    public void reflectAttributeValues(
                ObjectInstanceHandle objectHandle,
                AttributeHandleValueMap attributes,
                byte[] userSuppliedTag,
                OrderType sentOrdering,
                TransportationTypeHandle theTransport,
                LogicalTime time,
                OrderType receivedOrdering,
                MessageRetractionHandle retractionHandle,
                SupplementalReflectInfo reflectInfo) {
       attributes.forEach((attributeHandle, value) -> {
          lastUpdated.put(attributeHandle, time));
          timeManaged.add(attributeHandle);
          // decode value into your object
          ...
       }
    }
    

    For attributes that where updated Receive Order without time stamp, I used the userSuppliedTag to know when the attributed last had been updated (value in the tag for absolute and system clock at the time of receiving the attribute for relative) and then using the system clock to dead reckon.

    public void reflectAttributeValues(
                ObjectInstanceHandle objectHandle,
                AttributeHandleValueMap attributes,
                byte[] userSuppliedTag,
                OrderType sentOrdering,
                TransportationTypeHandle theTransport,
                SupplementalReflectInfo reflectInfo) {
        LogicalTime time;
        if (isRelativeTag(userSuppliedTag)) {
           time = factory.createSystemLogicalTime(System.currentTimeMillis());
        } else {
           time = decodeTag(userSuppliedTag);
        }
        attributes.forEach((attributeHandle, value)-> {
           lastUpdated.put(attributeHandle, time);
           timeManaged.remove(attributeHandle); // attributes might switch
           // decode value into your objects
           ...
        }
    }
    

    Then to dead reckon:

    private Vector3D getDeadReckonedWorldLocation(LogicalTime time) {
       LogicalTime lastUpdatedSpatial = lastUpdated.get(spatialAttributeHandle);
       if (!timeManaged.contains(spatialAttributeHandle)) {
          time = factory.createSystemLogicalTime(System.currentTimeMillis());
       }
       LogicalTimeInterval timeToDeadReckon = time.distance(lastUpdatedSpatial);
    
       return deadReckon(timeToDeadReckon);
    }
    

    Code here are simplified examples and may not compile, but they capture the solution I managed to come up with.