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.inertial;
17  
18  import com.irurueta.algebra.Matrix;
19  import com.irurueta.algebra.WrongSizeException;
20  import com.irurueta.units.Acceleration;
21  import com.irurueta.units.AccelerationConverter;
22  import com.irurueta.units.AccelerationUnit;
23  
24  import java.io.Serializable;
25  import java.util.Objects;
26  
27  /**
28   * Contains acceleration due to gravity resolved about ECEF or ECI frame, depending
29   * on the implementation.
30   */
31  @SuppressWarnings("CloneableClassWithoutClone")
32  public abstract class GravityOrGravitation<T extends GravityOrGravitation<?>> implements Serializable, Cloneable {
33      /**
34       * Number of components.
35       */
36      public static final int COMPONENTS = 3;
37  
38      /**
39       * Acceleration due to gravity through ECI or ECEF x-axis expressed in meters per squared second (m/s^2).
40       */
41      double gx;
42  
43      /**
44       * Acceleration due to gravity through ECI or ECEF y-axis expressed in meters per squared second (m/s^2).
45       */
46      double gy;
47  
48      /**
49       * Acceleration due to gravity through ECI or ECEF z-axis expressed in meters per squared second (m/s^2).
50       */
51      double gz;
52  
53      /**
54       * Constructor.
55       */
56      protected GravityOrGravitation() {
57      }
58  
59      /**
60       * Constructor.
61       *
62       * @param gx acceleration due to gravity through ECI or ECEF x-axis expressed in meters per squared second (m/s^2).
63       * @param gy acceleration due to gravity through ECI or ECEF y-axis expressed in meters per squared second (m/s^2).
64       * @param gz acceleration due to gravity through ECI or ECEF z-axis expressed in meters per squared second (m/s^2).
65       */
66      protected GravityOrGravitation(final double gx, final double gy, final double gz) {
67          setCoordinates(gx, gy, gz);
68      }
69  
70      /**
71       * Constructor.
72       *
73       * @param gx acceleration due to gravity through ECI or ECEF x-axis to be set.
74       * @param gy acceleration due to gravity through ECI or ECEF y-axis to be set.
75       * @param gz acceleration due to gravity through ECI or ECEF z-axis to be set.
76       */
77      protected GravityOrGravitation(final Acceleration gx, final Acceleration gy, final Acceleration gz) {
78          setCoordinates(gx, gy, gz);
79      }
80  
81      /**
82       * Constructor.
83       *
84       * @param input instance to copy data from.
85       */
86      protected GravityOrGravitation(final T input) {
87          copyFrom(input);
88      }
89  
90      /**
91       * Gets acceleration due to gravity through ECI or ECEF x-axis expressed in meters per squared second (m/s^2).
92       *
93       * @return acceleration due to gravity through ECI or ECEF x-axis.
94       */
95      public double getGx() {
96          return gx;
97      }
98  
99      /**
100      * Sets acceleration due to gravity through ECI or ECEF x-axis expressed in meters per squared second (m/s^2).
101      *
102      * @param gx acceleration due to gravity through ECI or ECEF x-axis.
103      */
104     public void setGx(final double gx) {
105         this.gx = gx;
106     }
107 
108     /**
109      * Gets acceleration due to gravity through ECI or ECEF y-axis expressed in meters per squared second (m/s^2).
110      *
111      * @return acceleration due to gravity through ECI or ECEF y-axis.
112      */
113     public double getGy() {
114         return gy;
115     }
116 
117     /**
118      * Sets acceleration due to gravity through ECI or ECEF y-axis expressed in meters per squared second (m/s^2).
119      *
120      * @param gy acceleration due to gravity through ECI or ECEF y-axis.
121      */
122     public void setGy(final double gy) {
123         this.gy = gy;
124     }
125 
126     /**
127      * Gets acceleration due to gravity through ECI or ECEF z-axis expressed in meters per squared second (m/s^2).
128      *
129      * @return acceleration due to gravity through ECI or ECEF z-axis.
130      */
131     public double getGz() {
132         return gz;
133     }
134 
135     /**
136      * Sets acceleration due to gravity through ECI or ECEF z-axis expressed in meters per squared second (m/s^2).
137      *
138      * @param gz acceleration due to gravity through ECI or ECEF z-axis.
139      */
140     public void setGz(final double gz) {
141         this.gz = gz;
142     }
143 
144     /**
145      * Sets gravity coordinates resolved about ECI or ECEF frame and expressed in meters per squared second (m/s^2).
146      *
147      * @param gx acceleration due to gravity through ECI or ECEF x-axis expressed in meters per squared second (m/s^2).
148      * @param gy acceleration due to gravity through ECI or ECEF y-axis expressed in meters per squared second (m/s^2).
149      * @param gz acceleration due to gravity through ECI or ECEF z-axis expressed in meters per squared second (m/s^2).
150      */
151     public void setCoordinates(final double gx, final double gy, final double gz) {
152         this.gx = gx;
153         this.gy = gy;
154         this.gz = gz;
155     }
156 
157     /**
158      * Gets acceleration due to gravity through ECI or ECEF x-axis.
159      *
160      * @param result instance where acceleration due to gravity through ECI or ECEF x-axis will be stored.
161      */
162     public void getGxAsAcceleration(final Acceleration result) {
163         result.setValue(gx);
164         result.setUnit(AccelerationUnit.METERS_PER_SQUARED_SECOND);
165     }
166 
167     /**
168      * Gets acceleration due to gravity through ECI or ECEF x-axis.
169      *
170      * @return acceleration due to gravity through ECI or ECEF x-axis.
171      */
172     public Acceleration getGxAsAcceleration() {
173         return new Acceleration(gx, AccelerationUnit.METERS_PER_SQUARED_SECOND);
174     }
175 
176     /**
177      * Sets acceleration due to gravity through ECI or ECEF x-axis.
178      *
179      * @param gravityX acceleration due to gravity through ECI or ECEF x-axis to be set.
180      */
181     public void setGx(final Acceleration gravityX) {
182         gx = AccelerationConverter.convert(gravityX.getValue().doubleValue(), gravityX.getUnit(),
183                 AccelerationUnit.METERS_PER_SQUARED_SECOND);
184     }
185 
186     /**
187      * Gets acceleration due to gravity through ECI or ECEF y-axis.
188      *
189      * @param result instance where acceleration due to gravity through ECI or ECEF y-axis will be stored.
190      */
191     public void getGyAsAcceleration(final Acceleration result) {
192         result.setValue(gy);
193         result.setUnit(AccelerationUnit.METERS_PER_SQUARED_SECOND);
194     }
195 
196     /**
197      * Gets acceleration due to gravity through ECI or ECEF y-axis.
198      *
199      * @return acceleration due to gravity through ECI or ECEF y-axis.
200      */
201     public Acceleration getGyAsAcceleration() {
202         return new Acceleration(gy, AccelerationUnit.METERS_PER_SQUARED_SECOND);
203     }
204 
205     /**
206      * Sets acceleration due to gravity through ECI or ECEF y-axis.
207      *
208      * @param gravityY acceleration due to gravity through ECI or ECEF y-axis to be set.
209      */
210     public void setGy(final Acceleration gravityY) {
211         gy = AccelerationConverter.convert(gravityY.getValue().doubleValue(), gravityY.getUnit(),
212                 AccelerationUnit.METERS_PER_SQUARED_SECOND);
213     }
214 
215     /**
216      * Gets acceleration due to gravity through ECI or ECEF z-axis.
217      *
218      * @param result instance where acceleration due to gravity through ECI or ECEF z-axis will be stored.
219      */
220     public void getGzAsAcceleration(final Acceleration result) {
221         result.setValue(gz);
222         result.setUnit(AccelerationUnit.METERS_PER_SQUARED_SECOND);
223     }
224 
225     /**
226      * Gets acceleration due to gravity through ECI or ECEF z-axis.
227      *
228      * @return acceleration due to gravity through ECI or ECEF z-axis.
229      */
230     public Acceleration getGzAsAcceleration() {
231         return new Acceleration(gz, AccelerationUnit.METERS_PER_SQUARED_SECOND);
232     }
233 
234     /**
235      * Sets acceleration due to gravity through ECI or ECEF z-axis.
236      *
237      * @param gravityZ acceleration due to gravity through ECI or ECEF z-axis to be set.
238      */
239     public void setGz(final Acceleration gravityZ) {
240         gz = AccelerationConverter.convert(gravityZ.getValue().doubleValue(), gravityZ.getUnit(),
241                 AccelerationUnit.METERS_PER_SQUARED_SECOND);
242     }
243 
244     /**
245      * Sets gravity coordinates.
246      *
247      * @param gravityX acceleration due to gravity through ECI or ECEF x-axis to be set.
248      * @param gravityY acceleration due to gravity through ECI or ECEF y-axis to be set.
249      * @param gravityZ acceleration due to gravity through ECI or ECEF z-axis to be set.
250      */
251     public void setCoordinates(final Acceleration gravityX, final Acceleration gravityY, final Acceleration gravityZ) {
252         setGx(gravityX);
253         setGy(gravityY);
254         setGz(gravityZ);
255     }
256 
257     /**
258      * Gets gravity norm.
259      *
260      * @return gravity norm.
261      */
262     public double getNorm() {
263         return Math.sqrt(gx * gx + gy * gy + gz * gz);
264     }
265 
266     /**
267      * Gets gravity norm as an acceleration.
268      *
269      * @param result instance where result will be stored.
270      */
271     public void getNormAsAcceleration(final Acceleration result) {
272         result.setValue(getNorm());
273         result.setUnit(AccelerationUnit.METERS_PER_SQUARED_SECOND);
274     }
275 
276     /**
277      * Gets gravity norm as an acceleration.
278      *
279      * @return an acceleration containing gravity norm.
280      */
281     public Acceleration getNormAsAcceleration() {
282         return new Acceleration(getNorm(), AccelerationUnit.METERS_PER_SQUARED_SECOND);
283     }
284 
285     /**
286      * Copies this instance data into provided instance.
287      *
288      * @param output destination instance where data will be copied to.
289      */
290     public void copyTo(final T output) {
291         output.gx = gx;
292         output.gy = gy;
293         output.gz = gz;
294     }
295 
296     /**
297      * Copies data of provided instance into this instance.
298      *
299      * @param input instance to copy data from.
300      */
301     public void copyFrom(final T input) {
302         gx = input.gx;
303         gy = input.gy;
304         gz = input.gz;
305     }
306 
307     /**
308      * Gets gravity coordinates expressed in meters per squared second (m/s^2) as an array.
309      *
310      * @param result array instance where gravity coordinates will be stored in
311      *               x,y,z order.
312      * @throws IllegalArgumentException if provided array does not have length 3.
313      */
314     public void asArray(final double[] result) {
315         if (result.length != COMPONENTS) {
316             throw new IllegalArgumentException();
317         }
318 
319         result[0] = gx;
320         result[1] = gy;
321         result[2] = gz;
322     }
323 
324     /**
325      * Gets gravity coordinates expressed in meters per squared second (m/s^2) as an array.
326      *
327      * @return array containing gravity coordinates in x,y,z order.
328      */
329     public double[] asArray() {
330         final var result = new double[COMPONENTS];
331         asArray(result);
332         return result;
333     }
334 
335     /**
336      * Gets gravity coordinates expressed in meters per squared second (m/s^2) as a column matrix.
337      * If provided matrix does not have size 3x1, it will be resized.
338      *
339      * @param result matrix instance where gravity coordinates will be stored in
340      *               x,y,z order.
341      */
342     @SuppressWarnings("DuplicatedCode")
343     public void asMatrix(final Matrix result) {
344         if (result.getRows() != COMPONENTS || result.getColumns() != 1) {
345             try {
346                 result.resize(COMPONENTS, 1);
347             } catch (final WrongSizeException ignore) {
348                 // never happens
349             }
350         }
351 
352         result.setElementAtIndex(0, gx);
353         result.setElementAtIndex(1, gy);
354         result.setElementAtIndex(2, gz);
355     }
356 
357     /**
358      * Gets gravity coordinates as a column matrix.
359      *
360      * @return a matrix containing gravity coordinates stored in x,y,z order.
361      */
362     public Matrix asMatrix() {
363         Matrix result;
364         try {
365             result = new Matrix(COMPONENTS, 1);
366             asMatrix(result);
367         } catch (final WrongSizeException ignore) {
368             // never happens
369             result = null;
370         }
371         return result;
372     }
373 
374     /**
375      * Computes and returns hash code for this instance. Hash codes are almost unique
376      * values that are useful for fast classification and storage of objects in collections.
377      *
378      * @return Hash code.
379      */
380     @Override
381     public int hashCode() {
382         return Objects.hash(gx, gy, gz);
383     }
384 
385 
386     /**
387      * Check if provided object is a T instance having exactly the same contents
388      * as this instance.
389      *
390      * @param obj object to be compared.
391      * @return true if both objects are considered to be equal, false otherwise.
392      */
393     @Override
394     public abstract boolean equals(final Object obj);
395 
396     /**
397      * Checks if provided instance has exactly the same contents as this instance.
398      *
399      * @param other instance to be compared.
400      * @return true if both instances are considered to be equal, false otherwise.
401      */
402     public boolean equals(final T other) {
403         return equals(other, 0.0);
404     }
405 
406     /**
407      * Checks if provided instance has contents similar to this instance up to provided
408      * threshold value.
409      *
410      * @param other     instance to be compared.
411      * @param threshold maximum allowed difference between gravity coordinates.
412      * @return true if both instances are considered to be equal (up to provided
413      * threshold), false otherwise.
414      */
415     public boolean equals(final T other, final double threshold) {
416         if (other == null) {
417             return false;
418         }
419 
420         return Math.abs(gx - other.gx) <= threshold && Math.abs(gy - other.gy) <= threshold
421                 && Math.abs(gz - other.gz) <= threshold;
422     }
423 }