Monado OpenXR Runtime
Loading...
Searching...
No Matches
hg_sync.hpp
Go to the documentation of this file.
1// Copyright 2022, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Mercury main header!
6 * @author Jakob Bornecrantz <jakob@collabora.com>
7 * @author Moshi Turner <moshiturner@protonmail.com>
8 * @ingroup tracking
9 */
10
11#pragma once
12
13#include "hg_interface.h"
14#include "hg_hand_size_opt.hpp"
16
19
20#include "onnx/onnx_wrapper.hpp"
21
22#include "xrt/xrt_defines.h"
23#include "xrt/xrt_frame.h"
24#include "xrt/xrt_tracking.h"
25
26#include "math/m_api.h"
27#include "math/m_vec2.h"
28#include "math/m_vec3.h"
29#include "math/m_mathinclude.h"
31
33#include "util/u_logging.h"
34#include "util/u_sink.h"
36#include "util/u_worker.h"
37#include "util/u_trace_marker.h"
38#include "util/u_debug.h"
39#include "util/u_frame.h"
40#include "util/u_var.h"
41
42#include <assert.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include <stdint.h>
47
48#include <opencv2/opencv.hpp>
49#include <onnxruntime_c_api.h>
50
51#include "kine_common.hpp"
53
54
55namespace xrt::tracking::hand::mercury {
56
57using namespace xrt::auxiliary::util;
58using namespace xrt::auxiliary::math;
59using namespace xrt::auxiliary::onnx;
60
61#define HG_TRACE(hgt, ...) U_LOG_IFL_T(hgt->log_level, __VA_ARGS__)
62#define HG_DEBUG(hgt, ...) U_LOG_IFL_D(hgt->log_level, __VA_ARGS__)
63#define HG_INFO(hgt, ...) U_LOG_IFL_I(hgt->log_level, __VA_ARGS__)
64#define HG_WARN(hgt, ...) U_LOG_IFL_W(hgt->log_level, __VA_ARGS__)
65#define HG_ERROR(hgt, ...) U_LOG_IFL_E(hgt->log_level, __VA_ARGS__)
66
67static constexpr uint16_t kDetectionInputSize = 160;
68static constexpr uint16_t kKeypointInputSize = 128;
69
70static constexpr uint16_t kKeypointOutputHeatmapSize = 22;
71static constexpr uint16_t kVisSpacerSize = 8;
72
73static const cv::Scalar RED(255, 30, 30);
74static const cv::Scalar YELLOW(255, 255, 0);
75static const cv::Scalar PINK(255, 0, 255);
76static const cv::Scalar GREEN(0, 255, 0);
77
78static const cv::Scalar colors[2] = {YELLOW, RED};
79
80constexpr enum xrt_hand_joint joints_5x5_to_26[5][5] = {
81 {
82 XRT_HAND_JOINT_WRIST,
83 XRT_HAND_JOINT_THUMB_METACARPAL,
84 XRT_HAND_JOINT_THUMB_PROXIMAL,
85 XRT_HAND_JOINT_THUMB_DISTAL,
86 XRT_HAND_JOINT_THUMB_TIP,
87 },
88 {
89 XRT_HAND_JOINT_INDEX_METACARPAL,
90 XRT_HAND_JOINT_INDEX_PROXIMAL,
91 XRT_HAND_JOINT_INDEX_INTERMEDIATE,
92 XRT_HAND_JOINT_INDEX_DISTAL,
93 XRT_HAND_JOINT_INDEX_TIP,
94 },
95 {
96 XRT_HAND_JOINT_MIDDLE_METACARPAL,
97 XRT_HAND_JOINT_MIDDLE_PROXIMAL,
98 XRT_HAND_JOINT_MIDDLE_INTERMEDIATE,
99 XRT_HAND_JOINT_MIDDLE_DISTAL,
100 XRT_HAND_JOINT_MIDDLE_TIP,
101 },
102 {
103 XRT_HAND_JOINT_RING_METACARPAL,
104 XRT_HAND_JOINT_RING_PROXIMAL,
105 XRT_HAND_JOINT_RING_INTERMEDIATE,
106 XRT_HAND_JOINT_RING_DISTAL,
107 XRT_HAND_JOINT_RING_TIP,
108 },
109 {
110 XRT_HAND_JOINT_LITTLE_METACARPAL,
111 XRT_HAND_JOINT_LITTLE_PROXIMAL,
112 XRT_HAND_JOINT_LITTLE_INTERMEDIATE,
113 XRT_HAND_JOINT_LITTLE_DISTAL,
114 XRT_HAND_JOINT_LITTLE_TIP,
115 },
116};
117
118namespace ROIProvenance {
119 enum ROIProvenance
120 {
121 HAND_DETECTION,
122 POSE_PREDICTION
123 };
124}
125
126
127// Forward declaration for ht_view
128struct HandTracking;
129struct ht_view;
130
131
132struct Hand3D
133{
134 struct xrt_vec3 kps[21];
135};
136
137using hand21_2d = std::array<vec2_5, 21>;
138
140{
141 Eigen::Quaternionf rot_quat = Eigen::Quaternionf::Identity();
142 float stereographic_radius = 0;
143 bool flip = false;
144 const t_camera_model_params &dist;
145
146 projection_instructions(const t_camera_model_params &dist) : dist(dist) {}
147};
148
150{
151 float *data = nullptr;
152 int64_t dimensions[4];
153 size_t num_dimensions = 0;
154
155 OrtValue *tensor = nullptr;
156 const char *name;
157};
158
160{
161 std::unique_ptr<OnnxWrapper> wrap = {};
162
163 std::vector<model_input_wrap> wraps = {};
164};
165
166// Multipurpose.
167// * Hand detector writes into center_px, size_px, found and hand_detection_confidence
168// * Keypoint estimator operates on this to a direction/radius for the stereographic projection, and for the associated
169// keypoints.
171{
172 ROIProvenance::ROIProvenance provenance;
173
174 // Either set by the detection model or by predict_new_regions_of_interest/back_project
175 xrt_vec2 center_px;
176 float size_px;
177
178 bool found;
179 float hand_detection_confidence;
180};
181
182
183
185{
186 ht_view *view;
187 // These are not duplicates of ht_view's regions_of_interest_this_frame!
188 // If some hands are already tracked, we have logic that only copies new ROIs to this frame's regions of
189 // interest.
190 hand_region_of_interest outputs[2];
191};
192
193
195{
196 ht_view *view;
197 bool hand_idx;
198};
199
201{
202 HandTracking *hgt;
203 onnx_state detection;
204 onnx_state keypoint[2];
205 int view;
206
207 struct t_camera_extra_info_one_view camera_info;
208
209 t_camera_model_params hgdist_orig;
210 // With fx, fy, cx, cy scaled to the current camera resolution as appropriate.
212
213
214 cv::Mat run_model_on_this;
215 cv::Mat debug_out_to_this;
216
217 struct hand_region_of_interest regions_of_interest_this_frame[2]; // left, right
218
219 struct keypoint_estimation_run_info run_info[2];
220};
221
223{
224 // After setup, these reference the same piece of memory.
225 cv::Mat mat;
226 xrt_frame *xrtframe = NULL;
227
228 // After pushing to the debug UI, we reference the frame here so that we can copy memory out of it for next
229 // frame.
230 xrt_frame *old_frame = NULL;
231};
232
233/*!
234 * Main class of Mercury hand tracking.
235 *
236 * @ingroup aux_tracking
237 */
239{
240public:
241 // Base thing, has to be first.
242 t_hand_tracking_sync base = {};
243
244 struct u_sink_debug debug_sink_ann = {};
245 struct u_sink_debug debug_sink_model = {};
246 struct xrt_hand_masks_sink *hand_masks_sink;
247
248 float multiply_px_coord_for_undistort;
249
250
251 struct t_stereo_camera_calibration *calib;
252
253 struct xrt_size calibration_one_view_size_px = {};
254
255 // So that we can calibrate cameras at 1280x800 but ship images over USB at 640x400
256 struct xrt_size last_frame_one_view_size_px = {};
257
258 struct ht_view views[2] = {};
259
260 struct model_output_visualizers visualizers;
261
263
265
266
267 float baseline = {};
268 xrt_pose hand_pose_camera_offset = {};
269
270 uint64_t current_frame_timestamp = {};
271
272 bool debug_scribble = false;
273
274 char models_folder[1024];
275
276 enum u_logging_level log_level = U_LOGGING_INFO;
277
278 lm::KinematicHandLM *kinematic_hands[2];
279
280 // These are produced by the keypoint estimator and consumed by the nonlinear optimizer
281 // left hand, right hand THEN left view, right view
282 struct one_frame_input keypoint_outputs[2];
283
284 // Used to track whether this hand has *ever* been seen during this user's session, so that we can spend some
285 // extra time optimizing their hand size if one of their hands isn't visible for the first bit.
286 bool hand_seen_before[2] = {false, false};
287
288 // Used to:
289 // * see if a hand is currently being tracked.
290 // * If so, don't replace the bounding box with that from a hand detection.
291 // * Also, if both hands are being tracked, we just don't run the hand detector.
292 bool last_frame_hand_detected[2] = {false, false};
293
294 // Used to decide whether to run the keypoint estimator/nonlinear optimizer.
295 bool this_frame_hand_detected[2] = {false, false};
296
297 // Used to determine pose-predicted regions of interest. Contains the last 2 hand keypoint positions, or less
298 // if the hand has just started being tracked.
299 HistoryBuffer<Eigen::Array<float, 3, 21>, 2> history_hands[2] = {};
300
301 // Contains the last 2 timestamps, or less if hand tracking has just started.
302 HistoryBuffer<uint64_t, 2> history_timestamps = {};
303
304 // It'd be a staring contest between your hand and the heat death of the universe!
305 uint64_t hand_tracked_for_num_frames[2] = {0, 0};
306
307
308 // left hand, right hand
309 Eigen::Array<float, 3, 21> pose_predicted_keypoints[2];
310
311 int detection_counter = 0;
312
313 /// Regularly updated from `hand_size_refinement`.
314 float target_hand_size = STANDARD_HAND_SIZE;
315
316
317 xrt_frame *debug_frame;
318
319
320 // This should be removed.
321 void (*keypoint_estimation_run_func)(void *);
322
323
324
325 struct xrt_pose left_in_right = {};
326
327 u_frame_times_widget ft_widget = {};
328
329 struct hg_tuneable_values tuneable_values;
330
331 HandSizeRefinement hand_size_refinement{};
332
333public:
334 explicit HandTracking();
335 ~HandTracking();
336
337 static inline HandTracking &
338 fromC(t_hand_tracking_sync *ht_sync)
339 {
340 return *reinterpret_cast<HandTracking *>(ht_sync);
341 }
342
343 static void
344 cCallbackProcess(struct t_hand_tracking_sync *ht_sync,
345 struct xrt_frame *left_frame,
346 struct xrt_frame *right_frame,
347 struct xrt_hand_joint_set *out_left_hand,
348 struct xrt_hand_joint_set *out_right_hand,
349 int64_t *out_timestamp_ns);
350
351 static void
352 cCallbackDestroy(t_hand_tracking_sync *ht_sync);
353};
354
355
356void
357init_hand_detection(HandTracking *hgt, onnx_state *wrap);
358
359void
360init_keypoint_estimation(HandTracking *hgt, onnx_state *wrap);
361
362// These are passed into C callbacks, so they have to be extern "C".
363extern "C" {
364//! Runs hand detection, expects `ptr` to be a `hand_detection_run_info *`
365void
366run_hand_detection(void *ptr);
367
368//! Runs keypoint estimation, excpets `ptr` to be a `keypoint_estimation_run_info *`
369void
370run_keypoint_estimation(void *ptr);
371};
372
373void
374release_onnx_state(onnx_state *wrap);
375
376
377void
379 bool flip_after,
380 float expand_val,
381 float twist,
382 Eigen::Array<float, 3, 21> &joints,
383 projection_instructions &out_instructions,
384 hand21_2d &out_hand);
385
386
387void
388make_projection_instructions_angular(xrt_vec3 direction_3d,
389 bool flip_after,
390 float angular_radius,
391 float expand_val,
392 float twist,
393 projection_instructions &out_instructions);
394
395void
396stereographic_project_image(const t_camera_model_params &dist,
397 const projection_instructions &instructions,
398 cv::Mat &input_image,
399 cv::Mat *debug_image,
400 const cv::Scalar &boundary_color,
401 cv::Mat &out);
402
403
404
405} // namespace xrt::tracking::hand::mercury
Stores some number of values in a ring buffer, overwriting the earliest-pushed-remaining element if o...
Definition u_template_historybuf.hpp:38
u_logging_level
Logging level enum.
Definition u_logging.h:45
@ U_LOGGING_INFO
Info messages: not very verbose, not indicating a problem.
Definition u_logging.h:48
xrt_hand_joint
Number of joints in a hand.
Definition xrt_defines.h:1452
Debug instrumentation for mercury_train or others to control hand tracking.
Mercury hand size optimization heuristics.
void make_projection_instructions(t_camera_model_params &dist, bool flip_after, float expand_val, float twist, Eigen::Array< float, 3, 21 > &joints, projection_instructions &out_instructions, hand21_2d &out_hand)
Definition hg_image_distorter.cpp:494
Public interface of Mercury hand tracking.
Random common stuff for Mercury kinematic optimizers.
Interface for Levenberg-Marquardt kinematic optimizer.
C interface to math library.
Interoperability helpers connecting internal math types and Eigen.
Wrapper header for <math.h> to ensure pi-related math constants are defined.
C vec2 math library.
C vec3 math library.
C++-only functionality in the Math helper library.
Definition m_documentation.hpp:15
onnxruntime wrapper objects and functions.
Definition u_worker.c:91
Definition hg_debug_instrumentation.hpp:23
Definition u_worker.c:50
Information about image boundary and camera orientation for one view.
Definition t_hand_tracking.h:82
Floating point calibration data for a single calibrated camera.
Definition t_camera_models.h:47
Synchronously processes frames and returns two hands.
Definition t_hand_tracking.h:120
Stereo camera calibration data to be given to trackers.
Definition t_tracking.h:261
Definition u_frame_times_widget.h:24
Allows more safely to debug sink inputs and outputs.
Definition u_sink.h:214
A worker group where you submit tasks to.
Definition u_worker.h:102
A worker pool, can shared between multiple groups worker pool.
Definition u_worker.h:33
Definition hg_sync.hpp:133
Main class of Mercury hand tracking.
Definition hg_sync.hpp:239
float target_hand_size
Regularly updated from hand_size_refinement.
Definition hg_sync.hpp:314
Definition hg_sync.hpp:201
Basic frame data structure - holds a pointer to buffer.
Definition xrt_frame.h:25
Joint set type used for hand tracking.
Definition xrt_defines.h:1531
An object to push xrt_hand_masks_sample to.
Definition xrt_tracking.h:204
A pose composed of a position and orientation.
Definition xrt_defines.h:502
Image size.
Definition xrt_defines.h:446
A 2 element vector with single floats.
Definition xrt_defines.h:268
A 3 element vector with single floats.
Definition xrt_defines.h:299
Camera (un)projection C API for various camera models.
Hand tracking interfaces.
Small debug helpers.
xrt_frame helpers.
Shared code for visualizing frametimes.
Basic logging functionality.
xrt_frame_sink converters and other helpers.
Ringbuffer implementation for keeping track of the past state of things.
Tracing support code, see Tracing support.
Variable tracking code.
Worker and threading pool.
Common defines and enums for XRT.
Data frame header.
Header defining the tracking system integration in Monado.