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 }