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.frames;
17  
18  import com.irurueta.algebra.Matrix;
19  import com.irurueta.algebra.WrongSizeException;
20  import com.irurueta.geometry.InhomogeneousPoint3D;
21  import com.irurueta.geometry.Point3D;
22  import com.irurueta.units.Distance;
23  import com.irurueta.units.DistanceConverter;
24  import com.irurueta.units.DistanceUnit;
25  
26  import java.io.Serializable;
27  import java.util.Objects;
28  
29  /**
30   * Contains body cartesian position with respect Earth, resolved about ECEF frame
31   * and expressed in meters (m).
32   */
33  public class ECEFPosition implements Serializable, Cloneable {
34  
35      /**
36       * Number of components.
37       */
38      public static final int COMPONENTS = 3;
39  
40      /**
41       * Cartesian x coordinate of body position expressed in meters (m) with respect ECEF frame, resolved
42       * along ECEF axes.
43       */
44      private double x;
45  
46      /**
47       * Cartesian y coordinate of body position expressed in meters (m) with respect ECEF frame, resolved
48       * along ECEF axes.
49       */
50      private double y;
51  
52      /**
53       * Cartesian z coordinate of body position expressed in meters (m) with respect ECEF frame, resolved
54       * along ECEF axes.
55       */
56      private double z;
57  
58      /**
59       * Constructor.
60       */
61      public ECEFPosition() {
62      }
63  
64      /**
65       * Constructor.
66       *
67       * @param x cartesian x coordinate of body position expressed in meters (m) and
68       *          resolved along ECEF-frame axes.
69       * @param y cartesian y coordinate of body position expressed in meters (m) and
70       *          resolved along ECEF-frame axes.
71       * @param z cartesian z coordinate of body position expressed in meters (m) and
72       *          resolved along ECEF-frame axes.
73       */
74      public ECEFPosition(final double x, final double y, final double z) {
75          setCoordinates(x, y, z);
76      }
77  
78      /**
79       * Constructor.
80       *
81       * @param x cartesian x coordinate of body position resolved along ECEF-frame axes.
82       * @param y cartesian y coordinate of body position resolved along ECEF-frame axes.
83       * @param z cartesian z coordinate of body position resolved along ECEF-frame axes.
84       */
85      public ECEFPosition(final Distance x, final Distance y, final Distance z) {
86          setCoordinates(x, y, z);
87      }
88  
89      /**
90       * Constructor.
91       *
92       * @param input ECEF body position to copy data from.
93       */
94      public ECEFPosition(final ECEFPosition input) {
95          copyFrom(input);
96      }
97  
98      /**
99       * Gets cartesian x coordinate of body position expressed in meters (m) with respect
100      * ECEF frame, resolved along ECEF axes.
101      *
102      * @return cartesian x coordinate of body position.
103      */
104     public double getX() {
105         return x;
106     }
107 
108     /**
109      * Sets cartesian x coordinate of body position expressed in meters (m) with respect
110      * ECEF frame, resolved along ECEF axes.
111      *
112      * @param x cartesian x coordinate of body position.
113      */
114     public void setX(final double x) {
115         this.x = x;
116     }
117 
118     /**
119      * Gets cartesian y coordinate of body position expressed in meters (m) with respect
120      * ECEF frame, resolved along ECEF axes.
121      *
122      * @return cartesian y coordinate of body position.
123      */
124     public double getY() {
125         return y;
126     }
127 
128     /**
129      * Sets cartesian y coordinate of body position expressed in meters (m) with respect
130      * ECEF frame, resolved along ECEF axes.
131      *
132      * @param y cartesian y coordinate of body position.
133      */
134     public void setY(final double y) {
135         this.y = y;
136     }
137 
138     /**
139      * Gets cartesian z coordinate of body position expressed in meters (m) with respect
140      * ECEF frame, resolved along ECEF axes.
141      *
142      * @return z coordinate of body position.
143      */
144     public double getZ() {
145         return z;
146     }
147 
148     /**
149      * Sets cartesian z coordinate of body position expressed in meters (m) with respect
150      * ECEF frame, resolved along ECEF axes.
151      *
152      * @param z cartesian z coordinate of body position.
153      */
154     public void setZ(final double z) {
155         this.z = z;
156     }
157 
158     /**
159      * Sets cartesian coordinates of body position expressed in meters (m) and resolved
160      * along ECEF-frame axes.
161      *
162      * @param x cartesian x coordinate of body position.
163      * @param y cartesian y coordinate of body position.
164      * @param z cartesian z coordinate of body position.
165      */
166     public void setCoordinates(final double x, final double y, final double z) {
167         this.x = x;
168         this.y = y;
169         this.z = z;
170     }
171 
172     /**
173      * Gets body position expressed in meters (m) and resolved along ECEF-frame axes.
174      *
175      * @return body position.
176      */
177     public Point3D getPosition() {
178         return new InhomogeneousPoint3D(x, y, z);
179     }
180 
181     /**
182      * Gets body position expressed in meters (m) and resolved along ECEF-frame axes.
183      *
184      * @param result instance where position data is copied to.
185      */
186     public void getPosition(final Point3D result) {
187         result.setInhomogeneousCoordinates(x, y, z);
188     }
189 
190     /**
191      * Sets body position expressed in meters (m) and resolved along ECEF-frame axes.
192      *
193      * @param point body position to be set.
194      */
195     public void setPosition(final Point3D point) {
196         x = point.getInhomX();
197         y = point.getInhomY();
198         z = point.getInhomZ();
199     }
200 
201     /**
202      * Gets cartesian x coordinate of body position resolved along ECEF-frame axes.
203      *
204      * @param result instance where cartesian x coordinate of body position will be
205      *               stored.
206      */
207     public void getDistanceX(final Distance result) {
208         result.setValue(x);
209         result.setUnit(DistanceUnit.METER);
210     }
211 
212     /**
213      * Gets cartesian x coordinate of body position resolved along ECEF-frame axes.
214      *
215      * @return x coordinate of body position resolved along ECEF-frame axes.
216      */
217     public Distance getDistanceX() {
218         return new Distance(x, DistanceUnit.METER);
219     }
220 
221     /**
222      * Sets cartesian x coordinate of body position resolved along ECEF-frame axes.
223      *
224      * @param x cartesian x coordinate of body position to be set.
225      */
226     public void setX(final Distance x) {
227         this.x = convertDistance(x);
228     }
229 
230     /**
231      * Gets cartesian y coordinate of body position resolved along ECEF-frame axes.
232      *
233      * @param result instance where cartesian y coordinate of body position will be
234      *               stored.
235      */
236     public void getDistanceY(final Distance result) {
237         result.setValue(y);
238         result.setUnit(DistanceUnit.METER);
239     }
240 
241     /**
242      * Gets cartesian y coordinate of body position resolved along ECEF-frame axes.
243      *
244      * @return y coordinate of body position resolved along ECEF-frame axes.
245      */
246     public Distance getDistanceY() {
247         return new Distance(y, DistanceUnit.METER);
248     }
249 
250     /**
251      * Sets cartesian y coordinate of body position resolved along ECEF-frame axes.
252      *
253      * @param y cartesian y coordinate of body position to be set.
254      */
255     public void setY(final Distance y) {
256         this.y = convertDistance(y);
257     }
258 
259     /**
260      * Gets cartesian z coordinate of body position resolved along ECEF-frame axes.
261      *
262      * @param result instance where cartesian z coordinate of body position will be
263      *               stored.
264      */
265     public void getDistanceZ(final Distance result) {
266         result.setValue(z);
267         result.setUnit(DistanceUnit.METER);
268     }
269 
270     /**
271      * Gets cartesian z coordinate of body position resolved along ECEF-frame axes.
272      *
273      * @return z coordinate of body position resolved along ECEF-frame axes.
274      */
275     public Distance getDistanceZ() {
276         return new Distance(z, DistanceUnit.METER);
277     }
278 
279     /**
280      * Sets cartesian z coordinate of body position resolved along ECEF-frame axes.
281      *
282      * @param z cartesian z coordinate of body position to be set.
283      */
284     public void setZ(final Distance z) {
285         this.z = convertDistance(z);
286     }
287 
288     /**
289      * Sets cartesian coordinates of body position and resolved along ECEF-frame axes.
290      *
291      * @param x cartesian x coordinate of body position.
292      * @param y cartesian y coordinate of body position.
293      * @param z cartesian z coordinate of body position.
294      */
295     public void setCoordinates(final Distance x, final Distance y, final Distance z) {
296         setX(x);
297         setY(y);
298         setZ(z);
299     }
300 
301     /**
302      * Gets norm of position expressed in meters (m), which represents the distance to
303      * Earth's center of mass.
304      *
305      * @return position norm expressed in meters (m).
306      */
307     public double getNorm() {
308         return Math.sqrt(x * x + y * y + z * z);
309     }
310 
311     /**
312      * Gets norm of position, which represents the distance to Earth's center of mass.
313      *
314      * @param result instance where result will be stored.
315      */
316     public void getNormAsDistance(final Distance result) {
317         result.setValue(getNorm());
318         result.setUnit(DistanceUnit.METER);
319     }
320 
321     /**
322      * Gets norm of position, which represents the distance to Earth's center of mass.
323      *
324      * @return position norm.
325      */
326     public Distance getNormAsDistance() {
327         return new Distance(getNorm(), DistanceUnit.METER);
328     }
329 
330     /**
331      * Copies this instance data into provided instance.
332      *
333      * @param output destination instance where data will be copied to.
334      */
335     public void copyTo(final ECEFPosition output) {
336         output.x = x;
337         output.y = y;
338         output.z = z;
339     }
340 
341     /**
342      * Copies data of provided instance into this instance.
343      *
344      * @param input instance to copy data from.
345      */
346     public void copyFrom(final ECEFPosition input) {
347         x = input.x;
348         y = input.y;
349         z = input.z;
350     }
351 
352     /**
353      * Gets position coordinates expressed in meters (m) as an array.
354      *
355      * @param result array instance where position coordinates will
356      *               be stored in x,y,z order.
357      * @throws IllegalArgumentException if provided array does not have length 3.
358      */
359     public void asArray(final double[] result) {
360         if (result.length != COMPONENTS) {
361             throw new IllegalArgumentException();
362         }
363 
364         result[0] = x;
365         result[1] = y;
366         result[2] = z;
367     }
368 
369     /**
370      * Gets position coordinates expressed in meters (m) as an array.
371      *
372      * @return array containing position coordinates in x,y,z order.
373      */
374     public double[] asArray() {
375         final var result = new double[COMPONENTS];
376         asArray(result);
377         return result;
378     }
379 
380     /**
381      * Gets position coordinates expressed in meters (m) as a column matrix.
382      * If provided matrix does not have size 3x1, it will be resized.
383      *
384      * @param result matrix instance where gravity coordinates will be stored in
385      *               x,y,z order.
386      */
387     @SuppressWarnings("DuplicatedCode")
388     public void asMatrix(final Matrix result) {
389         if (result.getRows() != COMPONENTS || result.getColumns() != 1) {
390             try {
391                 result.resize(COMPONENTS, 1);
392             } catch (final WrongSizeException ignore) {
393                 // never happens
394             }
395         }
396 
397         result.setElementAtIndex(0, x);
398         result.setElementAtIndex(1, y);
399         result.setElementAtIndex(2, z);
400     }
401 
402     /**
403      * Gets position coordinates expressed in meters (m) as a column matrix.
404      *
405      * @return position coordinates stored in x,y,z order.
406      */
407     public Matrix asMatrix() {
408         Matrix result;
409         try {
410             result = new Matrix(COMPONENTS, 1);
411             asMatrix(result);
412         } catch (final WrongSizeException ignore) {
413             // never happens
414             result = null;
415         }
416         return result;
417     }
418 
419     /**
420      * Computes and returns hash code for this instance. Hash codes are almost unique
421      * values that are useful for fast classification and storage of objects in
422      * collections.
423      *
424      * @return Hash code.
425      */
426     @Override
427     public int hashCode() {
428         return Objects.hash(x, y, z);
429     }
430 
431     /**
432      * Checks if provided object is an ECEFPosition having exactly the same contents
433      * as this instance.
434      *
435      * @param o Object to be compared.
436      * @return true if both objects are considered to be equal, false otherwise.
437      */
438     @Override
439     public boolean equals(Object o) {
440         if (this == o) {
441             return true;
442         }
443         if (o == null || getClass() != o.getClass()) {
444             return false;
445         }
446         final ECEFPosition other = (ECEFPosition) o;
447         return equals(other);
448     }
449 
450     /**
451      * Checks if provided instance has exactly the same contents as this instance.
452      *
453      * @param other instance to be compared.
454      * @return true if both instances are considered to be equal, false otherwise.
455      */
456     public boolean equals(final ECEFPosition other) {
457         return equals(other, 0.0);
458     }
459 
460     /**
461      * Checks if provided instance has contents similar to this instance up to provided
462      * threshold value.
463      *
464      * @param other     instance to be compared.
465      * @param threshold maximum difference allowed between position coordinates.
466      * @return true if both instances are considered to be equal (up to provided
467      * threshold), false otherwise.
468      */
469     public boolean equals(final ECEFPosition other, final double threshold) {
470         if (other == null) {
471             return false;
472         }
473 
474         return Math.abs(x - other.x) <= threshold
475                 && Math.abs(y - other.y) <= threshold
476                 && Math.abs(z - other.z) <= threshold;
477     }
478 
479     /**
480      * Makes a copy of this instance.
481      *
482      * @return a copy of this instance.
483      * @throws CloneNotSupportedException if clone fails for some reason.
484      */
485     @Override
486     protected Object clone() throws CloneNotSupportedException {
487         final var result = (ECEFPosition) super.clone();
488         copyTo(result);
489         return result;
490     }
491 
492     /**
493      * Converts distance instance into meters value.
494      *
495      * @param distance instance to be converted.
496      * @return converted value.
497      */
498     private double convertDistance(final Distance distance) {
499         return DistanceConverter.convert(distance.getValue().doubleValue(),
500                 distance.getUnit(), DistanceUnit.METER);
501     }
502 }