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 }