← Back

ofxRTLS

github.com/bensnell/ofxRTLS · @bensnell
OF 0.11 Bridges Virtual & Augmented Reality

OpenFrameworks Manager for Real-Time Location Systems

4 2 Last commit 5y ago Created 7y ago

README

ofxRTLS



Introduction



This addon is intended to act as a manager for any "Real Time Location System" and exports tracking information in a standardized format via the rtls-protocol. Supported tracking systems include:

Tracking SystemSupported
Platform
Notes
Optitrack Motive Trackerx6432-bit (x86) is not supported by Motive.
This uses Motive v2.2.0
OpenVR (e.g. HTC Vive)x64 (x86?)
Null Systemx64, x86This system exports fake data.
This addon also supports optional realtime post-processing of the data. Options include:

The addon also allows data to be saved and played back from the C3D file format.

System Requirements



This requires a Windows 10, x64 computer if using the Optitrack Motive system.

This has been developed with OpenFrameworks version 0.11.0

Dependencies



General Dependencies



rtls-protocol (C++)

Tracking System-Specific Dependencies



Post-Processing Dependencies



ofxRTLS expects a number of additional dependencies for postprocessing. Make sure they are included in the addons.make file of your project. See the example_motive_postprocess/addons.make for an example using Motive.

How to use this addon with your project



First, make sure you have properly installed all of the dependencies; there are various idiosyncrasies for each one. Ideally, make sure you can get the examples for each dependency up and running before starting to work with ofxRTLS.

Setup



1. Include the relative path to ofxRTLS in your addons.make file, as usual. However, <u>do not</u> include the path to ofxMotive or ofxOpenVRTracker in your addons.make file. Then, regenerate your project files using OpenFrameworks' ProjectGenerator.

2. In Visual Studios, in the Property Manager, right click your entire project and select Add Existing Property Sheet.... Then, choose ofxRTLS.props. <u>Do not</u> include any other RTLS-related property sheets.

If your application does not directly interface with a tracking system, but instead receives data in the protobuf format, use only the Protobuf.props sheet instead.

4. In your project Properties window, under Configuration Properties > C/C++ > Preprocessor > Preprocessor Definitions, select Edit from the dropdown menu on the right and at the bottom of the window, check the box that says Inherit from parent or project defaults.

This will build support for all tracking systems, postprocessing and recording/playback. However, use of these modules is optional and described in the next step.

Configuration



The addon is configured via a configuration file rtls-config.json in the folder bin/data/configs. This file has a similar form to this:

{
	"systems" : [
		"Null",
		"OpenVR",
		"Motive"
	],
	"postprocess" : true,
	"player" : true
}


List the names of any systems (case-insensitive) which you would like supported by the application. You can include support for any number and combination of systems. All systems listed will try to connect once the application starts. Also list whether you would like postprocessing and recording/playback supported. If no options are defined or this file is missing, then there is no support for any of these modules.

Note: This file must be set before running the application. These settings cannot be changed while the app is running.

Usage



Include the addon in your project as normal. Then create an ofxRTLS object, e.g.:

ofxRTLS tracker;

Then, in your setup() method:

tracker.setup(); tracker.start(); ofAddListener(tracker.newFrameReceived, this, &ofApp::myHandlerFunction);

(name your handler whatever you think is most appropriate, e.g. RTLSFrameReceived)

Finally, implement your handler, e.g.:

