diff options
Diffstat (limited to 'LibOVR/Src/OVR_Sensor2Impl.cpp')
-rw-r--r-- | LibOVR/Src/OVR_Sensor2Impl.cpp | 1124 |
1 files changed, 0 insertions, 1124 deletions
diff --git a/LibOVR/Src/OVR_Sensor2Impl.cpp b/LibOVR/Src/OVR_Sensor2Impl.cpp deleted file mode 100644 index f397f22..0000000 --- a/LibOVR/Src/OVR_Sensor2Impl.cpp +++ /dev/null @@ -1,1124 +0,0 @@ -/************************************************************************************ - -Filename : OVR_Sensor2Impl.cpp -Content : DK2 sensor device specific implementation. -Created : January 21, 2013 -Authors : Lee Cooper - -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_Sensor2Impl.h" -#include "OVR_SensorImpl_Common.h" -#include "OVR_Sensor2ImplUtil.h" -#include "Kernel/OVR_Alg.h" - -//extern FILE *SF_LOG_fp; - -namespace OVR { - -//------------------------------------------------------------------------------------- -// ***** Oculus Sensor2-specific packet data structures - -enum { - Sensor2_VendorId = Oculus_VendorId, - Sensor2_ProductId = 0x0021, - - Sensor2_BootLoader = 0x1001, - - Sensor2_DefaultReportRate = 1000, // Hz -}; - - -// Messages we care for -enum Tracker2MessageType -{ - Tracker2Message_None = 0, - Tracker2Message_Sensors = 11, - Tracker2Message_Unknown = 0x100, - Tracker2Message_SizeError = 0x101, -}; - - -struct Tracker2Sensors -{ - UInt16 LastCommandID; - UByte NumSamples; - UInt16 RunningSampleCount; // Named 'SampleCount' in the firmware docs. - SInt16 Temperature; - UInt32 SampleTimestamp; - TrackerSample Samples[2]; - SInt16 MagX, MagY, MagZ; - UInt16 FrameCount; - UInt32 FrameTimestamp; - UByte FrameID; - UByte CameraPattern; - UInt16 CameraFrameCount; // Named 'CameraCount' in the firmware docs. - UInt32 CameraTimestamp; - - Tracker2MessageType Decode(const UByte* buffer, int size) - { - if (size < 64) - return Tracker2Message_SizeError; - - LastCommandID = DecodeUInt16(buffer + 1); - NumSamples = buffer[3]; - RunningSampleCount = DecodeUInt16(buffer + 4); - Temperature = DecodeSInt16(buffer + 6); - SampleTimestamp = DecodeUInt32(buffer + 8); - - // Only unpack as many samples as there actually are. - UByte iterationCount = (NumSamples > 1) ? 2 : NumSamples; - - for (UByte i = 0; i < iterationCount; i++) - { - UnpackSensor(buffer + 12 + 16 * i, &Samples[i].AccelX, &Samples[i].AccelY, &Samples[i].AccelZ); - UnpackSensor(buffer + 20 + 16 * i, &Samples[i].GyroX, &Samples[i].GyroY, &Samples[i].GyroZ); - } - - MagX = DecodeSInt16(buffer + 44); - MagY = DecodeSInt16(buffer + 46); - MagZ = DecodeSInt16(buffer + 48); - - FrameCount = DecodeUInt16(buffer + 50); - - FrameTimestamp = DecodeUInt32(buffer + 52); - FrameID = buffer[56]; - CameraPattern = buffer[57]; - CameraFrameCount = DecodeUInt16(buffer + 58); - CameraTimestamp = DecodeUInt32(buffer + 60); - - return Tracker2Message_Sensors; - } -}; - -struct Tracker2Message -{ - Tracker2MessageType Type; - Tracker2Sensors Sensors; -}; - -// 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 Tracker2Sensors& update, UByte sampleNumber) -{ - const TrackerSample& sample = update.Samples[sampleNumber]; - float ax = (float)sample.AccelX; - float ay = (float)sample.AccelY; - float az = (float)sample.AccelZ; - - return Vector3f(ax, ay, az) * 0.0001f; -} - - -Vector3f MagFromBodyFrameUpdate(const Tracker2Sensors& update) -{ - return Vector3f( (float)update.MagX, (float)update.MagY, (float)update.MagZ) * 0.0001f; -} - -Vector3f EulerFromBodyFrameUpdate(const Tracker2Sensors& update, UByte sampleNumber) -{ - const TrackerSample& sample = update.Samples[sampleNumber]; - float gx = (float)sample.GyroX; - float gy = (float)sample.GyroY; - float gz = (float)sample.GyroZ; - - return Vector3f(gx, gy, gz) * 0.0001f; -} - -bool Sensor2DeviceImpl::decodeTracker2Message(Tracker2Message* message, UByte* buffer, int size) -{ - memset(message, 0, sizeof(Tracker2Message)); - - if (size < 4) - { - message->Type = Tracker2Message_SizeError; - return false; - } - - switch (buffer[0]) - { - case Tracker2Message_Sensors: - message->Type = message->Sensors.Decode(buffer, size); - break; - - default: - message->Type = Tracker2Message_Unknown; - break; - } - - return (message->Type < Tracker2Message_Unknown) && (message->Type != Tracker2Message_None); -} - -//------------------------------------------------------------------------------------- -// ***** Sensor2Device - -Sensor2DeviceImpl::Sensor2DeviceImpl(SensorDeviceCreateDesc* createDesc) - : SensorDeviceImpl(createDesc), - LastNumSamples(0), - LastRunningSampleCount(0), - FullCameraFrameCount(0), - LastCameraTime("C"), - LastFrameTime("F"), - LastSensorTime("S"), - LastFrameTimestamp(0) -{ - // 15 samples ok in min-window for DK2 since it uses microsecond clock. - TimeFilter = SensorTimeFilter(SensorTimeFilter::Settings(15)); - - pCalibration = new SensorCalibration(this); -} - -Sensor2DeviceImpl::~Sensor2DeviceImpl() -{ - delete pCalibration; -} - -void Sensor2DeviceImpl::openDevice() -{ - - // Read the currently configured range from sensor. - SensorRangeImpl sr(SensorRange(), 0); - - if (GetInternalDevice()->GetFeatureReport(sr.Buffer, SensorRangeImpl::PacketSize)) - { - sr.Unpack(); - sr.GetSensorRange(&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; - } - Coordinates = Coord_HMD; // TODO temporary to force it behave - - // Read/Apply sensor config. - setCoordinateFrame(Coordinates); - setReportRate(Sensor2_DefaultReportRate); - setOnboardCalibrationEnabled(false); - - // Must send DK2 keep-alive. Set Keep-alive at 10 seconds. - KeepAliveMuxReport keepAlive; - keepAlive.CommandId = 0; - keepAlive.INReport = 11; - keepAlive.Interval = 10 * 1000; - - // Device creation is done from background thread so we don't need to add this to the command queue. - KeepAliveMuxImpl keepAliveImpl(keepAlive); - GetInternalDevice()->SetFeatureReport(keepAliveImpl.Buffer, KeepAliveMuxImpl::PacketSize); - - // Read the temperature data from the device - pCalibration->Initialize(); -} - -bool Sensor2DeviceImpl::SetTrackingReport(const TrackingReport& data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::setTrackingReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::setTrackingReport(const TrackingReport& data) -{ - TrackingImpl ci(data); - return GetInternalDevice()->SetFeatureReport(ci.Buffer, TrackingImpl::PacketSize); -} - -bool Sensor2DeviceImpl::GetTrackingReport(TrackingReport* data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::getTrackingReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::getTrackingReport(TrackingReport* data) -{ - TrackingImpl ci; - if (GetInternalDevice()->GetFeatureReport(ci.Buffer, TrackingImpl::PacketSize)) - { - ci.Unpack(); - *data = ci.Settings; - return true; - } - - return false; -} - -bool Sensor2DeviceImpl::SetDisplayReport(const DisplayReport& data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::setDisplayReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::setDisplayReport(const DisplayReport& data) -{ - DisplayImpl di(data); - return GetInternalDevice()->SetFeatureReport(di.Buffer, DisplayImpl::PacketSize); -} - -bool Sensor2DeviceImpl::GetDisplayReport(DisplayReport* data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::getDisplayReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::getDisplayReport(DisplayReport* data) -{ - DisplayImpl di; - if (GetInternalDevice()->GetFeatureReport(di.Buffer, DisplayImpl::PacketSize)) - { - di.Unpack(); - *data = di.Settings; - return true; - } - - return false; -} - -bool Sensor2DeviceImpl::SetMagCalibrationReport(const MagCalibrationReport& data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::setMagCalibrationReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::setMagCalibrationReport(const MagCalibrationReport& data) -{ - MagCalibrationImpl mci(data); - return GetInternalDevice()->SetFeatureReport(mci.Buffer, MagCalibrationImpl::PacketSize); -} - -bool Sensor2DeviceImpl::GetMagCalibrationReport(MagCalibrationReport* data) -{ - // direct call if we are already on the device manager thread - if (GetCurrentThreadId() == GetManagerImpl()->GetThreadId()) - { - return getMagCalibrationReport(data); - } - - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::getMagCalibrationReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::getMagCalibrationReport(MagCalibrationReport* data) -{ - MagCalibrationImpl mci; - if (GetInternalDevice()->GetFeatureReport(mci.Buffer, MagCalibrationImpl::PacketSize)) - { - mci.Unpack(); - *data = mci.Settings; - return true; - } - - return false; -} - -bool Sensor2DeviceImpl::SetPositionCalibrationReport(const PositionCalibrationReport& data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::setPositionCalibrationReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::setPositionCalibrationReport(const PositionCalibrationReport& data) -{ - UByte version = GetDeviceInterfaceVersion(); - if (version < 5) - { - PositionCalibrationImpl_Pre5 pci(data); - return GetInternalDevice()->SetFeatureReport(pci.Buffer, PositionCalibrationImpl_Pre5::PacketSize); - } - - PositionCalibrationImpl pci(data); - return GetInternalDevice()->SetFeatureReport(pci.Buffer, PositionCalibrationImpl::PacketSize); -} - -bool Sensor2DeviceImpl::getPositionCalibrationReport(PositionCalibrationReport* data) -{ - UByte version = GetDeviceInterfaceVersion(); - if (version < 5) - { - PositionCalibrationImpl_Pre5 pci; - if (GetInternalDevice()->GetFeatureReport(pci.Buffer, PositionCalibrationImpl_Pre5::PacketSize)) - { - pci.Unpack(); - *data = pci.Settings; - return true; - } - - return false; - } - - PositionCalibrationImpl pci; - if (GetInternalDevice()->GetFeatureReport(pci.Buffer, PositionCalibrationImpl::PacketSize)) - { - pci.Unpack(); - *data = pci.Settings; - return true; - } - - return false; -} - -bool Sensor2DeviceImpl::GetAllPositionCalibrationReports(Array<PositionCalibrationReport>* data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::getAllPositionCalibrationReports, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::getAllPositionCalibrationReports(Array<PositionCalibrationReport>* data) -{ - PositionCalibrationReport pc; - bool result = getPositionCalibrationReport(&pc); - if (!result) - return false; - - int positions = pc.NumPositions; - data->Clear(); - data->Resize(positions); - - for (int i = 0; i < positions; i++) - { - result = getPositionCalibrationReport(&pc); - if (!result) - return false; - OVR_ASSERT(pc.NumPositions == positions); - - (*data)[pc.PositionIndex] = pc; - // IMU should be the last one - OVR_ASSERT(pc.PositionType == (pc.PositionIndex == positions - 1) ? - PositionCalibrationReport::PositionType_IMU : PositionCalibrationReport::PositionType_LED); - } - return true; -} - -bool Sensor2DeviceImpl::SetCustomPatternReport(const CustomPatternReport& data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::setCustomPatternReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::setCustomPatternReport(const CustomPatternReport& data) -{ - CustomPatternImpl cpi(data); - return GetInternalDevice()->SetFeatureReport(cpi.Buffer, CustomPatternImpl::PacketSize); -} - -bool Sensor2DeviceImpl::GetCustomPatternReport(CustomPatternReport* data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::getCustomPatternReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::getCustomPatternReport(CustomPatternReport* data) -{ - CustomPatternImpl cpi; - if (GetInternalDevice()->GetFeatureReport(cpi.Buffer, CustomPatternImpl::PacketSize)) - { - cpi.Unpack(); - *data = cpi.Settings; - return true; - } - - return false; -} - -bool Sensor2DeviceImpl::SetManufacturingReport(const ManufacturingReport& data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::setManufacturingReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::setManufacturingReport(const ManufacturingReport& data) -{ - ManufacturingImpl mi(data); - return GetInternalDevice()->SetFeatureReport(mi.Buffer, ManufacturingImpl::PacketSize); -} - -bool Sensor2DeviceImpl::GetManufacturingReport(ManufacturingReport* data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::getManufacturingReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::getManufacturingReport(ManufacturingReport* data) -{ - ManufacturingImpl mi; - if (GetInternalDevice()->GetFeatureReport(mi.Buffer, ManufacturingImpl::PacketSize)) - { - mi.Unpack(); - *data = mi.Settings; - return true; - } - - return false; -} - -bool Sensor2DeviceImpl::SetLensDistortionReport(const LensDistortionReport& data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::setLensDistortionReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::setLensDistortionReport(const LensDistortionReport& data) -{ - LensDistortionImpl ui(data); - return GetInternalDevice()->SetFeatureReport(ui.Buffer, LensDistortionImpl::PacketSize); -} - -bool Sensor2DeviceImpl::GetLensDistortionReport(LensDistortionReport* data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::getLensDistortionReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::getLensDistortionReport(LensDistortionReport* data) -{ - LensDistortionImpl ui; - if (GetInternalDevice()->GetFeatureReport(ui.Buffer, LensDistortionImpl::PacketSize)) - { - ui.Unpack(); - *data = ui.Settings; - return true; - } - - return false; -} - -bool Sensor2DeviceImpl::SetUUIDReport(const UUIDReport& data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::setUUIDReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::setUUIDReport(const UUIDReport& data) -{ - UUIDImpl ui(data); - return GetInternalDevice()->SetFeatureReport(ui.Buffer, UUIDImpl::PacketSize); -} - -bool Sensor2DeviceImpl::GetUUIDReport(UUIDReport* data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::getUUIDReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::getUUIDReport(UUIDReport* data) -{ - UUIDImpl ui; - if (GetInternalDevice()->GetFeatureReport(ui.Buffer, UUIDImpl::PacketSize)) - { - ui.Unpack(); - *data = ui.Settings; - return true; - } - - return false; -} - -bool Sensor2DeviceImpl::SetKeepAliveMuxReport(const KeepAliveMuxReport& data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::setKeepAliveMuxReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::setKeepAliveMuxReport(const KeepAliveMuxReport& data) -{ - KeepAliveMuxImpl kami(data); - return GetInternalDevice()->SetFeatureReport(kami.Buffer, KeepAliveMuxImpl::PacketSize); -} - -bool Sensor2DeviceImpl::GetKeepAliveMuxReport(KeepAliveMuxReport* data) -{ - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::getKeepAliveMuxReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::getKeepAliveMuxReport(KeepAliveMuxReport* data) -{ - KeepAliveMuxImpl kami; - if (GetInternalDevice()->GetFeatureReport(kami.Buffer, KeepAliveMuxImpl::PacketSize)) - { - kami.Unpack(); - *data = kami.Settings; - return true; - } - - return false; -} - -bool Sensor2DeviceImpl::SetTemperatureReport(const TemperatureReport& data) -{ - // direct call if we are already on the device manager thread - if (GetCurrentThreadId() == GetManagerImpl()->GetThreadId()) - { - return setTemperatureReport(data); - } - - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::setTemperatureReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::setTemperatureReport(const TemperatureReport& data) -{ - TemperatureImpl ti(data); - return GetInternalDevice()->SetFeatureReport(ti.Buffer, TemperatureImpl::PacketSize); -} - -bool Sensor2DeviceImpl::getTemperatureReport(TemperatureReport* data) -{ - TemperatureImpl ti; - if (GetInternalDevice()->GetFeatureReport(ti.Buffer, TemperatureImpl::PacketSize)) - { - ti.Unpack(); - *data = ti.Settings; - return true; - } - - return false; -} - -bool Sensor2DeviceImpl::GetAllTemperatureReports(Array<Array<TemperatureReport> >* data) -{ - // direct call if we are already on the device manager thread - if (GetCurrentThreadId() == GetManagerImpl()->GetThreadId()) - { - return getAllTemperatureReports(data); - } - - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::getAllTemperatureReports, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::getAllTemperatureReports(Array<Array<TemperatureReport> >* data) -{ - TemperatureReport t; - bool result = getTemperatureReport(&t); - if (!result) - return false; - - int bins = t.NumBins, samples = t.NumSamples; - data->Clear(); - data->Resize(bins); - for (int i = 0; i < bins; i++) - (*data)[i].Resize(samples); - - for (int i = 0; i < bins; i++) - for (int j = 0; j < samples; j++) - { - result = getTemperatureReport(&t); - if (!result) - return false; - OVR_ASSERT(t.NumBins == bins && t.NumSamples == samples); - - (*data)[t.Bin][t.Sample] = t; - } - return true; -} - -bool Sensor2DeviceImpl::GetGyroOffsetReport(GyroOffsetReport* data) -{ - // direct call if we are already on the device manager thread - if (GetCurrentThreadId() == GetManagerImpl()->GetThreadId()) - { - return getGyroOffsetReport(data); - } - - bool result; - if (!GetManagerImpl()->GetThreadQueue()-> - PushCallAndWaitResult(this, &Sensor2DeviceImpl::getGyroOffsetReport, &result, data)) - { - return false; - } - - return result; -} - -bool Sensor2DeviceImpl::getGyroOffsetReport(GyroOffsetReport* data) -{ - GyroOffsetImpl goi; - if (GetInternalDevice()->GetFeatureReport(goi.Buffer, GyroOffsetImpl::PacketSize)) - { - goi.Unpack(); - *data = goi.Settings; - return true; - } - - return false; -} - -void Sensor2DeviceImpl::onTrackerMessage(Tracker2Message* message) -{ - if (message->Type != Tracker2Message_Sensors) - return; - - const float sampleIntervalTimeUnit = (1.0f / 1000.f); - double scaledSampleIntervalTimeUnit = sampleIntervalTimeUnit; - Tracker2Sensors& s = message->Sensors; - - double absoluteTimeSeconds = 0.0; - - if (SequenceValid) - { - UInt32 runningSampleCountDelta; - - if (s.RunningSampleCount < LastRunningSampleCount) - { - // The running sample count on the device rolled around the 16 bit counter - // (expect to happen about once per minute), so RunningSampleCount - // needs a high word increment. - runningSampleCountDelta = ((((int)s.RunningSampleCount) + 0x10000) - (int)LastRunningSampleCount); - } - else - { - runningSampleCountDelta = (s.RunningSampleCount - LastRunningSampleCount); - } - - absoluteTimeSeconds = LastSensorTime.TimeSeconds; - scaledSampleIntervalTimeUnit = TimeFilter.ScaleTimeUnit(sampleIntervalTimeUnit); - - // If we missed a small number of samples, replicate the last sample. - if ((runningSampleCountDelta > LastNumSamples) && (runningSampleCountDelta <= 254)) - { - if (HandlerRef.HasHandlers()) - { - MessageBodyFrame sensors(this); - - sensors.AbsoluteTimeSeconds = absoluteTimeSeconds - s.NumSamples * scaledSampleIntervalTimeUnit; - sensors.TimeDelta = (float) ((runningSampleCountDelta - LastNumSamples) * scaledSampleIntervalTimeUnit); - sensors.Acceleration = LastAcceleration; - sensors.RotationRate = LastRotationRate; - sensors.MagneticField = LastMagneticField; - sensors.Temperature = LastTemperature; - - pCalibration->Apply(sensors); - HandlerRef.Call(sensors); - } - } - } - else - { - LastAcceleration = Vector3f(0); - LastRotationRate = Vector3f(0); - LastMagneticField= Vector3f(0); - LastTemperature = 0; - SequenceValid = true; - } - - LastNumSamples = s.NumSamples; - LastRunningSampleCount = s.RunningSampleCount; - - if (HandlerRef.HasHandlers()) - { - MessageBodyFrame sensors(this); - UByte iterations = s.NumSamples; - - if (s.NumSamples > 2) - { - iterations = 2; - sensors.TimeDelta = (float) ((s.NumSamples - 1) * scaledSampleIntervalTimeUnit); - } - else - { - sensors.TimeDelta = (float) scaledSampleIntervalTimeUnit; - } - - for (UByte i = 0; i < iterations; i++) - { - sensors.AbsoluteTimeSeconds = absoluteTimeSeconds - ( iterations - 1 - i ) * scaledSampleIntervalTimeUnit; - sensors.Acceleration = AccelFromBodyFrameUpdate(s, i); - sensors.RotationRate = EulerFromBodyFrameUpdate(s, i); - sensors.MagneticField= MagFromBodyFrameUpdate(s); - sensors.Temperature = s.Temperature * 0.01f; - - pCalibration->Apply(sensors); - HandlerRef.Call(sensors); - - // TimeDelta for the last two sample is always fixed. - sensors.TimeDelta = (float) scaledSampleIntervalTimeUnit; - } - - // Send pixel read only when frame timestamp changes. - if (LastFrameTimestamp != s.FrameTimestamp) - { - MessagePixelRead pixelRead(this); - // Prepare message for pixel read - pixelRead.PixelReadValue = s.FrameID; - pixelRead.RawFrameTime = s.FrameTimestamp; - pixelRead.RawSensorTime = s.SampleTimestamp; - pixelRead.SensorTimeSeconds = LastSensorTime.TimeSeconds; - pixelRead.FrameTimeSeconds = LastFrameTime.TimeSeconds; - - HandlerRef.Call(pixelRead); - LastFrameTimestamp = s.FrameTimestamp; - } - - UInt16 lowFrameCount = (UInt16) FullCameraFrameCount; - // Send message only when frame counter changes - if (lowFrameCount != s.CameraFrameCount) - { - // check for the rollover in the counter - if (s.CameraFrameCount < lowFrameCount) - FullCameraFrameCount += 0x10000; - // update the low bits - FullCameraFrameCount = (FullCameraFrameCount & ~0xFFFF) | s.CameraFrameCount; - - MessageExposureFrame vision(this); - vision.CameraPattern = s.CameraPattern; - vision.CameraFrameCount = FullCameraFrameCount; - vision.CameraTimeSeconds = LastCameraTime.TimeSeconds; - - HandlerRef.Call(vision); - } - - LastAcceleration = sensors.Acceleration; - LastRotationRate = sensors.RotationRate; - LastMagneticField= sensors.MagneticField; - LastTemperature = sensors.Temperature; - - //LastPixelRead = pixelRead.PixelReadValue; - //LastPixelReadTimeStamp = LastFrameTime; - } - else - { - if (s.NumSamples != 0) - { - UByte i = (s.NumSamples > 1) ? 1 : 0; - LastAcceleration = AccelFromBodyFrameUpdate(s, i); - LastRotationRate = EulerFromBodyFrameUpdate(s, i); - LastMagneticField = MagFromBodyFrameUpdate(s); - LastTemperature = s.Temperature * 0.01f; - } - } -} - -// Helper function to handle wrap-around of timestamps from Tracker2Message and convert them -// to system time. -// - Any timestamps that didn't increment keep their old system time. -// - This is a bit tricky since we don't know which one of timestamps has most recent time. -// - The first timestamp must be the IMU one; we assume that others can't be too much ahead of it - -void UpdateDK2Timestamps(SensorTimeFilter& tf, - SensorTimestampMapping** timestamps, UInt32 *rawValues, int count) -{ - int updateIndices[4]; - int updateCount = 0; - int i; - double now = Timer::GetSeconds(); - - OVR_ASSERT(count <= sizeof(updateIndices)/sizeof(int)); - - // Update timestamp wrapping for any values that changed. - for (i = 0; i < count; i++) - { - UInt32 lowMks = (UInt32)timestamps[i]->TimestampMks; // Low 32-bits are raw old timestamp. - - if (rawValues[i] != lowMks) - { - if (i == 0) - { - // Only check for rollover in the IMU timestamp - if (rawValues[i] < lowMks) - { - LogText("Timestamp %d rollover, was: %u, now: %u\n", i, lowMks, rawValues[i]); - timestamps[i]->TimestampMks += 0x100000000LL; - } - // Update the low bits - timestamps[i]->TimestampMks = (timestamps[i]->TimestampMks & 0xFFFFFFFF00000000LL) | rawValues[i]; - } - else - { - // Take the high bits from the main timestamp first (not a typo in the first argument!) - timestamps[i]->TimestampMks = - (timestamps[0]->TimestampMks & 0xFFFFFFFF00000000LL) | rawValues[i]; - // Now force it into the reasonable range around the expanded main timestamp - if (timestamps[i]->TimestampMks > timestamps[0]->TimestampMks + 0x1000000) - timestamps[i]->TimestampMks -= 0x100000000LL; - else if (timestamps[i]->TimestampMks + 0x100000000LL < timestamps[0]->TimestampMks + 0x1000000LL) - timestamps[i]->TimestampMks += 0x100000000LL; - } - - updateIndices[updateCount] = i; - updateCount++; - } - } - - - // TBD: Simplify. Update indices should no longer be needed with new TimeFilter accepting - // previous values. - // We might want to have multi-element checking time roll-over. - - static const double mksToSec = 1.0 / 1000000.0; - - for (int i = 0; i < updateCount; i++) - { - SensorTimestampMapping& ts = *timestamps[updateIndices[i]]; - - ts.TimeSeconds = tf.SampleToSystemTime(((double)ts.TimestampMks) * mksToSec, - now, ts.TimeSeconds, ts.DebugTag); - } -} - - -void Sensor2DeviceImpl::OnInputReport(UByte* pData, UInt32 length) -{ - bool processed = false; - if (!processed) - { - Tracker2Message message; - if (decodeTracker2Message(&message, pData, length)) - { - processed = true; - - // Process microsecond timestamps from DK2 tracker. - // Mapped and raw values must correspond to one another in each array. - // IMU timestamp must be the first one! - SensorTimestampMapping* tsMaps[3] = - { - &LastSensorTime, - &LastCameraTime, - &LastFrameTime - }; - UInt32 tsRawMks[3] = - { - message.Sensors.SampleTimestamp, - message.Sensors.CameraTimestamp, - message.Sensors.FrameTimestamp - }; - // Handle wrap-around and convert samples to system time for any samples that changed. - UpdateDK2Timestamps(TimeFilter, tsMaps, tsRawMks, sizeof(tsRawMks)/sizeof(tsRawMks[0])); - - onTrackerMessage(&message); - - /* - if (SF_LOG_fp) - { - static UInt32 lastFrameTs = 0; - static UInt32 lastCameraTs = 0; - - if ((lastFrameTs != message.Sensors.FrameTimestamp) || - (lastCameraTs = message.Sensors.CameraTimestamp)) - fprintf(SF_LOG_fp, "msg cameraTs: 0x%X frameTs: 0x%X sensorTs: 0x%X\n", - message.Sensors.CameraTimestamp, message.Sensors.FrameTimestamp, - message.Sensors.SampleTimestamp); - - lastFrameTs = message.Sensors.FrameTimestamp; - lastCameraTs = message.Sensors.CameraTimestamp; - } - */ - -#if 0 - // Checks for DK2 firmware bug. - static unsigned SLastSampleTime = 0; - if ((SLastSampleTime > message.Sensors.SampleTimestamp) && message.Sensors.SampleTimestamp > 1000000 ) - { - fprintf(SF_LOG_fp, "*** Sample Timestamp Wrap! ***\n"); - OVR_ASSERT (SLastSampleTime <= message.Sensors.SampleTimestamp); - } - SLastSampleTime = message.Sensors.SampleTimestamp; - - static unsigned SLastCameraTime = 0; - if ((SLastCameraTime > message.Sensors.CameraTimestamp) && message.Sensors.CameraTimestamp > 1000000 ) - { - fprintf(SF_LOG_fp, "*** Camera Timestamp Wrap! ***\n"); - OVR_ASSERT (SLastCameraTime <= message.Sensors.CameraTimestamp); - } - SLastCameraTime = message.Sensors.CameraTimestamp; - - static unsigned SLastFrameTime = 0; - if ((SLastFrameTime > message.Sensors.FrameTimestamp) && message.Sensors.FrameTimestamp > 1000000 ) - { - fprintf(SF_LOG_fp, "*** Frame Timestamp Wrap! ***\n"); - OVR_ASSERT (SLastFrameTime <= message.Sensors.FrameTimestamp); - } - SLastFrameTime = message.Sensors.FrameTimestamp; -#endif - } - } -} - -double Sensor2DeviceImpl::OnTicks(double tickSeconds) -{ - - if (tickSeconds >= NextKeepAliveTickSeconds) - { - // Must send DK2 keep-alive. Set Keep-alive at 10 seconds. - KeepAliveMuxReport keepAlive; - keepAlive.CommandId = 0; - keepAlive.INReport = 11; - keepAlive.Interval = 10 * 1000; - - // Device creation is done from background thread so we don't need to add this to the command queue. - KeepAliveMuxImpl keepAliveImpl(keepAlive); - GetInternalDevice()->SetFeatureReport(keepAliveImpl.Buffer, KeepAliveMuxImpl::PacketSize); - - // Emit keep-alive every few seconds. - double keepAliveDelta = 3.0; // Use 3-second interval. - NextKeepAliveTickSeconds = tickSeconds + keepAliveDelta; - } - return NextKeepAliveTickSeconds - tickSeconds; -} - -/* -// TBD: don't report calibration for now, until we figure out the logic between camera and mag yaw correction -bool Sensor2DeviceImpl::IsMagCalibrated() -{ - return pCalibration->IsMagCalibrated(); -} -*/ - -} // namespace OVR |