fork
Configure Feed
Select the types of activity you want to include in your feed.
The open source OpenXR runtime
fork
Configure Feed
Select the types of activity you want to include in your feed.
1// Copyright 2023-2024, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Visual-Intertial Tracking interface header.
6 * @author Mateo de Mayo <mateo.demayo@collabora.com>
7 * @author Simon Zeni <simon.zeni@collabora.com>
8 * @author Jakob Bornecrantz <jakob@collabora.com>
9 *
10 * This file contains the declaration of the @ref vit_tracker struct. This
11 * header is intended to appear in both consumers (e.g., Monado) and external
12 * visual-inertial tracking (VIT) systems (e.g., Basalt). The implementation of
13 * `vit_interface` is provided by the external system. Additional data types are
14 * declared for the communication between consumers and the system.
15 */
16
17#pragma once
18
19#if defined(__cplusplus)
20extern "C" {
21#endif
22
23#include <stdbool.h>
24#include <stdint.h>
25
26//! Compatibility with these values should be checked against @ref vit_api_get_version.
27#define VIT_HEADER_VERSION_MAJOR 2 //!< API Breakages
28#define VIT_HEADER_VERSION_MINOR 0 //!< Backwards compatible API changes
29#define VIT_HEADER_VERSION_PATCH 1 //!< Backw. comp. .h-implemented changes
30
31#define VIT_CAMERA_CALIBRATION_DISTORTION_MAX_COUNT 32
32
33/*!
34 * Result type used by the VIT system
35 *
36 * 0 is @ref VIT_SUCCESS, positive values are non fatal results and negative values are errors.
37 */
38typedef enum vit_result {
39 /*!
40 * Operation suceeded
41 */
42 VIT_SUCCESS = 0,
43
44 /*!
45 * The operation is not available on the current version
46 */
47 VIT_ERROR_INVALID_VERSION = -1,
48
49 /*!
50 * The operation received an invalid value.
51 */
52 VIT_ERROR_INVALID_VALUE = -2,
53
54 /*!
55 * The operation was not able to allocate memory to pursue the operation.
56 */
57 VIT_ERROR_ALLOCATION_FAILURE = -3,
58
59 /*!
60 * The operation requires an extension that is not supported.
61 */
62 VIT_ERROR_NOT_SUPPORTED = -4,
63
64 /*!
65 * The operation requires an extension that is not enabled.
66 */
67 VIT_ERROR_NOT_ENABLED = -5,
68} vit_result_t;
69
70/*!
71 * Image formats.
72 */
73typedef enum vit_image_format {
74 //! 8-bit luminance
75 VIT_IMAGE_FORMAT_L8 = 1,
76 //! 16-bit luminance
77 VIT_IMAGE_FORMAT_L16 = 2,
78 //! 24-bit rgb, tightly packed.
79 VIT_IMAGE_FORMAT_R8G8B8 = 3,
80} vit_image_format_t;
81
82/*!
83 * Camera calibration types.
84 */
85typedef enum vit_camera_distortion {
86 //! No distortion (pre-disotorted).
87 VIT_CAMERA_DISTORTION_NONE,
88 //! Distortion radial-tangential (OpenCV), 4 parameters.
89 VIT_CAMERA_DISTORTION_RT4,
90 //! Distortion radial-tangential (OpenCV), 5 parameters.
91 VIT_CAMERA_DISTORTION_RT5,
92 //! Distortion radial-tangential (OpenCV), 8 parameters.
93 VIT_CAMERA_DISTORTION_RT8,
94 //! Distortion Kannala-Brandt (OpenCV fisheye), 4 parameters.
95 VIT_CAMERA_DISTORTION_KB4,
96} vit_camera_distortion_t;
97
98/*!
99 * Optional functionality a tracker can provide.
100 */
101typedef enum vit_tracker_extension {
102 //! Allows to specify camera calibration data programatically
103 VIT_TRACKER_EXTENSION_ADD_CAMERA_CALIBRATION,
104 //! Allows to specify IMU calibration data programatically
105 VIT_TRACKER_EXTENSION_ADD_IMU_CALIBRATION,
106 //! Optionally provide timing information with the returned poses
107 VIT_TRACKER_EXTENSION_POSE_TIMING,
108 //! Optionally provide feature count information with the returned poses
109 VIT_TRACKER_EXTENSION_POSE_FEATURES,
110 //! Number of extensions
111 VIT_TRACKER_EXTENSION_COUNT,
112} vit_tracker_extension_t;
113
114/*!
115 * Set of extensions. Field order matches enumerators in @ref vit_tracker_extension.
116 */
117typedef struct vit_tracker_extension_set {
118 bool has_add_camera_calibration;
119 bool has_add_imu_calibration;
120 bool has_pose_timing;
121 bool has_pose_features;
122} vit_tracker_extension_set_t;
123
124/*!
125 * Visual-Inertial Tracking interface, opaque type.
126 */
127struct vit_tracker;
128typedef struct vit_tracker vit_tracker_t;
129
130/*!
131 * Pose interface, opaque type.
132 */
133struct vit_pose;
134typedef struct vit_pose vit_pose_t;
135
136/*!
137 * Names of the timestamps returned by `vit_pose_get_timings`
138 */
139typedef struct vit_tracker_timing_titles {
140 uint32_t count; //! Number of titles
141 const char **titles; //! Names of the measures timestamps
142} vit_tracker_timing_titles;
143
144/*!
145 * Parameters for creating the system pipeline.
146 */
147typedef struct vit_config {
148 //! Path to a implementation-specific config file. If null, use defaults.
149 const char *file;
150
151 //! Number of cameras to use. Required.
152 uint32_t cam_count;
153
154 //! Number of IMU to use. Required.
155 uint32_t imu_count;
156
157 //! If supported, whether to open the system's UI.
158 bool show_ui;
159} vit_config_t;
160
161/*!
162 * IMU sample type feed into VIT tracker
163 */
164typedef struct vit_imu_sample {
165 //! In nanoseconds
166 int64_t timestamp;
167
168 //! Acceleration in meters per second squared (m/s²)
169 float ax, ay, az;
170
171 //! Gyro in radians per second (rad/s)
172 float wx, wy, wz;
173} vit_imu_sample_t;
174
175/*!
176 * Region in image space that this mask covers.
177 */
178typedef struct vit_mask {
179 //! In pixels.
180 float x, y, w, h;
181} vit_mask_t;
182
183/*!
184 * Image sample type feed into VIT tracker
185 *
186 * Can easily be converted into an OpenCV Matrix for processing.
187 */
188typedef struct vit_img_sample {
189 uint32_t cam_index;
190
191 //! In nanoseconds, must increase monotonically.
192 int64_t timestamp;
193
194 // !Image data
195 uint8_t *data;
196 uint32_t width, height;
197 uint32_t stride, size;
198 vit_image_format_t format;
199
200 //! Regions to ignore
201 uint32_t mask_count;
202 vit_mask_t *masks;
203} vit_img_sample_t;
204
205/*!
206 * Data that is always returned from tracker.
207 */
208typedef struct vit_pose_data {
209 //! In nanoseconds, must increase monotonically.
210 int64_t timestamp;
211
212 //! Position vector.
213 float px, py, pz;
214
215 //! Orientation quaternion.
216 float ox, oy, oz, ow;
217
218 //! Linear velocity.
219 float vx, vy, vz;
220} vit_pose_data_t;
221
222/*!
223 * Result of pose timing request function.
224 */
225typedef struct vit_pose_timing {
226 uint32_t count;
227 const int64_t *timestamps;
228} vit_pose_timing_t;
229
230/*!
231 * One single feature, element of @ref vit_pose_features result.
232 */
233typedef struct vit_pose_feature {
234 int64_t id;
235 float u, v, depth;
236} vit_pose_feature_t;
237
238/*!
239 * Result of pose feature request function.
240 */
241typedef struct vit_pose_features {
242 uint32_t count;
243 const struct vit_pose_feature *features;
244} vit_pose_features_t;
245
246/*!
247 * Container of parameters for a pinhole camera calibration (fx, fy, cx, cy)
248 * with an optional distortion.
249 *
250 *`distortion_model` and its corresponding `distortion` parameters are not
251 * standardized in this struct to facilitate implementation prototyping.
252 */
253typedef struct vit_camera_calibration {
254 uint32_t camera_index; // <! For multi-camera setup. For stereo 0 ~ left, 1 ~ right.
255
256 int width, height; //<! Resolution
257 double frequency; //<! Frames per second
258 double fx, fy; //<! Focal point
259 double cx, cy; //<! Principal point
260 enum vit_camera_distortion model;
261 uint32_t distortion_count;
262 double distortion[VIT_CAMERA_CALIBRATION_DISTORTION_MAX_COUNT]; //!< Parameters for the distortion model
263 double transform[4 * 4]; //!< Row-major 4x4 camera transform w.r.t. the IMU (i.e., T_imu_cam)
264} vit_camera_calibration_t;
265
266typedef struct vit_inertial_calibration {
267 // Calibration intrinsics to apply to each raw measurement.
268
269 //! Row major 3x3 linear transformation for raw measurements alignment and scaling.
270 double transform[3 * 3];
271
272 //! Offset to add to raw measurements; called bias in other contexts.
273 double offset[3];
274
275 // Parameters for the random processes that model this IMU. See section "2.1
276 // Gyro Noise Model" of N. Trawny and S. I. Roumeliotis, "Indirect Kalman
277 // Filter for 3D Attitude Estimation". Analogous for accelerometers.
278 // http://mars.cs.umn.edu/tr/reports/Trawny05b.pdf#page=15
279
280 //! IMU internal bias ~ wiener process with steps N(0, σ²); this field is σ;
281 //! [σ] = U / sqrt(sec³) with U = rad if gyroscope, U = m/s if accelerometer.
282 double bias_std[3];
283
284 //! IMU measurement noise ~ N(0, σ²); this field is σ.
285 //! [σ] = U / sqrt(sec) with U = rad if gyroscope, U = m/s if accelerometer.
286 double noise_std[3];
287} vit_inertial_calibration_t;
288
289/*!
290 * Calibration for one IMU.
291 */
292typedef struct vit_imu_calibration {
293 uint32_t imu_index; //!< For multi-imu setup, usually just 0.
294
295 double frequency; //!< Samples per second
296 struct vit_inertial_calibration accel;
297 struct vit_inertial_calibration gyro;
298} vit_imu_calibration_t;
299
300/*
301 *
302 * Function prototypes.
303 *
304 */
305
306typedef vit_result_t (*PFN_vit_api_get_version)(uint32_t *out_major, uint32_t *out_minor, uint32_t *out_patch);
307typedef vit_result_t (*PFN_vit_tracker_create)(const vit_config_t *config, vit_tracker_t **out_tracker);
308typedef void (*PFN_vit_tracker_destroy)(vit_tracker_t *tracker);
309typedef vit_result_t (*PFN_vit_tracker_has_image_format)(const vit_tracker_t *tracker, vit_image_format_t image_format,
310 bool *out_supported);
311typedef vit_result_t (*PFN_vit_tracker_get_supported_extensions)(const vit_tracker_t *tracker,
312 vit_tracker_extension_set_t *out_exts);
313typedef vit_result_t (*PFN_vit_tracker_get_enabled_extensions)(const vit_tracker_t *tracker,
314 vit_tracker_extension_set_t *out_exts);
315typedef vit_result_t (*PFN_vit_tracker_enable_extension)(vit_tracker_t *tracker, vit_tracker_extension_t ext,
316 bool enable);
317typedef vit_result_t (*PFN_vit_tracker_start)(vit_tracker_t *tracker);
318typedef vit_result_t (*PFN_vit_tracker_stop)(vit_tracker_t *tracker);
319typedef vit_result_t (*PFN_vit_tracker_reset)(vit_tracker_t *tracker);
320typedef vit_result_t (*PFN_vit_tracker_is_running)(const vit_tracker_t *tracker, bool *out_bool);
321typedef vit_result_t (*PFN_vit_tracker_push_imu_sample)(vit_tracker_t *tracker, const vit_imu_sample_t *sample);
322typedef vit_result_t (*PFN_vit_tracker_push_img_sample)(vit_tracker_t *tracker, const vit_img_sample_t *sample);
323typedef vit_result_t (*PFN_vit_tracker_add_imu_calibration)(vit_tracker_t *tracker,
324 const vit_imu_calibration_t *calibration);
325typedef vit_result_t (*PFN_vit_tracker_add_camera_calibration)(vit_tracker_t *tracker,
326 const vit_camera_calibration_t *calibration);
327typedef vit_result_t (*PFN_vit_tracker_pop_pose)(vit_tracker_t *tracker, vit_pose_t **out_pose);
328typedef vit_result_t (*PFN_vit_tracker_get_timing_titles)(const vit_tracker_t *tracker,
329 vit_tracker_timing_titles *out_titles);
330typedef void (*PFN_vit_pose_destroy)(vit_pose_t *pose);
331typedef vit_result_t (*PFN_vit_pose_get_data)(const vit_pose_t *pose, vit_pose_data_t *out_data);
332typedef vit_result_t (*PFN_vit_pose_get_timing)(const vit_pose_t *pose, vit_pose_timing_t *out_timing);
333typedef vit_result_t (*PFN_vit_pose_get_features)(const vit_pose_t *pose, uint32_t camera_index,
334 vit_pose_features_t *out_features);
335
336/*
337 *
338 * Functions.
339 *
340 */
341
342#ifdef VIT_INTERFACE_IMPLEMENTATION
343
344/*!
345 * Returns the API version implemented by the VIT system.
346 */
347vit_result_t vit_api_get_version(uint32_t *out_major, uint32_t *out_minor, uint32_t *out_patch);
348
349/*!
350 * Creates a new VIT tracker. The caller is responsible of destroying it when done.
351 */
352vit_result_t vit_tracker_create(const vit_config_t *config, vit_tracker_t **out_tracker);
353
354/*!
355 * Destroys the VIT tracker and free all resources allocated.
356 */
357void vit_tracker_destroy(vit_tracker_t *tracker);
358
359/*!
360 * Verifies if the tracker supports a given `vit_image_format_t`.
361 */
362vit_result_t vit_tracker_has_image_format(const vit_tracker_t *tracker, vit_image_format_t image_format,
363 bool *out_supported);
364
365/*!
366 * Returns a set with the extensions supported by this tracker.
367 *
368 * @see vit_tracker_extension_t
369 */
370
371vit_result_t vit_tracker_get_supported_extensions(const vit_tracker_t *tracker, vit_tracker_extension_set_t *out_exts);
372
373/*!
374 * Returns a set with the extensions enabled in this tracker.
375 *
376 * @see vit_tracker_extension_t
377 */
378
379vit_result_t vit_tracker_get_enabled_extensions(const vit_tracker_t *tracker, vit_tracker_extension_set_t *out_exts);
380
381/*!
382 * Enables or disables a tracker extension.
383 *
384 * @see vit_tracker_extension_t
385 */
386vit_result_t vit_tracker_enable_extension(vit_tracker_t *tracker, vit_tracker_extension_t ext, bool value);
387
388/*!
389 * Starts the VIT tracker. Image and IMU samples can be pushed and pose can be retrieved.
390 *
391 * This function must be non blocking. The VIT system implementing it is expected to start its own event loop.
392 */
393vit_result_t vit_tracker_start(vit_tracker_t *tracker);
394
395/*!
396 * Stops the VIT tracker. The tracker wont accept image and IMU samples, and will not return poses.
397 */
398vit_result_t vit_tracker_stop(vit_tracker_t *tracker);
399
400/*!
401 * Resets the VIT tracker. The tracker internal state will be set to its original state.
402 */
403vit_result_t vit_tracker_reset(vit_tracker_t *tracker);
404
405/*!
406 * Verifies if the tracker is running.
407 */
408vit_result_t vit_tracker_is_running(const vit_tracker_t *tracker, bool *out_bool);
409
410/*!
411 * Push an IMU sample into the tracker.
412 *
413 * There must be a single producer thread pushing samples.
414 * Samples must have monotonically increasing timestamps.
415 * The implementation must be non-blocking.
416 * Thus, a separate consumer thread should process the samples.
417 */
418vit_result_t vit_tracker_push_imu_sample(vit_tracker_t *tracker, const vit_imu_sample_t *sample);
419
420/*!
421 * Push an image sample into the tracker.
422 *
423 * Same conditions as @ref push_imu_sample apply.
424 * When using N>1 cameras, the N frames must be pushed following @ref cam_index order.
425 * The bundle of N frames must have the same timestamps.
426 */
427vit_result_t vit_tracker_push_img_sample(vit_tracker_t *tracker, const vit_img_sample_t *sample);
428
429/*!
430 * Adds an inertial measurement unit calibration to the tracker. The tracker must not be started.
431 *
432 * Returns `VIT_ERROR_NOT_SUPPORTED` if the tracker doesn't offer the extension.
433 *
434 * @see vit_tracker_get_supported_extensions
435 * @see vit_tracker_extension_t
436 */
437vit_result_t vit_tracker_add_imu_calibration(vit_tracker_t *tracker, const vit_imu_calibration_t *calibration);
438
439/*!
440 * Adds a camera calibration to the tracker. The tracker must not be started.
441 *
442 * Returns `VIT_ERROR_NOT_SUPPORTED` if the tracker doesn't offer the extension.
443 *
444 * @see vit_tracker_get_supported_extensions
445 * @see vit_tracker_extension_t
446 */
447vit_result_t vit_tracker_add_camera_calibration(vit_tracker_t *tracker, const vit_camera_calibration_t *calibration);
448
449/*!
450 * Get the pose from the front of the tracking queue from the VIT tracker
451 *
452 * This function must be non-blocking and consumed by a single consummer.
453 *
454 * If @p out_pose is NULL the pose will be immediately destroyed.
455 *
456 * @param[out] out_pose Pose returned to the caller, NULL if there is not pose available or on error.
457 */
458vit_result_t vit_tracker_pop_pose(vit_tracker_t *tracker, vit_pose_t **out_pose);
459
460/*!
461 * Get the titles of the timestamps measured by the pose timings.
462 *
463 * Returns `VIT_ERROR_NOT_SUPPORTED` if the tracker doesn't offer the pose timing extension.
464 */
465vit_result_t vit_tracker_get_timing_titles(const vit_tracker_t *tracker, vit_tracker_timing_titles *out_titles);
466
467/*!
468 * Destroys a pose. All of the data, timing and features associated to it will be invalidated.
469 */
470void vit_pose_destroy(vit_pose_t *pose);
471
472/*!
473 * Gets the data form a given `vit_pose_t`.
474 *
475 * The data becomes invalid when the associated pose gets destroyed.
476 */
477vit_result_t vit_pose_get_data(const vit_pose_t *pose, vit_pose_data_t *out_data);
478
479/*!
480 * Gets the timing form a given `vit_pose_t`.
481 *
482 * The timing data becomes invalid when the associated pose gets destroyed.
483 */
484vit_result_t vit_pose_get_timing(const vit_pose_t *pose, vit_pose_timing_t *out_timing);
485
486/*!
487 * Gets the features form a given `vit_pose_t`.
488 *
489 * The features data becomes invalid when the associated pose gets destroyed.
490 */
491vit_result_t vit_pose_get_features(const vit_pose_t *pose, uint32_t camera_index, vit_pose_features_t *out_features);
492
493#endif
494
495#if defined(__cplusplus)
496}
497#endif