Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bugfix(server_core) Fix judder regression caused by streamer-client pose desync #2660

Merged
merged 8 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions alvr/client_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ impl ClientCoreContext {
poll_timestamp
};

// Guarantee that sent timestamps never go backwards by sending the poll time
let reported_timestamp = poll_timestamp;

The-personified-devil marked this conversation as resolved.
Show resolved Hide resolved
for (id, motion) in &mut device_motions {
let velocity_multiplier = *self.connection_context.velocities_multiplier.read();
motion.linear_velocity *= velocity_multiplier;
Expand All @@ -252,7 +255,7 @@ impl ClientCoreContext {

let mut head_pose_queue = self.connection_context.head_pose_queue.write();

head_pose_queue.push_back((target_timestamp, motion.pose));
head_pose_queue.push_back((reported_timestamp, motion.pose));

while head_pose_queue.len() > 1024 {
head_pose_queue.pop_front();
Expand Down Expand Up @@ -299,15 +302,15 @@ impl ClientCoreContext {
if let Some(sender) = &mut *self.connection_context.tracking_sender.lock() {
sender
.send_header(&Tracking {
target_timestamp,
target_timestamp: reported_timestamp,
device_motions,
hand_skeletons,
face_data,
})
.ok();

if let Some(stats) = &mut *self.connection_context.statistics_manager.lock() {
stats.report_input_acquired(target_timestamp);
stats.report_input_acquired(reported_timestamp);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion alvr/server_core/src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1012,7 +1012,8 @@ fn connection_pipeline(
thread::spawn(|| ())
};

*ctx.tracking_manager.write() = TrackingManager::new();
*ctx.tracking_manager.write() =
TrackingManager::new(initial_settings.connection.statistics_history_size);
let hand_gesture_manager = Arc::new(Mutex::new(HandGestureManager::new()));

let tracking_receive_thread = thread::spawn({
Expand Down
4 changes: 3 additions & 1 deletion alvr/server_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,9 @@ impl ServerCoreContext {
events_sender,
statistics_manager: RwLock::new(Some(stats)),
bitrate_manager: Mutex::new(BitrateManager::new(256, 60.0)),
tracking_manager: RwLock::new(TrackingManager::new()),
tracking_manager: RwLock::new(TrackingManager::new(
initial_settings.connection.statistics_history_size,
)),
decoder_config: Mutex::new(None),
video_mirror_sender: Mutex::new(None),
video_recording_file: Mutex::new(None),
Expand Down
17 changes: 8 additions & 9 deletions alvr/server_core/src/tracking/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ use std::{
};

const DEG_TO_RAD: f32 = PI / 180.0;
// A small history size is used, we just need to cover the time from packet received to data
// processed.
const MAX_HISTORY_SIZE: usize = 16;

#[derive(Debug)]
pub enum HandType {
Expand All @@ -60,16 +57,18 @@ pub struct TrackingManager {
device_motions_history: HashMap<u64, VecDeque<(Duration, DeviceMotion)>>,
hand_skeletons_history: [VecDeque<(Duration, [Pose; 26])>; 2],
last_face_data: FaceData,
max_history_size: usize,
}

impl TrackingManager {
pub fn new() -> TrackingManager {
pub fn new(max_history_size: usize) -> TrackingManager {
TrackingManager {
last_head_pose: Pose::default(),
inverse_recentering_origin: Pose::default(),
device_motions_history: HashMap::new(),
hand_skeletons_history: [VecDeque::new(), VecDeque::new()],
last_face_data: FaceData::default(),
max_history_size,
}
}

Expand Down Expand Up @@ -124,7 +123,7 @@ impl TrackingManager {
// Performs all kinds of tracking transformations, driven by settings.
pub fn report_device_motions(
&mut self,
config: &HeadsetConfig,
headset_config: &HeadsetConfig,
timestamp: Duration,
device_motions: &[(u64, DeviceMotion)],
) {
Expand All @@ -141,7 +140,7 @@ impl TrackingManager {
(*BODY_RIGHT_FOOT_ID, MotionConfig::default()),
]);

if let Switch::Enabled(controllers) = &config.controllers {
if let Switch::Enabled(controllers) = &headset_config.controllers {
let t = controllers.left_controller_position_offset;
let r = controllers.left_controller_rotation_offset;

Expand Down Expand Up @@ -219,7 +218,7 @@ impl TrackingManager {
if let Some(motions) = self.device_motions_history.get_mut(&device_id) {
motions.push_front((timestamp, motion));

if motions.len() > MAX_HISTORY_SIZE {
if motions.len() > self.max_history_size {
motions.pop_back();
}
} else {
Expand Down Expand Up @@ -247,7 +246,7 @@ impl TrackingManager {
// Note: we are iterating from most recent to oldest
for (ts, m) in motions {
match ts.cmp(&sample_timestamp) {
Ordering::Equal => return Some(*best_motion_ref),
Ordering::Equal => return Some(*m),
Ordering::Greater => {
let diff = ts.saturating_sub(sample_timestamp);
if diff < best_timestamp_diff {
Expand Down Expand Up @@ -280,7 +279,7 @@ impl TrackingManager {

skeleton_history.push_back((timestamp, skeleton));

if skeleton_history.len() > MAX_HISTORY_SIZE {
if skeleton_history.len() > self.max_history_size {
skeleton_history.pop_front();
}
}
Expand Down
Loading