View Javadoc
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 }