diff options
Diffstat (limited to 'LibOVR/Src/OVR_SensorFusion.h')
-rw-r--r-- | LibOVR/Src/OVR_SensorFusion.h | 582 |
1 files changed, 0 insertions, 582 deletions
diff --git a/LibOVR/Src/OVR_SensorFusion.h b/LibOVR/Src/OVR_SensorFusion.h deleted file mode 100644 index 2a17920..0000000 --- a/LibOVR/Src/OVR_SensorFusion.h +++ /dev/null @@ -1,582 +0,0 @@ -/************************************************************************************ - -PublicHeader: OVR.h -Filename : OVR_SensorFusion.h -Content : Methods that determine head orientation from sensor data over time -Created : October 9, 2012 -Authors : Michael Antonov, Steve LaValle, Dov Katz, Max Katsev, Dan Gierl - -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. - -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); -you may not use the Oculus VR Rift SDK except in compliance with the License, -which is provided at the time of installation or download, or which -otherwise accompanies this software in either electronic or hard copy form. - -You may obtain a copy of the License at - -http://www.oculusvr.com/licenses/LICENSE-3.1 - -Unless required by applicable law or agreed to in writing, the Oculus VR SDK -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -*************************************************************************************/ - -#ifndef OVR_SensorFusion_h -#define OVR_SensorFusion_h - -#include "OVR_Device.h" -#include "OVR_SensorFilter.h" -#include "Kernel/OVR_Timer.h" -#include "Kernel/OVR_Threads.h" -#include "Kernel/OVR_Lockless.h" - -// CAPI forward declarations. -typedef struct ovrPoseStatef_ ovrPoseStatef; -typedef struct ovrSensorState_ ovrSensorState; - -namespace OVR { - -struct HmdRenderInfo; - -//------------------------------------------------------------------------------------- -// ***** Sensor State - -// These values are reported as compatible with C API. - - -// PoseState describes the complete pose, or a rigid body configuration, at a -// point in time, including first and second derivatives. It is used to specify -// instantaneous location and movement of the headset. -// SensorState is returned as a part of the sensor state. - -template<class T> -class PoseState -{ -public: - typedef typename CompatibleTypes<Transform<T> >::Type CompatibleType; - - PoseState() : TimeInSeconds(0.0) { } - // float <-> double conversion constructor. - explicit PoseState(const PoseState<typename Math<T>::OtherFloatType> &src) - : Pose(src.Pose), - AngularVelocity(src.AngularVelocity), LinearVelocity(src.LinearVelocity), - AngularAcceleration(src.AngularAcceleration), LinearAcceleration(src.LinearAcceleration), - TimeInSeconds(src.TimeInSeconds) - { } - - // C-interop support: PoseStatef <-> ovrPoseStatef - PoseState(const typename CompatibleTypes<PoseState<T> >::Type& src) - : Pose(src.Pose), - AngularVelocity(src.AngularVelocity), LinearVelocity(src.LinearVelocity), - AngularAcceleration(src.AngularAcceleration), LinearAcceleration(src.LinearAcceleration), - TimeInSeconds(src.TimeInSeconds) - { } - - operator typename CompatibleTypes<PoseState<T> >::Type () const - { - typename CompatibleTypes<PoseState<T> >::Type result; - result.Pose = Pose; - result.AngularVelocity = AngularVelocity; - result.LinearVelocity = LinearVelocity; - result.AngularAcceleration = AngularAcceleration; - result.LinearAcceleration = LinearAcceleration; - result.TimeInSeconds = TimeInSeconds; - return result; - } - - - Transform<T> Pose; - Vector3<T> AngularVelocity; - Vector3<T> LinearVelocity; - Vector3<T> AngularAcceleration; - Vector3<T> LinearAcceleration; - // Absolute time of this state sample; always a double measured in seconds. - double TimeInSeconds; - - - // ***** Helpers for Pose integration - - // Stores and integrates gyro angular velocity reading for a given time step. - void StoreAndIntegrateGyro(Vector3d angVel, double dt); - // Stores and integrates position/velocity from accelerometer reading for a given time step. - void StoreAndIntegrateAccelerometer(Vector3d linearAccel, double dt); - - // Performs integration of state by adding next state delta to it - // to produce a combined state change - void AdvanceByDelta(const PoseState<T>& delta); -}; - - - -// External API returns pose as float, but uses doubles internally for quaternion precision. -typedef PoseState<float> PoseStatef; -typedef PoseState<double> PoseStated; - - -//------------------------------------------------------------------------------------- -// ***** Sensor State - - -// Bit flags describing the current status of sensor tracking. -enum StatusBits -{ - Status_OrientationTracked = 0x0001, // Orientation is currently tracked (connected and in use). - Status_PositionTracked = 0x0002, // Position is currently tracked (false if out of range). - Status_PositionConnected = 0x0020, // Position tracking HW is conceded. - // Status_HMDConnected = 0x0080 // HMD Display is available & connected. -}; - - -// Full state of of the sensor reported by GetSensorState() at a given absolute time. -class SensorState -{ -public: - SensorState() : Temperature(0), StatusFlags(0) { } - - // C-interop support - SensorState(const ovrSensorState& s); - operator ovrSensorState () const; - - // Pose state at the time that SensorState was requested. - PoseStatef Predicted; - // Actual recorded pose configuration based on sensor sample at a - // moment closest to the requested time. - PoseStatef Recorded; - - // Calibrated magnetometer reading, in Gauss, at sample time. - Vector3f Magnetometer; - // Sensor temperature reading, in degrees Celsius, at sample time. - float Temperature; - // Sensor status described by ovrStatusBits. - unsigned int StatusFlags; -}; - - - -//------------------------------------------------------------------------------------- - -class VisionHandler -{ -public: - virtual void OnVisionSuccess(const Transform<double>& cameraFromImu, UInt32 exposureCounter) = 0; - virtual void OnVisionPreviousFrame(const Transform<double>& cameraFromImu) = 0; - virtual void OnVisionFailure() = 0; - - // Get a configuration that represents the change over a short time interval - virtual Transform<double> GetVisionPrediction(UInt32 exposureCounter) = 0; -}; - -//------------------------------------------------------------------------------------- -// ***** SensorFusion - -// SensorFusion class accumulates Sensor notification messages to keep track of -// orientation, which involves integrating the gyro and doing correction with gravity. -// Magnetometer based yaw drift correction is also supported; it is usually enabled -// automatically based on loaded magnetometer configuration. -// Orientation is reported as a quaternion, from which users can obtain either the -// rotation matrix or Euler angles. -// -// The class can operate in two ways: -// - By user manually passing MessageBodyFrame messages to the OnMessage() function. -// - By attaching SensorFusion to a SensorDevice, in which case it will -// automatically handle notifications from that device. - - -class SensorFusion : public NewOverrideBase, public VisionHandler -{ - friend class SensorFusionDebug; - - enum - { - MagMaxReferences = 1000 - }; - -public: - - // ------------------------------------------------------------------------------- - // Critical components for tiny API - - SensorFusion(SensorDevice* sensor = 0); - ~SensorFusion(); - - // Attaches this SensorFusion to the IMU sensor device, from which it will receive - // notification messages. If a sensor is attached, manual message notification - // is not necessary. Calling this function also resets SensorFusion state. - bool AttachToSensor(SensorDevice* sensor); - - // Returns true if this Sensor fusion object is attached to the IMU. - bool IsAttachedToSensor() const; - - // Sets up head-and-neck model and device-to-pupil dimensions from the user's profile and the HMD stats. - // This copes elegantly if profile is NULL. - void SetUserHeadDimensions(Profile const &profile, HmdRenderInfo const &hmdRenderInfo); - - // Get the predicted pose (orientation, position) of the center pupil frame (CPF) at a specific point in time. - Transformf GetPoseAtTime(double absoluteTime) const; - - // Get the full dynamical system state of the CPF, which includes velocities and accelerations, - // predicted at a specified absolute point in time. - SensorState GetSensorStateAtTime(double absoluteTime) const; - - // Get the sensor status (same as GetSensorStateAtTime(...).Status) - unsigned int GetStatus() const; - - // End tiny API components - // ------------------------------------------------------------------------------- - - // Resets the current orientation. - void Reset (); - - // Configuration - void EnableMotionTracking(bool enable = true) { MotionTrackingEnabled = enable; } - bool IsMotionTrackingEnabled() const { return MotionTrackingEnabled; } - - // Accelerometer/Gravity Correction Control - // Enables/disables gravity correction (on by default). - void SetGravityEnabled (bool enableGravity); - bool IsGravityEnabled () const; - - // Vision Position and Orientation Configuration - // ----------------------------------------------- - bool IsVisionPositionEnabled () const; - void SetVisionPositionEnabled (bool enableVisionPosition); - - // compensates for a tilted camera - void SetCameraTiltCorrectionEnabled(bool enable); - bool IsCameraTiltCorrectionEnabled () const; - - // Message Handling Logic - // ----------------------------------------------- - // Notifies SensorFusion object about a new BodyFrame - // message from a sensor. - // Should be called by user if not attached to sensor. - void OnMessage (const MessageBodyFrame& msg); - - - // Interaction with vision - // ----------------------------------------------- - // Handle observation from vision system (orientation, position, time) - virtual void OnVisionSuccess(const Transform<double>& cameraFromImu, UInt32 exposureCounter); - - virtual void OnVisionPreviousFrame(const Transform<double>& cameraFromImu); - virtual void OnVisionFailure(); - // Get a configuration that represents the change over a short time interval - virtual Transform<double> GetVisionPrediction(UInt32 exposureCounter); - - double GetTime () const; - double GetVisionLatency () const; - - - // Detailed head dimension control - // ----------------------------------------------- - // These are now deprecated in favour of SetUserHeadDimensions() - Vector3f GetHeadModel() const; - void SetHeadModel(const Vector3f &headModel, bool resetNeckPivot = true ); - float GetCenterPupilDepth() const; - void SetCenterPupilDepth(float centerPupilDepth); - - - // Magnetometer and Yaw Drift Section: - // --------------------------------------- - - // Enables/disables magnetometer based yaw drift correction. - // Must also have mag calibration data for this correction to work. - void SetYawCorrectionEnabled(bool enable); - // Determines if yaw correction is enabled. - bool IsYawCorrectionEnabled () const; - - // Clear the reference points associating - // mag readings with orientations - void ClearMagReferences (); - - // Sets the focus filter direction to the current HMD direction - void SetFocusDirection(); - // Sets the focus filter to a direction in the body frame. Once set, a complementary filter - // will very slowly drag the world to keep the direction of the HMD within the FOV of the focus - void SetFocusDirection(Vector3d direction); - // Sets the FOV (in radians) of the focus. When the yaw difference between the HMD's current pose - // and the focus is smaller than the FOV, the complementary filter does not act. - void SetFocusFOV(double rads); - // Turns off the focus filter (equivalent to setting the focus to 0 - void ClearFocus(); - -private: - - // ----------------------------------------------- - - class BodyFrameHandler : public NewOverrideBase, public MessageHandler - { - SensorFusion* pFusion; - public: - BodyFrameHandler(SensorFusion* fusion) - : pFusion(fusion) {} - - ~BodyFrameHandler(); - - virtual void OnMessage(const Message& msg); - virtual bool SupportsMessageType(MessageType type) const; - }; - - - // ----------------------------------------------- - - // State version stored in lockless updater "queue" and used for - // prediction by GetPoseAtTime/GetSensorStateAtTime - struct LocklessState - { - PoseState<double> State; - float Temperature; - Vector3d Magnetometer; - unsigned int StatusFlags; - - LocklessState() : Temperature(0.0), StatusFlags(0) { }; - }; - - - // ----------------------------------------------- - - // Entry describing the state of the headset at the time of an exposure as reported by the DK2 board. - // This is used in combination with the vision data for - // incremental tracking based on IMU change and for drift correction - struct ExposureRecord - { - UInt32 ExposureCounter; - double ExposureTime; - // State of the headset at the time of exposure - PoseState<double> WorldFromImu; - // Change in state since the last exposure based on IMU data only - PoseState<double> ImuOnlyDelta; - // Did we have tracking for the entire interval between exposures - bool VisionTrackingAvailable; - - ExposureRecord() : ExposureCounter(0), ExposureTime(0.0), VisionTrackingAvailable(true) { } - ExposureRecord(UInt32 exposureCounter, double exposureTime, - const PoseState<double>& worldFromImu, const PoseState<double>& imuOnlyDelta) - : ExposureCounter(exposureCounter), ExposureTime(exposureTime), - WorldFromImu(worldFromImu), ImuOnlyDelta(imuOnlyDelta), VisionTrackingAvailable(true) { } - }; - - // ----------------------------------------------- - - // Entry describing the magnetometer reference point - // Used for mag yaw correction - struct MagReferencePoint - { - Vector3d InImuFrame; - Transformd WorldFromImu; - int Score; - - MagReferencePoint() { } - MagReferencePoint(const Vector3d& inImuFrame, const Transformd& worldFromImu, int score) - : InImuFrame(inImuFrame), WorldFromImu(worldFromImu), Score(score) { } - }; - - // ----------------------------------------------- - - // The phase of the head as estimated by sensor fusion - PoseState<double> WorldFromImu; - - // State that can be read without any locks, so that high priority rendering thread - // doesn't have to worry about being blocked by a sensor/vision threads that got preempted. - LocklessUpdater<LocklessState> UpdatedState; - - // The pose we got from Vision, augmented with velocity information from numerical derivatives - PoseState<double> CameraFromImu; - // Difference between the vision and sensor fusion poses at the time of last exposure adjusted - // by all the corrections applied since then - // NB: this one is unlike all the other poses/transforms we use, since it's a difference - // between 2 WorldFromImu transforms, but is stored in the world frame, not the IMU frame - // (see computeVisionError() for details) - // For composition purposes it should be considered a WorldFromWorld transform, where the left - // side comes from vision and the right - from sensor fusion - PoseState<double> VisionError; - // Past exposure records between the last update from vision and now - // (should only be one record unless vision latency is high) - CircularBuffer<ExposureRecord> ExposureRecordHistory; - // ExposureRecord that corresponds to the last pose we got from vision - ExposureRecord LastVisionExposureRecord; - // Incomplete ExposureRecord that will go into the history buffer when - // the new MessageExposureFrame is received - ExposureRecord NextExposureRecord; - // Timings of the previous exposure, used to populate ExposureRecordHistory - MessageExposureFrame LastMessageExposureFrame; - // Time of the last vision update - double LastVisionAbsoluteTime; - - unsigned int Stage; - BodyFrameHandler *pHandler; - - Vector3d FocusDirection; - double FocusFOV; - - SensorFilterBodyFrame FAccelInImuFrame, FAccelInCameraFrame; - SensorFilterd FAngV; - - Vector3d AccelOffset; - - bool EnableGravity; - - bool EnableYawCorrection; - bool MagCalibrated; - Array<MagReferencePoint> MagRefs; - int MagRefIdx; - Quatd MagCorrectionIntegralTerm; - - bool EnableCameraTiltCorrection; - // Describes the pose of the camera in the world coordinate system - Transformd WorldFromCamera; - double WorldFromCameraConfidence; - - bool MotionTrackingEnabled; - bool VisionPositionEnabled; - - // This is a signed distance, but positive because Z increases looking inward. - // This is expressed relative to the IMU in the HMD and corresponds to the location - // of the cyclopean virtual camera focal point if both the physical and virtual - // worlds are isometrically mapped onto each other. -Steve - float CenterPupilDepth; - // Describes the position of the user eyes relative to the IMU - Transformd ImuFromCpf; - // Position of the center of the screen relative to the IMU (loaded from the headset firmware) - Transformd ImuFromScreen; - // Built-in head model for faking position using orientation only - Transformd CpfFromNeck; - // Last known base of the neck pose used for head model computations - Transformd WorldFromNeck; - - //--------------------------------------------- - - // Internal handler for messages - // bypasses error checking. - void handleMessage(const MessageBodyFrame& msg); - void handleExposure(const MessageExposureFrame& msg); - - // Compute the difference between vision and sensor fusion data - PoseStated computeVisionError(); - // Apply headset yaw correction from magnetometer - // for models without camera or when camera isn't available - void applyMagYawCorrection(Vector3d mag, double deltaT); - // Apply headset tilt correction from the accelerometer - void applyTiltCorrection(double deltaT); - // Apply headset yaw correction from the camera - void applyVisionYawCorrection(double deltaT); - // Apply headset position correction from the camera - void applyPositionCorrection(double deltaT); - // Apply camera tilt correction from the accelerometer - void applyCameraTiltCorrection(Vector3d accel, double deltaT); - // Apply camera focus correction - void applyFocusCorrection(double deltaT); - - // If you have a known-good pose, this sets the neck pivot position. - void setNeckPivotFromPose ( Transformd const &pose ); -}; - - - -//------------------------------------------------------------------------------------- -// ***** SensorFusion - Inlines - -inline bool SensorFusion::IsAttachedToSensor() const -{ - return pHandler->IsHandlerInstalled(); -} - -inline void SensorFusion::SetGravityEnabled(bool enableGravity) -{ - EnableGravity = enableGravity; -} - -inline bool SensorFusion::IsGravityEnabled() const -{ - return EnableGravity; -} - -inline void SensorFusion::SetYawCorrectionEnabled(bool enable) -{ - EnableYawCorrection = enable; -} - -inline bool SensorFusion::IsYawCorrectionEnabled() const -{ - return EnableYawCorrection; -} - -inline bool SensorFusion::IsVisionPositionEnabled() const -{ - return VisionPositionEnabled; -} - -inline void SensorFusion::SetVisionPositionEnabled(bool enableVisionPosition) -{ - VisionPositionEnabled = enableVisionPosition; -} - -inline void SensorFusion::SetCameraTiltCorrectionEnabled(bool enable) -{ - EnableCameraTiltCorrection = enable; -} - -inline bool SensorFusion::IsCameraTiltCorrectionEnabled() const -{ - return EnableCameraTiltCorrection; -} - -inline double SensorFusion::GetVisionLatency() const -{ - return LastVisionAbsoluteTime - CameraFromImu.TimeInSeconds; -} - -inline double SensorFusion::GetTime() const -{ - return Timer::GetSeconds(); -} - -inline SensorFusion::BodyFrameHandler::~BodyFrameHandler() -{ - RemoveHandlerFromDevices(); -} - -inline bool SensorFusion::BodyFrameHandler::SupportsMessageType(MessageType type) const -{ - return (type == Message_BodyFrame || type == Message_ExposureFrame); -} - - -//------------------------------------------------------------------------------------- -// ***** PoseState - Inlines - -// Stores and integrates gyro angular velocity reading for a given time step. -template<class T> -void PoseState<T>::StoreAndIntegrateGyro(Vector3d angVel, double dt) -{ - AngularVelocity = angVel; - double angle = angVel.Length() * dt; - if (angle > 0) - Pose.Rotation = Pose.Rotation * Quatd(angVel, angle); -} - -template<class T> -void PoseState<T>::StoreAndIntegrateAccelerometer(Vector3d linearAccel, double dt) -{ - LinearAcceleration = linearAccel; - Pose.Translation += LinearVelocity * dt + LinearAcceleration * (dt * dt * 0.5); - LinearVelocity += LinearAcceleration * dt; -} - -// Performs integration of state by adding next state delta to it -// to produce a combined state change -template<class T> -void PoseState<T>::AdvanceByDelta(const PoseState<T>& delta) -{ - Pose.Rotation = Pose.Rotation * delta.Pose.Rotation; - Pose.Translation += delta.Pose.Translation + LinearVelocity * delta.TimeInSeconds; - LinearVelocity += delta.LinearVelocity; - TimeInSeconds += delta.TimeInSeconds; -} - -} // namespace OVR -#endif |