1 /*
2 * Copyright (C) 2019 Alberto Irurueta Carro (alberto@irurueta.com)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package com.irurueta.navigation.indoor.position;
17
18 import com.irurueta.geometry.InhomogeneousPoint2D;
19 import com.irurueta.geometry.Point2D;
20 import com.irurueta.navigation.LockedException;
21 import com.irurueta.navigation.indoor.Fingerprint;
22 import com.irurueta.navigation.indoor.RadioSource;
23 import com.irurueta.navigation.indoor.RadioSourceLocated;
24 import com.irurueta.navigation.indoor.RssiReading;
25 import com.irurueta.navigation.lateration.NonLinearLeastSquaresLateration2DSolver;
26
27 import java.util.List;
28
29 /**
30 * Estimates 2D position non-linearly using located radio sources and their RSSI readings at
31 * unknown locations.
32 * These kind of estimators can be used to determine the position of a given device by
33 * getting RSSI readings at an unknown location of different radio sources whose locations
34 * are known.
35 */
36 public class NonLinearRssiPositionEstimator2D extends NonLinearRssiPositionEstimator<Point2D> {
37
38 /**
39 * Constructor.
40 */
41 public NonLinearRssiPositionEstimator2D() {
42 super();
43 initialize();
44 }
45
46 /**
47 * Constructor.
48 *
49 * @param sources located radio sources used for lateration.
50 * @throws IllegalArgumentException if provided sources is null or the number of
51 * provided sources is less than the required
52 * minimum.
53 */
54 public NonLinearRssiPositionEstimator2D(final List<? extends RadioSourceLocated<Point2D>> sources) {
55 super();
56 initialize();
57 internalSetSources(sources);
58 }
59
60 /**
61 * Constructor.
62 *
63 * @param fingerprint fingerprint containing RSSI readings at an unknown location
64 * for provided located radio sources.
65 * @throws IllegalArgumentException if provided fingerprint is null.
66 */
67 public NonLinearRssiPositionEstimator2D(
68 final Fingerprint<? extends RadioSource, ? extends RssiReading<? extends RadioSource>> fingerprint) {
69 super();
70 initialize();
71 internalSetFingerprint(fingerprint);
72 }
73
74 /**
75 * Constructor.
76 *
77 * @param sources located radio sources used for lateration.
78 * @param fingerprint fingerprint containing readings at an unknown location for
79 * provided located radio sources.
80 * @throws IllegalArgumentException if either provided sources or fingerprint is
81 * null or the number of provided sources is less
82 * than the required minimum.
83 */
84 public NonLinearRssiPositionEstimator2D(
85 final List<? extends RadioSourceLocated<Point2D>> sources,
86 final Fingerprint<? extends RadioSource, ? extends RssiReading<? extends RadioSource>> fingerprint) {
87 super();
88 initialize();
89 internalSetSources(sources);
90 internalSetFingerprint(fingerprint);
91 }
92
93 /**
94 * Constructor.
95 *
96 * @param listener listener in charge of handling events.
97 */
98 public NonLinearRssiPositionEstimator2D(final RssiPositionEstimatorListener<Point2D> listener) {
99 super(listener);
100 initialize();
101 }
102
103 /**
104 * Constructor.
105 *
106 * @param sources located radio sources used for lateration.
107 * @param listener listener in charge of handling events.
108 * @throws IllegalArgumentException if provided sources is null or the number of
109 * provided sources is less than the required
110 * minimum.
111 */
112 public NonLinearRssiPositionEstimator2D(
113 final List<? extends RadioSourceLocated<Point2D>> sources,
114 final RssiPositionEstimatorListener<Point2D> listener) {
115 super(listener);
116 initialize();
117 internalSetSources(sources);
118 }
119
120 /**
121 * Constructor.
122 *
123 * @param fingerprint fingerprint containing readings at an unknown location for
124 * provided located radio sources.
125 * @param listener listener in charge of handling events.
126 * @throws IllegalArgumentException if provided fingerprint is null.
127 */
128 public NonLinearRssiPositionEstimator2D(
129 final Fingerprint<? extends RadioSource, ? extends RssiReading<? extends RadioSource>> fingerprint,
130 final RssiPositionEstimatorListener<Point2D> listener) {
131 super(listener);
132 initialize();
133 internalSetFingerprint(fingerprint);
134 }
135
136 /**
137 * Constructor.
138 *
139 * @param sources located radio sources used for lateration.
140 * @param fingerprint fingerprint containing readings at an unknown location for
141 * provided located radio sources.
142 * @param listener listener in charge of handling events.
143 * @throws IllegalArgumentException if either provided sources or fingerprint is
144 * null or the number of provided sources is less
145 * than the required minimum.
146 */
147 public NonLinearRssiPositionEstimator2D(
148 final List<? extends RadioSourceLocated<Point2D>> sources,
149 final Fingerprint<? extends RadioSource, ? extends RssiReading<? extends RadioSource>> fingerprint,
150 final RssiPositionEstimatorListener<Point2D> listener) {
151 super(listener);
152 initialize();
153 internalSetSources(sources);
154 internalSetFingerprint(fingerprint);
155 }
156
157 /**
158 * Constructor.
159 *
160 * @param initialPosition initial position to start position estimation.
161 */
162 public NonLinearRssiPositionEstimator2D(final Point2D initialPosition) {
163 super(initialPosition);
164 initialize();
165 }
166
167 /**
168 * Constructor.
169 *
170 * @param sources located radio sources used for lateration.
171 * @param initialPosition initial position to start position estimation.
172 * @throws IllegalArgumentException if provided sources is null or the number of
173 * provided sources is less than the required
174 * minimum.
175 */
176 public NonLinearRssiPositionEstimator2D(
177 final List<? extends RadioSourceLocated<Point2D>> sources, final Point2D initialPosition) {
178 super(initialPosition);
179 initialize();
180 internalSetSources(sources);
181 }
182
183 /**
184 * Constructor.
185 *
186 * @param fingerprint fingerprint containing RSSI readings at an unknown
187 * location for provided located radio sources.
188 * @param initialPosition initial position to start position estimation.
189 * @throws IllegalArgumentException if provided fingerprint is null.
190 */
191 public NonLinearRssiPositionEstimator2D(
192 final Fingerprint<? extends RadioSource, ? extends RssiReading<? extends RadioSource>> fingerprint,
193 final Point2D initialPosition) {
194 super(initialPosition);
195 initialize();
196 internalSetFingerprint(fingerprint);
197 }
198
199 /**
200 * Constructor.
201 *
202 * @param sources located radio sources used for lateration.
203 * @param fingerprint fingerprint containing readings at an unknown location
204 * for provided located radio sources.
205 * @param initialPosition initial position to start position estimation.
206 * @throws IllegalArgumentException if either provided sources or fingerprint is
207 * null or the number of provided sources is less
208 * than the required minimum.
209 */
210 public NonLinearRssiPositionEstimator2D(
211 final List<? extends RadioSourceLocated<Point2D>> sources,
212 final Fingerprint<? extends RadioSource, ? extends RssiReading<? extends RadioSource>> fingerprint,
213 final Point2D initialPosition) {
214 super(initialPosition);
215 initialize();
216 internalSetSources(sources);
217 internalSetFingerprint(fingerprint);
218 }
219
220 /**
221 * Constructor.
222 *
223 * @param initialPosition initial position to start position estimation.
224 * @param listener listener in charge of handling events.
225 */
226 public NonLinearRssiPositionEstimator2D(
227 final Point2D initialPosition, final RssiPositionEstimatorListener<Point2D> listener) {
228 super(initialPosition, listener);
229 initialize();
230 }
231
232 /**
233 * Constructor.
234 *
235 * @param sources located radio sources used for lateration.
236 * @param initialPosition initial position to start position estimation.
237 * @param listener listener in charge of handling events.
238 * @throws IllegalArgumentException if provided sources is null or the number of
239 * provided sources is less than the required
240 * minimum.
241 */
242 public NonLinearRssiPositionEstimator2D(
243 final List<? extends RadioSourceLocated<Point2D>> sources, final Point2D initialPosition,
244 final RssiPositionEstimatorListener<Point2D> listener) {
245 super(initialPosition, listener);
246 initialize();
247 internalSetSources(sources);
248 }
249
250 /**
251 * Constructor.
252 *
253 * @param fingerprint fingerprint containing readings at an unknown location
254 * for provided located radio sources.
255 * @param initialPosition initial position to start position estimation.
256 * @param listener listener in charge of handling events.
257 * @throws IllegalArgumentException if provided fingerprint is null.
258 */
259 public NonLinearRssiPositionEstimator2D(
260 final Fingerprint<? extends RadioSource, ? extends RssiReading<? extends RadioSource>> fingerprint,
261 final Point2D initialPosition, final RssiPositionEstimatorListener<Point2D> listener) {
262 super(initialPosition, listener);
263 initialize();
264 internalSetFingerprint(fingerprint);
265 }
266
267 /**
268 * Constructor.
269 *
270 * @param sources located radio sources used for lateration.
271 * @param fingerprint fingerprint containing readings at an unknown location
272 * for provided located radio sources.
273 * @param initialPosition initial position to start position estimation.
274 * @param listener listener in charge of handling events.
275 * @throws IllegalArgumentException if either provided sources or fingerprint is
276 * null or the number of provided sources is less
277 * than the required minimum.
278 */
279 public NonLinearRssiPositionEstimator2D(
280 final List<? extends RadioSourceLocated<Point2D>> sources,
281 final Fingerprint<? extends RadioSource, ? extends RssiReading<? extends RadioSource>> fingerprint,
282 final Point2D initialPosition, final RssiPositionEstimatorListener<Point2D> listener) {
283 super(initialPosition, listener);
284 initialize();
285 internalSetSources(sources);
286 internalSetFingerprint(fingerprint);
287 }
288
289 /**
290 * Gets estimated position.
291 *
292 * @return estimated position.
293 */
294 @Override
295 public Point2D getEstimatedPosition() {
296 if (estimatedPositionCoordinates == null) {
297 return null;
298 }
299
300 final var result = new InhomogeneousPoint2D();
301 getEstimatedPosition(result);
302 return result;
303 }
304
305 /**
306 * Sets positions, distances and standard deviations of distances on internal
307 * lateration solver.
308 *
309 * @param positions positions to be set.
310 * @param distances distances to be set.
311 * @param distanceStandardDeviations standard deviations of distances to be set.
312 */
313 @Override
314 @SuppressWarnings("Duplicates")
315 protected void setPositionsDistancesAndDistanceStandardDeviations(
316 final List<Point2D> positions, final List<Double> distances,
317 final List<Double> distanceStandardDeviations) {
318
319 final var size = positions.size();
320 Point2D[] positionsArray = new InhomogeneousPoint2D[size];
321 positionsArray = positions.toArray(positionsArray);
322
323 final var distancesArray = new double[size];
324 final var distanceStandardDeviationsArray = new double[size];
325 for (var i = 0; i < size; i++) {
326 distancesArray[i] = distances.get(i);
327 distanceStandardDeviationsArray[i] = distanceStandardDeviations.get(i);
328 }
329
330 try {
331 trilaterationSolver.setPositionsDistancesAndStandardDeviations(positionsArray, distancesArray,
332 distanceStandardDeviationsArray);
333 } catch (final LockedException e) {
334 throw new IllegalArgumentException(e);
335 }
336 }
337
338 /**
339 * Initializes lateration solver.
340 */
341 private void initialize() {
342 trilaterationSolver = new NonLinearLeastSquaresLateration2DSolver(laterationSolverListener);
343 }
344 }