Xml Scripts

OpenNI supports using XML as a configuration script. One can use such a script for creating nodes and configuring them, and for configuring the context itself (adding license keys, etc.). an XML script can be executed by calling xnContextRunXmlScript() (xn::Context::RunXmlScript()) and passing it a string representation of the XML script, or by calling xnContextRunXmlScriptFromFile() (xn::Context::RunXmlScriptFromFile()) and passing it an XML file to load.

# Structure

The XML must have one (and only) root node named OpenNI. Under this node there can be 3 optional sections: Licenses, Log and Production Nodes.

# Licenses

This section can provide additional license keys to be registered. The element name should be "Licenses", and it should contain a list of elements, each named "License" with two string attributes: "vendor" and "key". Each such element actually calls xnAddLicense() (xn::Context::AddLicense()). For example:

<Licenses>
<License vendor="vendor1" key="key1"/>
<License vendor="vendor2" key="key2"/>
</Licenses>

# Log

This section can configure OpenNI log system. The element name should be "Log". It can contain the following optional attributes:

- writeToConsole - "true" or "false" (default). Determines if log is written to the application console.
- writeToFile - "true" or "false" (default). Determines if log is written to a file. This file is located under a Log folder that is created under working directory.
- writeLineInfo - "true" (default) or "false". Determines if every log entry also contains the file name and line info from which it was written.

In addition, it can contain the following elements:

- LogLevel with the attribute value set to 0 (verbose), 1 (info), 2 (warnings) or 3 (errors, default). This determines the minimum log severity that is written.
- Masks with a list of Mask elements, each determines if a specific mask is on or off.
- Dumps with a list of Dump elements, each determines if a specific dump is on or off.

For example:

<Log writeToConsole="false" writeToFile="false" writeLineInfo="true">
<LogLevel value="3"/>
<Masks>
<Mask name="ALL" on="true" />
</Masks>
<Dumps>
<Dump name="SensorTimestamps" on="false" />
</Dumps>
</Log>

# Production Nodes

This section allows creation and configuration of nodes. The element name should be "ProductionNodes", and it can have several children performing various tasks:

## Global Mirror

The "ProductionNodes" element may contain an element called "GlobalMirror" which sets the global mirror (xnSetGlobalMirror(), xn::Context::SetGlobalMirror()), according to the "on" attribute ("true" or "false"). For example:

<ProductionNodes>
<GlobalMirror on="true" />
</ProductionNodes>

## Recordings

The "ProductionNodes" element may contain an element called "Recording" telling it to open a recording. For now, OpenNI supports file recordings using the "file" attribute:

<Recording file="c:\myfile.oni" />

You can also set the playback speed using the "playbackSpeed" attribute if you wish to fast forward, or to slow down the playback. Note that the special value 0.0 can be used to cause playing to be as fast as possible (no delay between frames). For example, to open a file and play it as twice as fast:

<Recording file="c:\myfile.oni" playbackSpeed="2.0"/>

## Nodes

The "ProductionNodes" element may contain one or more elements named "Node". Each such element asks OpenNI to enumerate and create a node (similar to xnCreateAnyProductionTree()). The "Node" element should have a string attribute named "type" which will have the type of the node to enumerate. The type can be one of the following:

- Device (XN_NODE_TYPE_DEVICE)
- Depth (XN_NODE_TYPE_DEPTH)
- Image (XN_NODE_TYPE_IMAGE)
- IR (XN_NODE_TYPE_IR)
- Audio (XN_NODE_TYPE_AUDIO)
- Gesture (XN_NODE_TYPE_GESTURE)
- User (XN_NODE_TYPE_USER)
- Scene (XN_NODE_TYPE_SCENE)
- Hands (XN_NODE_TYPE_HANDS)
- Recorder (XN_NODE_TYPE_RECORDER)

In addition the "Node" element can optionally have a "name" string attribute which will hold the requested name of the created node.

## Recorder

The "ProductionNodes" element may contain an element called "Recorder" telling it to record data from other nodes that were created in the xml script. Note that these nodes must be named explicitly.

For example, if two nodes were defined, named Image1 and Depth1, and we'd like to record their data into a file called MyFile.oni:

<Node type="Recorder">
<Configuration>
<RecorderDestination name="MyFile.oni"/>
<AddNodeToRecording name="Image1" codec="JPEG"/>
<AddNodeToRecording name="Depth1" codec="16zT"/>
</Configuration>
</Node>

### Queries

The "Node" element can also declare a query that will be used when enumerating for this node. It is done by adding a "Query" element to the "Node" element, which can have the following children:

- "Vendor", specifying the requested node vendor.
- "Name", specifying the requested node name.
- "MinVersion", specifying the requested node minimum version.
- "MaxVersion", specifying the requested node maximum version.
- "Capabilities", specifying a list of capabilities the node must support, each under a "Capability" sub-element.
- "MapOutputModes", specifying a list of map output mode that should be supported by the map generator, each under a "MapOutputMode" object, containing three attributes: "xRes", "yRes" and "fps".
- "MinUserPositions", specifying the minimum number of user positions supported by a depth generator that has the "UserPosition" capability.
- "ExistingNodeOnly", specifying that only existing nodes (e.g. nodes that were already created) will enumerate.
- "NonExistingNodeOnly", specifying that only non-existing nodes (e.g. nodes that were not created yet) will enumerate.
- "NeededNodes", specifying only production trees that contains specific nodes are valid. Those nodes are declared using a sub-element named "Node".

If more than one such element is present, all conditions are checked using the "AND" operator.

