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