12#include "xrt/xrt_config_build.h"
26#include <ceres/context.h>
36namespace xrt::tracking::constellation {
40struct ConstellationTracker;
44namespace xrt::tracking::constellation::optimizer::sensor_fusion {
46using namespace xrt::auxiliary;
47using namespace xrt::tracking;
48using namespace xrt::tracking::constellation::optimizer;
69 "the oldest keyframe in the window has to be sealed by the time it is evicted, so that marginalization "
70 "never has to fold an open keyframe into the prior");
93 std::array<xrt_vec2, XRT_CONSTELLATION_MAX_LEDS_PER_DEVICE>
points2d;
95 std::array<xrt_vec3, XRT_CONSTELLATION_MAX_LEDS_PER_DEVICE>
points3d;
112 std::array<DeviceObservation, XRT_TRACKING_MAX_CAMS> observations;
113 uint32_t num_observations;
128 static_assert(std::is_trivially_copyable_v<xrt_imu_sample>);
130 "the sample has to decompose into whole words to be stored and loaded atomically");
131 static_assert(std::atomic<uint64_t>::is_always_lock_free,
132 "a locking atomic here would put a mutex back on the IMU push path");
134 static constexpr size_t kNumWords =
sizeof(
xrt_imu_sample) /
sizeof(uint64_t);
139 std::array<std::atomic<uint64_t>, kNumWords> words;
144 std::array<uint64_t, kNumWords> raw;
145 std::memcpy(raw.data(), &sample,
sizeof(sample));
147 for (
size_t i = 0; i < kNumWords; i++) {
148 this->words[i].store(raw[i], std::memory_order_relaxed);
153 load() const noexcept
155 std::array<uint64_t, kNumWords> raw;
156 for (
size_t i = 0; i < kNumWords; i++) {
157 raw[i] = this->words[i].load(std::memory_order_relaxed);
161 std::memcpy(&sample, raw.data(),
sizeof(sample));
169 const uint64_t raw = this->words[
kTimestampWord].load(std::memory_order_relaxed);
172 std::memcpy(×tamp, &raw,
sizeof(timestamp));
199 return this->state == DevicePreintegrationState::Dirty;
206 .imu_preintegration = PreintegratedImuSamples::Identity(),
245 const t_constellation_device_id_t id;
283 std::atomic<timepoint_ns> latest_imu_ts_ns;
294 operator=(
const Device &) =
delete;
297 getLatestImuCalibration()
const;
359 std::array<xrt_vec2, XRT_CONSTELLATION_MAX_LEDS_PER_DEVICE> points2d;
360 std::array<xrt_vec3, XRT_CONSTELLATION_MAX_LEDS_PER_DEVICE> points3d;
369 uint32_t num_observations;
370 std::array<SnapshotObservation, XRT_TRACKING_MAX_CAMS> observations;
377 t_constellation_device_id_t id;
397 uint32_t num_keyframes;
399 std::array<SnapshotKeyframe, kSlidingWindowSize>
keyframes;
406 uint64_t num_late_samples_dropped{0};
408 int num_residuals{0};
409 int num_parameter_blocks{0};
410 uint32_t num_iterations{0};
414 double final_rms_sigma{0.0};
416 double solve_time_s{0.0};
425 ceres::Context *context;
455 std::array<std::array<CameraDescription, XRT_TRACKING_MAX_CAMS>, XRT_CONSTELLATION_MAX_TRACKING_MOSAICS>
483#ifdef XRT_FEATURE_RERUN
487 std::unique_ptr<struct RerunContext> rerun_context{
nullptr};
501 markDirtyFusionLocked();
517 sealAgedKeyframesLocked();
531 rebuildForEvictionLocked();
539 preintegrateDeviceLocked(
bool &work_remaining);
547 t_constellation_device_id_t
id,
u_logging_level
Logging level enum.
Definition u_logging.h:45
int64_t timepoint_ns
Integer timestamp type.
Definition u_time.h:77
Generic math helpers for IMU preintegration.
Small utility for keeping track of the history of an xrt_space_relation, ie.
Wrapper around OS threading native functions.
static constexpr uint32_t kKeyframeSealLagKeyframes
How many newer keyframes have to pile up before a keyframe gets sealed and marginalized.
Definition sensor_fusion.hpp:66
static constexpr uint32_t kImuBufferSize
The number of IMU samples to keep in our ring buffer.
Definition sensor_fusion.hpp:54
static constexpr uint32_t kMaxImuSamplesPerKeyframe
The most IMU samples we ever expect to find between two keyframes.
Definition sensor_fusion.hpp:61
DevicePreintegrationState
Definition sensor_fusion.hpp:178
@ Integrated
This preintegration is complete and will never change.
@ Dirty
Needs to be recomputed.
@ Empty
Does not refer to any real pre-integration. This term contributes nothing and can be skipped.
static constexpr uint32_t kMaxQueuedCameraSamples
How many camera samples may be queued for the fusion thread before new ones start being dropped.
Definition sensor_fusion.hpp:79
static constexpr uint32_t kSlidingWindowSize
How many keyframes to keep in our sliding window.
Definition sensor_fusion.hpp:51
Definition camera_model.h:21
Definition m_relation_history.cpp:50
All in one helper that handles locking, waiting for change and starting a thread.
Definition os_threading.h:500
The LED model is a series of points which define the real-world positions of all LEDs.
Definition t_constellation.h:311
Definition t_constellation_tracker_internal.hpp:128
Definition t_constellation_tracker_internal.hpp:453
Definition imu_preintegration.hpp:192
Definition sensor_fusion.hpp:310
camera_model params
Intrinsics and distortion, which is what turns a LED in the device's frame into a pixel.
Definition sensor_fusion.hpp:316
Definition sensor_fusion.hpp:243
void resetLocked()
Resets the device's state to a fresh state.
Definition sensor_fusion.cpp:2220
m_relation_history * relation_history
The relation history of the device, used as a fast way to retrieve the latest dead-reckoned poses.
Definition sensor_fusion.hpp:255
std::atomic< uint64_t > imu_write_count
The total number of IMU samples ever pushed for this device.
Definition sensor_fusion.hpp:281
std::optional< DeviceSolveState > latest_imu_reckon
The solved state for the latest IMU dead reckoned position.
Definition sensor_fusion.hpp:252
std::array< RingImuSample, kImuBufferSize > imu_samples
The buffered IMU samples, indexed by absolute sample index modulo kImuBufferSize.
Definition sensor_fusion.hpp:286
DeviceImuCalibration stored_imu_calibration
Pre-calibrated accelerometer bias, in meters per second squared.
Definition sensor_fusion.hpp:258
std::optional< DeviceSolveState > latest_solve
The latest fused solve.
Definition sensor_fusion.hpp:250
std::array< DevicePreintegration, kSlidingWindowSize > preintegrations
The preintegrated IMU samples between keyframes, as a ring running parallel to SensorFusion::keyframe...
Definition sensor_fusion.hpp:268
The IMU intrinsics the rig calibration happened to solve for, as the fusion takes them in as a seed.
Definition sensor_fusion.hpp:218
xrt_vec3_f64 accel_scale XRT_VEC3_ONE
Per-axis accelerometer scale, unitless.
Definition sensor_fusion.hpp:224
xrt_quat Qcv_model_imu XRT_QUAT_IDENTITY
The LED model -> IMU rotation.
Definition sensor_fusion.hpp:227
xrt_vec3_f64 gyro_bias XRT_VEC3_ZERO
Gyroscope bias, in radians per second.
Definition sensor_fusion.hpp:222
xrt_vec3_f64 accel_bias XRT_VEC3_ZERO
Accelerometer bias, in meters per second squared.
Definition sensor_fusion.hpp:220
Definition sensor_fusion.hpp:82
xrt_pose Tcv_cam_device_seed
The seed cam->device transform.
Definition sensor_fusion.hpp:90
std::array< xrt_vec3, XRT_CONSTELLATION_MAX_LEDS_PER_DEVICE > points3d
3D model correspondences
Definition sensor_fusion.hpp:95
uint32_t camera_idx
The camera that this observation is tied to.
Definition sensor_fusion.hpp:84
std::array< xrt_vec2, XRT_CONSTELLATION_MAX_LEDS_PER_DEVICE > points2d
2D observations
Definition sensor_fusion.hpp:93
xrt_pose Tcv_world_cam
The camera pose at the timestamp.
Definition sensor_fusion.hpp:87
Stores state for a single preintegration residual for a device.
Definition sensor_fusion.hpp:191
Definition sensor_fusion.hpp:231
timepoint_ns time_ns
The time of the solve.
Definition sensor_fusion.hpp:233
DeviceImuCalibration imu_calibration
The imu calibration at the solve.
Definition sensor_fusion.hpp:239
xrt_vec3_f64 world_velocity
The world velocity at the solve.
Definition sensor_fusion.hpp:237
xrt_pose Tcv_world_device
The world -> LED model pose at the solve.
Definition sensor_fusion.hpp:235
Definition sensor_fusion.hpp:101
uint32_t mosaic_idx
The mosaic this keyframe corresponds to.
Definition sensor_fusion.hpp:103
bool sealed
Set once this keyframe can no longer accept observations due to marginalization or age.
Definition sensor_fusion.hpp:110
timepoint_ns timestamp_ns
The timestamp of this observation.
Definition sensor_fusion.hpp:105
One IMU sample as it sits in Device::imu_samples.
Definition sensor_fusion.hpp:127
timepoint_ns loadTimestamp() const noexcept
Just the timestamp, so the bisection does not pull in six words it is only going to throw away.
Definition sensor_fusion.hpp:167
static constexpr size_t kTimestampWord
The word xrt_imu_sample::timestamp_ns lives in, which is the only one the collector's bisection needs...
Definition sensor_fusion.hpp:137
Definition sensor_fusion.hpp:423
os::Mutex lock
Locks heavy fusion operations, but no threading operations (such as wakeup/sleep).
Definition sensor_fusion.hpp:438
void pushImuSample(const xrt_imu_sample &sample)
Pushes an IMU sample for this particular device, IMU samples should be in OpenXR coordinate space.
Definition sensor_fusion.cpp:2693
uint64_t num_late_samples_dropped
How many camera samples have been dropped for turning up after their keyframe was already sealed.
Definition sensor_fusion.hpp:478
bool dirty
Whether the current state is dirty and we need to run an optimization.
Definition sensor_fusion.hpp:475
SolveSnapshot snapshot
The window and its solved states as of the most recent solve, filled by runFusionLocked once Ceres ha...
Definition sensor_fusion.hpp:496
bool pullReadyCameraSamplesLocked(timepoint_ns now_ns, std::vector< constellation::CameraSample > &pending)
Appends any camera samples into pending, before sorting pending by timestamp order.
Definition sensor_fusion.cpp:2395
void addCamera(const CameraDescription &camera_description)
Adds a camera to the sensor fusion.
Definition sensor_fusion.cpp:2475
void updateDeviceRelationHistoryLocked()
Uses the latest IMU reckoned solve and reckons it forward to the latest IMU sample.
Definition sensor_fusion.cpp:2943
std::vector< constellation::CameraSample > sample_queue
Camera samples handed over by pushCameraSample, in arrival order, waiting to be folded into the windo...
Definition sensor_fusion.hpp:464
uint32_t keyframeIdxLocked(uint32_t age) const
Returns the index of the keyframe in the ring buffer.
Definition sensor_fusion.cpp:2242
std::array< Keyframe, kSlidingWindowSize > keyframe_storage
Backing store for the keyframe ring.
Definition sensor_fusion.hpp:446
void setDeviceImuCalibration(const DeviceImuCalibration &calibration)
Hands a device the IMU intrinsics a rig calibration solved for.
Definition sensor_fusion.cpp:2484
uint32_t num_keyframes
How many slots of the ring hold real keyframes, saturating at kSlidingWindowSize.
Definition sensor_fusion.hpp:452
struct SensorFusionProblem * problem
The active Ceres problem.
Definition sensor_fusion.hpp:481
bool keyframeAgeForIdxLocked(size_t idx, uint32_t &out_age) const
The age of the keyframe currently living in ring slot idx, or false when no keyframe in the window do...
Definition sensor_fusion.cpp:2248
DevicePreintegration & preintegrationLocked(uint32_t age)
The preintegration covering the interval that ends at keyframeLocked(age).
Definition sensor_fusion.cpp:2278
void pushCameraSample(constellation::ConstellationTracker *tracker, const constellation::CameraSample &sample)
Hands a complete constellation camera sample to the fusion thread.
Definition sensor_fusion.cpp:2521
bool reckonToLatestImu(DeviceSolveState &inout_solve)
Dead reckons inout_solve forward through every IMU sample that has arrived since it,...
Definition sensor_fusion.cpp:2899
void getTrackedPose(timepoint_ns requested_time_ns, xrt_space_relation &out_relation)
Provides the latest predicted device pose for the requested timestamp.
Definition sensor_fusion.cpp:2736
std::array< std::array< CameraDescription, XRT_TRACKING_MAX_CAMS >, XRT_CONSTELLATION_MAX_TRACKING_MOSAICS > cameras
The cameras that are present in the system.
Definition sensor_fusion.hpp:456
uint64_t num_queued_samples_dropped
How many samples have been thrown away for arriving with sample_queue already at kMaxQueuedCameraSamp...
Definition sensor_fusion.hpp:472
void tickLocked(bool have_new_input)
Runs preintegration, and when have_new_input says the window has gained something to solve over,...
Definition sensor_fusion.cpp:2961
Keyframe & keyframeLocked(uint32_t age)
The keyframe age steps back from the newest, so age 0 is the newest keyframe in the window and num_ke...
Definition sensor_fusion.cpp:2262
void processCameraSampleLocked(const constellation::CameraSample &sample)
Folds one queued camera sample into the window, or drops if it's no longer able to be merged in.
Definition sensor_fusion.cpp:2584
uint64_t keyframe_head
One past the absolute index of the newest keyframe, so the newest keyframe is keyframe_head - 1.
Definition sensor_fusion.hpp:449
Definition sensor_fusion.hpp:376
uint32_t keyframe_mask
A bit per keyframe age the solve held a state for.
Definition sensor_fusion.hpp:380
xrt_quat Qcv_model_imu
Solved LED model -> IMU rotation.
Definition sensor_fusion.hpp:383
xrt_quat calibrated_Qcv_model_imu
The LED model -> IMU rotation from the rig calibration, for measuring how far the solve has walked fr...
Definition sensor_fusion.hpp:386
Definition sensor_fusion.hpp:364
One camera's view of one device at one keyframe.
Definition sensor_fusion.hpp:349
One solve, whole: what went in, what came out, and how the solver got there.
Definition sensor_fusion.hpp:393
double world_gravity_mag
Solved gravity magnitude, in meters per second squared.
Definition sensor_fusion.hpp:404
uint64_t solve_index
Counts solves over the life of the fusion, and is what the logger uses as a sequence timeline.
Definition sensor_fusion.hpp:395
std::string termination
Ceres' termination type, already stringified, since the logger has no business including Ceres header...
Definition sensor_fusion.hpp:419
double initial_rms_sigma
Residual RMS in standard deviations, before and after the solve. See kTargetResidualRmsSigma.
Definition sensor_fusion.hpp:413
std::array< SnapshotKeyframe, kSlidingWindowSize > keyframes
Newest first, so index i is keyframe age i.
Definition sensor_fusion.hpp:399
A device's solved state at one keyframe.
Definition sensor_fusion.hpp:328
xrt_vec3_f64 gyro_bias
Solved gyroscope bias, in radians per second.
Definition sensor_fusion.hpp:337
xrt_vec3_f64 accel_scale
Solved per-axis accelerometer scale, unitless.
Definition sensor_fusion.hpp:339
xrt_vec3_f64 velocity
Solved world-frame velocity, in meters per second.
Definition sensor_fusion.hpp:332
xrt_pose Tcv_world_device
Solved world -> LED model pose.
Definition sensor_fusion.hpp:330
xrt_vec3_f64 accel_bias
Solved accelerometer bias, in meters per second squared.
Definition sensor_fusion.hpp:335
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 relation with two spaces, includes velocity and acceleration.
Definition xrt_defines.h:713
A 3 element vector with single doubles.
Definition xrt_defines.h:322
Header defining the tracking system integration in Monado.
Header defining the constellation tracker parameters and functions.