1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.irurueta.ar.slam;
17
18 import com.irurueta.geometry.Quaternion;
19
20
21
22
23
24
25
26 public class AbsoluteOrientationConstantVelocityModelSlamCalibrator extends
27 AbsoluteOrientationBaseSlamCalibrator<AbsoluteOrientationConstantVelocityModelSlamCalibrationData> {
28
29
30
31
32 private double lastAngularSpeedX;
33
34
35
36
37 private double lastAngularSpeedY;
38
39
40
41
42 private double lastAngularSpeedZ;
43
44
45
46
47
48 private long lastTimestampNanos = -1;
49
50
51
52
53 private Quaternion lastOrientation = new Quaternion();
54
55
56
57
58 private final Quaternion deltaOrientation = new Quaternion();
59
60
61
62
63 public AbsoluteOrientationConstantVelocityModelSlamCalibrator() {
64 super(AbsoluteOrientationConstantVelocityModelSlamEstimator.CONTROL_LENGTH);
65 }
66
67
68
69
70 @Override
71 public void reset() {
72 super.reset();
73 lastOrientation = new Quaternion();
74 lastAngularSpeedX = lastAngularSpeedY = lastAngularSpeedZ = 0.0;
75 lastTimestampNanos = -1;
76 }
77
78
79
80
81
82
83 @Override
84 protected int getEstimatorStateLength() {
85 return AbsoluteOrientationConstantVelocityModelSlamEstimator.STATE_LENGTH;
86 }
87
88
89
90
91
92
93
94 @Override
95 public AbsoluteOrientationConstantVelocityModelSlamCalibrationData getCalibrationData() {
96 final var result = new AbsoluteOrientationConstantVelocityModelSlamCalibrationData();
97 getCalibrationData(result);
98 return result;
99 }
100
101
102
103
104
105 @SuppressWarnings("DuplicatedCode")
106 @Override
107 protected void processFullSample() {
108 if (listener != null) {
109 listener.onFullSampleReceived(this);
110 }
111
112 final var timestamp = getMostRecentTimestampNanos();
113 if (lastTimestampNanos < 0) {
114
115
116 lastOrientation.fromQuaternion(accumulatedOrientation);
117
118 lastAngularSpeedX = accumulatedAngularSpeedSampleX;
119 lastAngularSpeedY = accumulatedAngularSpeedSampleY;
120 lastAngularSpeedZ = accumulatedAngularSpeedSampleZ;
121
122 lastTimestampNanos = timestamp;
123
124 if (listener != null) {
125 listener.onFullSampleProcessed(this);
126 }
127
128 return;
129 }
130
131 accumulatedOrientation.normalize();
132
133 lastOrientation.inverse(deltaOrientation);
134 deltaOrientation.combine(accumulatedOrientation);
135 deltaOrientation.normalize();
136
137 final var deltaAngularSpeedX = accumulatedAngularSpeedSampleX - lastAngularSpeedX;
138 final var deltaAngularSpeedY = accumulatedAngularSpeedSampleY - lastAngularSpeedY;
139 final var deltaAngularSpeedZ = accumulatedAngularSpeedSampleZ - lastAngularSpeedZ;
140 final var deltaTimestamp = (timestamp - lastTimestampNanos) * NANOS_TO_SECONDS;
141
142 sample[0] = deltaOrientation.getA();
143 sample[1] = deltaOrientation.getB();
144 sample[2] = deltaOrientation.getC();
145 sample[3] = deltaOrientation.getD();
146 sample[4] = accumulatedAccelerationSampleX * deltaTimestamp;
147 sample[5] = accumulatedAccelerationSampleY * deltaTimestamp;
148 sample[6] = accumulatedAccelerationSampleZ * deltaTimestamp;
149 sample[7] = deltaAngularSpeedX;
150 sample[8] = deltaAngularSpeedY;
151 sample[9] = deltaAngularSpeedZ;
152 updateSample();
153
154 lastOrientation.combine(deltaOrientation);
155 lastAngularSpeedX = accumulatedAngularSpeedSampleX;
156 lastAngularSpeedY = accumulatedAngularSpeedSampleY;
157 lastAngularSpeedZ = accumulatedAngularSpeedSampleZ;
158
159 lastTimestampNanos = timestamp;
160
161 if (listener != null) {
162 listener.onFullSampleProcessed(this);
163 }
164 }
165 }