diff options
Diffstat (limited to 'LibOVR/Src/OVR_SensorImpl.cpp')
-rw-r--r-- | LibOVR/Src/OVR_SensorImpl.cpp | 1165 |
1 files changed, 0 insertions, 1165 deletions
diff --git a/LibOVR/Src/OVR_SensorImpl.cpp b/LibOVR/Src/OVR_SensorImpl.cpp deleted file mode 100644 index 91ae7e0..0000000 --- a/LibOVR/Src/OVR_SensorImpl.cpp +++ /dev/null @@ -1,1165 +0,0 @@ -/************************************************************************************ - -Filename : OVR_SensorImpl.cpp -Content : Oculus Sensor device implementation. -Created : March 7, 2013 -Authors : Lee Cooper, Dov Katz - -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. - -*************************************************************************************/ - -#include "OVR_SensorImpl.h" -#include "OVR_Sensor2Impl.h" -#include "OVR_SensorImpl_Common.h" -#include "OVR_JSON.h" -#include "OVR_Profile.h" -#include "Kernel/OVR_Alg.h" -#include <time.h> - -// HMDDeviceDesc can be created/updated through Sensor carrying DisplayInfo. - -#include "Kernel/OVR_Timer.h" - -//extern FILE *SF_LOG_fp; - -namespace OVR { - -using namespace Alg; - -//------------------------------------------------------------------------------------- -// ***** Oculus Sensor-specific packet data structures - -enum { - Sensor_VendorId = Oculus_VendorId, - Sensor_Tracker_ProductId = Device_Tracker_ProductId, - Sensor_Tracker2_ProductId = Device_Tracker2_ProductId, - Sensor_KTracker_ProductId = Device_KTracker_ProductId, - - Sensor_BootLoader = 0x1001, - - Sensor_DefaultReportRate = 500, // Hz - Sensor_MaxReportRate = 1000 // Hz -}; - - -// Messages we care for -enum TrackerMessageType -{ - TrackerMessage_None = 0, - TrackerMessage_Sensors = 1, - TrackerMessage_Unknown = 0x100, - TrackerMessage_SizeError = 0x101, -}; - - -struct TrackerSensors -{ - UByte SampleCount; - UInt16 Timestamp; - UInt16 LastCommandID; - SInt16 Temperature; - - TrackerSample Samples[3]; - - SInt16 MagX, MagY, MagZ; - - TrackerMessageType Decode(const UByte* buffer, int size) - { - if (size < 62) - return TrackerMessage_SizeError; - - SampleCount = buffer[1]; - Timestamp = DecodeUInt16(buffer + 2); - LastCommandID = DecodeUInt16(buffer + 4); - Temperature = DecodeSInt16(buffer + 6); - - //if (SampleCount > 2) - // OVR_DEBUG_LOG_TEXT(("TackerSensor::Decode SampleCount=%d\n", SampleCount)); - - // Only unpack as many samples as there actually are - int iterationCount = (SampleCount > 2) ? 3 : SampleCount; - - for (int i = 0; i < iterationCount; i++) - { - UnpackSensor(buffer + 8 + 16 * i, &Samples[i].AccelX, &Samples[i].AccelY, &Samples[i].AccelZ); - UnpackSensor(buffer + 16 + 16 * i, &Samples[i].GyroX, &Samples[i].GyroY, &Samples[i].GyroZ); - } - - MagX = DecodeSInt16(buffer + 56); - MagY = DecodeSInt16(buffer + 58); - MagZ = DecodeSInt16(buffer + 60); - - return TrackerMessage_Sensors; - } -}; - -struct TrackerMessage -{ - TrackerMessageType Type; - TrackerSensors Sensors; -}; - - -//------------------------------------------------------------------------------------- -// ***** SensorDisplayInfoImpl -SensorDisplayInfoImpl::SensorDisplayInfoImpl() - : CommandId(0), DistortionType(Base_None) -{ - memset(Buffer, 0, PacketSize); - Buffer[0] = 9; -} - -void SensorDisplayInfoImpl::Unpack() -{ - CommandId = Buffer[1] | (UInt16(Buffer[2]) << 8); - DistortionType = Buffer[3]; - HResolution = DecodeUInt16(Buffer+4); - VResolution = DecodeUInt16(Buffer+6); - HScreenSize = DecodeUInt32(Buffer+8) * (1/1000000.f); - VScreenSize = DecodeUInt32(Buffer+12) * (1/1000000.f); - VCenter = DecodeUInt32(Buffer+16) * (1/1000000.f); - LensSeparation = DecodeUInt32(Buffer+20) * (1/1000000.f); - -#if 0 - // These are not well-measured on most devices - probably best to ignore them. - OutsideLensSurfaceToScreen[0] = DecodeUInt32(Buffer+24) * (1/1000000.f); - OutsideLensSurfaceToScreen[1] = DecodeUInt32(Buffer+28) * (1/1000000.f); - // TODO: add spline-based distortion. - // TODO: currently these values are all zeros in the HMD itself. - DistortionK[0] = DecodeFloat(Buffer+32); - DistortionK[1] = DecodeFloat(Buffer+36); - DistortionK[2] = DecodeFloat(Buffer+40); - DistortionK[3] = DecodeFloat(Buffer+44); - DistortionK[4] = DecodeFloat(Buffer+48); - DistortionK[5] = DecodeFloat(Buffer+52); -#else - // The above are either measured poorly, or don't have values at all. - // To remove the temptation to use them, set them to junk. - OutsideLensSurfaceToScreen[0] = -1.0f; - OutsideLensSurfaceToScreen[1] = -1.0f; - DistortionK[0] = -1.0f; - DistortionK[1] = -1.0f; - DistortionK[2] = -1.0f; - DistortionK[3] = -1.0f; - DistortionK[4] = -1.0f; - DistortionK[5] = -1.0f; -#endif -} - - -//------------------------------------------------------------------------------------- -// ***** SensorDeviceFactory - -SensorDeviceFactory &SensorDeviceFactory::GetInstance() -{ - static SensorDeviceFactory instance; - return instance; -} - -void SensorDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor) -{ - - class SensorEnumerator : public HIDEnumerateVisitor - { - // Assign not supported; suppress MSVC warning. - void operator = (const SensorEnumerator&) { } - - DeviceFactory* pFactory; - EnumerateVisitor& ExternalVisitor; - public: - SensorEnumerator(DeviceFactory* factory, EnumerateVisitor& externalVisitor) - : pFactory(factory), ExternalVisitor(externalVisitor) { } - - virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId) - { - return pFactory->MatchVendorProduct(vendorId, productId); - } - - virtual void Visit(HIDDevice& device, const HIDDeviceDesc& desc) - { - - if (desc.ProductId == Sensor_BootLoader) - { // If we find a sensor in boot loader mode then notify the app - // about the existence of the device, but don't allow the app - // to create or access the device - BootLoaderDeviceCreateDesc createDesc(pFactory, desc); - ExternalVisitor.Visit(createDesc); - return; - } - - SensorDeviceCreateDesc createDesc(pFactory, desc); - ExternalVisitor.Visit(createDesc); - - // Check if the sensor returns DisplayInfo. If so, try to use it to override potentially - // mismatching monitor information (in case wrong EDID is reported by splitter), - // or to create a new "virtualized" HMD Device. - - SensorDisplayInfoImpl displayInfo; - - if (device.GetFeatureReport(displayInfo.Buffer, SensorDisplayInfoImpl::PacketSize)) - { - displayInfo.Unpack(); - - // If we got display info, try to match / create HMDDevice as well - // so that sensor settings give preference. - if (displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt) - { - SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo(displayInfo, ExternalVisitor); - } - } - } - }; - - //double start = Timer::GetProfileSeconds(); - - SensorEnumerator sensorEnumerator(this, visitor); - GetManagerImpl()->GetHIDDeviceManager()->Enumerate(&sensorEnumerator); - - //double totalSeconds = Timer::GetProfileSeconds() - start; -} - -bool SensorDeviceFactory::MatchVendorProduct(UInt16 vendorId, UInt16 productId) const -{ - return ((vendorId == Sensor_VendorId) && (productId == Sensor_Tracker_ProductId)) || - ((vendorId == Sensor_VendorId) && (productId == Sensor_Tracker2_ProductId)) || - ((vendorId == Sensor_VendorId) && (productId == Sensor_KTracker_ProductId)); -} - -bool SensorDeviceFactory::DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc) -{ - if (MatchVendorProduct(desc.VendorId, desc.ProductId)) - { - if (desc.ProductId == Sensor_BootLoader) - { // If we find a sensor in boot loader mode then notify the app - // about the existence of the device, but don't allow them - // to create or access the device - BootLoaderDeviceCreateDesc createDesc(this, desc); - pdevMgr->AddDevice_NeedsLock(createDesc); - return false; // return false to allow upstream boot loader factories to catch the device - } - else - { - SensorDeviceCreateDesc createDesc(this, desc); - return pdevMgr->AddDevice_NeedsLock(createDesc).GetPtr() != NULL; - } - } - return false; -} - -//------------------------------------------------------------------------------------- -// ***** SensorDeviceCreateDesc - -DeviceBase* SensorDeviceCreateDesc::NewDeviceInstance() -{ - if (HIDDesc.ProductId == Sensor_Tracker2_ProductId) - { - return new Sensor2DeviceImpl(this); - } - - return new SensorDeviceImpl(this); -} - -bool SensorDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const -{ - if ((info->InfoClassType != Device_Sensor) && - (info->InfoClassType != Device_None)) - return false; - - info->Type = Device_Sensor; - info->ProductName = HIDDesc.Product; - info->Manufacturer = HIDDesc.Manufacturer; - info->Version = HIDDesc.VersionNumber; - - if (info->InfoClassType == Device_Sensor) - { - SensorInfo* sinfo = (SensorInfo*)info; - sinfo->VendorId = HIDDesc.VendorId; - sinfo->ProductId = HIDDesc.ProductId; - sinfo->MaxRanges = SensorRangeImpl::GetMaxSensorRange(); - sinfo->SerialNumber = HIDDesc.SerialNumber; - } - return true; -} - -//------------------------------------------------------------------------------------- -// ***** SensorDevice - -SensorDeviceImpl::SensorDeviceImpl(SensorDeviceCreateDesc* createDesc) - : OVR::HIDDeviceImpl<OVR::SensorDevice>(createDesc, 0), - Coordinates(SensorDevice::Coord_Sensor), - HWCoordinates(SensorDevice::Coord_HMD), // HW reports HMD coordinates by default. - NextKeepAliveTickSeconds(0), - FullTimestamp(0), - MaxValidRange(SensorRangeImpl::GetMaxSensorRange()), - magCalibrated(false) -{ - SequenceValid = false; - LastSampleCount = 0; - LastTimestamp = 0; - - OldCommandId = 0; - - PrevAbsoluteTime = 0.0; - -#ifdef OVR_OS_ANDROID - pPhoneSensors = PhoneSensors::Create(); -#endif -} - -SensorDeviceImpl::~SensorDeviceImpl() -{ - // Check that Shutdown() was called. - OVR_ASSERT(!pCreateDesc->pDevice); -} - - -// Internal creation APIs. -bool SensorDeviceImpl::Initialize(DeviceBase* parent) -{ - if (HIDDeviceImpl<OVR::SensorDevice>::Initialize(parent)) - { - openDevice(); - return true; - } - - return false; -} - -void SensorDeviceImpl::openDevice() -{ - - // Read the currently configured range from sensor. - SensorRangeImpl sr(SensorRange(), 0); - - if (GetInternalDevice()->GetFeatureReport(sr.Buffer, SensorRangeImpl::PacketSize)) - { - sr.Unpack(); - sr.GetSensorRange(&CurrentRange); - // Increase the magnetometer range, since the default value is not enough in practice - CurrentRange.MaxMagneticField = 2.5f; - setRange(CurrentRange); - } - - // Read the currently configured calibration from sensor. - SensorFactoryCalibrationImpl sc; - if (GetInternalDevice()->GetFeatureReport(sc.Buffer, SensorFactoryCalibrationImpl::PacketSize)) - { - sc.Unpack(); - AccelCalibrationOffset = sc.AccelOffset; - GyroCalibrationOffset = sc.GyroOffset; - AccelCalibrationMatrix = sc.AccelMatrix; - GyroCalibrationMatrix = sc.GyroMatrix; - CalibrationTemperature = sc.Temperature; - } - - // If the sensor has "DisplayInfo" data, use HMD coordinate frame by default. - SensorDisplayInfoImpl displayInfo; - if (GetInternalDevice()->GetFeatureReport(displayInfo.Buffer, SensorDisplayInfoImpl::PacketSize)) - { - displayInfo.Unpack(); - Coordinates = (displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt) ? - Coord_HMD : Coord_Sensor; - } - - // Read/Apply sensor config. - setCoordinateFrame(Coordinates); - setReportRate(Sensor_DefaultReportRate); - - // Set Keep-alive at 10 seconds. - SensorKeepAliveImpl skeepAlive(10 * 1000); - GetInternalDevice()->SetFeatureReport(skeepAlive.Buffer, SensorKeepAliveImpl::PacketSize); - - // Load mag calibration - MagCalibrationReport report; - bool res = GetMagCalibrationReport(&report); - if (res && report.Version > 0) - { - magCalibration = report.Calibration; - magCalibrated = true; - } -} - -void SensorDeviceImpl::closeDeviceOnError() -{ - LogText("OVR::SensorDevice - Lost connection to '%s'\n", getHIDDesc()->Path.ToCStr()); - NextKeepAliveTickSeconds = 0; -} - -void SensorDeviceImpl::Shutdown() -{ - HIDDeviceImpl<OVR::SensorDevice>::Shutdown(); - - LogText("OVR::SensorDevice - Closed '%s'\n", getHIDDesc()->Path.ToCStr()); -} - -void SensorDeviceImpl::OnInputReport(UByte* pData, UInt32 length) -{ - - bool processed = false; - if (!processed) - { - TrackerMessage message; - if (decodeTrackerMessage(&message, pData, length)) - { - processed = true; - onTrackerMessage(&message); - } - } -} - -double SensorDeviceImpl::OnTicks(double tickSeconds) -{ - if (tickSeconds >= NextKeepAliveTickSeconds) - { - // Use 3-seconds keep alive by default. - double keepAliveDelta = 3.0; - - // Set Keep-alive at 10 seconds. - SensorKeepAliveImpl skeepAlive(10 * 1000); - // OnTicks is called from background thread so we don't need to add this to the command queue. - GetInternalDevice()->SetFeatureReport(skeepAlive.Buffer, SensorKeepAliveImpl::PacketSize); - - // Emit keep-alive every few seconds. - NextKeepAliveTickSeconds = tickSeconds + keepAliveDelta; - } - return NextKeepAliveTickSeconds - tickSeconds; -} - -bool SensorDeviceImpl::SetRange(const SensorRange& range, bool waitFlag) -{ - bool result = 0; - ThreadCommandQueue * threadQueue = GetManagerImpl()->GetThreadQueue(); - - if (!waitFlag) - { - return threadQueue->PushCall(this, &SensorDeviceImpl::setRange, range); - } - - if (!threadQueue->PushCallAndWaitResult(this, - &SensorDeviceImpl::setRange, - &result, - range)) - { - return false; - } - - return result; -} - -void SensorDeviceImpl::GetRange(SensorRange* range) const -{ - Lock::Locker lockScope(GetLock()); - *range = CurrentRange; -} - -bool SensorDeviceImpl::setRange(const SensorRange& range) -{ - SensorRangeImpl sr(range); - - if (GetInternalDevice()->SetFeatureReport(sr.Buffer, SensorRangeImpl::PacketSize)) - { - Lock::Locker lockScope(GetLock()); - sr.GetSensorRange(&CurrentRange); - return true; - } - - return false; -} - -void SensorDeviceImpl::SetCoordinateFrame(CoordinateFrame coordframe) -{ - // Push call with wait. - GetManagerImpl()->GetThreadQueue()-> - PushCall(this, &SensorDeviceImpl::setCoordinateFrame, coordframe, true); -} - -SensorDevice::CoordinateFrame SensorDeviceImpl::GetCoordinateFrame() const -{ - return Coordinates; -} - -Void SensorDeviceImpl::setCoordinateFrame(CoordinateFrame coordframe) -{ - - Coordinates = coordframe; - - // Read the original coordinate frame, then try to change it. - SensorConfigImpl scfg; - if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize)) - { - scfg.Unpack(); - } - - scfg.SetSensorCoordinates(coordframe == Coord_Sensor); - scfg.Pack(); - - GetInternalDevice()->SetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize); - - // Re-read the state, in case of older firmware that doesn't support Sensor coordinates. - if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize)) - { - scfg.Unpack(); - HWCoordinates = scfg.IsUsingSensorCoordinates() ? Coord_Sensor : Coord_HMD; - } - else - { - HWCoordinates = Coord_HMD; - } - return 0; -} - -void SensorDeviceImpl::SetReportRate(unsigned rateHz) -{ - // Push call with wait. - GetManagerImpl()->GetThreadQueue()-> - PushCall(this, &SensorDeviceImpl::setReportRate, rateHz, true); -} - -unsigned SensorDeviceImpl::GetReportRate() const -{ - // Read the original configuration - SensorConfigImpl scfg; - if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize)) - { - scfg.Unpack(); - return Sensor_MaxReportRate / (scfg.PacketInterval + 1); - } - return 0; // error -} - -Void SensorDeviceImpl::setReportRate(unsigned rateHz) -{ - // Read the original configuration - SensorConfigImpl scfg; - if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize)) - { - scfg.Unpack(); - } - - if (rateHz > Sensor_MaxReportRate) - rateHz = Sensor_MaxReportRate; - else if (rateHz == 0) - rateHz = Sensor_DefaultReportRate; - - scfg.PacketInterval = UInt16((Sensor_MaxReportRate / rateHz) - 1); - - scfg.Pack(); - - GetInternalDevice()->SetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize); - return 0; -} - -void SensorDeviceImpl::GetFactoryCalibration(Vector3f* AccelOffset, Vector3f* GyroOffset, - Matrix4f* AccelMatrix, Matrix4f* GyroMatrix, - float* Temperature) -{ - *AccelOffset = AccelCalibrationOffset; - *GyroOffset = GyroCalibrationOffset; - *AccelMatrix = AccelCalibrationMatrix; - *GyroMatrix = GyroCalibrationMatrix; - *Temperature = CalibrationTemperature; -} - -bool SensorDeviceImpl::IsMagCalibrated() -{ - return magCalibrated; -} - -void SensorDeviceImpl::SetOnboardCalibrationEnabled(bool enabled) -{ - // Push call with wait. - GetManagerImpl()->GetThreadQueue()-> - PushCall(this, &SensorDeviceImpl::setOnboardCalibrationEnabled, enabled, true); -} - -Void SensorDeviceImpl::setOnboardCalibrationEnabled(bool enabled) -{ - // Read the original configuration - SensorConfigImpl scfg; - if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize)) - { - scfg.Unpack(); - } - - if (enabled) - scfg.Flags |= (SensorConfigImpl::Flag_AutoCalibration | SensorConfigImpl::Flag_UseCalibration); - else - scfg.Flags &= ~(SensorConfigImpl::Flag_AutoCalibration | SensorConfigImpl::Flag_UseCalibration); - - scfg.Pack(); - - GetInternalDevice()->SetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize); - return 0; -} - -void SensorDeviceImpl::AddMessageHandler(MessageHandler* handler) -{ - if (handler) - SequenceValid = false; - DeviceBase::AddMessageHandler(handler); -} - -// Sensor reports data in the following coordinate system: -// Accelerometer: 10^-4 m/s^2; X forward, Y right, Z Down. -// Gyro: 10^-4 rad/s; X positive roll right, Y positive pitch up; Z positive yaw right. - - -// We need to convert it to the following RHS coordinate system: -// X right, Y Up, Z Back (out of screen) -// -Vector3f AccelFromBodyFrameUpdate(const TrackerSensors& update, UByte sampleNumber, - bool convertHMDToSensor = false) -{ - const TrackerSample& sample = update.Samples[sampleNumber]; - float ax = (float)sample.AccelX; - float ay = (float)sample.AccelY; - float az = (float)sample.AccelZ; - - Vector3f val = convertHMDToSensor ? Vector3f(ax, az, -ay) : Vector3f(ax, ay, az); - return val * 0.0001f; -} - - -Vector3f MagFromBodyFrameUpdate(const TrackerSensors& update, - Matrix4f magCalibration, - bool convertHMDToSensor = false) -{ - float mx = (float)update.MagX; - float my = (float)update.MagY; - float mz = (float)update.MagZ; - // Note: Y and Z are swapped in comparison to the Accel. - // This accounts for DK1 sensor firmware axis swap, which should be undone in future releases. - Vector3f mag = convertHMDToSensor ? Vector3f(mx, my, -mz) : Vector3f(mx, mz, my); - mag *= 0.0001f; - // Apply calibration - return magCalibration.Transform(mag); -} - -Vector3f EulerFromBodyFrameUpdate(const TrackerSensors& update, UByte sampleNumber, - bool convertHMDToSensor = false) -{ - const TrackerSample& sample = update.Samples[sampleNumber]; - float gx = (float)sample.GyroX; - float gy = (float)sample.GyroY; - float gz = (float)sample.GyroZ; - - Vector3f val = convertHMDToSensor ? Vector3f(gx, gz, -gy) : Vector3f(gx, gy, gz); - return val * 0.0001f; -} - -bool SensorDeviceImpl::decodeTrackerMessage(TrackerMessage* message, UByte* buffer, int size) -{ - memset(message, 0, sizeof(TrackerMessage)); - - if (size < 4) - { - message->Type = TrackerMessage_SizeError; - return false; - } - - switch (buffer[0]) - { - case TrackerMessage_Sensors: - message->Type = message->Sensors.Decode(buffer, size); - break; - - default: - message->Type = TrackerMessage_Unknown; - break; - } - - return (message->Type < TrackerMessage_Unknown) && (message->Type != TrackerMessage_None); -} - -void SensorDeviceImpl::onTrackerMessage(TrackerMessage* message) -{ - if (message->Type != TrackerMessage_Sensors) - return; - - const double timeUnit = (1.0 / 1000.0); - double scaledTimeUnit = timeUnit; - TrackerSensors& s = message->Sensors; - // DK1 timestamps the first sample, so the actual device time will be later - // by the time we get the message if there are multiple samples. - int timestampAdjust = (s.SampleCount > 0) ? s.SampleCount-1 : 0; - - const double now = Timer::GetSeconds(); - double absoluteTimeSeconds = 0.0; - - - if (SequenceValid) - { - unsigned timestampDelta; - - if (s.Timestamp < LastTimestamp) - { - // The timestamp rolled around the 16 bit counter, so FullTimeStamp - // needs a high word increment. - FullTimestamp += 0x10000; - timestampDelta = ((((int)s.Timestamp) + 0x10000) - (int)LastTimestamp); - } - else - { - timestampDelta = (s.Timestamp - LastTimestamp); - } - // Update the low word of FullTimeStamp - FullTimestamp = ( FullTimestamp & ~0xffff ) | s.Timestamp; - - double deviceTime = (FullTimestamp + timestampAdjust) * timeUnit; - absoluteTimeSeconds = TimeFilter.SampleToSystemTime(deviceTime, now, PrevAbsoluteTime); - scaledTimeUnit = TimeFilter.ScaleTimeUnit(timeUnit); - PrevAbsoluteTime = absoluteTimeSeconds; - - // If we missed a small number of samples, generate the sample that would have immediately - // proceeded the current one. Re-use the IMU values from the last processed sample. - if ((timestampDelta > LastSampleCount) && (timestampDelta <= 254)) - { - if (HandlerRef.HasHandlers()) - { - MessageBodyFrame sensors(this); - - sensors.AbsoluteTimeSeconds = absoluteTimeSeconds - s.SampleCount * scaledTimeUnit; - sensors.TimeDelta = (float)((timestampDelta - LastSampleCount) * scaledTimeUnit); - sensors.Acceleration = LastAcceleration; - sensors.RotationRate = LastRotationRate; - sensors.MagneticField = LastMagneticField; - sensors.Temperature = LastTemperature; - - HandlerRef.Call(sensors); - } - } - } - else - { - LastAcceleration = Vector3f(0); - LastRotationRate = Vector3f(0); - LastMagneticField= Vector3f(0); - LastTemperature = 0; - SequenceValid = true; - - // This is our baseline sensor to host time delta, - // it will be adjusted with each new message. - FullTimestamp = s.Timestamp; - - double deviceTime = (FullTimestamp + timestampAdjust) * timeUnit; - absoluteTimeSeconds = TimeFilter.SampleToSystemTime(deviceTime, now, PrevAbsoluteTime); - scaledTimeUnit = TimeFilter.ScaleTimeUnit(timeUnit); - PrevAbsoluteTime = absoluteTimeSeconds; - } - - LastSampleCount = s.SampleCount; - LastTimestamp = s.Timestamp; - - bool convertHMDToSensor = (Coordinates == Coord_Sensor) && (HWCoordinates == Coord_HMD); - -#ifdef OVR_OS_ANDROID - // LDC - Normally we get the coordinate system from the tracker. - // Since KTracker doesn't store it we'll always assume HMD coordinate system. - convertHMDToSensor = false; -#endif - - if (HandlerRef.HasHandlers()) - { - MessageBodyFrame sensors(this); - UByte iterations = s.SampleCount; - - if (s.SampleCount > 3) - { - iterations = 3; - sensors.TimeDelta = (float)((s.SampleCount - 2) * scaledTimeUnit); - } - else - { - sensors.TimeDelta = (float)scaledTimeUnit; - } - - for (UByte i = 0; i < iterations; i++) - { - sensors.AbsoluteTimeSeconds = absoluteTimeSeconds - ( iterations - 1 - i ) * scaledTimeUnit; - sensors.Acceleration = AccelFromBodyFrameUpdate(s, i, convertHMDToSensor); - sensors.RotationRate = EulerFromBodyFrameUpdate(s, i, convertHMDToSensor); - sensors.MagneticField = MagFromBodyFrameUpdate(s, magCalibration, convertHMDToSensor); - -#ifdef OVR_OS_ANDROID - replaceWithPhoneMag(&(sensors.MagneticField)); -#endif - sensors.Temperature = s.Temperature * 0.01f; - HandlerRef.Call(sensors); - // TimeDelta for the last two sample is always fixed. - sensors.TimeDelta = (float)scaledTimeUnit; - } - - LastAcceleration = sensors.Acceleration; - LastRotationRate = sensors.RotationRate; - LastMagneticField= sensors.MagneticField; - LastTemperature = sensors.Temperature; - } - else - { - UByte i = (s.SampleCount > 3) ? 2 : (s.SampleCount - 1); - LastAcceleration = AccelFromBodyFrameUpdate(s, i, convertHMDToSensor); - LastRotationRate = EulerFromBodyFrameUpdate(s, i, convertHMDToSensor); - LastMagneticField = MagFromBodyFrameUpdate(s, magCalibration, convertHMDToSensor); - -#ifdef OVR_OS_ANDROID - replaceWithPhoneMag(&LastMagneticField); -#endif - LastTemperature = s.Temperature * 0.01f; - } -} - - -#ifdef OVR_OS_ANDROID - -void SensorDeviceImpl::replaceWithPhoneMag(Vector3f* val) -{ - - // Native calibrated. - pPhoneSensors->SetMagSource(PhoneSensors::MagnetometerSource_Native); - - Vector3f magPhone; - pPhoneSensors->GetLatestMagValue(&magPhone); - - // Phone value is in micro-Tesla. Convert it to Gauss and flip axes. - magPhone *= 10000.0f/1000000.0f; - - Vector3f res; - res.x = -magPhone.y; - res.y = magPhone.x; - res.z = magPhone.z; - - *val = res; -} -#endif - -const int MAX_DEVICE_PROFILE_MAJOR_VERSION = 1; - -// Writes the current calibration for a particular device to a device profile file -bool SensorDeviceImpl::SetMagCalibrationReport(const MagCalibrationReport &data) -{ - // Get device info - SensorInfo sinfo; - GetDeviceInfo(&sinfo); - - // A named calibration may be specified for calibration in different - // environments, otherwise the default calibration is used - const char* calibrationName = "default"; - - // Generate a mag calibration event - JSON* calibration = JSON::CreateObject(); - // (hardcoded for now) the measurement and representation method - calibration->AddStringItem("Version", "2.0"); - calibration->AddStringItem("Name", "default"); - - // time stamp the calibration - char time_str[64]; - -#ifdef OVR_OS_WIN32 - struct tm caltime; - time_t now = time(0); - localtime_s(&caltime, &now); - strftime(time_str, 64, "%Y-%m-%d %H:%M:%S", &caltime); -#else - struct tm* caltime; - time_t now = time(0); - caltime = localtime(&now); - strftime(time_str, 64, "%Y-%m-%d %H:%M:%S", caltime); -#endif - - calibration->AddStringItem("Time", time_str); - - // write the full calibration matrix - char matrix[256]; - data.Calibration.ToString(matrix, 256); - calibration->AddStringItem("CalibrationMatrix", matrix); - // save just the offset, for backwards compatibility - // this can be removed when we don't want to support 0.2.4 anymore - Vector3f center(data.Calibration.M[0][3], data.Calibration.M[1][3], data.Calibration.M[2][3]); - Matrix4f tmp = data.Calibration; tmp.M[0][3] = tmp.M[1][3] = tmp.M[2][3] = 0; tmp.M[3][3] = 1; - center = tmp.Inverted().Transform(center); - Matrix4f oldcalmat; oldcalmat.M[0][3] = center.x; oldcalmat.M[1][3] = center.y; oldcalmat.M[2][3] = center.z; - oldcalmat.ToString(matrix, 256); - calibration->AddStringItem("Calibration", matrix); - - String path = GetBaseOVRPath(true); - path += "/Devices.json"; - - // Look for a preexisting device file to edit - Ptr<JSON> root = *JSON::Load(path); - if (root) - { // Quick sanity check of the file type and format before we parse it - JSON* version = root->GetFirstItem(); - if (version && version->Name == "Oculus Device Profile Version") - { - int major = atoi(version->Value.ToCStr()); - if (major > MAX_DEVICE_PROFILE_MAJOR_VERSION) - { - // don't use the file on unsupported major version number - root->Release(); - root = NULL; - } - } - else - { - root->Release(); - root = NULL; - } - } - - JSON* device = NULL; - if (root) - { - device = root->GetFirstItem(); // skip the header - device = root->GetNextItem(device); - while (device) - { // Search for a previous calibration with the same name for this device - // and remove it before adding the new one - if (device->Name == "Device") - { - JSON* item = device->GetItemByName("Serial"); - if (item && item->Value == sinfo.SerialNumber) - { // found an entry for this device - item = device->GetNextItem(item); - while (item) - { - if (item->Name == "MagCalibration") - { - JSON* name = item->GetItemByName("Name"); - if (name && name->Value == calibrationName) - { // found a calibration of the same name - item->RemoveNode(); - item->Release(); - break; - } - } - item = device->GetNextItem(item); - } - - - /* - this is removed temporarily, since this is a sensor fusion setting, not sensor itself - should be moved to the correct place when Brant has finished the user profile implementation - // update the auto-mag flag - item = device->GetItemByName("EnableYawCorrection"); - if (item) - item->dValue = (double)EnableYawCorrection; - else - device->AddBoolItem("EnableYawCorrection", EnableYawCorrection);*/ - - break; - } - } - - device = root->GetNextItem(device); - } - } - else - { // Create a new device root - root = *JSON::CreateObject(); - root->AddStringItem("Oculus Device Profile Version", "1.0"); - } - - if (device == NULL) - { - device = JSON::CreateObject(); - device->AddStringItem("Product", sinfo.ProductName); - device->AddNumberItem("ProductID", sinfo.ProductId); - device->AddStringItem("Serial", sinfo.SerialNumber); - // removed temporarily, see above - //device->AddBoolItem("EnableYawCorrection", EnableYawCorrection); - - root->AddItem("Device", device); - } - - // Create and the add the new calibration event to the device - device->AddItem("MagCalibration", calibration); - return root->Save(path); -} - -// Loads a saved calibration for the specified device from the device profile file -bool SensorDeviceImpl::GetMagCalibrationReport(MagCalibrationReport* data) -{ - data->Version = 0; - data->Calibration.SetIdentity(); - - // Get device info - SensorInfo sinfo; - GetDeviceInfo(&sinfo); - - // A named calibration may be specified for calibration in different - // environments, otherwise the default calibration is used - const char* calibrationName = "default"; - - String path = GetBaseOVRPath(true); - path += "/Devices.json"; - - // Load the device profiles - Ptr<JSON> root = *JSON::Load(path); - if (root == NULL) - return false; - - // Quick sanity check of the file type and format before we parse it - JSON* version = root->GetFirstItem(); - if (version && version->Name == "Oculus Device Profile Version") - { - int major = atoi(version->Value.ToCStr()); - if (major > MAX_DEVICE_PROFILE_MAJOR_VERSION) - return false; // don't parse the file on unsupported major version number - } - else - { - return false; - } - - JSON* device = root->GetNextItem(version); - while (device) - { // Search for a previous calibration with the same name for this device - // and remove it before adding the new one - if (device->Name == "Device") - { - JSON* item = device->GetItemByName("Serial"); - if (item && item->Value == sinfo.SerialNumber) - { // found an entry for this device - - JSON* autoyaw = device->GetItemByName("EnableYawCorrection"); - // as a temporary HACK, return no calibration if EnableYawCorrection is off - // this will force disable yaw correction in SensorFusion - // proper solution would load the value in the Profile, which SensorFusion can access - if (autoyaw && autoyaw->dValue == 0) - return true; - - item = device->GetNextItem(item); - while (item) - { - if (item->Name == "MagCalibration") - { - JSON* calibration = item; - JSON* name = calibration->GetItemByName("Name"); - if (name && name->Value == calibrationName) - { // found a calibration with this name - - int major = 0; - JSON* version = calibration->GetItemByName("Version"); - if (version) - major = atoi(version->Value.ToCStr()); - - if (major > data->Version && major <= 2) - { - time_t now; - time(&now); - - // parse the calibration time - //time_t calibration_time = now; - JSON* caltime = calibration->GetItemByName("Time"); - if (caltime) - { - const char* caltime_str = caltime->Value.ToCStr(); - - tm ct; - memset(&ct, 0, sizeof(tm)); - -#ifdef OVR_OS_WIN32 - struct tm nowtime; - localtime_s(&nowtime, &now); - ct.tm_isdst = nowtime.tm_isdst; - sscanf_s(caltime_str, "%d-%d-%d %d:%d:%d", - &ct.tm_year, &ct.tm_mon, &ct.tm_mday, - &ct.tm_hour, &ct.tm_min, &ct.tm_sec); -#else - struct tm* nowtime = localtime(&now); - ct.tm_isdst = nowtime->tm_isdst; - sscanf(caltime_str, "%d-%d-%d %d:%d:%d", - &ct.tm_year, &ct.tm_mon, &ct.tm_mday, - &ct.tm_hour, &ct.tm_min, &ct.tm_sec); -#endif - ct.tm_year -= 1900; - ct.tm_mon--; - //calibration_time = mktime(&ct); - } - - // parse the calibration matrix - JSON* cal = calibration->GetItemByName("CalibrationMatrix"); - if (!cal) - cal = calibration->GetItemByName("Calibration"); - if (cal) - { - data->Calibration = Matrix4f::FromString(cal->Value.ToCStr()); - data->Version = (UByte)major; - } - } - } - } - item = device->GetNextItem(item); - } - - return true; - } - } - - device = root->GetNextItem(device); - } - - return true; -} - - -bool SensorDeviceImpl::SetSerialReport(const SerialReport& data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::setSerialReport, &result, data)) - { - return false; - } - - return result; -} - -bool SensorDeviceImpl::setSerialReport(const SerialReport& data) -{ - SerialImpl di(data); - return GetInternalDevice()->SetFeatureReport(di.Buffer, SerialImpl::PacketSize); -} - -bool SensorDeviceImpl::GetSerialReport(SerialReport* data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::getSerialReport, &result, data)) - { - return false; - } - - return result; -} - -bool SensorDeviceImpl::getSerialReport(SerialReport* data) -{ - SerialImpl di; - if (GetInternalDevice()->GetFeatureReport(di.Buffer, SerialImpl::PacketSize)) - { - di.Unpack(); - *data = di.Settings; - return true; - } - - return false; -} - -} // namespace OVR |