1
2
3
4
5
6
7
8
9
10
11
12
13
14
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.RssiReading;
25 import com.irurueta.navigation.lateration.HomogeneousLinearLeastSquaresLaterationSolver;
26 import com.irurueta.navigation.lateration.InhomogeneousLinearLeastSquaresLaterationSolver;
27 import com.irurueta.navigation.lateration.LaterationException;
28 import com.irurueta.navigation.lateration.LaterationSolver;
29 import com.irurueta.navigation.lateration.LaterationSolverListener;
30
31 import java.util.ArrayList;
32 import java.util.List;
33
34
35
36
37
38
39
40
41
42
43 public abstract class LinearRssiPositionEstimator<P extends Point<P>> extends RssiPositionEstimator<P> {
44
45
46
47
48
49 public static final boolean DEFAULT_USE_HOMOGENEOUS_LINEAR_SOLVER = true;
50
51
52
53
54 protected HomogeneousLinearLeastSquaresLaterationSolver<P> homogeneousTrilaterationSolver;
55
56
57
58
59 protected InhomogeneousLinearLeastSquaresLaterationSolver<P> inhomogeneousTrilaterationSolver;
60
61
62
63
64 protected LaterationSolverListener<P> laterationSolverListener;
65
66
67
68
69 protected boolean useHomogeneousLinearSolver = DEFAULT_USE_HOMOGENEOUS_LINEAR_SOLVER;
70
71
72
73
74 protected LinearRssiPositionEstimator() {
75 super();
76 init();
77 }
78
79
80
81
82
83
84 protected LinearRssiPositionEstimator(final RssiPositionEstimatorListener<P> listener) {
85 super(listener);
86 init();
87 }
88
89
90
91
92
93
94
95 public boolean isHomogeneousLinearSolverUsed() {
96 return useHomogeneousLinearSolver;
97 }
98
99
100
101
102
103
104
105
106 public void setHomogeneousLinearSolverUsed(final boolean useHomogeneousLinearSolver) throws LockedException {
107 if (isLocked()) {
108 throw new LockedException();
109 }
110
111 this.useHomogeneousLinearSolver = useHomogeneousLinearSolver;
112 }
113
114
115
116
117
118
119 @Override
120 public int getMinRequiredSources() {
121 return useHomogeneousLinearSolver ? homogeneousTrilaterationSolver.getMinRequiredPositionsAndDistances()
122 : inhomogeneousTrilaterationSolver.getMinRequiredPositionsAndDistances();
123 }
124
125
126
127
128
129
130 @Override
131 public boolean isReady() {
132 return (!useHomogeneousLinearSolver && inhomogeneousTrilaterationSolver.isReady())
133 || (useHomogeneousLinearSolver && homogeneousTrilaterationSolver.isReady());
134 }
135
136
137
138
139
140
141 @Override
142 public boolean isLocked() {
143 return inhomogeneousTrilaterationSolver.isLocked() || homogeneousTrilaterationSolver.isLocked();
144 }
145
146
147
148
149
150
151
152
153
154 @SuppressWarnings("Duplicates")
155 @Override
156 public void estimate() throws LockedException, NotReadyException, PositionEstimationException {
157 try {
158 if (useHomogeneousLinearSolver) {
159 homogeneousTrilaterationSolver.solve();
160 estimatedPositionCoordinates = homogeneousTrilaterationSolver.getEstimatedPositionCoordinates();
161 } else {
162 inhomogeneousTrilaterationSolver.solve();
163 estimatedPositionCoordinates = inhomogeneousTrilaterationSolver.getEstimatedPositionCoordinates();
164 }
165 } catch (final LaterationException e) {
166 throw new PositionEstimationException(e);
167 }
168 }
169
170
171
172
173
174
175 @Override
176 public P[] getPositions() {
177 return useHomogeneousLinearSolver ? homogeneousTrilaterationSolver.getPositions()
178 : inhomogeneousTrilaterationSolver.getPositions();
179 }
180
181
182
183
184
185
186
187
188 @Override
189 public double[] getDistances() {
190 return useHomogeneousLinearSolver ? homogeneousTrilaterationSolver.getDistances()
191 : inhomogeneousTrilaterationSolver.getDistances();
192 }
193
194
195
196
197
198
199
200
201
202 @Override
203 protected void internalSetSources(final List<? extends RadioSourceLocated<P>> sources) {
204 super.internalSetSources(sources);
205 buildPositionsAndDistances();
206 }
207
208
209
210
211
212
213
214
215
216 @Override
217 protected void internalSetFingerprint(
218 final Fingerprint<? extends RadioSource, ? extends RssiReading<? extends RadioSource>> fingerprint) {
219 super.internalSetFingerprint(fingerprint);
220 buildPositionsAndDistances();
221 }
222
223
224
225
226
227
228
229 protected abstract void setPositionsAndDistances(final List<P> positions, final List<Double> distances);
230
231
232
233
234 @SuppressWarnings("Duplicates")
235 private void init() {
236 laterationSolverListener = new LaterationSolverListener<>() {
237 @Override
238 public void onSolveStart(final LaterationSolver<P> solver) {
239 if (listener != null) {
240 listener.onEstimateStart(LinearRssiPositionEstimator.this);
241 }
242 }
243
244 @Override
245 public void onSolveEnd(final LaterationSolver<P> solver) {
246 if (listener != null) {
247 listener.onEstimateEnd(LinearRssiPositionEstimator.this);
248 }
249 }
250 };
251 }
252
253
254
255
256 @SuppressWarnings("Duplicates")
257 private void buildPositionsAndDistances() {
258 if ((useHomogeneousLinearSolver && homogeneousTrilaterationSolver == null)
259 || (!useHomogeneousLinearSolver && inhomogeneousTrilaterationSolver == null)) {
260 return;
261 }
262
263 final var min = getMinRequiredSources();
264 if (sources == null || fingerprint == null || sources.size() < min || fingerprint.getReadings() == null
265 || fingerprint.getReadings().size() < min) {
266 return;
267 }
268
269 final var positions = new ArrayList<P>();
270 final var distances = new ArrayList<Double>();
271 PositionEstimatorHelper.buildPositionsAndDistances(sources, fingerprint, positions, distances);
272
273 setPositionsAndDistances(positions, distances);
274 }
275 }