1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.irurueta.navigation.indoor.radiosource;
17
18 import com.irurueta.geometry.Accuracy2D;
19 import com.irurueta.geometry.InhomogeneousPoint2D;
20 import com.irurueta.geometry.Point2D;
21 import com.irurueta.navigation.LockedException;
22 import com.irurueta.navigation.indoor.Beacon;
23 import com.irurueta.navigation.indoor.BeaconLocated2D;
24 import com.irurueta.navigation.indoor.RadioSource;
25 import com.irurueta.navigation.indoor.RadioSourceLocated;
26 import com.irurueta.navigation.indoor.RangingReadingLocated;
27 import com.irurueta.navigation.indoor.WifiAccessPoint;
28 import com.irurueta.navigation.indoor.WifiAccessPointLocated2D;
29 import com.irurueta.navigation.lateration.HomogeneousLinearLeastSquaresLateration2DSolver;
30 import com.irurueta.navigation.lateration.InhomogeneousLinearLeastSquaresLateration2DSolver;
31 import com.irurueta.navigation.lateration.NonLinearLeastSquaresLateration2DSolver;
32
33 import java.util.List;
34
35
36
37
38
39
40
41
42
43
44 @SuppressWarnings("DuplicatedCode")
45 public class RangingRadioSourceEstimator2D<S extends RadioSource> extends RangingRadioSourceEstimator<S, Point2D> {
46
47
48
49
50 public RangingRadioSourceEstimator2D() {
51 super();
52 }
53
54
55
56
57
58
59
60
61 public RangingRadioSourceEstimator2D(final List<? extends RangingReadingLocated<S, Point2D>> readings) {
62 super(readings);
63 }
64
65
66
67
68
69
70 public RangingRadioSourceEstimator2D(final RangingRadioSourceEstimatorListener<S, Point2D> listener) {
71 super(listener);
72 }
73
74
75
76
77
78
79
80
81
82 public RangingRadioSourceEstimator2D(
83 final List<? extends RangingReadingLocated<S, Point2D>> readings,
84 final RangingRadioSourceEstimatorListener<S, Point2D> listener) {
85 super(readings, listener);
86 }
87
88
89
90
91
92
93
94 public RangingRadioSourceEstimator2D(final Point2D initialPosition) {
95 super(initialPosition);
96 }
97
98
99
100
101
102
103
104
105
106
107 public RangingRadioSourceEstimator2D(
108 final List<? extends RangingReadingLocated<S, Point2D>> readings, final Point2D initialPosition) {
109 super(readings, initialPosition);
110 }
111
112
113
114
115
116
117
118
119 public RangingRadioSourceEstimator2D(
120 final Point2D initialPosition, final RangingRadioSourceEstimatorListener<S, Point2D> listener) {
121 super(initialPosition, listener);
122 }
123
124
125
126
127
128
129
130
131
132
133
134 public RangingRadioSourceEstimator2D(
135 final List<? extends RangingReadingLocated<S, Point2D>> readings, final Point2D initialPosition,
136 final RangingRadioSourceEstimatorListener<S, Point2D> listener) {
137 super(readings, initialPosition, listener);
138 }
139
140
141
142
143
144
145
146 @Override
147 public int getMinReadings() {
148 return Point2D.POINT2D_INHOMOGENEOUS_COORDINATES_LENGTH + 1;
149 }
150
151
152
153
154
155
156
157 @Override
158 public int getNumberOfDimensions() {
159 return Point2D.POINT2D_INHOMOGENEOUS_COORDINATES_LENGTH;
160 }
161
162
163
164
165
166
167 @Override
168 public Point2D getEstimatedPosition() {
169 if (estimatedPositionCoordinates == null) {
170 return null;
171 }
172
173 final var result = new InhomogeneousPoint2D();
174 getEstimatedPosition(result);
175 return result;
176 }
177
178
179
180
181
182
183 @Override
184 @SuppressWarnings("unchecked")
185 public RadioSourceLocated<Point2D> getEstimatedRadioSource() {
186 final var readings = getReadings();
187 if (readings == null || readings.isEmpty()) {
188 return null;
189 }
190 final var source = readings.get(0).getSource();
191
192 final var estimatedPosition = getEstimatedPosition();
193 if (estimatedPosition == null) {
194 return null;
195 }
196
197 final var estimatedPositionCovariance = getEstimatedPositionCovariance();
198
199 if (source instanceof WifiAccessPoint accessPoint) {
200 return new WifiAccessPointLocated2D(accessPoint.getBssid(), accessPoint.getFrequency(),
201 accessPoint.getSsid(), estimatedPosition, estimatedPositionCovariance);
202 } else if (source instanceof Beacon beacon) {
203 return new BeaconLocated2D(beacon.getIdentifiers(), beacon.getTransmittedPower(), beacon.getFrequency(),
204 beacon.getBluetoothAddress(), beacon.getBeaconTypeCode(), beacon.getManufacturer(),
205 beacon.getServiceUuid(), beacon.getBluetoothName(), estimatedPosition, estimatedPositionCovariance);
206 } else {
207 return null;
208 }
209 }
210
211
212
213
214 @Override
215 protected void buildLinearSolverIfNeeded() {
216 if (initialPosition == null || !nonLinearSolverEnabled) {
217 if (useHomogeneousLinearSolver && homogeneousLinearSolver == null) {
218 homogeneousLinearSolver = new HomogeneousLinearLeastSquaresLateration2DSolver();
219 }
220 if (!useHomogeneousLinearSolver && inhomogeneousLinearSolver == null) {
221 inhomogeneousLinearSolver = new InhomogeneousLinearLeastSquaresLateration2DSolver();
222 }
223 }
224 }
225
226
227
228
229 @Override
230 protected void buildNonLinearSolverIfNeeded() {
231 if (nonLinearSolver == null && nonLinearSolverEnabled) {
232 nonLinearSolver = new NonLinearLeastSquaresLateration2DSolver();
233 }
234 }
235
236
237
238
239 @Override
240 protected void buildAccuracyIfNeeded() {
241 if (accuracy == null && useReadingPositionCovariances) {
242 accuracy = new Accuracy2D();
243
244
245 accuracy.setStandardDeviationFactor(1.0);
246 }
247 }
248
249
250
251
252
253
254
255
256
257
258
259
260 @Override
261 protected void setPositionsDistancesAndDistanceStandardDeviations(
262 final List<Point2D> positions, final List<Double> distances, final List<Double> distanceStandardDeviations)
263 throws LockedException {
264 final var size = positions.size();
265 Point2D[] positionsArray = new InhomogeneousPoint2D[size];
266 positionsArray = positions.toArray(positionsArray);
267
268 final var distancesArray = new double[size];
269 final var distanceStandardDeviationsArray = new double[size];
270 for (var i = 0; i < size; i++) {
271 distancesArray[i] = distances.get(i);
272 distanceStandardDeviationsArray[i] = distanceStandardDeviations.get(i);
273 }
274
275 if (initialPosition == null || !nonLinearSolverEnabled) {
276 if (homogeneousLinearSolver != null) {
277 homogeneousLinearSolver.setPositionsAndDistances(positionsArray, distancesArray);
278 }
279 if (inhomogeneousLinearSolver != null) {
280 inhomogeneousLinearSolver.setPositionsAndDistances(positionsArray, distancesArray);
281 }
282 }
283
284 if (nonLinearSolver != null && nonLinearSolverEnabled) {
285 nonLinearSolver.setPositionsDistancesAndStandardDeviations(positionsArray, distancesArray,
286 distanceStandardDeviationsArray);
287 }
288 }
289 }