Sensor Scol plugin
Multi platform sensors for handled devices
orientationTracker.cpp
1#include <scolPlugin.h>
2#include "orientationTracker.h"
3#include "tools/SO3Util.h"
4#include "SSensor.h"
5
6static const float defaultNeckHorizontalOffset = 0.08f;
7static const float defaultNeckVerticalOffset = 0.075f;
8
9OrientationTracker::OrientationTracker() :
10 mDisplayFromDevice(Quaternion(1.0f, 0.0f, 0.0f, 0.0f)),
11 mInertialReferenceFrameFromWorld(Quaternion(sqrt(0.5f), -sqrt(0.5f), 0.0f, 0.0f)),
12 mLastGyroEventTimestamp(0),
13 mOrientationCorrectionAngle(0),
14 mNeckModelEnabled(true)
15{
16 mNeckModelTranslation = Matrix4::IDENTITY;
17 Matrix4 translationMatrix;
18 translationMatrix.makeTrans(0.0f, - defaultNeckVerticalOffset, defaultNeckHorizontalOffset);
19 mNeckModelTranslation = mNeckModelTranslation * translationMatrix;
20}
21
22OrientationTracker::~OrientationTracker()
23{
24}
25
26void OrientationTracker::startTracking(DeviceOrientation orientation)
27{
28 updateDeviceOrientation(orientation);
29 mBiasEstimator.reset();
30 mTracker.reset();
31}
32
33void OrientationTracker::processGyro(Vector3d gyro, int64_t sensorTimeStamp)
34{
35 // event.timestamp have no consistent values between constructors ^^;
36 mLastGyroEventTimestamp = GetTickCountNano();
37 mBiasEstimator.processGyroscope(gyro, sensorTimeStamp);
38 mBiasEstimator.getGyroBias(mGyroBias);
39
40 Vector3d::sub(gyro, mGyroBias, gyro);
41 mTracker.processGyro(gyro, sensorTimeStamp);
42}
43
44void OrientationTracker::processAcceleration(Vector3d acc, int64_t sensorTimeStamp)
45{
46 mTracker.processAcc(acc, sensorTimeStamp);
47 mBiasEstimator.processAccelerometer(acc, sensorTimeStamp);
48}
49
50void OrientationTracker::processMag(Vector3d mag, int64_t sensorTimeStamp)
51{
52 mTracker.processMag(mag, sensorTimeStamp);
53}
54
55void OrientationTracker::stopTracking()
56{
57}
58
59bool OrientationTracker::isReady()
60{
61 return mTracker.isReady();
62}
63
64Quaternion OrientationTracker::lastHeadView(double timeOffsetInSeconds)
65{
66 if (mLastGyroEventTimestamp == 0)
67 {
68 return Quaternion::IDENTITY;
69 }
70
71 double secondsSinceLastGyroEvent = (double)(GetTickCountNano() - mLastGyroEventTimestamp) * 1.e-09;
72 double secondsToPredictForward = secondsSinceLastGyroEvent + 0.016;//(timeOffsetInSeconds * 0.5);// use static time like in the original code timeOffsetInSeconds;
73
74 double* predictedMat = mTracker.getPredictedMatrix(secondsToPredictForward);
75 if (mNeckModelEnabled)
76 {
77 Matrix4 headmat(predictedMat);
78 headmat = mNeckModelTranslation * headmat;
79 headmat.convert(predictedMat);
80 }
81
82 Quaternion frameQuat = Quaternion::FromRotationMatrix(predictedMat);
83 if (!isReady())
84 return Quaternion::IDENTITY;
85
86 frameQuat = mInertialReferenceFrameFromWorld * frameQuat * mDisplayFromDevice;
87 return frameQuat;
88}
89
90void OrientationTracker::updateDeviceOrientation(DeviceOrientation orientation)
91{
92 if (orientation == ROTATION_0)
93 {
94 mDisplayFromDevice = Quaternion(1.0f, 0.0f, 0.0f, 0.0f);
95 }
96 else if (orientation == ROTATION_90) // we invert here 90 / 270
97 {
98 // Z 270°
99 mDisplayFromDevice = Quaternion(sqrt(0.5f), 0.0f, 0.0f, sqrt(0.5f));
100 mDisplayFromDevice = Quaternion(0.0f, 0.0f, 0.0f, 1.0f) * mDisplayFromDevice;
101 }
102 else if (orientation == ROTATION_180)
103 {
104 mDisplayFromDevice = Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
105 }
106 else if (orientation == ROTATION_270)
107 {
108 // Z 90°
109 mDisplayFromDevice = Quaternion(sqrt(0.5f), 0.0f, 0.0f, sqrt(0.5f));
110 }
111}
112
113bool OrientationTracker::neckModelEnabled()
114{
115 return mNeckModelEnabled;
116}
117
118void OrientationTracker::setNeckModelEnabled(bool enabled)
119{
120 mNeckModelEnabled = enabled;
121}