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