Monado OpenXR Runtime
Loading...
Searching...
No Matches
rig_calibration.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 Constellation tracker rig calibration.
6 * @author Beyley Cardellio <ep1cm1n10n123@gmail.com>
7 * @ingroup tracking
8 */
9
10#pragma once
11
12// Included for XRT_FEATURE_RERUN, which the layout of RigCalibration depends on.
13#include "xrt/xrt_config_build.h"
14
15#include "os/os_threading.h"
16
17#include "util/u_var.h"
18
20
21#include "pose_optimize.hpp"
22#include "math.hpp"
23
24#include <vector>
25#include <array>
26#include <map>
27#include <memory>
28
29
30namespace xrt::tracking::constellation {
31
32// Declared here rather than included, since the tracker's internal header is the one that includes this file.
33struct CameraSample;
34struct ConstellationTracker;
35
36}; // namespace xrt::tracking::constellation
37
38namespace xrt::tracking::constellation::optimizer::rig_calibration {
39
40using namespace xrt::tracking::constellation;
41namespace os = xrt::auxiliary::os;
42
43/*!
44 * One camera's view of one device at one exposure, as the LED correspondences the tracker labelled.
45 */
47{
48public: // Fields
49 uint32_t mosaic_idx;
50 uint32_t camera_idx;
51
52 timepoint_ns timestamp_ns;
53
54 /*!
55 * The seed pose that the tracker recovered. This may not have any actual measurement taken into account.
56 */
58
59 uint32_t num_points;
60 //! The 2D blob points
61 std::array<xrt_vec2, XRT_CONSTELLATION_MAX_LEDS_PER_DEVICE> points2d;
62 //! The 3D blob points, in the device's frame. Same order as @ref points2d.
63 std::array<xrt_vec3, XRT_CONSTELLATION_MAX_LEDS_PER_DEVICE> points3d;
64};
65
67{
68public: // Fields
69 std::vector<DeviceCameraSample> camera_samples;
70 std::vector<xrt_imu_sample> imu_samples;
71
72public: // Methods
74};
75
77{
78public: // Fields
79 size_t mosaic_idx;
80 size_t camera_idx;
81
82 //! Intrinsics and distortion, which is what turns a LED in the device's frame into a pixel.
84
85 //! Where the camera sits in the world, in OpenCV space. Only read when @ref has_concrete_pose is set.
87
88 /*!
89 * Whether the camera has a concrete pose, in which case @ref Tcv_world_cam is where it is held for the whole
90 * solve. If false, the camera's pose will be optimized for.
91 */
93};
94
95//! The IMU intrinsics the calibration solved for.
97{
98public: // Fields
99 //! Accelerometer bias, in meters per second squared.
101 //! Gyroscope bias, in radians per second.
103 //! Per-axis accelerometer scale, unitless.
105
106 //! The LED model -> IMU rotation.
108};
109
110//! The pose the calibration ended up with for a single camera.
112{
113public: // Fields
114 size_t mosaic_idx;
115 size_t camera_idx;
116
117 //! The pose of the camera, in OpenCV space.
119
120 //! Carried through from the description, so a consumer can reproject the observations this pose was fit to.
122
123 //! False when the pose was handed to the optimizer as a constraint instead of being solved for.
125 //! True when the camera was pinned at the origin with only its pitch and roll free.
127};
128
129//! The device state the calibration solved for at a single keyframe.
131{
132public: // Fields
133 timepoint_ns timestamp_ns;
134
135 //! The world -> LED model pose of the device, in OpenCV space.
137 //! The linear velocity of the device in world space, in meters per second, in OpenCV space.
139
140 //! The camera observations which constrained this keyframe.
141 std::vector<DeviceCameraSample> camera_samples;
142};
143
144//! The output of a successful @ref RigCalibration::optimize call.
146{
147public: // Fields
148 //! The device whose samples the solve ran on.
149 t_constellation_device_id_t device_id;
150
151 ImuCalibration imu;
152 //! The magnitude of gravity, in meters per second squared. Shared by every device the solve covered.
154 std::vector<CameraCalibration> cameras;
155 std::vector<KeyframeCalibration> keyframes;
156
157 //! How well each kind of factor was fit at the solution.
159 FactorFitness camera_fitness;
160
161 //! Solver cost before the solve, `1/2 ||f(x_0)||^2`.
163 //! Solver cost after the solve, `1/2 ||f(x)||^2`.
165 //! How many iterations the solver took.
167};
168
170{
171private: // Fields
172 u_logging_level log_level;
173 std::map<t_constellation_device_id_t, DeviceSamples> device_samples;
174 std::vector<CameraDescription> cameras;
175 mutable os::Mutex lock;
176 bool collecting_data{false};
177
178#ifdef XRT_FEATURE_RERUN
179 std::unique_ptr<struct RerunContext> rerun_context{nullptr};
180#endif
181
182 u_var_button u_var_button_begin_collecting_data{};
183 u_var_button u_var_button_end_collecting_data{};
184 u_var_button u_var_button_optimize{};
185
186public: // Methods
189
190 //! Adds a camera to the rig with an optional anchored world pose.
191 void
192 addCamera(const CameraDescription &camera_description);
193
194 //! Begins collecting data for the rig optimization.
195 void
197
198 //! Ends collecting data for the rig optimization.
199 void
201
202 //! Returns whether the rig calibration is currently collecting data.
203 bool
205
206 //! Pushes a complete camera sample. Must be called with `tracker->device_lock` held.
207 void
208 pushCameraSample(ConstellationTracker *tracker, const CameraSample &sample);
209 //! Pushes an IMU sample for this particular device, IMU samples should be in OpenXR coordinate space.
210 void
211 pushImuSample(t_constellation_device_id_t device_id, const xrt_imu_sample &sample);
212
213 //! Runs the optimizer on the data that has been passed
214 bool
215 optimize(CalibrationResult &out_result);
216
217 bool
218 numSamplesForBestDevice(size_t &out_num_samples) const;
219
220private: // Methods
221 //! Must be called with `lock` already held.
222 bool
223 bestDeviceLocked(t_constellation_device_id_t &out_device) const;
224
226 getDeviceSamplesLocked(t_constellation_device_id_t device_id);
227
228 /*!
229 * Runs one full solve over the given samples, with every camera timestamp shifted by @p camera_time_offset_ns.
230 *
231 * Shifting is what makes the offset sweep possible: a constant error in the camera timestamps shows up as
232 * camera factors that cannot be reconciled with the IMU, so the offset which minimizes the camera fitness is
233 * the negative of that error.
234 *
235 * @param device_id The device whose samples these are, only carried through into the result.
236 * @param camera_samples The camera samples to solve against. Taken by value because the offset is
237 * applied to the copy and the ordering is reworked in place.
238 * @param imu_samples The IMU samples to solve against, must already be sorted by timestamp.
239 * @param camera_time_offset_ns Added to every camera sample timestamp before anything else happens.
240 * @param[out] out_result Written only when this returns true.
241 *
242 * @return True when the solve produced a usable solution.
243 */
244 bool
245 solveWithCameraTimeOffset(t_constellation_device_id_t device_id,
246 const std::vector<CameraDescription> &cameras,
247 std::vector<DeviceCameraSample> camera_samples,
248 const std::vector<xrt_imu_sample> &imu_samples,
249 time_duration_ns camera_time_offset_ns,
250 CalibrationResult &out_result);
251};
252
253}; // namespace xrt::tracking::constellation::optimizer::rig_calibration
u_logging_level
Logging level enum.
Definition u_logging.h:45
int64_t timepoint_ns
Integer timestamp type.
Definition u_time.h:77
int64_t time_duration_ns
Integer duration type in nanoseconds.
Definition u_time.h:88
Generic math helpers for constellation optimizer code.
Wrapper around OS threading native functions.
RANSAC PnP pose refinement.
Definition camera_model.h:21
Simple pushable button.
Definition u_var.h:86
Definition t_constellation_tracker_internal.hpp:128
Definition t_constellation_tracker_internal.hpp:453
How well one kind of sensor was fit, so that a bad solve can be attributed to the sensor that could n...
Definition math.hpp:31
The output of a successful RigCalibration::optimize call.
Definition rig_calibration.hpp:146
int iterations
How many iterations the solver took.
Definition rig_calibration.hpp:166
double initial_cost
Solver cost before the solve, 1/2 ||f(x_0)||^2.
Definition rig_calibration.hpp:162
double final_cost
Solver cost after the solve, 1/2 ||f(x)||^2.
Definition rig_calibration.hpp:164
FactorFitness imu_fitness
How well each kind of factor was fit at the solution.
Definition rig_calibration.hpp:158
double gravity_mag
The magnitude of gravity, in meters per second squared. Shared by every device the solve covered.
Definition rig_calibration.hpp:153
t_constellation_device_id_t device_id
The device whose samples the solve ran on.
Definition rig_calibration.hpp:149
The pose the calibration ended up with for a single camera.
Definition rig_calibration.hpp:112
camera_model params
Carried through from the description, so a consumer can reproject the observations this pose was fit ...
Definition rig_calibration.hpp:121
bool is_2dof
True when the camera was pinned at the origin with only its pitch and roll free.
Definition rig_calibration.hpp:126
bool optimized
False when the pose was handed to the optimizer as a constraint instead of being solved for.
Definition rig_calibration.hpp:124
xrt_pose Tcv_world_cam
The pose of the camera, in OpenCV space.
Definition rig_calibration.hpp:118
camera_model params
Intrinsics and distortion, which is what turns a LED in the device's frame into a pixel.
Definition rig_calibration.hpp:83
xrt_pose Tcv_world_cam
Where the camera sits in the world, in OpenCV space. Only read when has_concrete_pose is set.
Definition rig_calibration.hpp:86
bool has_concrete_pose
Whether the camera has a concrete pose, in which case Tcv_world_cam is where it is held for the whole...
Definition rig_calibration.hpp:92
One camera's view of one device at one exposure, as the LED correspondences the tracker labelled.
Definition rig_calibration.hpp:47
xrt_pose Tcv_cam_device_seed
The seed pose that the tracker recovered.
Definition rig_calibration.hpp:57
std::array< xrt_vec3, XRT_CONSTELLATION_MAX_LEDS_PER_DEVICE > points3d
The 3D blob points, in the device's frame. Same order as points2d.
Definition rig_calibration.hpp:63
std::array< xrt_vec2, XRT_CONSTELLATION_MAX_LEDS_PER_DEVICE > points2d
The 2D blob points.
Definition rig_calibration.hpp:61
The IMU intrinsics the calibration solved for.
Definition rig_calibration.hpp:97
xrt_quat Qcv_model_imu
The LED model -> IMU rotation.
Definition rig_calibration.hpp:107
xrt_vec3_f64 accel_bias
Accelerometer bias, in meters per second squared.
Definition rig_calibration.hpp:100
xrt_vec3_f64 gyro_bias
Gyroscope bias, in radians per second.
Definition rig_calibration.hpp:102
xrt_vec3_f64 accel_scale
Per-axis accelerometer scale, unitless.
Definition rig_calibration.hpp:104
The device state the calibration solved for at a single keyframe.
Definition rig_calibration.hpp:131
xrt_pose Tcv_world_device
The world -> LED model pose of the device, in OpenCV space.
Definition rig_calibration.hpp:136
xrt_vec3 velocity_m_s
The linear velocity of the device in world space, in meters per second, in OpenCV space.
Definition rig_calibration.hpp:138
std::vector< DeviceCameraSample > camera_samples
The camera observations which constrained this keyframe.
Definition rig_calibration.hpp:141
void pushCameraSample(ConstellationTracker *tracker, const CameraSample &sample)
Pushes a complete camera sample. Must be called with tracker->device_lock held.
Definition rig_calibration.cpp:1195
bool isCollectingData()
Returns whether the rig calibration is currently collecting data.
Definition rig_calibration.cpp:1188
bool optimize(CalibrationResult &out_result)
Runs the optimizer on the data that has been passed.
Definition rig_calibration.cpp:1299
void endCollectingData()
Ends collecting data for the rig optimization.
Definition rig_calibration.cpp:1181
void addCamera(const CameraDescription &camera_description)
Adds a camera to the rig with an optional anchored world pose.
Definition rig_calibration.cpp:1164
void pushImuSample(t_constellation_device_id_t device_id, const xrt_imu_sample &sample)
Pushes an IMU sample for this particular device, IMU samples should be in OpenXR coordinate space.
Definition rig_calibration.cpp:1280
void beginCollectingData()
Begins collecting data for the rig optimization.
Definition rig_calibration.cpp:1172
IMU Sample.
Definition xrt_tracking.h:143
A pose composed of a position and orientation.
Definition xrt_defines.h:522
A quaternion with single floats.
Definition xrt_defines.h:246
A 3 element vector with single doubles.
Definition xrt_defines.h:322
A 3 element vector with single floats.
Definition xrt_defines.h:310
Header defining the tracking system integration in Monado.
Variable tracking code.