Monado OpenXR Runtime
m_clock_tracking.h
Go to the documentation of this file.
1// Copyright 2022, Collabora, Ltd.
2// Copyright 2024, Jan Schmidt
3// SPDX-License-Identifier: BSL-1.0
4/*!
5 * @file
6 * @brief Helpers to estimate offsets between clocks
7 * @author Mateo de Mayo <mateo.demayo@collabora.com>
8 * @ingroup aux_math
9 */
10
11#pragma once
12
13#include "xrt/xrt_defines.h"
14#include "util/u_time.h"
15
16#ifdef __cplusplus
17extern "C" {
18#endif
19
20/*!
21 * Helper to estimate the offset between two clocks using exponential smoothing.
22 *
23 * Given a sample from two timestamp domains A and B that should have been
24 * sampled as close as possible, together with an estimate of the offset between
25 * A clock and B clock (or zero), it applies a smoothing average on the
26 * estimated offset and returns @p a in B clock.
27 *
28 * This estimator can be used when clock observations are arriving with a low
29 * delay and small jitter, or when accuracy is less important (on the order of
30 * the jitter that is present). It is very computationally cheap.
31 *
32 * @param freq About how many times per second this function is called. Helps setting a good decay value.
33 * @param a Timestamp in clock A of the event
34 * @param b Timestamp in clock B of the event
35 * @param[in,out] inout_a2b Pointer to the current offset estimate from A to B, or 0 if unknown.
36 * Value pointed-to will be updated.
37 * @return timepoint_ns @p a in B clock
38 */
39static inline timepoint_ns
41{
42 // This formulation of exponential filtering uses a fixed-precision integer for the
43 // alpha value and operates on the delta between the old and new a2b to avoid
44 // precision / overflow problems.
45
46 // Totally arbitrary way of computing alpha, if you have a better one, replace it
47 const time_duration_ns alpha = 1000 * (1.0 - 12.5 / freq); // Weight to put on accumulated a2b
48 time_duration_ns old_a2b = *inout_a2b;
49 time_duration_ns got_a2b = b - a;
50 time_duration_ns new_a2b;
51 if (old_a2b == 0) { // a2b has not been set yet
52 new_a2b = got_a2b;
53 } else {
54 new_a2b = ((old_a2b - got_a2b) * alpha) / 1000 + got_a2b;
55 }
56 *inout_a2b = new_a2b;
57 return a + new_a2b;
58}
59
60/*!
61 * Helper to estimate the offset between two clocks using a windowed
62 * minimum-skew estimation plus exponential smoothing. The algorithm
63 * tracks the smallest offset within the window, on the theory that
64 * minima represent samples with the lowest transmission delay and jitter.
65 *
66 * More computationally intensive than the simple m_clock_offset_a2b estimator,
67 * but can estimate a clock with accuracy in the microsecond range
68 * even in the presence of 10s of milliseconds of jitter.
69 *
70 * Based on the approach in Dominique Fober, Yann Orlarey, Stéphane Letz.
71 * Real Time Clock Skew Estimation over Network Delays. [Technical Report] GRAME. 2005.
72 * https://hal.science/hal-02158803/document
73 */
75
76/*!
77 * Allocate a struct m_clock_windowed_skew_tracker with a
78 * window of @param window_samples samples.
79 */
81m_clock_windowed_skew_tracker_alloc(const size_t window_samples);
82void
83m_clock_windowed_skew_tracker_reset(struct m_clock_windowed_skew_tracker *t);
84void
85m_clock_windowed_skew_tracker_destroy(struct m_clock_windowed_skew_tracker *t);
86
87void
88m_clock_windowed_skew_tracker_push(struct m_clock_windowed_skew_tracker *t,
89 const timepoint_ns local_ts,
90 const timepoint_ns remote_ts);
91
92bool
93m_clock_windowed_skew_tracker_to_local(struct m_clock_windowed_skew_tracker *t,
94 const timepoint_ns remote_ts,
95 timepoint_ns *local_ts);
96bool
97m_clock_windowed_skew_tracker_to_remote(struct m_clock_windowed_skew_tracker *t,
98 const timepoint_ns local_ts,
99 timepoint_ns *remote_ts);
100
101#ifdef __cplusplus
102}
103#endif
int64_t timepoint_ns
Integer timestamp type.
Definition: u_time.h:70
int64_t time_duration_ns
Integer duration type in nanoseconds.
Definition: u_time.h:81
static timepoint_ns m_clock_offset_a2b(float freq, timepoint_ns a, timepoint_ns b, time_duration_ns *inout_a2b)
Helper to estimate the offset between two clocks using exponential smoothing.
Definition: m_clock_tracking.h:40
struct m_clock_windowed_skew_tracker * m_clock_windowed_skew_tracker_alloc(const size_t window_samples)
Allocate a struct m_clock_windowed_skew_tracker with a window of.
Definition: m_clock_tracking.c:65
Definition: m_clock_tracking.c:35
Time-keeping: a clock that is steady, convertible to system time, and ideally high-resolution.
Common defines and enums for XRT.