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.Reading;
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 LinearMixedPositionEstimator<P extends Point<P>> extends MixedPositionEstimator<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 LinearMixedPositionEstimator() {
75 super();
76 init();
77 }
78
79
80
81
82
83
84 protected LinearMixedPositionEstimator(final MixedPositionEstimatorListener<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
122 ? 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 (LaterationException e) {
167 throw new PositionEstimationException(e);
168 }
169 }
170
171
172
173
174
175
176 @Override
177 public P[] getPositions() {
178 return useHomogeneousLinearSolver
179 ? homogeneousTrilaterationSolver.getPositions() : inhomogeneousTrilaterationSolver.getPositions();
180 }
181
182
183
184
185
186
187
188
189 @Override
190 public double[] getDistances() {
191 return useHomogeneousLinearSolver
192 ? homogeneousTrilaterationSolver.getDistances() : 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 Reading<? 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(LinearMixedPositionEstimator.this);
242 }
243 }
244
245 @Override
246 public void onSolveEnd(final LaterationSolver<P> solver) {
247 if (listener != null) {
248 listener.onEstimateEnd(LinearMixedPositionEstimator.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 var 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 }