OpenNI 1.5.4: The Production Graph


The Production Graph

The production graph is a network of production nodes. This is the principal OpenNI object model. The fundamental purpose and functionality of the production graph is to identify and track blobs as human hands or users.

A production graph is composed of a production node, and optionally a list of other production nodes needed for this production node. Each production node has a type (one of the types defined by the OpenNI specification), a vendor name, and a specific name (unique for this type and vendor), and a version. For example, a UserGenerator node may need a DepthGenerator node, which in turn might need a Device node.

Enumerating the Registered Modules

When OpenNI is initializing, it loads each registered module, and asks it for the types of nodes it implements. Then, when an application asks for a specific generated product, OpenNI enumerates every module that declared itself as generating that product, for currently possible production graphs. Each module builds a list of nodes it can create right now (possible by enumerating for other node types), and returns it to OpenNI. OpenNI then appends all those lists together, and returns them to the application. The application can then choose the specific node it wants to use right now, and asks OpenNI to create it.

Creating Production Nodes

There are several ways to create production nodes:

Enumerating to Create Production Nodes

The result from an enumeration operation is a pointer to the first node of a linked list, representing all the matching node alternatives. Each node alternative contains the provider description, an optional instance name (that can be used by the provider as proprietary information, like a device S/N), and a list of the node's dependencies (other needed nodes).

Enumerating with Constraints

When an application wants to create a production node, in most cases it will prefer (or even demand) certain constraints from those nodes. For example, an application might need the node to support a specific capability it needs. For this reason, the enumeration functions can take a Query object as a parameter (see Queries for C, or xn::Query for C++).

OpenNI can also return existing nodes during enumeration, if they match the requested criterias.

Enumerating only for a Particular Type

As a shortcut, in case the application doesn't care about different nodes, and just needs any node of the requested type, it can do so using one of the following functions:

In C++ this can be done using

Note that just like in the full enumeration process, these functions also allow the application to specify certain constraints about the created nodes with a Query object, such as the vendor that supplies the generator, a version number, certain capabilities, and more (see Queries for the C functions, or xn::Query for the C++ functions).

Node Handles

In the C interface, each production node in the context is accessed using a node handle.

Every function on a specific node takes the node handle as its first argument. In C++, every class inheriting from xn::NodeWrapper holds the handle as a member, making it easier for applications to use the methods.

Building the Production Graph

An application usually needs just one 3D vision product to be generated by OpenNI (human pose, gestures recognition, etc.). However this generated product is usually produced using a production graph. This means the vision product can be generated in a number of ways - either by different algorithms or the same algorithm using different raw data for processing.

When an application asks OpenNI for a specific generated product, OpenNI returns a list of all currently possible ways of producing it. This depends on installed modules, currently attached devices, and available licenses.

A production graph is represented using an object called Node Info (see Production Node Info for C, or xn::NodeInfo for C++). This object contains information about the current node, such as its vendor, name, version, and most importantly, its type. The node info object can represent either an existing node that was already created, or an option for creating a node. For example, if an application enumerates for a node in the first time with xnEnumerateProductionTrees, it will probably get a node info object which is not connected to an existing node. Once the application chooses to create this node with xnCreateProductionTree, a node will be created, and the node info object will also hold the node handle.

The application can choose a production graph according to some or all nodes in the graph. For example, suppose an application asks for a User Generator. A User Generator requires a Depth Generator to operate, and suppose there are two types of Depth Generators installed on the machine. In this case the application would get two production chains for the User Generator: One for each option of the underlying Depth Generator. The application can then choose the preferred production graph according to its considerations, e.g. choosing a specific vendor, or choosing a depth node that provides certain capabilities.

Each Node Info object holds a list of needed nodes, thus creating a nodes graph. The list of needed nodes is accessed using an object called Node Info List (see Production Node Info List for C, or xn::NodeInfoList for C++).

Understanding the Create() method


The Create() method creates a production node from available production node alternatives of the same type. For example, if you call the Create() method of an ImageGenerator object, on successful execution the method returns a reference to an ImageGenerator node.

        XnStatus Create (Context &context, Query *pQuery=NULL, EnumerationErrors *pErrors=NULL)
[in]ContextContext in which to create the production node.
[in]pQueryOptional. Filters the production node alternatives.
[in,out]pErrorsOptional. Returns information about production nodes that could not be created.


In order to create any type of production node (e.g., a UserGenerator node) the application calls this method of the instantiated production object (e.g., a UserGenerator object). However, an appropriate OpenNI module (plug-in) must first be installed on the computer to provide that required type of production node (e.g., a UserGenerator node).

This method enumerates all available production node alternatives, taking into account any defined query. The method selects any one of the matching node alternatives it has found, in order to create the required type of production node.

By default, if an existing node matches the filter, the Create() method will return a reference to the existing node, and so it will not create a new node.

If no query is defined, this method uses any available node alternative to create the node. Thus in this case, no assumption can be made about which of the available production node alternatives the method will select to create the new node.

To fine control the selection the application can define an appropriate query to narrow down the number of production node alternatives for creating the required production node, so that only matching nodes will be considered for selection.

The Create() method is equivalent to calling EnumerateProductionTrees() followed by CreateProductionTree() on the first result. That is, to call CreateProductionTree() on the first production node alternative that EnumerateProductionTrees() returns.

On successful execution, the production object (e.g., the UserGenerator object) references the newly created production node (e.g., a UserGenerator node). The application can then use the other methods of the node.

The production node that is returned is always a complete production graph. That is to say, the returned node will bring with it all other dependant nodes it requires for generating its output data. For example, if the required production node is a UserGenerator node, and its dependencies include a DepthGenerator node, then the new UserGenerator node reference will also bring with it a reference to a DepthGenerator node, creating a new DepthGenerator node if necessary.

If the production node returned is the base of a production graph (e.g., a Device node), then it does not have any dependencies and so the node will not bring with it any associated nodes at all. In this case the length and breadth of the returned production graph will be just the single new node reference.

Generated on Wed May 16 2012 10:16:06 for OpenNI 1.5.4 by   doxygen