OpenNI 1.5.4
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:

- Using the @ref xn::Context::EnumerateProductionTrees() 
  "EnumerateProductionTrees()" method – choosing one result and 
  calling CreateProductionTree() with this result 
- Using the @ref xn::Context::CreateAnyProductionTree() 
  "CreateAnyProductionTree()" method – shorthand for enumerating and 
  choosing any result 
- Using XML files       

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 @ref node_alternative 
"node alternatives". Each @ref node_alternative "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 @ref xn::Query "Query" object as a parameter (see @ref queries for C, 
or @ref xn::Query for C++). 
Note
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: 

- @ref xnCreateDepthGenerator()
- @ref xnCreateImageGenerator()
- @ref xnCreateIRGenerator()
- @ref xnCreateAudioGenerator()
- @ref xnCreateGestureGenerator()
- @ref xnCreateSceneAnalyzer()
- @ref xnCreateHandsGenerator()
- @ref xnCreateUserGenerator()

In C++ this can be done using

- @ref xn::DepthGenerator::Create()
- @ref xn::ImageGenerator::Create()
- @ref xn::IRGenerator::Create()
- @ref xn::AudioGenerator::Create()
- @ref xn::GestureGenerator::Create()
- @ref xn::SceneAnalyzer::Create()
- @ref xn::HandsGenerator::Create()
- @ref xn::UserGenerator::Create()

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 @ref xn::Query "Query" object, such as the vendor 
that supplies the generator, a version number, certain capabilities, and 
more (see @ref queries for the C functions, or @ref xn::Query for the 
C++ functions). 

Node Handles

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

Every function on a specific node takes the node handle as its first 
argument. In C++, every class inheriting from @ref 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 
@ref prdnodeinfo for C, or @ref 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 @ref 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 @ref 
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 @ref infolist for C, or @ref xn::NodeInfoList for 
C++). 

Understanding the Create() method

    <b>Purpose</b>

    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)
Parameters
[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.
    <b>Remarks</b>

    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.