Monado OpenXR Runtime
Loading...
Searching...
No Matches
t_constellation_tracker_internal.hpp
Go to the documentation of this file.
1// Copyright 2026, Beyley Cardellio
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Internal ures for the constellation tracker.
6 * @author Beyley Cardellio <ep1cm1n10n123@gmail.com>
7 * @ingroup tracking
8 */
9
10#pragma once
11
12#include "xrt/xrt_config_build.h"
13#include "xrt/xrt_frame.h"
14#include "xrt/xrt_tracking.h"
15
16#include "util/u_debug.h"
17#include "util/u_logging.h"
18#include "util/u_var.h"
19#include "util/u_threading.h"
20#include "util/u_weak_ptr.hpp"
21#include "util/u_sink.h"
22#include "util/u_frame.h"
24
26
27#include "math/m_api.h"
28
29#include <vector>
30#include <memory>
31#include <mutex>
32#include <shared_mutex>
33#include <optional>
34#include <stdexcept>
35#include <array>
36#include <fstream>
37
39#include "led_search_model.h"
40#include "pose_optimize.h"
41#include "pose_metrics.h"
43
44
45#define CT_TRACE(ct, ...) U_LOG_IFL_T(ct->log_level, __VA_ARGS__)
46#define CT_DEBUG(ct, ...) U_LOG_IFL_D(ct->log_level, __VA_ARGS__)
47#define CT_INFO(ct, ...) U_LOG_IFL_I(ct->log_level, __VA_ARGS__)
48#define CT_WARN(ct, ...) U_LOG_IFL_W(ct->log_level, __VA_ARGS__)
49#define CT_ERROR(ct, ...) U_LOG_IFL_E(ct->log_level, __VA_ARGS__)
50
51#define MIN_ROT_ERROR DEG_TO_RAD(30)
52#define MIN_POS_ERROR 0.10
53
54/*
55 *
56 * Forward declares for C callback functions
57 *
58 */
59
60extern "C" void
61constellation_tracker_camera_push_blobs(t_blob_sink *tbs, t_blob_observation *tbo);
62
63extern "C" void
64constellation_tracker_camera_destroy(t_blob_sink *tbs);
65
66extern "C" void *
67constellation_tracker_camera_slow_thread(void *ptr);
68
69extern "C" void *
70constellation_tracker_camera_fast_thread(void *ptr);
71
72extern "C" void
73constellation_tracker_node_break_apart(xrt_frame_node *node);
74
75extern "C" void
76constellation_tracker_node_destroy(xrt_frame_node *node);
77
78
79namespace xrt::tracking::constellation {
80
81namespace os = xrt::auxiliary::os;
82
83// Forward-declares
84struct Camera;
85struct CameraMosaic;
86struct ConstellationTracker;
87struct DataRecorder;
88struct Device;
89
91{
92 //! The ID of the device.
93 t_constellation_device_id_t device_id{XRT_CONSTELLATION_INVALID_DEVICE_ID};
94
95 //! The "predicted" pose, which is the pose the device expects itself to be at at the time of the blobservation.
96 std::optional<xrt_pose> Txr_world_device_prior{std::nullopt};
97
98 //! The final found pose of the device in this specific sample.
99 std::optional<xrt_pose> Tcv_cam_device_found{std::nullopt};
100
101 //! Whether the device needs to have the slow processing thread run over it
103};
104
106{
107public: // Fields
108 t_blobwatch *source{nullptr};
109 uint64_t id{};
110 int64_t timestamp_ns{};
111 t_blob blobs[XRT_CONSTELLATION_MAX_BLOBS_PER_FRAME]{};
112 uint32_t blob_count{};
113
114 //! The camera's position in the constellation tracker's tracking origin
115 std::optional<xrt_pose> Txr_world_cam{std::nullopt};
116
117 std::array<DeviceState, XRT_CONSTELLATION_MAX_DEVICES> device_states{};
118 uint32_t device_count{};
119
120 uint32_t mosaic_index;
121 uint32_t camera_index;
122
123public: // Methods
124 std::optional<DeviceState *>
125 GetDeviceState(t_constellation_device_id_t device_id);
126
127 CameraSample(t_blob_observation &blobservation, Camera *camera);
128
129 CameraSample() = default;
130
131 void
132 MarkMatchingBlobs(ConstellationTracker *ct,
134 t_constellation_device_id_t device_id,
135 pose_metrics_blob_match_info &blob_match_info);
136
138 ToBlobObservation() const &
139 {
140 t_blob_observation obs = {
141 .source = this->source,
142 .id = this->id,
143 .timestamp_ns = this->timestamp_ns,
144 .blobs = const_cast<t_blob *>(this->blobs),
145 .num_blobs = this->blob_count,
146 };
147
148 return obs;
149 }
150
152 ToBlobObservation() && = delete;
154 ToBlobObservation() const && = delete;
155};
156
158{
159public: // Fields
160 //! Whether to draw the blobs in the sample
161 bool draw_blobs{true};
162 //! Whether to draw the raw blob IDs
163 bool draw_blob_ids{false};
164 //! Whether to draw the device IDs on the blobs where possible
165 bool draw_blob_device_ids{true};
166 //! Whether to draw the LED IDs on the blobs where possible
167 bool draw_blob_led_ids{false};
168
169 //! Whether to draw the prior device pose in the sample, if it exists.
170 bool draw_prior{false};
171 //! Whether to draw the final device pose in the sample, if it exists.
172 bool draw_found{false};
173
174public: // Methods
175 void
176 SetupDebugTracking(void *root);
177};
178
179struct Camera
180{
181public: // Fields
182 t_blob_sink base = {
183 .push_blobs = constellation_tracker_camera_push_blobs,
184 .destroy = constellation_tracker_camera_destroy,
185 };
186
187 //! The owner tracker, so we can retrieve it from the blob sink callback
189 std::weak_ptr<CameraMosaic> mosaic;
190
191 t_camera_calibration calibration;
192
193 camera_model model;
194
195 CameraScribbleSettings scribble_settings{};
196
197 //! The index in the mosaic
198 size_t index;
199
200 //! Does "slow" processing for this camera when fast recovery paths fail.
201 os_thread_helper slow_processing_thread{};
202 struct
203 {
204 std::optional<CameraSample> sample{std::nullopt};
205
206 correspondence_search *cs{nullptr};
207
208 u_sink_debug debug_sink{};
209 } slow_processing_thread_data;
210
211 /*!
212 * Does "fast" processing for this camera, trying to recover a pose quickly. It's valid for this to happen at
213 * the same time as a slow process.
214 */
215 os_thread_helper fast_processing_thread{};
216 struct
217 {
218 std::optional<CameraSample> sample{std::nullopt};
219
220 correspondence_search *cs{nullptr};
221
222 u_sink_debug debug_sink{};
223 } fast_processing_thread_data;
224
225 //! Locks all processing data
226 mutable os::Mutex processing_lock;
227 //! All data protected by the processing lock
228 struct
229 {
230 xrt_pose Txr_origin_cam;
231 bool has_concrete_pose;
232 } locked_data;
233
234public: // Methods (t_constellation_tracker.cpp)
235 static Camera *
236 Get(t_blob_sink *tbs)
237 {
238 return container_of(tbs, Camera, base);
239 }
240
241 Camera(ConstellationTracker *tracker,
242 std::weak_ptr<CameraMosaic> mosaic,
243 const t_constellation_tracker_camera &camera_params,
244 enum u_logging_level *log_level_ptr,
245 size_t index);
246
247 ~Camera();
248
249 // Delete all copy/move ctors, since the pointers for `base` need to be stable
250 Camera(const Camera &) = delete;
251 Camera(Camera &&) = delete;
252 Camera &
253 operator=(const Camera &) = delete;
254 Camera &
255 operator=(Camera &&) = delete;
256
257 std::optional<xrt_pose>
258 GetWorldPose(timepoint_ns when_ns);
259
260 void
261 DeferSampleToSlowThread(CameraSample &sample);
262
263 //! Fast matching based on prior pose
264 bool
265 TryDevicePose(std::unique_ptr<Device> &device,
266 CameraSample &sample,
267 xrt_pose &Tcv_cam_world,
268 std::optional<xrt_pose> &Tcv_world_device_prior,
269 xrt_pose &Tcv_world_device_candidate,
270 xrt_pose &Tcv_cam_device_found);
271
272 bool
273 TryDeviceBlobRecovery(std::unique_ptr<Device> &device,
274 CameraSample &sample,
275 xrt_pose &Tcv_cam_world,
276 std::optional<xrt_pose> &Tcv_world_device_prior,
277 xrt_pose &Tcv_cam_device_found);
278
279 void
280 SlowSampleProcess(CameraSample &sample);
281
282 //! Returns whether a slow search is needed
283 bool
284 FastSampleProcess(CameraSample &sample);
285
286 void
287 PushPose(CameraSample &sample,
288 std::unique_ptr<Device> &device,
289 pose_metrics &score,
290 xrt_pose &Tcv_cam_device,
291 bool optimize);
292
293public: // Public (constellation_debug_scribble.cpp)
294 void
295 DebugScribbleSample(CameraSample &sample, bool fast);
296};
297
299{
300public: // Fields
301 std::vector<std::unique_ptr<Camera>> cameras;
302 //! The index of this mosaic in the tracker.
303 size_t index;
304
306
307public: // Methods
309 const t_constellation_tracker_camera_mosaic &mosaic_params,
310 size_t index);
311
312 ~CameraMosaic() = default;
313
314 std::optional<xrt_pose>
315 GetTrackingOriginPose(timepoint_ns when_ns);
316};
317
318struct Device
319{
320public: // Fields
323
324 t_constellation_device_id_t id;
325
326 // @todo remove when clang-format is updated in CI
327 // clang-format off
328 t_constellation_search_model *search_model{nullptr};
329
330 // @todo These need to be pulled from the device and put into the sample.
331 // Right now we just hardcode them since we don't have any real sensor fusion.
332 xrt_vec3 prior_pos_error{MIN_POS_ERROR, MIN_POS_ERROR, MIN_POS_ERROR};
333 xrt_vec3 prior_rot_error{MIN_ROT_ERROR, MIN_ROT_ERROR, MIN_ROT_ERROR};
334 float gravity_error_rad{MIN_ROT_ERROR}; /* Gravity vector uncertainty in radians 0..M_PI */
335
336 mutable os::Mutex data_lock;
337 struct
338 {
339 std::optional<xrt_pose> Txr_world_device_last_known;
340 } locked_data;
341 // clang-format on
342
343public: // Methods
346 t_constellation_device_id_t id);
347
348 ~Device();
349};
350
351// Separate base struct with our interface implementations so that `ConstellationTrackerBase` remains a standard layout
352// type and we can safely use `container_of` on it.
354{
355 xrt_frame_node node = {
356 .next = nullptr,
357 .break_apart = constellation_tracker_node_break_apart,
358 .destroy = constellation_tracker_node_destroy,
359 };
360 xrt_tracking_origin tracking_origin = {
361 .name = "Constellation Tracker",
363 .initial_offset = XRT_POSE_IDENTITY,
364 };
365};
366
368{
369public: // Fields
370 //! Whether the constellation tracker is running
371 bool running = true;
372
373 enum u_logging_level log_level = U_LOGGING_WARN;
374
376
377 bool single_threaded{false};
378
379 std::vector<std::shared_ptr<CameraMosaic>> mosaics;
380
381 std::shared_mutex device_lock;
382 std::vector<std::unique_ptr<Device>> devices;
383 t_constellation_device_id_t next_device_id{0};
384
385 std::unique_ptr<DataRecorder> data_recorder{};
386
387#ifdef XRT_FEATURE_RERUN
388 std::unique_ptr<struct RerunContext> rerun_stream{};
389#endif
390
391public: // Methods
392 static ConstellationTracker *
393 Get(xrt_frame_node *node)
394 {
395 return static_cast<ConstellationTracker *>(container_of(node, ConstellationTrackerBase, node));
396 }
397
398 ConstellationTracker(t_constellation_tracker_params *params);
399
400 ~ConstellationTracker();
401
402 // Delete all copy/move ctors, since the pointers for `node` need to be stable
403 ConstellationTracker(const ConstellationTracker &) = delete;
404 ConstellationTracker(ConstellationTracker &&) = delete;
405 ConstellationTracker &
406 operator=(const ConstellationTracker &) = delete;
407 ConstellationTracker &
408 operator=(ConstellationTracker &&) = delete;
409
410 void
411 SetupVariableTracking();
412
413 t_constellation_device_id_t
415
416 void
417 RemoveDevice(t_constellation_device_id_t device_id);
418};
419
420}; // namespace xrt::tracking::constellation
Definition device.hpp:68
Ab-initio blob<->LED correspondence search.
u_logging_level
Logging level enum.
Definition u_logging.h:45
@ U_LOGGING_WARN
Warning messages: indicating a potential problem.
Definition u_logging.h:49
int64_t timepoint_ns
Integer timestamp type.
Definition u_time.h:77
#define container_of(ptr, type, field)
Get the holder from a pointer to a field.
Definition xrt_compiler.h:226
@ XRT_TRACKING_TYPE_CONSTELLATION
The device(s) are tracked through a constellation of lights as seen by cameras.
Definition xrt_tracking.h:63
LED search model management code.
C interface to math library.
Metrics for constellation tracking poses.
RANSAC PnP pose refinement.
Definition t_rift_blobwatch.c:82
Definition camera_model.h:19
Definition correspondence_search.h:92
All in one helper that handles locking, waiting for change and starting a thread.
Definition os_threading.h:499
Definition pose_metrics.h:85
Definition pose_metrics.h:61
Definition t_constellation.h:80
A generic interface to allow a tracking system to receive "snapshots" of seen t_blob in a frame.
Definition t_constellation.h:101
void(* push_blobs)(struct t_blob_sink *tbs, struct t_blob_observation *observation)
Push a set of blobs into the sink.
Definition t_constellation.h:109
A blob is a 2d position in a camera sensor's view that is being tracked.
Definition t_constellation.h:37
Definition t_constellation.h:152
Essential calibration data for a single camera, or single lens/sensor of a stereo camera.
Definition t_tracking.h:236
Definition led_search_model.h:40
A constellation tracker camera mosaic is a set of cameras that may or may not be physically attached,...
Definition t_constellation_tracker.h:60
A constellation tracker camera is a single camera that the constellation tracker will use to track de...
Definition t_constellation_tracker.h:34
Parameters for adding a device to the constellation tracker.
Definition t_constellation_tracker.h:79
A constellation tracker device is a device that the constellation tracker will attempt to track in 6d...
Definition t_constellation.h:327
The LED model is a series of points which define the real-world positions of all LEDs.
Definition t_constellation.h:266
Definition t_constellation_tracker.h:104
A constellation tracker tracking source is an arbitrary source of tracking data for the constellation...
Definition t_constellation.h:221
Allows more safely to debug sink inputs and outputs.
Definition u_sink.h:214
Definition t_constellation_tracker_internal.hpp:180
os::Mutex processing_lock
Locks all processing data.
Definition t_constellation_tracker_internal.hpp:226
ConstellationTracker * tracker
The owner tracker, so we can retrieve it from the blob sink callback.
Definition t_constellation_tracker_internal.hpp:188
size_t index
The index in the mosaic.
Definition t_constellation_tracker_internal.hpp:198
Definition t_constellation_tracker_internal.hpp:299
size_t index
The index of this mosaic in the tracker.
Definition t_constellation_tracker_internal.hpp:303
Definition t_constellation_tracker_internal.hpp:106
std::optional< xrt_pose > Txr_world_cam
The camera's position in the constellation tracker's tracking origin.
Definition t_constellation_tracker_internal.hpp:115
Definition t_constellation_tracker_internal.hpp:158
Definition t_constellation_tracker_internal.hpp:354
Definition t_constellation_tracker_internal.hpp:368
Definition t_constellation_tracker_internal.hpp:319
Definition t_constellation_tracker_internal.hpp:91
t_constellation_device_id_t device_id
The ID of the device.
Definition t_constellation_tracker_internal.hpp:93
std::optional< xrt_pose > Txr_world_device_prior
The "predicted" pose, which is the pose the device expects itself to be at at the time of the blobser...
Definition t_constellation_tracker_internal.hpp:96
std::optional< xrt_pose > Tcv_cam_device_found
The final found pose of the device in this specific sample.
Definition t_constellation_tracker_internal.hpp:99
bool needs_slow_processing
Whether the device needs to have the slow processing thread run over it.
Definition t_constellation_tracker_internal.hpp:102
A interface object used for destroying a frame graph.
Definition xrt_frame.h:87
void(* break_apart)(struct xrt_frame_node *node)
Called first in when the graph is being destroyed, remove any references frames and other objects and...
Definition xrt_frame.h:94
A pose composed of a position and orientation.
Definition xrt_defines.h:492
A tracking system or device origin.
Definition xrt_tracking.h:78
char name[256]
For debugging.
Definition xrt_tracking.h:80
A 3 element vector with single floats.
Definition xrt_defines.h:289
Header defining the tracking system integration in Monado.
Header defining the constellation tracker parameters and functions.
Small debug helpers.
xrt_frame helpers.
xrt_frame helpers for scribbling onto frames.
Basic logging functionality.
xrt_frame_sink converters and other helpers.
Slightly higher level thread safe helpers.
Variable tracking code.
C++ helpers for weak pointers.
Data frame header.
Header defining the tracking system integration in Monado.