@@ -13,9 +13,10 @@ use crate::{
1313 input_mapping:: ButtonMappingManager ,
1414} ;
1515use alvr_common:: {
16- BODY_CHEST_ID , BODY_HIPS_ID , BODY_LEFT_ELBOW_ID , BODY_LEFT_FOOT_ID , BODY_LEFT_KNEE_ID ,
17- BODY_RIGHT_ELBOW_ID , BODY_RIGHT_FOOT_ID , BODY_RIGHT_KNEE_ID , ConnectionError ,
18- DEVICE_ID_TO_PATH , DeviceMotion , HAND_LEFT_ID , HAND_RIGHT_ID , HEAD_ID , Pose , ViewParams ,
16+ AngleSlidingWindowAverage , BODY_CHEST_ID , BODY_HIPS_ID , BODY_LEFT_ELBOW_ID , BODY_LEFT_FOOT_ID ,
17+ BODY_LEFT_KNEE_ID , BODY_RIGHT_ELBOW_ID , BODY_RIGHT_FOOT_ID , BODY_RIGHT_KNEE_ID ,
18+ ConnectionError , DEVICE_ID_TO_PATH , DeviceMotion , HAND_LEFT_ID , HAND_RIGHT_ID , HEAD_ID , Pose ,
19+ SlidingWindowAverage , ViewParams ,
1920 glam:: { Quat , Vec2 , Vec3 } ,
2021 parking_lot:: Mutex ,
2122} ;
@@ -42,6 +43,12 @@ pub enum HandType {
4243 Right = 1 ,
4344}
4445
46+ struct RecenteringMarker {
47+ string : String ,
48+ average_angle : AngleSlidingWindowAverage ,
49+ average_position : SlidingWindowAverage < Vec2 > ,
50+ }
51+
4552// todo: Move this struct to Settings and use it for every tracked device
4653#[ derive( Default ) ]
4754struct MotionConfig {
@@ -55,6 +62,7 @@ pub struct TrackingManager {
5562 last_head_pose : Pose , // client's reference space
5663 inverse_recentering_origin : Pose , // client's reference space
5764 device_motions_history : HashMap < u64 , VecDeque < ( Duration , DeviceMotion ) > > ,
65+ recentering_marker : Option < RecenteringMarker > ,
5866 markers : HashMap < String , Pose > ,
5967 hand_skeletons_history : [ VecDeque < ( Duration , [ Pose ; 26 ] ) > ; 2 ] ,
6068 max_history_size : usize ,
@@ -66,6 +74,7 @@ impl TrackingManager {
6674 last_head_pose : Pose :: IDENTITY ,
6775 inverse_recentering_origin : Pose :: IDENTITY ,
6876 device_motions_history : HashMap :: new ( ) ,
77+ recentering_marker : None ,
6978 markers : HashMap :: new ( ) ,
7079 hand_skeletons_history : [ VecDeque :: new ( ) , VecDeque :: new ( ) ] ,
7180 max_history_size,
@@ -84,35 +93,61 @@ impl TrackingManager {
8493 let marker_z_axis = marker_pose. orientation * Vec3 :: Z ;
8594 let angle_from_y = Vec3 :: angle_between ( marker_z_axis, Vec3 :: Y ) ;
8695
87- let orientation = if ( angle_from_y - FRAC_PI_2 ) . abs ( ) < FRAC_PI_4 {
96+ let marker_y_angle = if ( angle_from_y - FRAC_PI_2 ) . abs ( ) < FRAC_PI_4 {
8897 // The marker is vertical
89- let y_angle = Vec2 :: new ( marker_z_axis. x , marker_z_axis. z )
98+ Vec2 :: new ( marker_z_axis. x , marker_z_axis. z )
9099 . normalize ( )
91- . angle_to ( Vec2 :: Y ) ; // (this Y is on the XZ plane -> Z)
92- Quat :: from_rotation_y ( y_angle)
100+ . angle_to ( Vec2 :: Y ) // (this Y is on the XZ plane -> Z)
93101 } else {
94102 let marker_x_axis = marker_pose. orientation * Vec3 :: X ;
95- let y_angle = Vec2 :: new ( marker_x_axis. x , marker_x_axis. z )
103+ Vec2 :: new ( marker_x_axis. x , marker_x_axis. z )
96104 . normalize ( )
97- . angle_to ( Vec2 :: X ) ;
98- Quat :: from_rotation_y ( y_angle)
105+ . angle_to ( Vec2 :: X )
106+ } ;
107+ let marker_floor_position =
108+ Vec2 :: new ( marker_pose. position . x , marker_pose. position . z ) ;
109+
110+ self . recentering_marker
111+ . take_if ( |rm| rm. string != colocation_config. qr_code_string ) ;
112+ let recentering_marker = if let Some ( rm) = & mut self . recentering_marker {
113+ rm. average_angle . submit_sample ( marker_y_angle) ;
114+ rm. average_position . submit_sample ( marker_floor_position) ;
115+ rm
116+ } else {
117+ self . recentering_marker . insert ( RecenteringMarker {
118+ string : colocation_config. qr_code_string . clone ( ) ,
119+ average_angle : AngleSlidingWindowAverage :: new (
120+ marker_y_angle,
121+ self . max_history_size ,
122+ ) ,
123+ average_position : SlidingWindowAverage :: new (
124+ marker_floor_position,
125+ self . max_history_size ,
126+ ) ,
127+ } )
99128 } ;
100129
130+ let average_angle =
131+ Quat :: from_rotation_y ( recentering_marker. average_angle . get_average ( ) ) ;
101132 let position = {
102- let marker_offset_2d = Vec3 :: new (
133+ let marker_offset_2d = Vec2 :: new (
103134 colocation_config. floor_offset [ 0 ] ,
104- 0.0 ,
105135 colocation_config. floor_offset [ 1 ] ,
106136 ) ;
107- let marker_position_2d =
108- Vec3 :: new ( marker_pose. position . x , 0.0 , marker_pose. position . z ) ;
109137
110- marker_position_2d - marker_offset_2d
138+ let offset_2d = recentering_marker. average_position . get_average ( )
139+ - marker_offset_2d;
140+ Vec3 :: new ( offset_2d. x , 0.0 , offset_2d. y )
111141 } ;
142+ alvr_common:: debug!(
143+ "Recentering from marker. Angle: {average_angle}, Position: {position}"
144+ ) ;
112145
113146 Pose {
114147 position,
115- orientation,
148+ orientation : Quat :: from_rotation_y (
149+ recentering_marker. average_angle . get_average ( ) ,
150+ ) ,
116151 }
117152 } else {
118153 // In case the marker is not found, abort recentering, we still want to use
@@ -432,13 +467,15 @@ pub fn tracking_loop(
432467 & tracking. device_motions ,
433468 ) ;
434469
435- tracking_manager_lock. report_markers ( tracking. markers ) ;
436- if matches ! (
437- headset_config. recentering_mode,
438- RecenteringMode :: Stage { .. }
439- ) {
440- tracking_manager_lock. recenter ( & headset_config. recentering_mode ) ;
441- } ;
470+ if !tracking. markers . is_empty ( ) {
471+ tracking_manager_lock. report_markers ( tracking. markers ) ;
472+ if matches ! (
473+ headset_config. recentering_mode,
474+ RecenteringMode :: Stage { .. }
475+ ) {
476+ tracking_manager_lock. recenter ( & headset_config. recentering_mode ) ;
477+ } ;
478+ }
442479
443480 if let Some ( skeleton) = tracking. hand_skeletons [ 0 ] {
444481 tracking_manager_lock. report_hand_skeleton ( HandType :: Left , timestamp, skeleton) ;
0 commit comments