void ofApp::myHandlerFunction(RTLSEventArgs& args) { TrackableFrame frameReceived = args.frame; // Do whatever you need to do :) }

Take a look at the examples for a more in-depth look at using ofxRTLS with ofxMotive and ofxOpenVRTracker.

Data



The data exported over the RTLS-protocol protobuf format is detailed here. However, this addon does not currently make use of all fields in the protocol, since some field data is not provided by certain systems.

TrackableFrame



Data is sent in a TrackableFrame, which represents a single frame of data captured at the same time. These frames are sent sequentially; however, if the communication layer is UDP, there is no guarantee of frames arriving sequentially.

A TrackableFrame can contain multiple Trackable's. There is no limit to the number of Trackables that can be contained within a TrackableFrame.

A TrackableFrame contains the following parameters:

NameTypeOptional?Description
trackablesrepeated TrackableNoThe list of objects currently being tracked. All objects in this list are presently visible and tracking.
frame_IDuint64NoThis frame's frame number.
timestampuint64NoThis frame's timestamp.
contextstringNoA json-formatted string containing information about the source of this data (see below).
The TrackableFrame's context field will always contain information about the data's source. When this utf-8 encoded json string is parsed, the json object possess the following information in key-value pairs.

KeyKey MeaningValues (one of the following)
s<u>s</u>ystem0 for Null System
1 for OpenVR
2 for Motive
t<u>t</u>ype0 for samples (markers, tracked objects) (e.g. IR LEDs, Retroreflective Objects, etc.)
1 for observers (references, contributors) (e.g. cameras, base stations, etc.)
The frame context applies to all trackables contained within it. Data from two different systems will never be sent in the same TrackableFrame. If multiple types of data are being sent (for example, both marker data {t:0} and camera data {t:1}), then each will be sent in its own TrackableFrame.

Trackable



A Trackable describes an object that is currently being tracked. In theory, a Trackable can also contain other Trackable's; however, this addon only makes use of one level of Trackable depth. In other words, a Trackable will never be the child to another Trackable.

A Trackable contains many parameters. Some of the parameters are used to uniquely identify the trackable. Those parameters include:

NameTypeOptional?Description
idint32YesA unique number that permanently identifies this object at least over the server's lifetime. An id of 0 indicates that this object has no id. Only nonzero id's are valid.
cuidstringYesA unique string used to temporarily persist trackables across frames. An empty cuid string indicates that this object has no cuid.
namestringYesThe name of this tracked object. An empty name string indicates that this object has no name.
\ The above parameters are optional insofar as at least one of them must be present in any given trackable in order for the trackable to be valid.

These "identifiable" parameters are used to identify an object across frames and distinguish it from other objects. The identifiability priority proceeds as follows:

1. The id is the most robust indicator of uniqueness, possessing both reliability and persistence. In other words, an object with id = 128 will always have this id. If this id isn't present, then this specific object isn't present. If this object ever re-appears, it will reappear with the same id. If valid, this parameter should be used to identify objects. If invalid, proceed to the next parameter: 2. The cuid is a reliable indicator of unqiueness; however, it is not persistent. In other words: an object with cuid = 5400-201 may spontaneously change cuid at any point, for example, if it becomes temporarily occluded. When this object re-appears, it will have a different cuid. Thus, for the duration of time an object retains a given cuid, it is trackable across frames. Said another way, if this cuid appears on frame t and frame t+1, then the object represented by this cuid on the first frame will be same object represented by this cuid on the next frame. cuid's are nonrepeatable, meaning they will never repeat twice during the same session of the application. If valid, use this parameter to identify objects. If not, proceed to the next parameter: 3. The name has no guarantee of being reliable nor persistent; however, it may be used as an efficient measure of uniqueness when all other parameters are invalid. If all other parameters are invalid, then name will be a reliable and persistent measure of uniquness. If any other parameters are valid, then name will not be a reliable or persistent measure of uniqueness, and will likely contain less immediately relevant information like the informal name of an object, if applicable. If valid, use this parameter to identify objects. If not, this trackable is not valid.

Location information for a Trackable is encoded in the following parameters:

NameTypeOptional?Description
positionPosition (x, y, z)NoThe position of the object. All trackables must contain positional information.
orientationOrientation (x, y, z, w)YesThe orientation of the object expressed as a quaternion. This field may not be available, depending on the tracking system. Currently, the only system that supports this is OpenVR (RTLS_OPENVR).
Lastly, the context parameter (if available) contains any remaining information about a Trackable:

NameTypeOptional?Description
contextstringYesA utf-8 encoded json string containing miscellanous flags and parameters that cannot be described by any of the other RTLS protocol Trackable parameters. Invalid if empty.
If valid, the context field once parsed will contain a list of keys and values. Possible pairs include:

KeyKey MeaningValues (one of the following)
m<u>m</u>ight need recalibration
Note: This only applies to Trackable's of type 1 (observers, cameras, etc.)
0 for false (by default)
1 for true

Recording and Playback



Raw data coming directly from the tracking systems can be recorded and played back, as long as the application includes recording/playback support ("player" : true). Data is saved as a C3D file. Postprocessing options for this data can be changed later on. A recorded file must be played back with an application that supports the corresponding tracking system. For example, a take recorded using the Motive system cannot be played back on a server that has only has OpenVR support.

C3D file data can be passively viewed using the third-party visualization utility Mokka.

Examples



An example as been provided in the folder example.

Postprocessing Options



If postprocessing is enabled, the following actions are available and can be individually toggled ON and OFF. They will be executed in this order. See below for more documentation on each action.

ActionDescription
Map IDsMap the ID parameter from one value to another, using a json dictionary supplied in the data folder. This mapping supports many-to-one and one-to-one mappings.
Remove Unidentifiable Before HungarianRemove trackables that are unable to be identified. A trackable with an id <= 0, no cuid, and no name, will be considered unidentifiable.
Apply HungarianUse the Hungarian (linear assignment) algorithm to track objects and provide continuity to identifiable information. See below for a detailed explanation of options.
Remove Unidentifiable Before FiltersSame as above, but applied again, before Filters. It is highly reocmmended that this is enabled (there are few, if any, use cases to the contrary).
Apply FiltersApply smoothing and filtering to all remaining trackables with adjustable sets of filter operators.

Map IDs



Parameters include:

ParameterDescription
ID Dict PathPath to the json dictionary.
The json dictionary should resemble this structure, where 2 ** nBits indicates the number of values in the dictionary. The dict contains a list of this length, where each index will be a key mapped to the value in its spot in the list. For example, the ID 0 maps to the value -1, while the ID 5 maps to the value 10.

{
   "nBits":3,
   "dict":[
      -1,
      2,
      4,
      6,
      8,
      10,
      12,
      14
   ]
}


Remove Unidentifiable (at multiple locations)



Remove any trackables which cannot be identified. Unidentifiable trackables have the TrackableKeyType none. The key type is found using the following function.

``C++ TrackableKeyType getTrackableKeyType(const Trackable& t) { if (t.id() > 0) return KEY_ID; if (!t.cuid().empty()) return KEY_CUID; if (!t.name().empty()) return KEY_NAME; return KEY_NONE; } ` Note that zero and negative id's are considered invalid and will be removed by this action.

Apply Hungarian



Parameters include:

ParameterDescription
Temporary Key TypesA string list of temporary key types, comma-delimited. Key types include: id, cuid, name, none. A trackable with a temporary key contains a key that is likely to change. The trackable is not defined by its key; rather, it is passively identified by its key.
Permanent Key TypesA string list of permanent key types, comma-delimited. Key types include: id, cuid, name, none. A trackable with a permanent key contains a key that will not change. The trackable is defined by its key.
Item RadiusIn the trackable's native units, the approximate radius of a trackable. This is used for calculating the intersection over union within the Hungarian solver. A smaller radius will result in greater sensitivity of cost, but may lose out on spatial relations and dependencies.
From Dataset PermananceThe permanence of samples used in the Hungarian solver's FROM dataset. An enumerated value with the available values TEMPORARY, PERMANENT, TEMPORARY_AND_PERMANENT. By default, this should be TEMPORARY. Including PERMANENT will provide additional, perhaps superfluous content, for the solver. If included, it is recommended not to allow remapping using permanent keys (see below parameters).
To Dataset PermananceThe permanence of samples used in the Hungarian solver's TO dataset. An enumerated value with the available values TEMPORARY, PERMANENT, TEMPORARY_AND_PERMANENT. By default, this should be TEMPORARY. Including PERMANENT will provide additional, perhaps superfluous content, for the solver. If included, it is recommended not to allow remapping using permanent keys (see below parameters).
Map Recursion LimitThe recursion limit of the key mapping search.
Remove Matching KeysRemove trackables whose keys match from the dataset before passing to the solver. Including these trackables may provide additional, superfluous context to the solver, but may also open you up to vulnerabilities in trackable matching. By default, this should be true.
Assign CUIDs to UnIDAssign a cuid to an unidentifiable trackable. By default, this value is false. Only set to true if you plan to provide the postprocessor with trackables without IDs and would like to track them.
CUID Start CounterWhat positive integer value should assigned cuid's start at?
Allow Remap From PermAre remappings from permanent key types allowed? If so, it is highly recommended that you remove matching keys before solve, since this will prevent permanent IDs from separating during tracking. By default, this value is false`. Set

Get this addon