ovr_sdk
diff LibOVR/Src/Tracking/Tracking_SensorStateReader.cpp @ 0:1b39a1b46319
initial 0.4.4
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 14 Jan 2015 06:51:16 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LibOVR/Src/Tracking/Tracking_SensorStateReader.cpp Wed Jan 14 06:51:16 2015 +0200 1.3 @@ -0,0 +1,207 @@ 1.4 +/************************************************************************************ 1.5 + 1.6 +Filename : Tracking_SensorStateReader.cpp 1.7 +Content : Separate reader component that is able to recover sensor pose 1.8 +Created : June 4, 2014 1.9 +Authors : Chris Taylor 1.10 + 1.11 +Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. 1.12 + 1.13 +Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); 1.14 +you may not use the Oculus VR Rift SDK except in compliance with the License, 1.15 +which is provided at the time of installation or download, or which 1.16 +otherwise accompanies this software in either electronic or hard copy form. 1.17 + 1.18 +You may obtain a copy of the License at 1.19 + 1.20 +http://www.oculusvr.com/licenses/LICENSE-3.2 1.21 + 1.22 +Unless required by applicable law or agreed to in writing, the Oculus VR SDK 1.23 +distributed under the License is distributed on an "AS IS" BASIS, 1.24 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.25 +See the License for the specific language governing permissions and 1.26 +limitations under the License. 1.27 + 1.28 +*************************************************************************************/ 1.29 + 1.30 +#include "Tracking_SensorStateReader.h" 1.31 +#include "Tracking_PoseState.h" 1.32 + 1.33 +namespace OVR { namespace Tracking { 1.34 + 1.35 + 1.36 +//------------------------------------------------------------------------------------- 1.37 + 1.38 +// This is a "perceptually tuned predictive filter", which means that it is optimized 1.39 +// for improvements in the VR experience, rather than pure error. In particular, 1.40 +// jitter is more perceptible at lower speeds whereas latency is more perceptible 1.41 +// after a high-speed motion. Therefore, the prediction interval is dynamically 1.42 +// adjusted based on speed. Significant more research is needed to further improve 1.43 +// this family of filters. 1.44 +static Pose<double> calcPredictedPose(const PoseState<double>& poseState, double predictionDt) 1.45 +{ 1.46 + Pose<double> pose = poseState.ThePose; 1.47 + const double linearCoef = 1.0; 1.48 + Vector3d angularVelocity = poseState.AngularVelocity; 1.49 + double angularSpeed = angularVelocity.Length(); 1.50 + 1.51 + // This could be tuned so that linear and angular are combined with different coefficients 1.52 + double speed = angularSpeed + linearCoef * poseState.LinearVelocity.Length(); 1.53 + 1.54 + const double slope = 0.2; // The rate at which the dynamic prediction interval varies 1.55 + double candidateDt = slope * speed; // TODO: Replace with smoothstep function 1.56 + 1.57 + double dynamicDt = predictionDt; 1.58 + 1.59 + // Choose the candidate if it is shorter, to improve stability 1.60 + if (candidateDt < predictionDt) 1.61 + { 1.62 + dynamicDt = candidateDt; 1.63 + } 1.64 + 1.65 + if (angularSpeed > 0.001) 1.66 + { 1.67 + pose.Rotation = pose.Rotation * Quatd(angularVelocity, angularSpeed * dynamicDt); 1.68 + } 1.69 + 1.70 + pose.Translation += poseState.LinearVelocity * dynamicDt; 1.71 + 1.72 + return pose; 1.73 +} 1.74 + 1.75 + 1.76 +//// SensorStateReader 1.77 + 1.78 +SensorStateReader::SensorStateReader() : 1.79 + Updater(NULL), 1.80 + LastLatWarnTime(0.) 1.81 +{ 1.82 +} 1.83 + 1.84 +void SensorStateReader::SetUpdater(const CombinedSharedStateUpdater* updater) 1.85 +{ 1.86 + Updater = updater; 1.87 +} 1.88 + 1.89 +void SensorStateReader::RecenterPose() 1.90 +{ 1.91 + if (!Updater) 1.92 + { 1.93 + return; 1.94 + } 1.95 + 1.96 + /* 1.97 + This resets position to center in x, y, z, and resets yaw to center. 1.98 + Other rotation components are not affected. 1.99 + */ 1.100 + 1.101 + const LocklessSensorState lstate = Updater->SharedSensorState.GetState(); 1.102 + 1.103 + Posed worldFromCpf = lstate.WorldFromImu.ThePose * lstate.ImuFromCpf; 1.104 + double hmdYaw, hmdPitch, hmdRoll; 1.105 + worldFromCpf.Rotation.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&hmdYaw, &hmdPitch, &hmdRoll); 1.106 + 1.107 + Posed worldFromCentered(Quatd(Axis_Y, hmdYaw), worldFromCpf.Translation); 1.108 + 1.109 + CenteredFromWorld = worldFromCentered.Inverted(); 1.110 +} 1.111 + 1.112 +bool SensorStateReader::GetSensorStateAtTime(double absoluteTime, TrackingState& ss) const 1.113 +{ 1.114 + if (!Updater) 1.115 + { 1.116 + ss.StatusFlags = 0; 1.117 + return false; 1.118 + } 1.119 + 1.120 + const LocklessSensorState lstate = Updater->SharedSensorState.GetState(); 1.121 + 1.122 + // Update time 1.123 + ss.HeadPose.TimeInSeconds = absoluteTime; 1.124 + 1.125 + // Update the status flags 1.126 + ss.StatusFlags = lstate.StatusFlags; 1.127 + // If no hardware is connected, override the tracking flags 1.128 + if (0 == (ss.StatusFlags & Status_HMDConnected)) 1.129 + { 1.130 + ss.StatusFlags &= ~Status_TrackingMask; 1.131 + } 1.132 + if (0 == (ss.StatusFlags & Status_PositionConnected)) 1.133 + { 1.134 + ss.StatusFlags &= ~(Status_PositionTracked | Status_CameraPoseTracked); 1.135 + } 1.136 + 1.137 + // If tracking info is invalid, 1.138 + if (0 == (ss.StatusFlags & Status_TrackingMask)) 1.139 + { 1.140 + return false; 1.141 + } 1.142 + 1.143 + // Delta time from the last available data 1.144 + double pdt = absoluteTime - lstate.WorldFromImu.TimeInSeconds; 1.145 + static const double maxPdt = 0.1; 1.146 + 1.147 + // If delta went negative due to synchronization problems between processes or just a lag spike, 1.148 + if (pdt < 0.) 1.149 + { 1.150 + pdt = 0.; 1.151 + } 1.152 + else if (pdt > maxPdt) 1.153 + { 1.154 + if (LastLatWarnTime != lstate.WorldFromImu.TimeInSeconds) 1.155 + { 1.156 + LastLatWarnTime = lstate.WorldFromImu.TimeInSeconds; 1.157 + LogText("[SensorStateReader] Prediction interval too high: %f s, clamping at %f s\n", pdt, maxPdt); 1.158 + } 1.159 + pdt = maxPdt; 1.160 + } 1.161 + 1.162 + ss.HeadPose = PoseStatef(lstate.WorldFromImu); 1.163 + // Do prediction logic and ImuFromCpf transformation 1.164 + ss.HeadPose.ThePose = Posef(CenteredFromWorld * calcPredictedPose(lstate.WorldFromImu, pdt) * lstate.ImuFromCpf); 1.165 + 1.166 + ss.CameraPose = Posef(CenteredFromWorld * lstate.WorldFromCamera); 1.167 + 1.168 + Posed worldFromLeveledCamera = Posed(Quatd(), lstate.WorldFromCamera.Translation); 1.169 + ss.LeveledCameraPose = Posef(CenteredFromWorld * worldFromLeveledCamera); 1.170 + 1.171 + ss.RawSensorData = lstate.RawSensorData; 1.172 + ss.LastVisionProcessingTime = lstate.LastVisionProcessingTime; 1.173 + ss.LastVisionFrameLatency = lstate.LastVisionFrameLatency; 1.174 + 1.175 + return true; 1.176 +} 1.177 + 1.178 +bool SensorStateReader::GetPoseAtTime(double absoluteTime, Posef& transform) const 1.179 +{ 1.180 + TrackingState ss; 1.181 + if (!GetSensorStateAtTime(absoluteTime, ss)) 1.182 + { 1.183 + return false; 1.184 + } 1.185 + 1.186 + transform = ss.HeadPose.ThePose; 1.187 + 1.188 + return true; 1.189 +} 1.190 + 1.191 +uint32_t SensorStateReader::GetStatus() const 1.192 +{ 1.193 + if (!Updater) 1.194 + { 1.195 + return 0; 1.196 + } 1.197 + 1.198 + const LocklessSensorState lstate = Updater->SharedSensorState.GetState(); 1.199 + 1.200 + // If invalid, 1.201 + if (0 == (lstate.StatusFlags & Status_TrackingMask)) 1.202 + { 1.203 + // Return 0 indicating no orientation nor position tracking 1.204 + return 0; 1.205 + } 1.206 + 1.207 + return lstate.StatusFlags; 1.208 +} 1.209 + 1.210 +}} // namespace OVR::Tracking