View Javadoc
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.Point;
19  import com.irurueta.navigation.LockedException;
20  import com.irurueta.navigation.NotReadyException;
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.Reading;
25  
26  import java.util.List;
27  
28  /**
29   * Base class for position estimators using located radio sources and their readings at
30   * an unknown location (i.e. a non located fingerprint).
31   * These kind of estimators can be used to determine the position of a given device by
32   * getting readings at an unknown location of different radio sources whose locations
33   * are known.
34   *
35   * @param <P> a {@link Point} type.
36   * @param <R> a {@link Reading} type.
37   * @param <L> a {@link PositionEstimatorListener} type.
38   */
39  public abstract class PositionEstimator<P extends Point<?>,
40          R extends Reading<? extends RadioSource>,
41          L extends PositionEstimatorListener<? extends PositionEstimator<?, ?, ?>>> {
42  
43      /**
44       * Located radio sources used for lateration.
45       */
46      protected List<? extends RadioSourceLocated<P>> sources;
47  
48      /**
49       * Fingerprint containing readings at an unknown location for provided located radio sources.
50       */
51      protected Fingerprint<? extends RadioSource, ? extends R> fingerprint;
52  
53      /**
54       * Listener to be notified of events raised by this instance.
55       */
56      protected L listener;
57  
58      /**
59       * Estimated inhomogeneous position coordinates.
60       */
61      protected double[] estimatedPositionCoordinates;
62  
63      /**
64       * Constructor.
65       */
66      protected PositionEstimator() {
67      }
68  
69      /**
70       * Constructor.
71       *
72       * @param listener listener in charge of handling events.
73       */
74      protected PositionEstimator(final L listener) {
75          this.listener = listener;
76      }
77  
78      /**
79       * Gets located radio sources used for lateration.
80       *
81       * @return located radio sources used for lateration.
82       */
83      public List<RadioSourceLocated<P>> getSources() {
84          //noinspection unchecked
85          return (List<RadioSourceLocated<P>>) sources;
86      }
87  
88      /**
89       * Sets located radio sources used for lateration.
90       *
91       * @param sources located radio sources used for lateration.
92       * @throws LockedException          if estimator is locked.
93       * @throws IllegalArgumentException if provided value is null or the number of provided
94       *                                  sources is less than the required minimum.
95       */
96      public void setSources(final List<? extends RadioSourceLocated<P>> sources) throws LockedException {
97          if (isLocked()) {
98              throw new LockedException();
99          }
100 
101         internalSetSources(sources);
102     }
103 
104     /**
105      * Gets fingerprint containing readings at an unknown location for provided located
106      * radio sources.
107      *
108      * @return fingerprint containing readings at an unknown location for provided
109      * located radio sources.
110      */
111     public Fingerprint<RadioSource, Reading<RadioSource>> getFingerprint() {
112         //noinspection unchecked
113         return (Fingerprint<RadioSource, Reading<RadioSource>>) fingerprint;
114     }
115 
116     /**
117      * Sets fingerprint containing readings at an unknown location for provided located
118      * radio sources.
119      *
120      * @param fingerprint fingerprint containing readings at an unknown location for
121      *                    provided located radio sources.
122      * @throws LockedException          if estimator is locked.
123      * @throws IllegalArgumentException if provided value is null.
124      */
125     public void setFingerprint(final Fingerprint<? extends RadioSource, ? extends R> fingerprint)
126             throws LockedException {
127         if (isLocked()) {
128             throw new LockedException();
129         }
130 
131         internalSetFingerprint(fingerprint);
132     }
133 
134     /**
135      * Gets listener to be notified of events raised by this instance.
136      *
137      * @return listener to be notified of events raised by this instance.
138      */
139     public L getListener() {
140         return listener;
141     }
142 
143     /**
144      * Sets listener to be notified of events raised by this instance.
145      *
146      * @param listener listener to be notified of events raised by this instance.
147      * @throws LockedException if estimator is locked.
148      */
149     public void setListener(final L listener) throws LockedException {
150         if (isLocked()) {
151             throw new LockedException();
152         }
153         this.listener = listener;
154     }
155 
156     /**
157      * Gets estimated inhomogeneous position coordinates.
158      *
159      * @return estimated inhomogeneous position coordinates.
160      */
161     public double[] getEstimatedPositionCoordinates() {
162         return estimatedPositionCoordinates;
163     }
164 
165     /**
166      * Gets estimated position and stores result into provided instance.
167      *
168      * @param estimatedPosition instance where estimated position will be stored.
169      */
170     public void getEstimatedPosition(final P estimatedPosition) {
171         if (estimatedPositionCoordinates != null) {
172             for (int i = 0; i < estimatedPositionCoordinates.length; i++) {
173                 estimatedPosition.setInhomogeneousCoordinate(i, estimatedPositionCoordinates[i]);
174             }
175         }
176     }
177 
178     /**
179      * Gets minimum required number of located radio sources to perform lateration.
180      *
181      * @return minimum required number of located radio sources to perform
182      * lateration.
183      */
184     public abstract int getMinRequiredSources();
185 
186     /**
187      * Indicates whether estimator is ready to find a solution.
188      *
189      * @return true if estimator is ready, false otherwise.
190      */
191     public abstract boolean isReady();
192 
193     /**
194      * Returns boolean indicating whether this estimator is locked because an
195      * estimation is already in progress.
196      *
197      * @return true if estimator is locked, false otherwise.
198      */
199     public abstract boolean isLocked();
200 
201     /**
202      * Estimates position based on provided located radio sources and readings of such
203      * radio sources at an unknown location.
204      *
205      * @throws LockedException             if estimator is locked.
206      * @throws NotReadyException           if estimator is not ready.
207      * @throws PositionEstimationException if estimation fails for some other reason.
208      */
209     public abstract void estimate() throws LockedException, NotReadyException, PositionEstimationException;
210 
211     /**
212      * Gets estimated position.
213      *
214      * @return estimated position.
215      */
216     public abstract P getEstimatedPosition();
217 
218     /**
219      * Gets known positions of radio sources used internally to solve lateration.
220      *
221      * @return known positions used internally.
222      */
223     public abstract P[] getPositions();
224 
225     /**
226      * Gets Euclidean distances from known located radio sources to
227      * the location of provided readings in a fingerprint.
228      * Distance values are used internally to solve lateration.
229      *
230      * @return Euclidean distances used internally.
231      */
232     public abstract double[] getDistances();
233 
234     /**
235      * Internally sets located radio sources used for lateration.
236      *
237      * @param sources located radio sources used for lateration.
238      * @throws IllegalArgumentException if provided value is null or the number of
239      *                                  provided sources is less than the required
240      *                                  minimum.
241      */
242     @SuppressWarnings("Duplicates")
243     protected void internalSetSources(final List<? extends RadioSourceLocated<P>> sources) {
244         if (sources == null) {
245             throw new IllegalArgumentException();
246         }
247 
248         if (sources.size() < getMinRequiredSources()) {
249             throw new IllegalArgumentException();
250         }
251 
252         this.sources = sources;
253     }
254 
255     /**
256      * Internally sets fingerprint containing readings at an unknown location for
257      * provided located radio sources.
258      *
259      * @param fingerprint fingerprint containing readings at an unknown location for
260      *                    provided located radio sources.
261      * @throws IllegalArgumentException if provided value is null.
262      */
263     protected void internalSetFingerprint(final Fingerprint<? extends RadioSource, ? extends R> fingerprint) {
264         if (fingerprint == null) {
265             throw new IllegalArgumentException();
266         }
267 
268         this.fingerprint = fingerprint;
269     }
270 }