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 }