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.lateration; 17 18 import com.irurueta.geometry.InhomogeneousPoint3D; 19 import com.irurueta.geometry.Point3D; 20 import com.irurueta.geometry.Sphere; 21 import com.irurueta.navigation.LockedException; 22 23 /** 24 * Solves a Trilateration problem with an instance of the least squares optimizer. 25 */ 26 public class NonLinearLeastSquaresLateration3DSolver extends NonLinearLeastSquaresLaterationSolver<Point3D> { 27 28 /** 29 * Constructor. 30 */ 31 public NonLinearLeastSquaresLateration3DSolver() { 32 super(); 33 } 34 35 /** 36 * Constructor. 37 * 38 * @param positions known positions of static nodes. 39 * @param distances euclidean distances from static nodes to mobile node. 40 * @throws IllegalArgumentException if either positions or distances are null, don't have the same length or their 41 * length is smaller than required (3 for 2D points or 4 for 3D points) or fitter 42 * is null. 43 */ 44 public NonLinearLeastSquaresLateration3DSolver(final Point3D[] positions, final double[] distances) { 45 super(positions, distances); 46 } 47 48 /** 49 * Constructor. 50 * 51 * @param initialPosition initial position to start lateration solving. 52 */ 53 public NonLinearLeastSquaresLateration3DSolver(final Point3D initialPosition) { 54 super(initialPosition); 55 } 56 57 /** 58 * Constructor. 59 * 60 * @param positions known positions of static nodes. 61 * @param distances euclidean distances from static nodes to mobile node. 62 * @param initialPosition initial position to start lateration solving. 63 * @throws IllegalArgumentException if either positions or distances are null, don't have the same length or their 64 * length is smaller than required (3 for 2D points or 4 for 3D points) or fitter 65 * is null. 66 */ 67 public NonLinearLeastSquaresLateration3DSolver( 68 final Point3D[] positions, final double[] distances, final Point3D initialPosition) { 69 super(positions, distances, initialPosition); 70 } 71 72 /** 73 * Constructor. 74 * 75 * @param listener listener to be notified of events raised by this instance. 76 */ 77 public NonLinearLeastSquaresLateration3DSolver(final LaterationSolverListener<Point3D> listener) { 78 super(listener); 79 } 80 81 /** 82 * Constructor. 83 * 84 * @param positions known positions of static nodes. 85 * @param distances euclidean distances from static nodes to mobile node. 86 * @param listener listener to be notified of events raised by this instance. 87 * @throws IllegalArgumentException if either positions or distances are null, don't have the same length or their 88 * length is smaller than required (3 for 2D points or 4 for 3D points) or fitter 89 * is null. 90 */ 91 public NonLinearLeastSquaresLateration3DSolver( 92 final Point3D[] positions, final double[] distances, final LaterationSolverListener<Point3D> listener) { 93 super(positions, distances, listener); 94 } 95 96 /** 97 * Constructor. 98 * 99 * @param initialPosition initial position to start lateration solving. 100 * @param listener listener to be notified of events raised by this instance. 101 */ 102 public NonLinearLeastSquaresLateration3DSolver( 103 final Point3D initialPosition, final LaterationSolverListener<Point3D> listener) { 104 super(initialPosition, listener); 105 } 106 107 /** 108 * Constructor. 109 * 110 * @param positions known positions of static nodes. 111 * @param distances euclidean distances from static nodes to mobile node. 112 * @param initialPosition initial position to start lateration solving. 113 * @param listener listener to be notified of events raised by this instance. 114 * @throws IllegalArgumentException if either positions or distances are null, don't have the same length or their 115 * length is smaller than required (3 for 2D points or 4 for 3D points) or fitter 116 * is null. 117 */ 118 public NonLinearLeastSquaresLateration3DSolver( 119 final Point3D[] positions, final double[] distances, final Point3D initialPosition, 120 final LaterationSolverListener<Point3D> listener) { 121 super(positions, distances, initialPosition, listener); 122 } 123 124 /** 125 * Constructor. 126 * 127 * @param spheres spheres defining positions and distances. 128 * @throws IllegalArgumentException if spheres is null or if length of spheres array is less than 2. 129 */ 130 public NonLinearLeastSquaresLateration3DSolver(final Sphere[] spheres) { 131 super(); 132 internalSetSpheres(spheres); 133 } 134 135 /** 136 * Constructor. 137 * 138 * @param spheres spheres defining positions and distances. 139 * @param initialPosition initial position to start lateration solving. 140 * @throws IllegalArgumentException if spheres is null or if length of spheres array is less than 2. 141 */ 142 public NonLinearLeastSquaresLateration3DSolver(final Sphere[] spheres, final Point3D initialPosition) { 143 super(initialPosition); 144 internalSetSpheres(spheres); 145 } 146 147 /** 148 * Constructor. 149 * 150 * @param spheres spheres defining positions and distances. 151 * @param listener listener to be notified of events raised by this instance. 152 * @throws IllegalArgumentException if spheres is null or if length of spheres array is less than 2. 153 */ 154 public NonLinearLeastSquaresLateration3DSolver( 155 final Sphere[] spheres, final LaterationSolverListener<Point3D> listener) { 156 super(listener); 157 internalSetSpheres(spheres); 158 } 159 160 /** 161 * Constructor. 162 * 163 * @param spheres spheres defining positions and distances. 164 * @param initialPosition initial position to start lateration solving. 165 * @param listener listener to be notified of events raised by this instance. 166 * @throws IllegalArgumentException if spheres is null or if length of spheres array is less than 2. 167 */ 168 public NonLinearLeastSquaresLateration3DSolver( 169 final Sphere[] spheres, final Point3D initialPosition, final LaterationSolverListener<Point3D> listener) { 170 super(initialPosition, listener); 171 internalSetSpheres(spheres); 172 } 173 174 /** 175 * Constructor. 176 * 177 * @param positions known positions of static nodes. 178 * @param distances euclidean distances from static nodes to mobile node. 179 * @param distanceStandardDeviations standard deviations of provided measured distances. 180 * @throws IllegalArgumentException if either positions, distances or standard deviations 181 * are null, don't have the same length of their length is smaller than required 182 * (2 points). 183 */ 184 public NonLinearLeastSquaresLateration3DSolver( 185 final Point3D[] positions, final double[] distances, final double[] distanceStandardDeviations) { 186 super(positions, distances, distanceStandardDeviations); 187 } 188 189 /** 190 * Constructor. 191 * 192 * @param positions known positions of static nodes. 193 * @param distances euclidean distances from static nodes to mobile node. 194 * @param distanceStandardDeviations standard deviations of provided measured distances. 195 * @param initialPosition initial position to start lateration solving. 196 * @throws IllegalArgumentException if either positions, distances or standard deviations 197 * are null, don't have the same length of their length is smaller than required 198 * (2 points). 199 */ 200 public NonLinearLeastSquaresLateration3DSolver( 201 final Point3D[] positions, final double[] distances, final double[] distanceStandardDeviations, 202 final Point3D initialPosition) { 203 super(positions, distances, distanceStandardDeviations, initialPosition); 204 } 205 206 /** 207 * Constructor. 208 * 209 * @param positions known positions of static nodes. 210 * @param distances euclidean distances from static nodes to mobile node. 211 * @param distanceStandardDeviations standard deviations of provided measured distances. 212 * @param listener listener to be notified of events raised by this instance. 213 * @throws IllegalArgumentException if either positions, distances or standard deviations 214 * are null, don't have the same length of their length is smaller than required 215 * (2 points). 216 */ 217 public NonLinearLeastSquaresLateration3DSolver( 218 final Point3D[] positions, final double[] distances, final double[] distanceStandardDeviations, 219 final LaterationSolverListener<Point3D> listener) { 220 super(positions, distances, distanceStandardDeviations, listener); 221 } 222 223 /** 224 * Constructor. 225 * 226 * @param positions known positions of static nodes. 227 * @param distances euclidean distances from static nodes to mobile node. 228 * @param distanceStandardDeviations standard deviations of provided measured distances. 229 * @param initialPosition initial position to start lateration solving. 230 * @param listener listener to be notified of events raised by this instance. 231 * @throws IllegalArgumentException if either positions, distances or standard deviations 232 * are null, don't have the same length of their length is smaller than required 233 * (2 points). 234 */ 235 public NonLinearLeastSquaresLateration3DSolver( 236 final Point3D[] positions, final double[] distances, final double[] distanceStandardDeviations, 237 final Point3D initialPosition, final LaterationSolverListener<Point3D> listener) { 238 super(positions, distances, distanceStandardDeviations, initialPosition, listener); 239 } 240 241 /** 242 * Constructor. 243 * 244 * @param spheres spheres defining positions and distances. 245 * @param distanceStandardDeviations standard deviations of provided measured distances. 246 * @throws IllegalArgumentException if spheres is null or if length of spheres array is less than 2. 247 */ 248 public NonLinearLeastSquaresLateration3DSolver( 249 final Sphere[] spheres, final double[] distanceStandardDeviations) { 250 super(); 251 internalSetSpheresAndStandardDeviations(spheres, distanceStandardDeviations); 252 } 253 254 /** 255 * Constructor. 256 * 257 * @param spheres spheres defining positions and distances. 258 * @param distanceStandardDeviations standard deviations of provided measured distances. 259 * @param initialPosition initial position to start lateration solving. 260 * @throws IllegalArgumentException if spheres is null or if length of spheres array is less than 2. 261 */ 262 public NonLinearLeastSquaresLateration3DSolver( 263 final Sphere[] spheres, final double[] distanceStandardDeviations, final Point3D initialPosition) { 264 super(initialPosition); 265 internalSetSpheresAndStandardDeviations(spheres, distanceStandardDeviations); 266 } 267 268 /** 269 * Constructor. 270 * 271 * @param spheres spheres defining positions and distances. 272 * @param distanceStandardDeviations standard deviations of provided measured distances. 273 * @param listener listener to be notified of events raised by this instance. 274 * @throws IllegalArgumentException if spheres is null or if length of spheres array is less than 2. 275 */ 276 public NonLinearLeastSquaresLateration3DSolver( 277 final Sphere[] spheres, final double[] distanceStandardDeviations, 278 final LaterationSolverListener<Point3D> listener) { 279 super(listener); 280 internalSetSpheresAndStandardDeviations(spheres, distanceStandardDeviations); 281 } 282 283 /** 284 * Constructor. 285 * 286 * @param spheres spheres defining positions and distances. 287 * @param distanceStandardDeviations standard deviations of provided measured distances. 288 * @param initialPosition initial position to start lateration solving. 289 * @param listener listener to be notified of events raised by this instance. 290 * @throws IllegalArgumentException if spheres is null or if length of spheres array is less than 2. 291 */ 292 public NonLinearLeastSquaresLateration3DSolver( 293 final Sphere[] spheres, final double[] distanceStandardDeviations, final Point3D initialPosition, 294 final LaterationSolverListener<Point3D> listener) { 295 super(initialPosition, listener); 296 internalSetSpheresAndStandardDeviations(spheres, distanceStandardDeviations); 297 } 298 299 /** 300 * Gets spheres defined by provided positions and distances. 301 * 302 * @return spheres defined by provided positions and distances. 303 */ 304 public Sphere[] getSpheres() { 305 if (positions == null) { 306 return null; 307 } 308 309 final var result = new Sphere[positions.length]; 310 311 for (var i = 0; i < positions.length; i++) { 312 result[i] = new Sphere(positions[i], distances[i]); 313 } 314 return result; 315 } 316 317 /** 318 * Sets spheres defining positions and Euclidean distances. 319 * 320 * @param spheres spheres defining positions and distances. 321 * @throws IllegalArgumentException if spheres is null or length of array of spheres 322 * is less than 2. 323 * @throws LockedException if instance is busy solving the lateration problem. 324 */ 325 public void setSpheres(final Sphere[] spheres) throws LockedException { 326 if (isLocked()) { 327 throw new LockedException(); 328 } 329 internalSetSpheres(spheres); 330 } 331 332 /** 333 * Sets spheres defining positions and Euclidean distances along with the standard 334 * deviations of provided spheres radii. 335 * 336 * @param spheres spheres defining positions and distances. 337 * @param radiusStandardDeviations standard deviations of circles radii. 338 * @throws IllegalArgumentException if spheres is null, length of arrays is less than 339 * 2 or don't have the same length. 340 * @throws LockedException if instance is busy solving the lateration problem. 341 */ 342 public void setSpheresAndStandardDeviations(final Sphere[] spheres, final double[] radiusStandardDeviations) 343 throws LockedException { 344 if (isLocked()) { 345 throw new LockedException(); 346 } 347 internalSetSpheresAndStandardDeviations(spheres, radiusStandardDeviations); 348 } 349 350 /** 351 * Gets number of dimensions of provided points. 352 * 353 * @return always returns 3 dimensions. 354 */ 355 @Override 356 public int getNumberOfDimensions() { 357 return Point3D.POINT3D_INHOMOGENEOUS_COORDINATES_LENGTH; 358 } 359 360 /** 361 * Minimum required number of positions and distances. 362 * At least 4 positions and distances will be required to solve a 3D problem. 363 * 364 * @return minimum required number of positions and distances. 365 */ 366 @Override 367 public int getMinRequiredPositionsAndDistances() { 368 return Point3D.POINT3D_INHOMOGENEOUS_COORDINATES_LENGTH + 1; 369 } 370 371 /** 372 * Gets estimated position. 373 * 374 * @return estimated position. 375 */ 376 @Override 377 public Point3D getEstimatedPosition() { 378 if (estimatedPositionCoordinates == null) { 379 return null; 380 } 381 382 final var position = new InhomogeneousPoint3D(); 383 getEstimatedPosition(position); 384 return position; 385 } 386 387 /** 388 * Internally sets spheres defining positions and Euclidean distances. 389 * 390 * @param spheres spheres defining positions and distances. 391 * @throws IllegalArgumentException if spheres is null or length of array of spheres 392 * is less than 2. 393 */ 394 public void internalSetSpheres(final Sphere[] spheres) { 395 if (spheres == null || spheres.length < getMinRequiredPositionsAndDistances()) { 396 throw new IllegalArgumentException(); 397 } 398 399 final var positions = new Point3D[spheres.length]; 400 final var distances = new double[spheres.length]; 401 for (var i = 0; i < spheres.length; i++) { 402 final var sphere = spheres[i]; 403 positions[i] = sphere.getCenter(); 404 distances[i] = sphere.getRadius(); 405 } 406 407 internalSetPositionsAndDistances(positions, distances); 408 } 409 410 /** 411 * Internally sets spheres defining positions and Euclidean distances along with the standard 412 * deviations of provided spheres radii. 413 * 414 * @param spheres spheres defining positions and distances. 415 * @param radiusStandardDeviations standard deviations of circles radii. 416 * @throws IllegalArgumentException if spheres is null, length of arrays is less than 417 * 2 or don't have the same length. 418 */ 419 private void internalSetSpheresAndStandardDeviations( 420 final Sphere[] spheres, final double[] radiusStandardDeviations) { 421 if (spheres == null || spheres.length < getMinRequiredPositionsAndDistances()) { 422 throw new IllegalArgumentException(); 423 } 424 425 if (radiusStandardDeviations == null) { 426 throw new IllegalArgumentException(); 427 } 428 429 if (radiusStandardDeviations.length != spheres.length) { 430 throw new IllegalArgumentException(); 431 } 432 433 final var positions = new Point3D[spheres.length]; 434 final var distances = new double[spheres.length]; 435 for (var i = 0; i < spheres.length; i++) { 436 final var sphere = spheres[i]; 437 positions[i] = sphere.getCenter(); 438 distances[i] = sphere.getRadius(); 439 } 440 441 internalSetPositionsDistancesAndStandardDeviations(positions, distances, radiusStandardDeviations); 442 } 443 }