MAK RTIspy API Documentation for HLA 4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
4 - Monitoring RTI Service Invocations

Table of Contents

The key to finding out when RTI Ambassador functions are called by a federate, is the DtRtiAmbassadorObserver class (ambObserver.h, ambObserver1516.h, and ambObserver1516e.h).

DtRtiAmbassadorObserver is a base class whose interface closely resembles that of the RTI::RTIambassador. You can create a subclass of DtRtiAmbassadorObserver, and provide implementations for any functions you want to monitor. For example, if you want to print a message every time an interaction is sent, override sendInteraction() in your observer with a version that will do so. Then, register an instance of your observer with the RTI, by calling addObserver() on the DtRtiAmbassadorImplementor, typically from within InitPlugin(). Whenever an RTI Ambassador function is called by a federate, the call is executed, then the RTI calls the comparable function on any DtRtiAmbassadorObservers that are currently observing the RTI. The following example shows how to create a subclass of DtRtiAmbassadorObserver, and register it with the RTI:

class MyObserver : public DtRtiAmbassadorObserver
{
public:
// Override any base class functions you choose, to be notified
// when the corresponding RTI::RTIambassador function is called
virtual void sendInteraction (
RTI::InteractionClassHandle theInteraction,
const RTI::ParameterHandleValuePairSet& theParameters,
const char *theTag, RTI::Exception* except = NULL)
{
printf("SendInteraction called for class %d\n", theInteraction);
}
...
};
void InitLRCPlugin(DtRtiAmbassadorImplementor* implementor)
{
// Create an instance of your observer, and register it with the
// implementor.
MyObserver* observer = new MyObserver();
implementor->addObserver("MyObserver", observer);
};

The RTI deletes your observer when DtRtiAmbassadorImplementor is destroyed, so you should not try to delete the observer yourself if it is registered with the RTI. If, during execution, you want to unregister your observer, use DtRtiAmbassadorImplementor::removeObserver(). If you remove an observer, you are responsible for deleting it. You unregister an observer by name.

You can register more than one observer with the RTI. Appropriate functions will be called on all of them.

DtRtiAmbassadorObserver's function prototypes differ slightly from those in the RTI::RTIambassdor (the RTI's external API). Most functions include an optional RTI::Exception* argument, and some include arguments that match the return types of the corresponding RTI::RTIambassador functions. This is to allow your code to learn not only what RTI calls are being made by a federate, but what the results of those calls are. If a non-NULL value is passed as the except argument to a DtRtiAmbassadorObserver function, that means the federate's call to the RTI service generated an exception. The except argument is a copy of the RTI::Exception object that was thrown to the federate. For RTI::RTIambassador service calls that generate return values, the value returned to the federate is passed to the observer's function as an extra argument. For example, DtRtiAmbassadorObserver::registerObjectInstance() takes an argument called handle, which represents the handle that was returned to the federate when it called RTI::RTIambassador::registerObjectInstance().

The MAK RTI's implementation of the management object model (MOM) uses an observer to generate ReportServiceInvocation interactions.

4.1 Monitoring Federate Ambassador Services

Being notified when the RTI invokes RTI::FederateAmbassador services works slightly differently from RTIAmbassador. You must subclass DtFedAmbWrapper (fedAmbWrap.h, fedAmbWrap1516.h, and fedAmbWrap1516e.h), and register an instance of your subclass with the RTI using DtRtiAmbassadorImplementor::addFedAmbWrapper().

DtFedAmbWrapper is derived from RTI::FederateAmbassador, so it inherits the Federate Ambassador's public API. Normally, when the RTI wants to make calls to a federate, it invokes the appropriate functions on the RTI::FederateAmbassador object that has been passed to the RTI by the federate (for example, reflectAttributeValues()). However, if your plug-in has a federate ambassador wrapper registered with the RTI, federate ambassador calls are made on your wrapper instead, allowing you to intercept calls to the federate ambassador.

Because you are intercepting calls that were destined for the federate, it is your responsibility to make sure that calls still get made on the federate's original RTI::FederateAmbassador. To help you do this, DtFedAmbWrapper maintains a pointer to that original ambassador, which we refer to as its child ambassador. Furthermore, the default implementation of all DtFedAmbWrapper functions is to call the corresponding function on its child ambassador. So for functions that you do not specifically override in your DtFedAmbWrapper subclass, you do not have to do anything special to make sure that the federate gets the data it needs. But for functions that you override, you must call down to the base DtFedAmbWrapper's version of the function at some point within your function.

The following example creates and registers a DtFedAmbWrapper that intercepts the receiveInteraction call, and prints a message both before and after the federate's version of this function is executed:

class MyFedAmbWrapper : public DtFedAmbWrapper
{
public:
virtual void receiveInteraction (
RTI::InteractionClassHandle theInteraction,
const RTI::ParameterHandleValuePairSet& theParameters,
const char* theTag)
throw (
RTI::InteractionClassNotKnown,
RTI::InteractionParameterNotKnown,
RTI::FederateInternalError)
{
printf("About to call receiveInteraction.\n");
// Make sure to call down to the base class so that the
// "real" Federate Ambassador function is called.
theInteraction, theParameters, theTag);
printf("Just called receiveInteraction.\n");
}
};
void InitLRCPlugin(DtRtiAmbassadorImplementor* implementor)
{
// Create an instance of your observer, and register it with the
// implementor
MyFedAmbWrapper* wrapper = new MyFedAmbWrapper();
implementor->addFedAmbWrapper(wrapper);
};

As long as a wrapper is registered with the RTI, the RTI deletes it when the DtRtiAmbassadorImplementor is destroyed. However, you can remove a wrapper at any time using DtRtiAmbassadorImplementor's removeFedAmbWrapper(), at which point you regain ownership of the wrapper.

You can chain federate ambassador wrappers together, so that you can have, for example, an outer wrapper wrapping an inner wrapper, which wraps the federate's original RTI::FederateAmbassador (arbitrary length chains are supported). If you register multiple wrappers, each subsequent wrapper becomes the new top-level wrapper, and its child ambassador automatically becomes the previous wrapper. The innermost wrapper has the federate's original ambassador as its child. In effect, outer-wrappers intercept calls from lower-level wrappers, but if you always call down to the base DtFedAmbWrapper's version of each function that you override, you will ensure that each wrapper invokes its child ambassador's version of the function, and that the federate's version will eventually be called.

[<< Initializing a Plug-in] [Home] [Top of Page] [Creating Custom RTI Managers >>]


Document ID: Generated on Sun Jul 20 16:15:30 EDT 2025 from SVN revision 277985
Copyright © 2005-2025 MAK Technologies Inc. All Rights Reserved (www.mak.com)