mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-04 06:06:17 +00:00
d/vive: Improve ticks-to-nanoseconds conversion
This commit is contained in:
parent
aa617a9d8b
commit
aaf5fe1b7b
|
@ -10,6 +10,11 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <asm/byteorder.h>
|
||||||
|
|
||||||
|
#include "util/u_time.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Printing functions.
|
* Printing functions.
|
||||||
|
@ -21,3 +26,36 @@
|
||||||
#define VIVE_INFO(d, ...) U_LOG_IFL_I(d->log_level, __VA_ARGS__)
|
#define VIVE_INFO(d, ...) U_LOG_IFL_I(d->log_level, __VA_ARGS__)
|
||||||
#define VIVE_WARN(d, ...) U_LOG_IFL_W(d->log_level, __VA_ARGS__)
|
#define VIVE_WARN(d, ...) U_LOG_IFL_W(d->log_level, __VA_ARGS__)
|
||||||
#define VIVE_ERROR(d, ...) U_LOG_IFL_E(d->log_level, __VA_ARGS__)
|
#define VIVE_ERROR(d, ...) U_LOG_IFL_E(d->log_level, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define VIVE_CLOCK_FREQ 48e6 // 48 MHz
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Helper function to convert raw device ticks to nanosecond timestamps.
|
||||||
|
*
|
||||||
|
* `inout` params should start as the results from the previous sample call.
|
||||||
|
* For the first call, pass zero for the `inout` params.
|
||||||
|
*
|
||||||
|
* @param sample_ticks_raw Current sample ticks
|
||||||
|
* @param[in, out] inout_prev_ticks Overwritten with `sample_ticks_raw`
|
||||||
|
* @param[in, out] inout_ts_ns Resulting timestamp in nanoseconds
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
ticks_to_ns(uint32_t sample_ticks_raw, uint32_t *inout_prev_ticks, timepoint_ns *inout_ts_ns)
|
||||||
|
{
|
||||||
|
uint32_t sample_ticks = __le32_to_cpu(sample_ticks_raw);
|
||||||
|
uint32_t prev_ticks = *inout_prev_ticks;
|
||||||
|
|
||||||
|
uint32_t delta_ticks = 0;
|
||||||
|
if (prev_ticks < sample_ticks) {
|
||||||
|
delta_ticks = sample_ticks - prev_ticks;
|
||||||
|
} else { // Handle overflow
|
||||||
|
delta_ticks = (UINT32_MAX - prev_ticks) + sample_ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
const double one_tick_in_s = (1 / VIVE_CLOCK_FREQ);
|
||||||
|
const double one_tick_in_ns = one_tick_in_s * U_TIME_1S_IN_NS;
|
||||||
|
time_duration_ns delta_ns = delta_ticks * one_tick_in_ns;
|
||||||
|
|
||||||
|
*inout_prev_ticks = sample_ticks;
|
||||||
|
*inout_ts_ns += delta_ns;
|
||||||
|
}
|
||||||
|
|
|
@ -92,8 +92,6 @@ enum vive_controller_input_index
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define VIVE_CLOCK_FREQ 48000000.0f // Hz = 48 MHz
|
|
||||||
|
|
||||||
#define DEFAULT_HAPTIC_FREQ 150.0f
|
#define DEFAULT_HAPTIC_FREQ 150.0f
|
||||||
#define MIN_HAPTIC_DURATION 0.05f
|
#define MIN_HAPTIC_DURATION 0.05f
|
||||||
|
|
||||||
|
@ -529,29 +527,6 @@ controller_handle_analog_trigger(struct vive_controller_device *d, struct vive_c
|
||||||
VIVE_TRACE(d, "Trigger %f\n", d->state.trigger);
|
VIVE_TRACE(d, "Trigger %f\n", d->state.trigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t
|
|
||||||
calc_dt_raw_and_handle_overflow(struct vive_controller_device *d, uint32_t sample_time)
|
|
||||||
{
|
|
||||||
uint64_t dt_raw = (uint64_t)sample_time - (uint64_t)d->imu.last_sample_time_raw;
|
|
||||||
d->imu.last_sample_time_raw = sample_time;
|
|
||||||
|
|
||||||
// The 32-bit tick counter has rolled over,
|
|
||||||
// adjust the "negative" value to be positive.
|
|
||||||
// It's easiest to do this with 64-bits.
|
|
||||||
if (dt_raw > 0xFFFFFFFF) {
|
|
||||||
dt_raw += 0x100000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (uint32_t)dt_raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint64_t
|
|
||||||
cald_dt_ns(uint32_t dt_raw)
|
|
||||||
{
|
|
||||||
double f = (double)(dt_raw) / VIVE_CLOCK_FREQ;
|
|
||||||
uint64_t diff_ns = (uint64_t)(f * 1000.0 * 1000.0 * 1000.0);
|
|
||||||
return diff_ns;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vive_controller_handle_imu_sample(struct vive_controller_device *d, struct watchman_imu_sample *sample)
|
vive_controller_handle_imu_sample(struct vive_controller_device *d, struct watchman_imu_sample *sample)
|
||||||
|
@ -560,8 +535,7 @@ vive_controller_handle_imu_sample(struct vive_controller_device *d, struct watch
|
||||||
|
|
||||||
/* ouvrt: "Time in 48 MHz ticks, but we are missing the low byte" */
|
/* ouvrt: "Time in 48 MHz ticks, but we are missing the low byte" */
|
||||||
uint32_t time_raw = d->last_ticks | (sample->timestamp_hi << 8);
|
uint32_t time_raw = d->last_ticks | (sample->timestamp_hi << 8);
|
||||||
uint32_t dt_raw = calc_dt_raw_and_handle_overflow(d, time_raw);
|
ticks_to_ns(time_raw, &d->imu.last_sample_ticks, &d->imu.last_sample_ts_ns);
|
||||||
uint64_t dt_ns = cald_dt_ns(dt_raw);
|
|
||||||
|
|
||||||
d->imu.ts_received_ns = os_monotonic_get_ns();
|
d->imu.ts_received_ns = os_monotonic_get_ns();
|
||||||
|
|
||||||
|
@ -619,11 +593,10 @@ vive_controller_handle_imu_sample(struct vive_controller_device *d, struct watch
|
||||||
angular_velocity = fixed_angular_velocity;
|
angular_velocity = fixed_angular_velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->imu.time_ns += dt_ns;
|
|
||||||
d->last.acc = acceleration;
|
d->last.acc = acceleration;
|
||||||
d->last.gyro = angular_velocity;
|
d->last.gyro = angular_velocity;
|
||||||
|
|
||||||
m_imu_3dof_update(&d->fusion, d->imu.time_ns, &acceleration, &angular_velocity);
|
m_imu_3dof_update(&d->fusion, d->imu.last_sample_ts_ns, &acceleration, &angular_velocity);
|
||||||
|
|
||||||
d->rot_filtered = d->fusion.rot;
|
d->rot_filtered = d->fusion.rot;
|
||||||
|
|
||||||
|
|
|
@ -53,8 +53,8 @@ struct vive_controller_device
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint64_t time_ns;
|
timepoint_ns last_sample_ts_ns;
|
||||||
uint32_t last_sample_time_raw;
|
uint32_t last_sample_ticks;
|
||||||
timepoint_ns ts_received_ns;
|
timepoint_ns ts_received_ns;
|
||||||
} imu;
|
} imu;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include "vive_protocol.h"
|
#include "vive_protocol.h"
|
||||||
|
|
||||||
|
|
||||||
#define VIVE_CLOCK_FREQ 48e6 // 48 MHz
|
|
||||||
|
|
||||||
DEBUG_GET_ONCE_LOG_OPTION(vive_log, "VIVE_LOG", U_LOGGING_WARN)
|
DEBUG_GET_ONCE_LOG_OPTION(vive_log, "VIVE_LOG", U_LOGGING_WARN)
|
||||||
|
|
||||||
|
@ -241,39 +240,16 @@ oldest_sequence_index(uint8_t a, uint8_t b, uint8_t c)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t
|
|
||||||
calc_dt_raw_and_handle_overflow(struct vive_device *d, uint32_t sample_time)
|
|
||||||
{
|
|
||||||
uint64_t dt_raw = (uint64_t)sample_time - (uint64_t)d->imu.last_sample_time_raw;
|
|
||||||
d->imu.last_sample_time_raw = sample_time;
|
|
||||||
|
|
||||||
// The 32-bit tick counter has rolled over,
|
|
||||||
// adjust the "negative" value to be positive.
|
|
||||||
// It's easiest to do this with 64-bits.
|
|
||||||
if (dt_raw > 0xFFFFFFFF) {
|
|
||||||
dt_raw += 0x100000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (uint32_t)dt_raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint64_t
|
|
||||||
cald_dt_ns(uint32_t dt_raw)
|
|
||||||
{
|
|
||||||
double f = (double)(dt_raw) / VIVE_CLOCK_FREQ;
|
|
||||||
uint64_t diff_ns = (uint64_t)(f * 1000.0 * 1000.0 * 1000.0);
|
|
||||||
return diff_ns;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_imu(struct vive_device *d, const void *buffer)
|
update_imu(struct vive_device *d, const void *buffer)
|
||||||
{
|
{
|
||||||
XRT_TRACE_MARKER();
|
XRT_TRACE_MARKER();
|
||||||
|
|
||||||
|
uint64_t now_ns = os_monotonic_get_ns();
|
||||||
|
|
||||||
const struct vive_imu_report *report = buffer;
|
const struct vive_imu_report *report = buffer;
|
||||||
const struct vive_imu_sample *sample = report->sample;
|
const struct vive_imu_sample *sample = report->sample;
|
||||||
uint8_t last_seq = d->imu.sequence;
|
uint8_t last_seq = d->imu.sequence;
|
||||||
d->imu.ts_received_ns = os_monotonic_get_ns();
|
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
|
@ -298,10 +274,7 @@ update_imu(struct vive_device *d, const void *buffer)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t time_raw = __le32_to_cpu(sample->time);
|
ticks_to_ns(sample->time, &d->imu.last_sample_ticks, &d->imu.last_sample_ts_ns);
|
||||||
uint32_t dt_raw = calc_dt_raw_and_handle_overflow(d, time_raw);
|
|
||||||
uint64_t dt_ns = cald_dt_ns(dt_raw);
|
|
||||||
|
|
||||||
|
|
||||||
int16_t acc[3] = {
|
int16_t acc[3] = {
|
||||||
(int16_t)__le16_to_cpu(sample->acc[0]),
|
(int16_t)__le16_to_cpu(sample->acc[0]),
|
||||||
|
@ -371,7 +344,6 @@ update_imu(struct vive_device *d, const void *buffer)
|
||||||
default: VIVE_ERROR(d, "Unhandled Vive variant"); return;
|
default: VIVE_ERROR(d, "Unhandled Vive variant"); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->imu.time_ns += dt_ns;
|
|
||||||
d->imu.sequence = seq;
|
d->imu.sequence = seq;
|
||||||
|
|
||||||
struct xrt_space_relation rel = {0};
|
struct xrt_space_relation rel = {0};
|
||||||
|
@ -379,9 +351,9 @@ update_imu(struct vive_device *d, const void *buffer)
|
||||||
XRT_SPACE_RELATION_ORIENTATION_VALID_BIT | XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT;
|
XRT_SPACE_RELATION_ORIENTATION_VALID_BIT | XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT;
|
||||||
|
|
||||||
os_mutex_lock(&d->fusion.mutex);
|
os_mutex_lock(&d->fusion.mutex);
|
||||||
m_imu_3dof_update(&d->fusion.i3dof, d->imu.time_ns, &acceleration, &angular_velocity);
|
m_imu_3dof_update(&d->fusion.i3dof, d->imu.last_sample_ts_ns, &acceleration, &angular_velocity);
|
||||||
rel.pose.orientation = d->fusion.i3dof.rot;
|
rel.pose.orientation = d->fusion.i3dof.rot;
|
||||||
m_relation_history_push(d->fusion.relation_hist, &rel, d->imu.ts_received_ns);
|
m_relation_history_push(d->fusion.relation_hist, &rel, now_ns);
|
||||||
os_mutex_unlock(&d->fusion.mutex);
|
os_mutex_unlock(&d->fusion.mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xrt/xrt_device.h"
|
#include "xrt/xrt_device.h"
|
||||||
#include "math/m_imu_3dof.h"
|
|
||||||
#include "os/os_threading.h"
|
#include "os/os_threading.h"
|
||||||
#include "util/u_logging.h"
|
#include "util/u_logging.h"
|
||||||
#include "util/u_distortion_mesh.h"
|
#include "util/u_distortion_mesh.h"
|
||||||
|
#include "math/m_imu_3dof.h"
|
||||||
#include "math/m_relation_history.h"
|
#include "math/m_relation_history.h"
|
||||||
|
|
||||||
#include "vive/vive_config.h"
|
#include "vive/vive_config.h"
|
||||||
|
@ -42,10 +42,9 @@ struct vive_device
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint64_t time_ns;
|
timepoint_ns last_sample_ts_ns;
|
||||||
|
uint32_t last_sample_ticks;
|
||||||
uint8_t sequence;
|
uint8_t sequence;
|
||||||
uint32_t last_sample_time_raw;
|
|
||||||
timepoint_ns ts_received_ns;
|
|
||||||
} imu;
|
} imu;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
|
@ -56,7 +55,6 @@ struct vive_device
|
||||||
uint8_t button;
|
uint8_t button;
|
||||||
} board;
|
} board;
|
||||||
|
|
||||||
|
|
||||||
enum u_logging_level log_level;
|
enum u_logging_level log_level;
|
||||||
bool disconnect_notified;
|
bool disconnect_notified;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue