OpenTracker

An Open Architecture for Reconfigurable Tracking based on XML | Contact

Integration Guide

This document is a short guide to how to use and integrate OpenTracker in your project.

Before Integration

We assume that you already downloaded and compiled OpenTracker. If you need help on that, look at the Install HowTo.

Integration

The typical use of OpenTracker is as input library. You would specify a configuration file for the handling and transformation of the tracking data and then read it at some specified places out of the tracker tree. This involves setting up and running the OpenTracker main loop and getting at the actual data.

Context Class

The class Context provides all you need to work with the OpenTracker library. It manages the modules, uses a parser to build the run time data structure from a configuration file and implements the main loop. One object of type Context always manages exactly the data flow graph specified in one configuration file.

To be able to parse a configuration file a Context needs node factories that instantiate the different node types. These can be added using the member function addFactory. Moreover modules need to be added with the member function addModule which takes also the name of the configuration element. Typically actual modules implement both the Module and the NodeFactory interface and need to be added as both. The default constructor instantiates a clean Context without any modules or factories. To get a Context object with the default modules and node factories call the constructor with the value 1. In this case the object will also clean up the instantiated modules.

Now the object is ready to parse a configuration file. The member parseConfiguration takes a string with the path and filename of an XML configuration file. See the User's Guide for the syntax and semantics of such a file. It builds the run time data structure and the Context is now ready to perform any computations.

Next the member function start tells all modules that the processing is about to begin. Then the following member functions are called in order in a loop to process the data flow.

  1. pushEvent - calls pushEvent on all modules to create new events and process them.
  2. pullEvent - calls pullEvent on all modules to read data out of the data flow graph and process any Queue an Timedependend nodes.
  3. stop - queries all modules, if they encountered a reason to stop. If one or more modules return 1, the member returns 1 itself telling the application to quit.

After the the application decides to quit and leaves the main loop the member function close should be called to give the Context and the module a chance to clean up resources.

An application can either call these members in its own main loop or execute the member function run instead, which implements initialization, the loop and cleanup. See also the source code for the standalone tracking program as an example.

The following code example shows how to use the Context node in your own main loop :

Context context( 1 );                                       // create a new context
	    context.parseConfiguration("mypath/myconfig.xml");     // parse a configuration file
	    
	    ...  your own initialization
	    context.start();                                       // start the context when you are ready
	    
	    while( context.stop() != 1 && quit != 1 )              // loop until context our your code quits
	    {
	    ... do your own processing
	    context.pushEvent();                               // push event and
	    context.pullEvent();                               // pull event
	    }
	    ... your own cleanup
	    context.close();                                       // clean up finally

Using the Context main loop is even simpler, as the following example shows :

Context context( 1 );                                       // create a new context
	    context.parseConfiguration("mypath/myconfig.xml");     // parse a configuration file

	    context.run();                                         // does everything for you !
	

Using Callback Nodes

The simplest way to get data out of the data flow graph is to use Callback nodes. These nodes execute callback functions whenever they receive an event. To use such nodes the application needs access to the CallbackModule which implements these nodes. Therefore the application needs to retrieve a pointer to the callback module from the context. The module is stored under the name "CallbackConfig". The following code example shows how to do this :

void callbackF( Event & event );                    // definition of the callback function 
	    
	    Context context( 1 );                               // create a context
            // get callback module from the context
	    CallbackModule * callbackMod = (CallbackModule *)context.getModule("CallbackConfig");

	    context.parseConfiguration("mypath/myconfig.xml");  // parse the configuration file

	    callbackMod->setCallback( "cb1", &callbackF );    // sets the callback function

The context is created. Then the CallbackModule is retrieved via getModule. Now the configuration file is parsed and any nodes of type Callback are created. Every Callback node has a unique name that is used to set a callback function afterwards. The next line uses the member function setCallback to set the function callbackF as the callback of the node with the name cb1.

Using your own Node Type

You can also define and implement a new node type derived from Node to get data out of the tracker tree. Please refer to the Programmer's Guide for detailed informatio t how to do that.

copyright (c) Graz University of Technology | Webmaster