Skip to content

Commit

Permalink
fix(client_core): 🐛 Cap prediction to avoid head and controllers flyi…
Browse files Browse the repository at this point in the history
…ng off (#2635)

* fix(client_core): 🐛 Cap prediction to avoid head and controllers flying off

* Add Max prediction setting
  • Loading branch information
zmerp authored Jan 18, 2025
1 parent 393f894 commit 66bbc3c
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 7 deletions.
2 changes: 2 additions & 0 deletions alvr/client_core/src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ pub struct ConnectionContext {
pub view_params: RwLock<[ViewParams; 2]>,
pub uses_multimodal_protocol: RelaxedAtomic,
pub velocities_multiplier: RwLock<f32>,
pub max_prediction: RwLock<Duration>,
}

fn set_hud_message(event_queue: &Mutex<VecDeque<ClientCoreEvent>>, message: &str) {
Expand Down Expand Up @@ -205,6 +206,7 @@ fn connection_pipeline(
let negotiated_config = stream_config.negotiated_config;

*ctx.velocities_multiplier.write() = settings.extra.velocities_multiplier;
*ctx.max_prediction.write() = Duration::from_millis(settings.headset.max_prediction_ms);

*ctx.statistics_manager.lock() = Some(StatisticsManager::new(
settings.connection.statistics_history_size,
Expand Down
18 changes: 11 additions & 7 deletions alvr/client_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,15 @@ impl ClientCoreContext {
) {
dbg_client_core!("send_tracking");

let target_timestamp =
if let Some(stats) = &*self.connection_context.statistics_manager.lock() {
poll_timestamp + stats.average_total_pipeline_latency()
} else {
poll_timestamp
};
let max_prediction = *self.connection_context.max_prediction.read();

let target_timestamp = if let Some(stats) =
&*self.connection_context.statistics_manager.lock()
{
poll_timestamp + Duration::max(stats.average_total_pipeline_latency(), max_prediction)
} else {
poll_timestamp
};

for (id, motion) in &mut device_motions {
let velocity_multiplier = *self.connection_context.velocities_multiplier.read();
Expand All @@ -260,7 +263,8 @@ impl ClientCoreContext {
motion.linear_velocity = Vec3::ZERO;
motion.angular_velocity = Vec3::ZERO;
} else if let Some(stats) = &*self.connection_context.statistics_manager.lock() {
let tracker_timestamp = poll_timestamp + stats.tracker_prediction_offset();
let tracker_timestamp = poll_timestamp
+ Duration::max(stats.tracker_prediction_offset(), max_prediction);

*motion = motion.predict(poll_timestamp, tracker_timestamp);
}
Expand Down
8 changes: 8 additions & 0 deletions alvr/session/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,13 @@ Tilted: the world gets tilted when long pressing the oculus button. This is usef
#[schema(flag = "steamvr-restart")]
#[schema(strings(display_name = "VMC"))]
pub vmc: Switch<VMCConfig>,

#[schema(strings(
help = "Maximum prediction for head and controllers. Used to avoid too much jitter during loading."
))]
#[schema(flag = "real-time")]
#[schema(gui(slider(min = 0, max = 200, step = 5)), suffix = "ms")]
pub max_prediction_ms: u64,
}

#[derive(SettingsSchema, Serialize, Deserialize, Clone, Copy)]
Expand Down Expand Up @@ -1823,6 +1830,7 @@ pub fn session_settings_default() -> SettingsDefault {
rotation_recentering_mode: RotationRecenteringModeDefault {
variant: RotationRecenteringModeDefaultVariant::Yaw,
},
max_prediction_ms: 100,
},
connection: ConnectionConfigDefault {
stream_protocol: SocketProtocolDefault {
Expand Down

0 comments on commit 66bbc3c

Please sign in to comment.