For example, the following will try to create a depth node, supplied by vendor1, named name1, from version 1.0.0.0 to 3.1.0.5, supporting the "UserPosition" and "Mirror" capabilities, supporting a VGA, 30 FPS output mode, supporting at least 2 user positions, and one that uses the "MyDevice" node.

<Node type="Depth" name="MyDepth">
<Query>
<Vendor>vendor1</Vendor>
<Name>name1</Name>
<MinVersion>1.0.0.0</MinVersion>
<MaxVersion>3.1.0.5</MaxVersion>
<Capabilities>
<Capability>UserPosition</Capability>
<Capability>Mirror</Capability>
</Capabilities>
<MapOutputModes>
<MapOutputMode xRes="640" yRes="480" FPS="30"/>
</MapOutputModes>
<MinUserPositions>2</MinUserPositions>
<NeededNodes>
<Node>MyDevice</Node>
</NeededNodes>
</Query>
</Node>

### Configuration

Each "Node" element can also contain a list of configuration changes to be performed. This list should be placed under a "Configuration" element. The sub-elements of the "Configuration" element will be executed serially. Those commands can be:

Node Type

Configuration

Syntax

Values

Matching API

Generators which support the Mirror capability

Mirror

    <Mirror on="" />

'on' can be "true" or "false"

SetMirror()

All Map Generators

MapOutputMode

    <MapOutputMode xRes="" yRes="" FPS="" />

SetMapOutputMode()

Map Generators which supports Cropping capability

Cropping

    <Cropping enabled="" xOffset="" yOffset="" xSize="" ySize="" />

SetCropping()

Image Generators

PixelFormat

    <PixelFormat>X</PixelFormat>

X can be "RGB24", "YUV422", "Grayscale8", "Grayscale16" or "MJPEG"

SetPixelFormat()

Audio Generators

WaveOutputMode

    <WaveOutputMode sampleRate="" bitsPerSample="" channels="" />

SetWaveOutputMode()

Generators which supports the FrameSync capability

FrameSync

    <FrameSync>X</FrameSync>

X should be the name of an already existing node (or one that is declared previous in this script)

FrameSyncWith()

Generators which supports the AlternativeViewPoint capability

AlternativeViewPoint

    <AlternativeViewPoint>X</AlternativeViewPoint>

X should be the name of an already existing node (or one that is declared previous in this script)

SetViewPoint()

Recorder

RecorderDestination

    <RecorderDestination medium="" name="" />

'medium' should be "file" and 'name' should be the path to the file

SetDestination()

Recorder

AddNodeToRecording

    <AddNodeToRecording name="" codec="" />

'name' should be the name of an existing node and 'codec' is optional for setting another codec for this node.

AddNodeToRecording()

Depth Generators which supports the UserPosition capability

UserPosition

    <UserPosition index="">
        <Min x="" y="" z="" />
        <Max x="" y="" z="" />
    </UserPosition>

SetUserPosition()

All Nodes

Property

    <Property name="" type="" value="" />

'name' is the name of the property, 'type' can be "int", "real" or "string"

SetIntProperty() SetRealProperty() SetStringProperty()

In addition, the application can request to lock this node for changes (preventing any configuration change to this node once configuration is done) by using the "lock" attribute, and setting it to "true" or "false" (default). This calls xnLockNodeForChanges() (xn::ProductionNode::LockForChanges()).

The following example create 3 nodes of types image, depth and audio. The image node to use QVGA output on 60 FPS with RGB24 pixel format. It also sets a cropping area, and turning on mirror. The Depth node is configured to VGA output on 30 FPS. It also sets the position of the user to a bounding box located between (128, 128, 500) and (600, 400, 2000). The depth node also configures a special property, proprietary to vendor "VendorX". The audio is configured to be sampled at 44100 Hz, in stereo mode and 16-bit per sample. Enumeration takes place only for nodes that support those configurations.

<ProductionNodes>
<Node type="Image">
<Query>
<MapOutputModes>
<MapOutputMode xRes="320" yRes="240" FPS="60"/>
</MapOutputModes>
<Capabilities>
<Capability>Cropping</Capability>
<Capability>Mirror</Capability>
</Capabilities>
</Query>
<Configuration>
<MapOutputMode xRes="320" yRes="240" FPS="60"/>
<PixelFormat>RGB24</PixelFormat>
<Cropping enabled="true" xOffset="28" yOffset="28" xSize="200" ySize="160" />
<Mirror on="true" />
</Configuration>
</Node>
<Node type="Depth">
<Query>
<Vendor>VendorX</Vendor>
<MapOutputModes>
<MapOutputMode xRes="640" yRes="480" FPS="30"/>
</MapOutputModes>
<Capabilities>
<Capability>UserPosition</Capability>
</Capabilities>
</Query>
<Configuration>
<MapOutputMode xRes="640" yRes="480" FPS="30"/>
<UserPosition index="0">
<Min x="128" y="128" z="500"/>
<Max x="600" y="400" z="2000"/>
</UserPosition>
<Property type="int" name="VendorXDummyProp" value="3" />
</Configuration>
</Node>
<Node type="Audio">
<Configuration>
<WaveOutputMode sampleRate="44100" bitsPerSample="16" channels="2" />
</Configuration>
</Node>
</ProductionNodes>

### Start Generating

By default, when all nodes under the "ProductionNodes" element are created and configured, a call is made to xnStartGeneratingAll() (xn::Context::StartGeneratingAll()). If the application wants another behavior, it can place the "startGenerating" attribute containing "true" or "false", on any node, and also on the "ProductionNodes" element (which defines whether or not to start generate all). For example, the following will create two nodes: image and depth, but only start generate the depth one:

<ProductionNodes startGenerating="false">
<Node type="Image" />
<Node type="Depth" startGenerating="true" />
</ProductionNodes>