1 /*
2 * Copyright (C) 2018 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.radiosource;
17
18 import com.irurueta.algebra.Matrix;
19 import com.irurueta.geometry.Point;
20 import com.irurueta.navigation.LockedException;
21 import com.irurueta.navigation.NotReadyException;
22 import com.irurueta.navigation.indoor.RadioSourceLocated;
23 import com.irurueta.navigation.indoor.ReadingLocated;
24
25 import java.util.List;
26
27 /**
28 * Estimates a radio source. Usually this implies at least the estimation of
29 * the radio source location, however, implementations of this class might
30 * estimate additional parameters.
31 *
32 * @param <P> a {@link Point} type.
33 * @param <R> a {@link ReadingLocated} type.
34 * @param <L> a {@link RadioSourceEstimatorListener} type.
35 */
36 public abstract class RadioSourceEstimator<P extends Point<?>, R extends ReadingLocated<P>,
37 L extends RadioSourceEstimatorListener<? extends RadioSourceEstimator<?, ?, ?>>> {
38
39 /**
40 * Estimated position.
41 */
42 protected double[] estimatedPositionCoordinates;
43
44 /**
45 * Covariance of estimated parameters (position, transmitted power and path-loss exponent).
46 * Size of this matrix will depend on which parameters estimation is enabled.
47 */
48 protected Matrix estimatedCovariance;
49
50 /**
51 * Covariance of estimated position.
52 * Size of this matrix will depend on the number of dimensions
53 * of estimated position (either 2 or 3).
54 * This value will only be available when position estimation is enabled.
55 */
56 protected Matrix estimatedPositionCovariance;
57
58
59 /**
60 * Located signal readings belonging to the same radio source to be estimated.
61 */
62 protected List<? extends R> readings;
63
64 /**
65 * Indicates whether estimator is locked during estimation.
66 */
67 protected boolean locked;
68
69 /**
70 * Listener in charge of attending events raised by this instance.
71 */
72 protected L listener;
73
74 /**
75 * Constructor.
76 */
77 protected RadioSourceEstimator() {
78 }
79
80 /**
81 * Constructor.
82 * Sets located radio signal readings belonging to the same radio source.
83 *
84 * @param readings radio signal readings belonging to the same
85 * radio source.
86 * @throws IllegalArgumentException if readings are not valid.
87 */
88 protected RadioSourceEstimator(final List<? extends R> readings) {
89 internalSetReadings(readings);
90 }
91
92 /**
93 * Constructor.
94 *
95 * @param listener listener in charge of attending events raised by this instance.
96 */
97 protected RadioSourceEstimator(final L listener) {
98 this.listener = listener;
99 }
100
101 /**
102 * Constructor.
103 * Sets radio signal readings belonging to the same radio source.
104 *
105 * @param readings radio signal readings belonging to the same radio source.
106 * @param listener listener in charge of attending events raised by this instance.
107 * @throws IllegalArgumentException if fingerprints are not valid.
108 */
109 protected RadioSourceEstimator(final List<? extends R> readings, final L listener) {
110 this(readings);
111 this.listener = listener;
112 }
113
114 /**
115 * Indicates whether estimator is locked during estimation.
116 *
117 * @return true if estimator is locked, false otherwise.
118 */
119 public boolean isLocked() {
120 return locked;
121 }
122
123 /**
124 * Gets radio signal readings belonging to the same radio source to be estimated.
125 *
126 * @return radio signal readings belonging to the same radio source.
127 */
128 public List<R> getReadings() {
129 //noinspection unchecked
130 return (List<R>) readings;
131 }
132
133 /**
134 * Sets radio signal readings belonging to the same radio source.
135 *
136 * @param readings Wi-Fi signal readings belonging to the same radio source.
137 * @throws LockedException if estimator is locked.
138 * @throws IllegalArgumentException if readings are not valid.
139 */
140 public void setReadings(final List<? extends R> readings) throws LockedException {
141 if (isLocked()) {
142 throw new LockedException();
143 }
144
145 internalSetReadings(readings);
146 }
147
148 /**
149 * Gets listener in charge of attending events raised by this instance.
150 *
151 * @return listener in charge of attending events raised by this instance.
152 */
153 public L getListener() {
154 return listener;
155 }
156
157 /**
158 * Sets listener in charge of attending events raised by this instance.
159 *
160 * @param listener listener in charge of attending events raised by this
161 * instance.
162 * @throws LockedException if estimator is locked.
163 */
164 public void setListener(final L listener) throws LockedException {
165 if (isLocked()) {
166 throw new LockedException();
167 }
168
169 this.listener = listener;
170 }
171
172 /**
173 * Indicates whether readings are valid or not.
174 * Readings are considered valid when there are enough readings.
175 *
176 * @param readings readings to be validated.
177 * @return true if readings are valid, false otherwise.
178 */
179 public boolean areValidReadings(final List<? extends R> readings) {
180 return readings != null && readings.size() >= getMinReadings();
181 }
182
183 /**
184 * Gets estimated inhomogeneous position coordinates.
185 *
186 * @return estimated inhomogeneous position coordinates.
187 */
188 public double[] getEstimatedPositionCoordinates() {
189 return estimatedPositionCoordinates;
190 }
191
192 /**
193 * Gets estimated position and stores result into provided instance.
194 *
195 * @param estimatedPosition instance where estimated position will be stored.
196 */
197 public void getEstimatedPosition(final P estimatedPosition) {
198 if (estimatedPositionCoordinates != null) {
199 for (int i = 0; i < estimatedPositionCoordinates.length; i++) {
200 estimatedPosition.setInhomogeneousCoordinate(i, estimatedPositionCoordinates[i]);
201 }
202 }
203 }
204
205 /**
206 * Gets covariance for estimated position and power.
207 * Matrix contains information in the following order:
208 * Top-left sub-matrix contains covariance of position,
209 * then follows transmitted power variance, and finally
210 * the last element contains path-loss exponent variance.
211 *
212 * @return covariance for estimated parameters.
213 */
214 public Matrix getEstimatedCovariance() {
215 return estimatedCovariance;
216 }
217
218 /**
219 * Gets estimated position covariance.
220 * Size of this matrix will depend on the number of dimensions
221 * of estimated position (either 2 or 3).
222 * This value will only be available when position estimation is enabled.
223 *
224 * @return estimated position covariance or null.
225 */
226 public Matrix getEstimatedPositionCovariance() {
227 return estimatedPositionCovariance;
228 }
229
230 /**
231 * Indicates whether this instance is ready to start the estimation.
232 *
233 * @return true if this instance is ready, false otherwise.
234 */
235 public abstract boolean isReady();
236
237 /**
238 * Gets minimum required number of readings to estimate
239 * power, position and path-loss exponent.
240 * This value depends on the number of parameters to
241 * be estimated, but for position only, this is 3
242 * readings for 2D, and 4 readings for 3D.
243 *
244 * @return minimum required number of readings.
245 */
246 public abstract int getMinReadings();
247
248 /**
249 * Gets number of dimensions of position points.
250 *
251 * @return number of dimensions of position points.
252 */
253 public abstract int getNumberOfDimensions();
254
255 /**
256 * Gets estimated radio source position.
257 *
258 * @return estimated radio source position.
259 */
260 public abstract P getEstimatedPosition();
261
262 /**
263 * Gets estimated located radio source.
264 *
265 * @param <S> type of located radio source.
266 * @return estimated located radio source.
267 */
268 public abstract <S extends RadioSourceLocated<P>> S getEstimatedRadioSource();
269
270 /**
271 * Estimate radio source.
272 *
273 * @throws RadioSourceEstimationException if estimation fails.
274 * @throws NotReadyException if estimator is not ready.
275 * @throws LockedException if estimator is locked.
276 */
277 public abstract void estimate() throws RadioSourceEstimationException, NotReadyException, LockedException;
278
279 /**
280 * Internally sets radio signal readings belonging to the same radio source.
281 *
282 * @param readings radio signal readings belonging to the same radio source.
283 * @throws IllegalArgumentException if readings are null or not enough readings
284 * are available.
285 */
286 protected void internalSetReadings(final List<? extends R> readings) {
287 if (!areValidReadings(readings)) {
288 throw new IllegalArgumentException();
289 }
290
291 this.readings = readings;
292 }
293 }