1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.irurueta.ar.sfm;
18
19 import com.irurueta.ar.slam.AbsoluteOrientationBaseSlamEstimator;
20 import com.irurueta.ar.slam.BaseCalibrationData;
21 import com.irurueta.geometry.MetricTransformation3D;
22 import com.irurueta.geometry.Point3D;
23 import com.irurueta.geometry.Rotation3D;
24
25 import java.util.ArrayList;
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 public abstract class BaseAbsoluteOrientationSlamSparseReconstructor<
42 D extends BaseCalibrationData,
43 C extends BaseSlamSparseReconstructorConfiguration<D, C>,
44 R extends BaseSlamSparseReconstructor<D, C, R, L, S>,
45 L extends BaseSlamSparseReconstructorListener<R>,
46 S extends AbsoluteOrientationBaseSlamEstimator<D>> extends
47 BaseSlamSparseReconstructor<D, C, R, L, S> {
48
49
50
51
52 private Rotation3D firstOrientation;
53
54
55
56
57 private Rotation3D invFirstOrientation;
58
59
60
61
62
63
64
65
66
67 protected BaseAbsoluteOrientationSlamSparseReconstructor(final C configuration, final L listener) {
68 super(configuration, listener);
69 }
70
71
72
73
74
75
76
77
78
79 public void updateOrientationSample(final long timestamp, final Rotation3D orientation) {
80 if (slamEstimator != null) {
81 slamEstimator.updateOrientationSample(timestamp, orientation);
82 }
83 if (firstOrientation == null) {
84
85 firstOrientation = orientation.toQuaternion();
86 invFirstOrientation = firstOrientation.inverseRotationAndReturnNew();
87 }
88 }
89
90
91
92
93
94
95
96 @SuppressWarnings("DuplicatedCode")
97 protected boolean updateScaleAndOrientation(final boolean isInitialPairOfViews) {
98
99 try {
100 final var metricCamera1 = previousMetricEstimatedCamera.getCamera();
101 final var metricCamera2 = currentMetricEstimatedCamera.getCamera();
102
103 double slamPosX;
104 double slamPosY;
105 double slamPosZ;
106 double scale;
107 if (isInitialPairOfViews) {
108
109 slamPosX = slamEstimator.getStatePositionX();
110 slamPosY = slamEstimator.getStatePositionY();
111 slamPosZ = slamEstimator.getStatePositionZ();
112
113 slamPosition.setInhomogeneousCoordinates(slamPosX, slamPosY, slamPosZ);
114
115 metricCamera1.decompose(false, true);
116 metricCamera2.decompose(false, true);
117
118 final var center1 = metricCamera1.getCameraCenter();
119 final var center2 = metricCamera2.getCameraCenter();
120
121 final var baseline = center1.distanceTo(slamPosition);
122 final var estimatedBaseline = center1.distanceTo(center2);
123
124 scale = currentScale = baseline / estimatedBaseline;
125 } else {
126 scale = currentScale;
127 }
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158 final var scaleAndOrientationTransformation = new MetricTransformation3D(scale);
159 scaleAndOrientationTransformation.setRotation(invFirstOrientation);
160
161
162 final var euclideanCamera1 = scaleAndOrientationTransformation.transformAndReturnNew(metricCamera1);
163 final var euclideanCamera2 = scaleAndOrientationTransformation.transformAndReturnNew(metricCamera2);
164
165 euclideanCamera2.decompose(false, true);
166 slamEstimator.correctWithPositionMeasure(euclideanCamera2.getCameraCenter(),
167 configuration.getCameraPositionCovariance());
168
169 if (!isInitialPairOfViews) {
170 slamPosX = slamEstimator.getStatePositionX();
171 slamPosY = slamEstimator.getStatePositionY();
172 slamPosZ = slamEstimator.getStatePositionZ();
173 slamPosition.setInhomogeneousCoordinates(slamPosX, slamPosY, slamPosZ);
174
175
176 final var euclideanCenter2 = euclideanCamera2.getCameraCenter();
177
178 final var euclideanPosX = euclideanCenter2.getInhomX();
179 final var euclideanPosY = euclideanCenter2.getInhomY();
180 final var euclideanPosZ = euclideanCenter2.getInhomZ();
181
182 final var scaleVariationX = euclideanPosX / slamPosX;
183 final var scaleVariationY = euclideanPosY / slamPosY;
184 final var scaleVariationZ = euclideanPosZ / slamPosZ;
185
186 final var scaleVariation = (scaleVariationX + scaleVariationY + scaleVariationZ) / 3.0;
187 scale *= scaleVariation;
188 currentScale = scale;
189 scaleAndOrientationTransformation.setScale(currentScale);
190
191
192 scaleAndOrientationTransformation.transform(metricCamera2, euclideanCamera2);
193 }
194 final var sqrScale = scale * scale;
195
196 previousEuclideanEstimatedCamera = new EstimatedCamera();
197 previousEuclideanEstimatedCamera.setCamera(euclideanCamera1);
198 previousEuclideanEstimatedCamera.setViewId(previousMetricEstimatedCamera.getViewId());
199 previousEuclideanEstimatedCamera.setQualityScore(previousMetricEstimatedCamera.getQualityScore());
200 if (previousMetricEstimatedCamera.getCovariance() != null) {
201 previousEuclideanEstimatedCamera.setCovariance(previousMetricEstimatedCamera.getCovariance()
202 .multiplyByScalarAndReturnNew(sqrScale));
203 }
204
205 currentEuclideanEstimatedCamera = new EstimatedCamera();
206 currentEuclideanEstimatedCamera.setCamera(euclideanCamera2);
207 currentEuclideanEstimatedCamera.setViewId(currentMetricEstimatedCamera.getViewId());
208 currentEuclideanEstimatedCamera.setQualityScore(currentMetricEstimatedCamera.getQualityScore());
209 if (currentMetricEstimatedCamera.getCovariance() != null) {
210 currentEuclideanEstimatedCamera.setCovariance(currentMetricEstimatedCamera.getCovariance()
211 .multiplyByScalarAndReturnNew(sqrScale));
212 }
213
214
215 final var numPoints = activeMetricReconstructedPoints.size();
216 final var metricReconstructedPoints3D = new ArrayList<Point3D>();
217 for (final var reconstructedPoint : activeMetricReconstructedPoints) {
218 metricReconstructedPoints3D.add(reconstructedPoint.getPoint());
219 }
220
221 final var euclideanReconstructedPoints3D = scaleAndOrientationTransformation.transformPointsAndReturnNew(
222 metricReconstructedPoints3D);
223
224
225 activeEuclideanReconstructedPoints = new ArrayList<>();
226 ReconstructedPoint3D euclideanPoint;
227 ReconstructedPoint3D metricPoint;
228 for (var i = 0; i < numPoints; i++) {
229 metricPoint = activeMetricReconstructedPoints.get(i);
230
231 euclideanPoint = new ReconstructedPoint3D();
232 euclideanPoint.setId(metricPoint.getId());
233 euclideanPoint.setPoint(euclideanReconstructedPoints3D.get(i));
234 euclideanPoint.setInlier(metricPoint.isInlier());
235 euclideanPoint.setQualityScore(metricPoint.getQualityScore());
236 if (metricPoint.getCovariance() != null) {
237 euclideanPoint.setCovariance(metricPoint.getCovariance().multiplyByScalarAndReturnNew(sqrScale));
238 }
239 euclideanPoint.setColorData(metricPoint.getColorData());
240
241 activeEuclideanReconstructedPoints.add(euclideanPoint);
242 }
243
244 return true;
245
246 } catch (final Exception e) {
247 failed = true;
248
249 listener.onFail((R) this);
250
251 return false;
252 }
253 }
254 }