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