2020-01-13 23:30:27 +00:00
|
|
|
// Copyright 2019-2020, Collabora, Ltd.
|
2019-07-23 16:29:14 +00:00
|
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
|
|
/*!
|
|
|
|
* @file
|
|
|
|
* @brief Tracking API interface.
|
|
|
|
* @author Pete Black <pblack@collabora.com>
|
|
|
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
2020-01-13 23:30:27 +00:00
|
|
|
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
2019-10-12 11:24:19 +00:00
|
|
|
* @ingroup aux_tracking
|
2019-07-23 16:29:14 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "xrt/xrt_frame.h"
|
|
|
|
|
2019-09-29 14:30:11 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
2019-07-23 16:29:14 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2019-10-12 11:24:19 +00:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* @defgroup aux_tracking Tracking
|
|
|
|
* @ingroup aux
|
|
|
|
* @brief Trackers, filters and associated helper code.
|
|
|
|
*
|
|
|
|
*
|
2019-11-09 12:47:57 +00:00
|
|
|
* ### Coordinate system
|
2019-10-12 11:24:19 +00:00
|
|
|
*
|
|
|
|
* Right now there is no specific convention on where a tracking systems
|
|
|
|
* coordinate system is centered, and is something we probably need to figure
|
|
|
|
* out. Right now the stereo based tracking system used by the PSVR and PSMV
|
|
|
|
* tracking system is centered on the camera that OpenCV decided is origin.
|
|
|
|
*
|
|
|
|
* To go a bit further on the PSVR/PSMV case. Think about a idealized start up
|
|
|
|
* case, the user is wearing the HMD headset and holding two PSMV controllers.
|
2019-11-09 12:47:57 +00:00
|
|
|
* The HMD's coordinate system axis are perfectly parallel with the user
|
|
|
|
* coordinate with the user's coordinate system. Where -Z is forward. The user
|
2019-10-12 11:24:19 +00:00
|
|
|
* holds the controllers with the ball pointing up and the buttons on the back
|
|
|
|
* pointing forward. Which if you read the documentation of @ref psmv_device
|
|
|
|
* will that the axis of the PSMV are also perfectly aligned with the users
|
|
|
|
* coordinate system. So everything "attached" to the user have it's coordinate
|
|
|
|
* system parallel to the user's.
|
|
|
|
*
|
|
|
|
* The camera on the other hand is looking directly at the user, it's Z-axis and
|
|
|
|
* X-axis is flipped in relation to the user's. So to compare what is sees to
|
|
|
|
* what the user sees, everything is rotated 180° around the Y-axis.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* @dir auxiliary/tracking
|
|
|
|
* @ingroup aux
|
|
|
|
*
|
|
|
|
* @brief Trackers, filters and associated helper code.
|
|
|
|
*/
|
|
|
|
|
2019-11-16 23:29:29 +00:00
|
|
|
/*!
|
|
|
|
* @ingroup aux_tracking
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2019-10-12 11:24:19 +00:00
|
|
|
|
2019-09-21 18:04:48 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Pre-declare
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct xrt_tracked_psmv;
|
2019-09-21 18:08:11 +00:00
|
|
|
struct xrt_tracked_psvr;
|
2019-11-16 23:17:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Calibration data.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2020-01-13 23:30:27 +00:00
|
|
|
//! Maximum size of rectilinear distortion coefficient array
|
|
|
|
#define XRT_DISTORTION_MAX_DIM (5)
|
|
|
|
|
2019-11-16 23:17:11 +00:00
|
|
|
/*!
|
2020-01-13 23:30:27 +00:00
|
|
|
* @brief Essential calibration data for a single camera, or single lens/sensor
|
|
|
|
* of a stereo camera.
|
2019-11-16 23:17:11 +00:00
|
|
|
*/
|
2020-01-13 23:30:27 +00:00
|
|
|
struct t_camera_calibration
|
2019-11-16 23:17:11 +00:00
|
|
|
{
|
2020-01-13 23:30:27 +00:00
|
|
|
//! Source image size
|
2019-11-16 23:17:11 +00:00
|
|
|
struct xrt_size image_size_pixels;
|
2019-11-16 23:27:32 +00:00
|
|
|
|
2020-01-13 23:30:27 +00:00
|
|
|
//! Camera intrinsics matrix
|
|
|
|
double intrinsics[3][3];
|
|
|
|
|
|
|
|
//! Rectilinear distortion coefficients: k1, k2, p1, p2[, k3[, k4, k5,
|
|
|
|
//! k6[, s1, s2, s3, s4]]
|
|
|
|
double distortion[XRT_DISTORTION_MAX_DIM];
|
2019-11-16 23:17:11 +00:00
|
|
|
|
2020-01-13 23:30:27 +00:00
|
|
|
//! Fisheye camera distortion coefficients
|
|
|
|
double distortion_fisheye[4];
|
|
|
|
|
|
|
|
//! Is the camera fisheye?
|
|
|
|
bool use_fisheye;
|
|
|
|
};
|
2019-11-16 23:17:11 +00:00
|
|
|
/*!
|
2020-01-13 23:30:27 +00:00
|
|
|
* Stereo camera calibration data to be given to trackers.
|
2019-11-16 23:17:11 +00:00
|
|
|
*/
|
2020-01-13 23:30:27 +00:00
|
|
|
struct t_stereo_camera_calibration
|
2019-11-16 23:17:11 +00:00
|
|
|
{
|
2020-01-16 14:57:36 +00:00
|
|
|
//! Calibration of individual views/sensor
|
|
|
|
struct t_camera_calibration view[2];
|
2020-01-13 23:30:27 +00:00
|
|
|
|
|
|
|
//! Source image size.
|
2019-11-16 23:17:11 +00:00
|
|
|
struct xrt_size image_size_pixels;
|
|
|
|
|
2020-01-16 14:57:36 +00:00
|
|
|
//! Translation from first to second in the stereo pair.
|
2019-11-16 23:17:11 +00:00
|
|
|
double camera_translation[3];
|
2020-01-16 14:57:36 +00:00
|
|
|
//! Rotation matrix from first to second in the stereo pair.
|
2019-11-16 23:17:11 +00:00
|
|
|
double camera_rotation[3][3];
|
2020-01-13 23:30:27 +00:00
|
|
|
|
2019-11-16 23:17:11 +00:00
|
|
|
//! Essential matrix.
|
|
|
|
double camera_essential[3][3];
|
|
|
|
//! Fundamental matrix.
|
|
|
|
double camera_fundamental[3][3];
|
|
|
|
};
|
|
|
|
|
2019-11-17 12:37:19 +00:00
|
|
|
|
2019-11-16 23:17:11 +00:00
|
|
|
/*!
|
|
|
|
* Free stereo calibration data.
|
|
|
|
*/
|
|
|
|
void
|
2020-01-13 23:30:27 +00:00
|
|
|
t_stereo_camera_calibration_free(struct t_stereo_camera_calibration **data_ptr);
|
2019-11-16 23:17:11 +00:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* Load stereo calibration data from a given file.
|
|
|
|
*/
|
|
|
|
bool
|
2020-01-13 23:30:27 +00:00
|
|
|
t_stereo_camera_calibration_load_v1(
|
|
|
|
FILE *calib_file, struct t_stereo_camera_calibration **out_data);
|
2019-11-16 23:17:11 +00:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* Load a stereo calibration struct from a hardcoded place.
|
|
|
|
*/
|
|
|
|
bool
|
2020-01-13 23:30:27 +00:00
|
|
|
t_stereo_camera_calibration_load_v1_hack(
|
|
|
|
struct t_stereo_camera_calibration **out_data);
|
2019-09-21 18:04:48 +00:00
|
|
|
|
2019-07-23 16:29:14 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Conversion functions.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct t_convert_table
|
|
|
|
{
|
|
|
|
uint8_t v[256][256][256][3];
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
t_convert_fill_table(struct t_convert_table *t);
|
|
|
|
|
|
|
|
void
|
|
|
|
t_convert_make_y8u8v8_to_r8g8b8(struct t_convert_table *t);
|
|
|
|
|
|
|
|
void
|
|
|
|
t_convert_make_y8u8v8_to_h8s8v8(struct t_convert_table *t);
|
|
|
|
|
|
|
|
void
|
|
|
|
t_convert_make_h8s8v8_to_r8g8b8(struct t_convert_table *t);
|
|
|
|
|
|
|
|
void
|
|
|
|
t_convert_in_place_y8u8v8_to_r8g8b8(uint32_t width,
|
|
|
|
uint32_t height,
|
|
|
|
size_t stride,
|
|
|
|
void *data_ptr);
|
|
|
|
|
|
|
|
void
|
|
|
|
t_convert_in_place_y8u8v8_to_h8s8v8(uint32_t width,
|
|
|
|
uint32_t height,
|
|
|
|
size_t stride,
|
|
|
|
void *data_ptr);
|
|
|
|
|
|
|
|
void
|
|
|
|
t_convert_in_place_h8s8v8_to_r8g8b8(uint32_t width,
|
|
|
|
uint32_t height,
|
|
|
|
size_t stride,
|
|
|
|
void *data_ptr);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Filter functions.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define T_HSV_SIZE 32
|
|
|
|
#define T_HSV_STEP (256 / T_HSV_SIZE)
|
|
|
|
|
|
|
|
#define T_HSV_DEFAULT_PARAMS() \
|
|
|
|
{ \
|
|
|
|
{ \
|
|
|
|
{165, 30, 160, 100}, \
|
|
|
|
{135, 30, 160, 100}, \
|
|
|
|
{95, 30, 160, 100}, \
|
|
|
|
}, \
|
|
|
|
{128, 80}, \
|
|
|
|
}
|
|
|
|
|
|
|
|
struct t_hsv_filter_color
|
|
|
|
{
|
|
|
|
uint8_t hue_min;
|
|
|
|
uint8_t hue_range;
|
|
|
|
|
|
|
|
uint8_t s_min;
|
|
|
|
|
|
|
|
uint8_t v_min;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct t_hsv_filter_params
|
|
|
|
{
|
|
|
|
struct t_hsv_filter_color color[3];
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
uint8_t s_max;
|
|
|
|
uint8_t v_min;
|
|
|
|
} white;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct t_hsv_filter_large_table
|
|
|
|
{
|
|
|
|
uint8_t v[256][256][256];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct t_hsv_filter_optimized_table
|
|
|
|
{
|
|
|
|
uint8_t v[T_HSV_SIZE][T_HSV_SIZE][T_HSV_SIZE];
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
t_hsv_build_convert_table(struct t_hsv_filter_params *params,
|
|
|
|
struct t_convert_table *t);
|
|
|
|
|
|
|
|
void
|
|
|
|
t_hsv_build_large_table(struct t_hsv_filter_params *params,
|
|
|
|
struct t_hsv_filter_large_table *t);
|
|
|
|
|
|
|
|
void
|
|
|
|
t_hsv_build_optimized_table(struct t_hsv_filter_params *params,
|
|
|
|
struct t_hsv_filter_optimized_table *t);
|
|
|
|
|
|
|
|
XRT_MAYBE_UNUSED static inline uint8_t
|
|
|
|
t_hsv_filter_sample(struct t_hsv_filter_optimized_table *t,
|
|
|
|
uint32_t y,
|
|
|
|
uint32_t u,
|
|
|
|
uint32_t v)
|
|
|
|
{
|
|
|
|
return t->v[y / T_HSV_STEP][u / T_HSV_STEP][v / T_HSV_STEP];
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2019-08-22 13:15:41 +00:00
|
|
|
t_hsv_filter_create(struct xrt_frame_context *xfctx,
|
|
|
|
struct t_hsv_filter_params *params,
|
2019-07-23 16:29:14 +00:00
|
|
|
struct xrt_frame_sink *sinks[4],
|
|
|
|
struct xrt_frame_sink **out_sink);
|
|
|
|
|
|
|
|
|
2019-09-21 18:04:48 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Tracker code.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
t_psmv_start(struct xrt_tracked_psmv *xtmv);
|
|
|
|
|
|
|
|
int
|
|
|
|
t_psmv_create(struct xrt_frame_context *xfctx,
|
|
|
|
struct xrt_colour_rgb_f32 *rgb,
|
2020-01-13 23:30:27 +00:00
|
|
|
struct t_stereo_camera_calibration *data,
|
2019-09-21 18:04:48 +00:00
|
|
|
struct xrt_tracked_psmv **out_xtmv,
|
|
|
|
struct xrt_frame_sink **out_sink);
|
|
|
|
|
2019-09-21 18:08:11 +00:00
|
|
|
int
|
|
|
|
t_psvr_start(struct xrt_tracked_psvr *xtvr);
|
|
|
|
|
|
|
|
int
|
|
|
|
t_psvr_create(struct xrt_frame_context *xfctx,
|
2020-01-13 23:30:27 +00:00
|
|
|
struct t_stereo_camera_calibration *data,
|
2019-09-21 18:08:11 +00:00
|
|
|
struct xrt_tracked_psvr **out_xtvr,
|
|
|
|
struct xrt_frame_sink **out_sink);
|
|
|
|
|
2019-11-16 23:17:11 +00:00
|
|
|
|
2019-09-27 19:11:17 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Camera calibration
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define T_CALIBRATION_DEFAULT_PARAMS \
|
|
|
|
{ \
|
2019-11-22 11:41:36 +00:00
|
|
|
false, T_BOARD_CHECKERS, \
|
|
|
|
{ \
|
|
|
|
9, 7, 0.025f, true, 5, \
|
|
|
|
}, \
|
|
|
|
{ \
|
|
|
|
9, \
|
|
|
|
7, \
|
|
|
|
0.025f, \
|
|
|
|
}, \
|
|
|
|
{ \
|
|
|
|
5, \
|
|
|
|
17, \
|
|
|
|
0.02f, \
|
|
|
|
}, \
|
2019-11-22 14:20:19 +00:00
|
|
|
{ \
|
|
|
|
false, \
|
|
|
|
20, \
|
|
|
|
}, \
|
2020-01-14 20:38:58 +00:00
|
|
|
20, 5, 20, 1, false, true \
|
2019-09-27 19:11:17 +00:00
|
|
|
}
|
|
|
|
|
2019-11-22 11:41:36 +00:00
|
|
|
/*!
|
|
|
|
* Board pattern type.
|
|
|
|
*/
|
|
|
|
enum t_board_pattern
|
|
|
|
{
|
|
|
|
T_BOARD_CHECKERS,
|
|
|
|
T_BOARD_CIRCLES,
|
|
|
|
T_BOARD_ASYMMETRIC_CIRCLES,
|
|
|
|
};
|
|
|
|
|
2020-01-14 20:38:58 +00:00
|
|
|
struct t_calibration_status
|
|
|
|
{
|
|
|
|
//! Is calibration finished?
|
|
|
|
bool finished;
|
|
|
|
//! Was the target found this frame?
|
|
|
|
bool found;
|
|
|
|
//! Number of frames collected
|
|
|
|
int num_collected;
|
|
|
|
//! Number of moving frames before another capture
|
|
|
|
int cooldown;
|
|
|
|
//! Number of non-moving frames before capture.
|
|
|
|
int waits_remaining;
|
|
|
|
};
|
|
|
|
|
2019-09-27 19:11:17 +00:00
|
|
|
struct t_calibration_params
|
|
|
|
{
|
2019-11-20 23:46:12 +00:00
|
|
|
//! Should we use fisheye version of the calibration functions.
|
|
|
|
bool use_fisheye;
|
|
|
|
|
2019-11-22 11:41:36 +00:00
|
|
|
//! What type of pattern are we using for calibration.
|
|
|
|
enum t_board_pattern pattern;
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
int cols;
|
|
|
|
int rows;
|
|
|
|
float size_meters;
|
|
|
|
|
|
|
|
bool subpixel_enable;
|
|
|
|
int subpixel_size;
|
|
|
|
} checkers;
|
2019-09-28 01:45:28 +00:00
|
|
|
|
2019-11-22 11:41:36 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
int cols;
|
|
|
|
int rows;
|
|
|
|
float distance_meters;
|
|
|
|
} circles;
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
int cols;
|
|
|
|
int rows;
|
|
|
|
float diagonal_distance_meters;
|
|
|
|
} asymmetric_circles;
|
2019-11-18 19:13:12 +00:00
|
|
|
|
2019-11-22 14:20:19 +00:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
bool enabled;
|
|
|
|
int num_images;
|
|
|
|
} load;
|
|
|
|
|
2019-11-22 12:20:53 +00:00
|
|
|
int num_cooldown_frames;
|
2019-11-19 23:38:48 +00:00
|
|
|
int num_wait_for;
|
|
|
|
int num_collect_total;
|
|
|
|
int num_collect_restart;
|
2019-11-20 21:58:17 +00:00
|
|
|
|
2019-11-21 22:35:39 +00:00
|
|
|
/*!
|
|
|
|
* Should we mirror the RGB image?
|
|
|
|
*
|
|
|
|
* Before text is written out, has no effect on actual image capture.
|
|
|
|
*/
|
|
|
|
bool mirror_rgb_image;
|
|
|
|
|
2019-11-20 21:58:17 +00:00
|
|
|
bool save_images;
|
2019-09-27 19:11:17 +00:00
|
|
|
};
|
|
|
|
|
2020-01-14 20:38:58 +00:00
|
|
|
/*!
|
|
|
|
* @brief Create the camera calibration frame sink.
|
|
|
|
*
|
|
|
|
* @param xfctx Context for frame transport.
|
|
|
|
* @param params Parameters to use during calibration. Values copied, pointer
|
|
|
|
* not retained.
|
|
|
|
* @param status Optional pointer to structure for status information. Pointer
|
|
|
|
* retained, and pointed-to struct modified.
|
|
|
|
* @param gui Frame sink
|
|
|
|
* @param out_sink Output: created frame sink.
|
|
|
|
*/
|
2019-09-27 19:11:17 +00:00
|
|
|
int
|
|
|
|
t_calibration_stereo_create(struct xrt_frame_context *xfctx,
|
2020-01-14 20:38:58 +00:00
|
|
|
const struct t_calibration_params *params,
|
|
|
|
struct t_calibration_status *status,
|
2019-09-27 19:11:17 +00:00
|
|
|
struct xrt_frame_sink *gui,
|
|
|
|
struct xrt_frame_sink **out_sink);
|
|
|
|
|
2019-09-21 18:04:48 +00:00
|
|
|
|
2019-07-23 16:29:14 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Sink creation functions.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
t_convert_yuv_or_yuyv_create(struct xrt_frame_sink *next,
|
|
|
|
struct xrt_frame_sink **out_sink);
|
|
|
|
|
2019-09-27 19:11:17 +00:00
|
|
|
|
2019-07-23 16:29:14 +00:00
|
|
|
|
|
|
|
int
|
2019-08-22 13:15:41 +00:00
|
|
|
t_debug_hsv_picker_create(struct xrt_frame_context *xfctx,
|
|
|
|
struct xrt_frame_sink *passthrough,
|
2019-07-23 16:29:14 +00:00
|
|
|
struct xrt_frame_sink **out_sink);
|
|
|
|
|
|
|
|
int
|
2019-08-22 13:15:41 +00:00
|
|
|
t_debug_hsv_viewer_create(struct xrt_frame_context *xfctx,
|
|
|
|
struct xrt_frame_sink *passthrough,
|
2019-07-23 16:29:14 +00:00
|
|
|
struct xrt_frame_sink **out_sink);
|
|
|
|
|
|
|
|
int
|
2019-08-22 13:15:41 +00:00
|
|
|
t_debug_hsv_filter_create(struct xrt_frame_context *xfctx,
|
|
|
|
struct xrt_frame_sink *passthrough,
|
2019-07-23 16:29:14 +00:00
|
|
|
struct xrt_frame_sink **out_sink);
|
|
|
|
|
2019-10-12 11:24:19 +00:00
|
|
|
/*!
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
2019-07-23 16:29:14 +00:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|