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.frames; 17 18 import com.irurueta.algebra.Matrix; 19 import com.irurueta.algebra.WrongSizeException; 20 import com.irurueta.geometry.InvalidRotationMatrixException; 21 import com.irurueta.geometry.Rotation3D; 22 import com.irurueta.units.Angle; 23 import com.irurueta.units.AngleConverter; 24 import com.irurueta.units.AngleUnit; 25 import com.irurueta.units.Distance; 26 import com.irurueta.units.DistanceConverter; 27 import com.irurueta.units.DistanceUnit; 28 import com.irurueta.units.Speed; 29 import com.irurueta.units.SpeedConverter; 30 import com.irurueta.units.SpeedUnit; 31 32 import java.io.Serializable; 33 import java.util.Objects; 34 35 /** 36 * Contains position, velocity and coordinates transformation matrix expressed in NED frame. 37 * Position is expressed as latitude, longitude and height. 38 * Velocity of body frame is expressed with respect ECEF frame and resolved along north, east and down axes, 39 * as defined in {@link FrameType#LOCAL_NAVIGATION_FRAME}. 40 */ 41 public class NEDFrame implements Frame, Serializable, Cloneable { 42 43 /** 44 * Number of coordinates representing velocity. 45 */ 46 public static final int NUM_VELOCITY_COORDINATES = 3; 47 48 /** 49 * Latitude expressed in radians. 50 */ 51 private double latitude; 52 53 /** 54 * Longitude expressed in radians. 55 */ 56 private double longitude; 57 58 /** 59 * Height expressed in meters. 60 */ 61 private double height; 62 63 /** 64 * Coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF frame and 65 * resolved along North axis. 66 */ 67 private double vn; 68 69 /** 70 * Coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF frame and 71 * resolved along East axis. 72 */ 73 private double ve; 74 75 /** 76 * Coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF frame and 77 * resolved along Down axis. 78 */ 79 private double vd; 80 81 /** 82 * Body to NED coordinate transformation matrix. 83 */ 84 private CoordinateTransformation c; 85 86 /** 87 * Constructor. 88 * Initializes position and velocity coordinates to zero and the coordinate transformation matrix to the 89 * identity. 90 */ 91 public NEDFrame() { 92 c = new CoordinateTransformation(FrameType.BODY_FRAME, FrameType.LOCAL_NAVIGATION_FRAME); 93 } 94 95 /** 96 * Constructor. 97 * 98 * @param c Body to NED (Local Navigation frame) coordinate transformation matrix to be set. 99 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 100 */ 101 public NEDFrame(final CoordinateTransformation c) throws InvalidSourceAndDestinationFrameTypeException { 102 setCoordinateTransformation(c); 103 } 104 105 /** 106 * Constructor. 107 * 108 * @param latitude latitude expressed in radians. 109 * @param longitude longitude expressed in radians. 110 * @param height height expressed in meters. 111 */ 112 public NEDFrame(final double latitude, final double longitude, final double height) { 113 this(); 114 setPosition(latitude, longitude, height); 115 } 116 117 /** 118 * Constructor. 119 * 120 * @param latitude latitude expressed in radians to be set. 121 * @param longitude longitude expressed in radians to be set. 122 * @param height height to be set. 123 */ 124 public NEDFrame(final double latitude, final double longitude, final Distance height) { 125 this(); 126 setPosition(latitude, longitude, height); 127 } 128 129 /** 130 * Constructor. 131 * 132 * @param latitude latitude to be set. 133 * @param longitude longitude to be set. 134 * @param height height expressed in meters to be set. 135 */ 136 public NEDFrame(final Angle latitude, final Angle longitude, final double height) { 137 this(); 138 setPosition(latitude, longitude, height); 139 } 140 141 /** 142 * Constructor. 143 * 144 * @param latitude latitude to be set. 145 * @param longitude longitude to be set. 146 * @param height height to be set. 147 */ 148 public NEDFrame(final Angle latitude, final Angle longitude, final Distance height) { 149 this(); 150 setPosition(latitude, longitude, height); 151 } 152 153 /** 154 * Constructor. 155 * 156 * @param position curvilinear position containing latitude, longitude and height. 157 */ 158 public NEDFrame(final NEDPosition position) { 159 this(); 160 setPosition(position); 161 } 162 163 /** 164 * Constructor. 165 * 166 * @param latitude latitude expressed in radians. 167 * @param longitude longitude expressed in radians. 168 * @param height height expressed in meters. 169 * @param vn coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 170 * frame and resolved along North axis. 171 * @param ve coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 172 * frame and resolved along East axis. 173 * @param vd coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 174 * frame and resolved along Down axis. 175 */ 176 public NEDFrame(final double latitude, final double longitude, final double height, 177 final double vn, final double ve, final double vd) { 178 this(latitude, longitude, height); 179 setVelocityCoordinates(vn, ve, vd); 180 } 181 182 /** 183 * Constructor. 184 * 185 * @param latitude latitude expressed in radians to be set. 186 * @param longitude longitude expressed in radians to be set. 187 * @param height height to be set. 188 * @param vn coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 189 * frame and resolved along North axis. 190 * @param ve coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 191 * frame and resolved along East axis. 192 * @param vd coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 193 * frame and resolved along Down axis. 194 */ 195 public NEDFrame(final double latitude, final double longitude, final Distance height, 196 final double vn, final double ve, final double vd) { 197 this(latitude, longitude, height); 198 setVelocityCoordinates(vn, ve, vd); 199 } 200 201 /** 202 * Constructor. 203 * 204 * @param latitude latitude to be set. 205 * @param longitude longitude to be set. 206 * @param height height expressed in meters to be set. 207 * @param vn coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 208 * frame and resolved along North axis. 209 * @param ve coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 210 * frame and resolved along East axis. 211 * @param vd coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 212 * frame and resolved along Down axis. 213 */ 214 public NEDFrame(final Angle latitude, final Angle longitude, final double height, 215 final double vn, final double ve, final double vd) { 216 this(latitude, longitude, height); 217 setVelocityCoordinates(vn, ve, vd); 218 } 219 220 /** 221 * Constructor. 222 * 223 * @param latitude latitude to be set. 224 * @param longitude longitude to be set. 225 * @param height height to be set. 226 * @param vn coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 227 * frame and resolved along North axis. 228 * @param ve coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 229 * frame and resolved along East axis. 230 * @param vd coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 231 * frame and resolved along Down axis. 232 */ 233 public NEDFrame(final Angle latitude, final Angle longitude, final Distance height, 234 final double vn, final double ve, final double vd) { 235 this(latitude, longitude, height); 236 setVelocityCoordinates(vn, ve, vd); 237 } 238 239 /** 240 * Constructor. 241 * 242 * @param latitude latitude expressed in radians. 243 * @param longitude longitude expressed in radians. 244 * @param height height expressed in meters. 245 * @param speedN coordinate of velocity of body frame with respect ECEF frame and resolved along North axis. 246 * @param speedE coordinate of velocity of body frame with respect ECEF frame and resolved along East axis. 247 * @param speedD coordinate of velocity of body frame with respect ECEF frame and resolved along Down axis. 248 */ 249 public NEDFrame(final double latitude, final double longitude, final double height, 250 final Speed speedN, final Speed speedE, final Speed speedD) { 251 this(latitude, longitude, height); 252 setSpeedCoordinates(speedN, speedE, speedD); 253 } 254 255 /** 256 * Constructor. 257 * 258 * @param latitude latitude expressed in radians. 259 * @param longitude longitude expressed in radians. 260 * @param height height to be set. 261 * @param speedN coordinate of velocity of body frame with respect ECEF frame and resolved along North axis. 262 * @param speedE coordinate of velocity of body frame with respect ECEF frame and resolved along East axis. 263 * @param speedD coordinate of velocity of body frame with respect ECEF frame and resolved along Down axis. 264 */ 265 public NEDFrame(final double latitude, final double longitude, final Distance height, 266 final Speed speedN, final Speed speedE, final Speed speedD) { 267 this(latitude, longitude, height); 268 setSpeedCoordinates(speedN, speedE, speedD); 269 } 270 271 /** 272 * Constructor. 273 * 274 * @param latitude latitude to be set. 275 * @param longitude longitude to be set. 276 * @param height height expressed in meters to be set 277 * @param speedN coordinate of velocity of body frame with respect ECEF frame and resolved along North axis. 278 * @param speedE coordinate of velocity of body frame with respect ECEF frame and resolved along East axis. 279 * @param speedD coordinate of velocity of body frame with respect ECEF frame and resolved along Down axis. 280 */ 281 public NEDFrame(final Angle latitude, final Angle longitude, final double height, 282 final Speed speedN, final Speed speedE, final Speed speedD) { 283 this(latitude, longitude, height); 284 setSpeedCoordinates(speedN, speedE, speedD); 285 } 286 287 /** 288 * Constructor. 289 * 290 * @param latitude latitude to be set. 291 * @param longitude longitude to be set. 292 * @param height height to be set. 293 * @param speedN coordinate of velocity of body frame with respect ECEF frame and resolved along North axis. 294 * @param speedE coordinate of velocity of body frame with respect ECEF frame and resolved along East axis. 295 * @param speedD coordinate of velocity of body frame with respect ECEF frame and resolved along Down axis. 296 */ 297 public NEDFrame(final Angle latitude, final Angle longitude, final Distance height, 298 final Speed speedN, final Speed speedE, final Speed speedD) { 299 this(latitude, longitude, height); 300 setSpeedCoordinates(speedN, speedE, speedD); 301 } 302 303 /** 304 * Constructor. 305 * 306 * @param position curvilinear position to be set containing latitude, longitude and height. 307 * @param velocity velocity of body frame resolved along North, East, Down axes. 308 */ 309 public NEDFrame(final NEDPosition position, final NEDVelocity velocity) { 310 this(position); 311 setVelocity(velocity); 312 } 313 314 /** 315 * Constructor. 316 * 317 * @param latitude latitude expressed in radians. 318 * @param longitude longitude expressed in radians. 319 * @param height height expressed in meters. 320 * @param c Body to NED (Local Navigation frame) coordinate transformation matrix to be set. 321 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 322 */ 323 public NEDFrame(final double latitude, final double longitude, final double height, 324 final CoordinateTransformation c) throws InvalidSourceAndDestinationFrameTypeException { 325 this(latitude, longitude, height); 326 setCoordinateTransformation(c); 327 } 328 329 /** 330 * Constructor. 331 * 332 * @param latitude latitude to be set. 333 * @param longitude longitude to be set. 334 * @param height height expressed in meters to be set. 335 * @param c Body to NED (Local Navigation frame) coordinate transformation matrix to be set. 336 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 337 */ 338 public NEDFrame(final Angle latitude, final Angle longitude, final double height, 339 final CoordinateTransformation c) throws InvalidSourceAndDestinationFrameTypeException { 340 this(latitude, longitude, height); 341 setCoordinateTransformation(c); 342 } 343 344 /** 345 * Constructor. 346 * 347 * @param latitude latitude to be set. 348 * @param longitude longitude to be set. 349 * @param height height to be set. 350 * @param c Body to NED (Local Navigation frame) coordinate transformation matrix to be set. 351 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 352 */ 353 public NEDFrame(final Angle latitude, final Angle longitude, final Distance height, 354 final CoordinateTransformation c) throws InvalidSourceAndDestinationFrameTypeException { 355 this(latitude, longitude, height); 356 setCoordinateTransformation(c); 357 } 358 359 /** 360 * Constructor. 361 * 362 * @param position curvilinear position containing latitude, longitude and height. 363 * @param c Body to NED (Local Navigation frame) coordinate transformation matrix to be set. 364 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 365 */ 366 public NEDFrame(final NEDPosition position, final CoordinateTransformation c) 367 throws InvalidSourceAndDestinationFrameTypeException { 368 this(position); 369 setCoordinateTransformation(c); 370 } 371 372 /** 373 * Constructor. 374 * 375 * @param latitude latitude expressed in radians. 376 * @param longitude longitude expressed in radians. 377 * @param height height expressed in meters. 378 * @param vn coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 379 * frame and resolved along North axis. 380 * @param ve coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 381 * frame and resolved along East axis. 382 * @param vd coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 383 * frame and resolved along Down axis. 384 * @param c Body to NED (Local Navigation frame) coordinate transformation matrix to be set. 385 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 386 */ 387 public NEDFrame(final double latitude, final double longitude, final double height, 388 final double vn, final double ve, final double vd, 389 final CoordinateTransformation c) throws InvalidSourceAndDestinationFrameTypeException { 390 this(latitude, longitude, height, vn, ve, vd); 391 setCoordinateTransformation(c); 392 } 393 394 /** 395 * Constructor. 396 * 397 * @param latitude latitude expressed in radians to be set. 398 * @param longitude longitude expressed in radians to be set. 399 * @param height height to be set. 400 * @param vn coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 401 * frame and resolved along North axis. 402 * @param ve coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 403 * frame and resolved along East axis. 404 * @param vd coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 405 * frame and resolved along Down axis. 406 * @param c Body to NED (Local Navigation frame) coordinate transformation matrix to be set. 407 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 408 */ 409 public NEDFrame(final double latitude, final double longitude, final Distance height, 410 final double vn, final double ve, final double vd, 411 final CoordinateTransformation c) throws InvalidSourceAndDestinationFrameTypeException { 412 this(latitude, longitude, height, vn, ve, vd); 413 setCoordinateTransformation(c); 414 } 415 416 /** 417 * Constructor. 418 * 419 * @param latitude latitude to be set. 420 * @param longitude longitude to be set. 421 * @param height height expressed in meters to be set. 422 * @param vn coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 423 * frame and resolved along North axis. 424 * @param ve coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 425 * frame and resolved along East axis. 426 * @param vd coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 427 * frame and resolved along Down axis. 428 * @param c Body to NED (Local Navigation frame) coordinate transformation matrix to be set. 429 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 430 */ 431 public NEDFrame(final Angle latitude, final Angle longitude, final double height, 432 final double vn, final double ve, final double vd, 433 final CoordinateTransformation c) throws InvalidSourceAndDestinationFrameTypeException { 434 this(latitude, longitude, height, vn, ve, vd); 435 setCoordinateTransformation(c); 436 } 437 438 /** 439 * Constructor. 440 * 441 * @param latitude latitude to be set. 442 * @param longitude longitude to be set. 443 * @param height height to be set. 444 * @param vn coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 445 * frame and resolved along North axis. 446 * @param ve coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 447 * frame and resolved along East axis. 448 * @param vd coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF 449 * frame and resolved along Down axis. 450 * @param c Body to NED (Local Navigation frame) coordinate transformation matrix to be set. 451 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 452 */ 453 public NEDFrame(final Angle latitude, final Angle longitude, final Distance height, 454 final double vn, final double ve, final double vd, 455 final CoordinateTransformation c) throws InvalidSourceAndDestinationFrameTypeException { 456 this(latitude, longitude, height, vn, ve, vd); 457 setCoordinateTransformation(c); 458 } 459 460 /** 461 * Constructor. 462 * 463 * @param latitude latitude expressed in radians. 464 * @param longitude longitude expressed in radians. 465 * @param height height expressed in meters. 466 * @param speedN coordinate of velocity of body frame with respect ECEF frame and resolved along North axis. 467 * @param speedE coordinate of velocity of body frame with respect ECEF frame and resolved along East axis. 468 * @param speedD coordinate of velocity of body frame with respect ECEF frame and resolved along Down axis. 469 * @param c Body to NED (Local Navigation frame) coordinate transformation matrix to be set. 470 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 471 */ 472 public NEDFrame(final double latitude, final double longitude, final double height, 473 final Speed speedN, final Speed speedE, final Speed speedD, 474 final CoordinateTransformation c) throws InvalidSourceAndDestinationFrameTypeException { 475 this(latitude, longitude, height, speedN, speedE, speedD); 476 setCoordinateTransformation(c); 477 } 478 479 /** 480 * Constructor. 481 * 482 * @param latitude latitude expressed in radians. 483 * @param longitude longitude expressed in radians. 484 * @param height height to be set. 485 * @param speedN coordinate of velocity of body frame with respect ECEF frame and resolved along North axis. 486 * @param speedE coordinate of velocity of body frame with respect ECEF frame and resolved along East axis. 487 * @param speedD coordinate of velocity of body frame with respect ECEF frame and resolved along Down axis. 488 * @param c Body to NED (Local Navigation frame) coordinate transformation matrix to be set. 489 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 490 */ 491 public NEDFrame(final double latitude, final double longitude, final Distance height, 492 final Speed speedN, final Speed speedE, final Speed speedD, 493 final CoordinateTransformation c) throws InvalidSourceAndDestinationFrameTypeException { 494 this(latitude, longitude, height, speedN, speedE, speedD); 495 setCoordinateTransformation(c); 496 } 497 498 /** 499 * Constructor. 500 * 501 * @param latitude latitude to be set. 502 * @param longitude longitude to be set. 503 * @param height height expressed in meters to be set 504 * @param speedN coordinate of velocity of body frame with respect ECEF frame and resolved along North axis. 505 * @param speedE coordinate of velocity of body frame with respect ECEF frame and resolved along East axis. 506 * @param speedD coordinate of velocity of body frame with respect ECEF frame and resolved along Down axis. 507 * @param c Body to NED (Local Navigation frame) coordinate transformation matrix to be set. 508 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 509 */ 510 public NEDFrame(final Angle latitude, final Angle longitude, final double height, 511 final Speed speedN, final Speed speedE, final Speed speedD, 512 final CoordinateTransformation c) throws InvalidSourceAndDestinationFrameTypeException { 513 this(latitude, longitude, height, speedN, speedE, speedD); 514 setCoordinateTransformation(c); 515 } 516 517 /** 518 * Constructor. 519 * 520 * @param latitude latitude to be set. 521 * @param longitude longitude to be set. 522 * @param height height to be set. 523 * @param speedN coordinate of velocity of body frame with respect ECEF frame and resolved along North axis. 524 * @param speedE coordinate of velocity of body frame with respect ECEF frame and resolved along East axis. 525 * @param speedD coordinate of velocity of body frame with respect ECEF frame and resolved along Down axis. 526 * @param c Body to NED (Local Navigation frame) coordinate transformation matrix to be set. 527 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 528 */ 529 public NEDFrame(final Angle latitude, final Angle longitude, final Distance height, 530 final Speed speedN, final Speed speedE, final Speed speedD, 531 final CoordinateTransformation c) throws InvalidSourceAndDestinationFrameTypeException { 532 this(latitude, longitude, height, speedN, speedE, speedD); 533 setCoordinateTransformation(c); 534 } 535 536 /** 537 * Constructor. 538 * 539 * @param position curvilinear position to be set containing latitude, longitude and height. 540 * @param velocity velocity of body frame resolved along North, East, Down axes. 541 * @param c Body to NED (Local Navigation frame) coordinate transformation matrix to be set. 542 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 543 */ 544 public NEDFrame(final NEDPosition position, final NEDVelocity velocity, 545 final CoordinateTransformation c) throws InvalidSourceAndDestinationFrameTypeException { 546 this(position, velocity); 547 setCoordinateTransformation(c); 548 } 549 550 /** 551 * Constructor. 552 * 553 * @param input NED frame to copy data from. 554 */ 555 public NEDFrame(final NEDFrame input) { 556 this(); 557 copyFrom(input); 558 } 559 560 /** 561 * Gets latitude expressed in radians. 562 * 563 * @return latitude expressed in radians. 564 */ 565 public double getLatitude() { 566 return latitude; 567 } 568 569 /** 570 * Sets latitude expressed in radians. 571 * 572 * @param latitude latitude expressed in radians to be set. 573 */ 574 public void setLatitude(final double latitude) { 575 this.latitude = latitude; 576 } 577 578 /** 579 * Gets longitude expressed in radians. 580 * 581 * @return longitude expressed in radians. 582 */ 583 public double getLongitude() { 584 return longitude; 585 } 586 587 /** 588 * Sets longitude expressed in radians. 589 * 590 * @param longitude longitude expressed in radians to be set. 591 */ 592 public void setLongitude(final double longitude) { 593 this.longitude = longitude; 594 } 595 596 /** 597 * Gets height expressed in meters. 598 * 599 * @return height expressed in meters. 600 */ 601 public double getHeight() { 602 return height; 603 } 604 605 /** 606 * Sets height expressed in meters. 607 * 608 * @param height height expressed in meters to be set. 609 */ 610 public void setHeight(final double height) { 611 this.height = height; 612 } 613 614 /** 615 * Sets body position. 616 * 617 * @param latitude latitude expressed in radians to be set. 618 * @param longitude longitude expressed in radians to be set. 619 * @param height height expressed in meters to be set. 620 */ 621 public void setPosition(final double latitude, final double longitude, final double height) { 622 this.latitude = latitude; 623 this.longitude = longitude; 624 this.height = height; 625 } 626 627 /** 628 * Gets latitude. 629 * 630 * @param result instance where latitude will be stored. 631 */ 632 public void getLatitudeAngle(final Angle result) { 633 result.setValue(latitude); 634 result.setUnit(AngleUnit.RADIANS); 635 } 636 637 /** 638 * Gets latitude. 639 * 640 * @return latitude. 641 */ 642 public Angle getLatitudeAngle() { 643 return new Angle(latitude, AngleUnit.RADIANS); 644 } 645 646 /** 647 * Sets latitude. 648 * 649 * @param latitudeAngle latitude to be set. 650 */ 651 public void setLatitudeAngle(final Angle latitudeAngle) { 652 latitude = AngleConverter.convert(latitudeAngle.getValue().doubleValue(), latitudeAngle.getUnit(), 653 AngleUnit.RADIANS); 654 } 655 656 /** 657 * Gets longitude. 658 * 659 * @param result instance where longitude will be stored. 660 */ 661 public void getLongitudeAngle(final Angle result) { 662 result.setValue(longitude); 663 result.setUnit(AngleUnit.RADIANS); 664 } 665 666 /** 667 * Gets longitude. 668 * 669 * @return longitude. 670 */ 671 public Angle getLongitudeAngle() { 672 return new Angle(longitude, AngleUnit.RADIANS); 673 } 674 675 /** 676 * Sets longitude. 677 * 678 * @param longitudeAngle longitude to be set. 679 */ 680 public void setLongitudeAngle(final Angle longitudeAngle) { 681 longitude = AngleConverter.convert(longitudeAngle.getValue().doubleValue(), longitudeAngle.getUnit(), 682 AngleUnit.RADIANS); 683 } 684 685 /** 686 * Gets height. 687 * 688 * @param result instance where height will be stored. 689 */ 690 public void getHeightDistance(final Distance result) { 691 result.setValue(height); 692 result.setUnit(DistanceUnit.METER); 693 } 694 695 /** 696 * Gets height. 697 * 698 * @return height. 699 */ 700 public Distance getHeightDistance() { 701 return new Distance(height, DistanceUnit.METER); 702 } 703 704 /** 705 * Sets height. 706 * 707 * @param heightDistance height to be set. 708 */ 709 public void setHeightDistance(final Distance heightDistance) { 710 height = DistanceConverter.convert(heightDistance.getValue().doubleValue(), heightDistance.getUnit(), 711 DistanceUnit.METER); 712 } 713 714 /** 715 * Sets body position. 716 * 717 * @param latitude latitude expressed in radians to be set. 718 * @param longitude longitude expressed in radians to be set. 719 * @param height height to be set. 720 */ 721 public void setPosition(final double latitude, final double longitude, final Distance height) { 722 this.latitude = latitude; 723 this.longitude = longitude; 724 setHeightDistance(height); 725 } 726 727 /** 728 * Sets body position. 729 * 730 * @param latitude latitude to be set. 731 * @param longitude longitude to be set. 732 * @param height height expressed in meters to be set. 733 */ 734 public void setPosition(final Angle latitude, final Angle longitude, final double height) { 735 setLatitudeAngle(latitude); 736 setLongitudeAngle(longitude); 737 this.height = height; 738 } 739 740 /** 741 * Sets body position. 742 * 743 * @param latitude latitude to be set. 744 * @param longitude longitude to be set. 745 * @param height height to be set. 746 */ 747 public void setPosition(final Angle latitude, final Angle longitude, final Distance height) { 748 setLatitudeAngle(latitude); 749 setLongitudeAngle(longitude); 750 setHeightDistance(height); 751 } 752 753 /** 754 * Gets curvilinear position, expressed in terms of latitude, longitude and height. 755 * 756 * @param result instance where curvilinear coordinates will be stored. 757 */ 758 public void getPosition(final NEDPosition result) { 759 result.setCoordinates(latitude, longitude, height); 760 } 761 762 /** 763 * Gets curvilinear position, expressed in terms of latitude, longitude and height. 764 * 765 * @return curvilinear coordinates. 766 */ 767 public NEDPosition getPosition() { 768 return new NEDPosition(latitude, longitude, height); 769 } 770 771 /** 772 * Sets curvilinear position, expressed in terms of latitude, longitude and height. 773 * 774 * @param position curvilinear position to be set. 775 */ 776 public void setPosition(final NEDPosition position) { 777 latitude = position.getLatitude(); 778 longitude = position.getLongitude(); 779 height = position.getHeight(); 780 } 781 782 /** 783 * Gets coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF frame and 784 * resolved along North axis. 785 * 786 * @return North velocity coordinate value. 787 */ 788 public double getVn() { 789 return vn; 790 } 791 792 /** 793 * Sets coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF frame and 794 * resolved along North axis. 795 * 796 * @param vn North velocity coordinate value. 797 */ 798 public void setVn(final double vn) { 799 this.vn = vn; 800 } 801 802 /** 803 * Gets coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF frame and 804 * resolved along East axis. 805 * 806 * @return East velocity coordinate value. 807 */ 808 public double getVe() { 809 return ve; 810 } 811 812 /** 813 * Sets coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF frame and 814 * resolved along East axis. 815 * 816 * @param ve East velocity coordinate value. 817 */ 818 public void setVe(final double ve) { 819 this.ve = ve; 820 } 821 822 /** 823 * Gets coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF frame and 824 * resolved along Down axis. 825 * 826 * @return Down velocity coordinate value. 827 */ 828 public double getVd() { 829 return vd; 830 } 831 832 /** 833 * Sets coordinate of velocity of body frame expressed in meters per second (m/s) with respect ECEF frame and 834 * resolved along Down axis. 835 * 836 * @param vd Down velocity coordinate value. 837 */ 838 public void setVd(final double vd) { 839 this.vd = vd; 840 } 841 842 /** 843 * Sets velocity coordinates of body frame expressed in meters per second (m/s) resolved along North, East, Down 844 * axes. 845 * 846 * @param vn North velocity coordinate value. 847 * @param ve East velocity coordinate value. 848 * @param vd Down velocity coordinate value. 849 */ 850 public void setVelocityCoordinates(final double vn, final double ve, final double vd) { 851 this.vn = vn; 852 this.ve = ve; 853 this.vd = vd; 854 } 855 856 /** 857 * Gets norm of velocity expressed in meters per second (m/s), which represents 858 * the speed of the body. 859 * 860 * @return norm of velocity expressed in meters per second (m/s). 861 */ 862 public double getVelocityNorm() { 863 return Math.sqrt(vn * vn + ve * ve + vd * vd); 864 } 865 866 /** 867 * Gets norm of velocity, which represents the speed of the body. 868 * 869 * @param result velocity norm. 870 */ 871 public void getVelocityNormAsSpeed(final Speed result) { 872 result.setValue(getVelocityNorm()); 873 result.setUnit(SpeedUnit.METERS_PER_SECOND); 874 } 875 876 /** 877 * Gets norm of velocity, which represents the speed of the body. 878 * 879 * @return velocity norm. 880 */ 881 public Speed getVelocityNormAsSpeed() { 882 return new Speed(getVelocityNorm(), SpeedUnit.METERS_PER_SECOND); 883 } 884 885 /** 886 * Gets coordinate of velocity of body frame with respect ECEF frame and 887 * resolved along North axis. 888 * 889 * @param result instance where North velocity coordinate will be stored. 890 */ 891 public void getSpeedN(final Speed result) { 892 result.setValue(vn); 893 result.setUnit(SpeedUnit.METERS_PER_SECOND); 894 } 895 896 /** 897 * Gets coordinate of velocity of body frame with respect ECEF frame and 898 * resolved along North axis. 899 * 900 * @return North velocity coordinate. 901 */ 902 public Speed getSpeedN() { 903 return new Speed(vn, SpeedUnit.METERS_PER_SECOND); 904 } 905 906 /** 907 * Sets coordinate of velocity of body frame with respect ECEF frame and 908 * resolved along North axis. 909 * 910 * @param speedN North velocity coordinate to be set. 911 */ 912 public void setSpeedN(final Speed speedN) { 913 vn = SpeedConverter.convert(speedN.getValue().doubleValue(), speedN.getUnit(), SpeedUnit.METERS_PER_SECOND); 914 } 915 916 /** 917 * Gets coordinate of velocity of body frame with respect ECEF frame and 918 * resolved along East axis. 919 * 920 * @param result instance where East velocity coordinate will be stored. 921 */ 922 public void getSpeedE(final Speed result) { 923 result.setValue(ve); 924 result.setUnit(SpeedUnit.METERS_PER_SECOND); 925 } 926 927 /** 928 * Gets coordinate of velocity of body frame with respect ECEF frame and 929 * resolved along East axis. 930 * 931 * @return East velocity coordinate. 932 */ 933 public Speed getSpeedE() { 934 return new Speed(ve, SpeedUnit.METERS_PER_SECOND); 935 } 936 937 /** 938 * Sets coordinate of velocity of body frame with respect ECEF frame and 939 * resolved along East axis. 940 * 941 * @param speedE East velocity coordinate to be set. 942 */ 943 public void setSpeedE(final Speed speedE) { 944 ve = SpeedConverter.convert(speedE.getValue().doubleValue(), speedE.getUnit(), SpeedUnit.METERS_PER_SECOND); 945 } 946 947 /** 948 * Gets coordinate of velocity of body frame with respect ECEF frame and 949 * resolved along Down axis. 950 * 951 * @param result instance where Down velocity coordinate will be stored. 952 */ 953 public void getSpeedD(final Speed result) { 954 result.setValue(vd); 955 result.setUnit(SpeedUnit.METERS_PER_SECOND); 956 } 957 958 /** 959 * Gets coordinate of velocity of body frame with respect ECEF frame and 960 * resolved along Down axis. 961 * 962 * @return Down velocity coordinate. 963 */ 964 public Speed getSpeedD() { 965 return new Speed(vd, SpeedUnit.METERS_PER_SECOND); 966 } 967 968 /** 969 * Sets coordinate of velocity of body frame with respect ECEF frame and 970 * resolved along Down axis. 971 * 972 * @param speedD Down velocity coordinate to be set. 973 */ 974 public void setSpeedD(final Speed speedD) { 975 vd = SpeedConverter.convert(speedD.getValue().doubleValue(), speedD.getUnit(), SpeedUnit.METERS_PER_SECOND); 976 } 977 978 /** 979 * Sets velocity coordinates of body frame resolved along North, East, Down 980 * axes. 981 * 982 * @param speedN North velocity coordinate. 983 * @param speedE East velocity coordinate. 984 * @param speedD Down velocity coordinate. 985 */ 986 public void setSpeedCoordinates(final Speed speedN, final Speed speedE, final Speed speedD) { 987 setSpeedN(speedN); 988 setSpeedE(speedE); 989 setSpeedD(speedD); 990 } 991 992 /** 993 * Gets velocity coordinates of body frame resolved along North, East, Down axes. 994 * 995 * @param result instance where velocity values will be stored. 996 */ 997 public void getVelocity(final NEDVelocity result) { 998 result.setCoordinates(vn, ve, vd); 999 } 1000 1001 /** 1002 * Gets velocity coordinates of body frame resolved along North, East, Down axes. 1003 * 1004 * @return velocity coordinates. 1005 */ 1006 public NEDVelocity getVelocity() { 1007 return new NEDVelocity(vn, ve, vd); 1008 } 1009 1010 /** 1011 * Sets velocity coordinates of body frame resolved along North, East, Down axes. 1012 * 1013 * @param velocity velocity to be set. 1014 */ 1015 public void setVelocity(final NEDVelocity velocity) { 1016 vn = velocity.getVn(); 1017 ve = velocity.getVe(); 1018 vd = velocity.getVd(); 1019 } 1020 1021 /** 1022 * Gets coordinate transformation matrix. 1023 * 1024 * @return coordinate transformation matrix. 1025 */ 1026 @Override 1027 public CoordinateTransformation getCoordinateTransformation() { 1028 final var result = new CoordinateTransformation(FrameType.BODY_FRAME, FrameType.LOCAL_NAVIGATION_FRAME); 1029 getCoordinateTransformation(result); 1030 return result; 1031 } 1032 1033 /** 1034 * Gets coordinate transformation matrix. 1035 * 1036 * @param result instance where coordinate transformation matrix will be copied to. 1037 */ 1038 @Override 1039 public void getCoordinateTransformation(final CoordinateTransformation result) { 1040 c.copyTo(result); 1041 } 1042 1043 /** 1044 * Gets coordinate transformation matrix. 1045 * This is equivalent to calling getCoordinateTransformation().getMatrix(), but more efficient 1046 * 1047 * @return coordinate transformation matrix. 1048 */ 1049 @Override 1050 public Matrix getCoordinateTransformationMatrix() { 1051 Matrix result; 1052 try { 1053 result = new Matrix(CoordinateTransformation.ROWS, CoordinateTransformation.COLS); 1054 getCoordinateTransformationMatrix(result); 1055 } catch (final WrongSizeException ignore) { 1056 // never happens 1057 result = null; 1058 } 1059 return result; 1060 } 1061 1062 /** 1063 * Gets coordinate transformation matrix. 1064 * This is equivalent to calling getCoordinateTransformation().getMatrix(), but more efficient 1065 * 1066 * @param result instance where coordinate transformation matrix will be copied to. 1067 */ 1068 @Override 1069 public void getCoordinateTransformationMatrix(final Matrix result) { 1070 c.matrix.copyTo(result); 1071 } 1072 1073 /** 1074 * Sets coordinate transformation matrix keeping current source and destination {@link FrameType}. 1075 * This is more efficient than getting a copy of coordinate transformation calling to 1076 * {@link #getCoordinateTransformation()}, setting coordinate matrix into copied coordinate transformation and 1077 * then setting the coordinate transformation calling 1078 * {@link #setCoordinateTransformation(CoordinateTransformation)}. 1079 * 1080 * @param matrix a 3x3 coordinate transformation matrix to be set. 1081 * @param threshold threshold to validate rotation matrix. 1082 * @throws InvalidRotationMatrixException if provided matrix is not a valid rotation matrix (3x3 and orthonormal). 1083 * @throws IllegalArgumentException if provided threshold is negative. 1084 */ 1085 @Override 1086 public void setCoordinateTransformationMatrix(final Matrix matrix, final double threshold) 1087 throws InvalidRotationMatrixException { 1088 c.setMatrix(matrix,threshold); 1089 } 1090 1091 /** 1092 * Sts coordinate transformation matrix keeping current source and destination {@link FrameType}. 1093 * This is more efficient than getting a copy of coordinate transformation calling to 1094 * {@link #getCoordinateTransformation()}, setting coordinate matrix into copied coordinate transformation and 1095 * then setting the coordinate transformation calling 1096 * {@link #setCoordinateTransformation(CoordinateTransformation)}. 1097 * 1098 * @param matrix a 3x3 coordinate transformation matrix to be set. 1099 * @throws InvalidRotationMatrixException if provided matrix is not a valid rotation matrix (3x3 and orthonormal). 1100 */ 1101 @Override 1102 public void setCoordinateTransformationMatrix(final Matrix matrix) throws InvalidRotationMatrixException { 1103 c.setMatrix(matrix); 1104 } 1105 1106 /** 1107 * Gets coordinate transformation as a new 3D rotation instance. 1108 * This is equivalent to calling getCoordinateTransformation().asRotation(), but more efficient. 1109 * 1110 * @return new coordinate transformation as a 3D rotation. 1111 * @throws InvalidRotationMatrixException if internal matrix cannot be converted to a 3D rotation. 1112 */ 1113 @Override 1114 public Rotation3D getCoordinateTransformationRotation() throws InvalidRotationMatrixException { 1115 return c.asRotation(); 1116 } 1117 1118 /** 1119 * Gets coordinate transformation as a 3D rotation. 1120 * This is equivalent to calling getCoordinateTransformation().asRotation(), but more efficient. 1121 * 1122 * @param result instance where coordinate transformation 3D rotation will be copied to. 1123 * @throws InvalidRotationMatrixException if internal matrix cannot be converted to a 3D rotation. 1124 */ 1125 @Override 1126 public void getCoordinateTransformationRotation(final Rotation3D result) throws InvalidRotationMatrixException { 1127 c.asRotation(result); 1128 } 1129 1130 /** 1131 * Sets coordinate transformation from 3D rotation and keeping current source and destination {@link FrameType}. 1132 * This is more efficient than getting a copy of coordinate transformation calling to 1133 * {@link #getCoordinateTransformation()}, setting rotation into copied coordinate transformation and 1134 * then setting the coordinate transformation calling 1135 * {@link #setCoordinateTransformation(CoordinateTransformation)}. 1136 * 1137 * @param rotation set rotation into current coordinate rotation. 1138 */ 1139 @Override 1140 public void setCoordinateTransformationRotation(final Rotation3D rotation) { 1141 c.fromRotation(rotation); 1142 } 1143 1144 /** 1145 * Sets coordinate transformation matrix. 1146 * Provided value must be a body to NED transformation matrix. 1147 * 1148 * @param c coordinate transformation matrix to be set. 1149 * @throws InvalidSourceAndDestinationFrameTypeException if source or destination frame types are invalid. 1150 */ 1151 @Override 1152 public void setCoordinateTransformation(final CoordinateTransformation c) 1153 throws InvalidSourceAndDestinationFrameTypeException { 1154 if (!isValidCoordinateTransformation(c)) { 1155 throw new InvalidSourceAndDestinationFrameTypeException(); 1156 } 1157 1158 this.c = c; 1159 } 1160 1161 /** 1162 * Checks whether provided coordinate transformation matrix is valid or not. 1163 * Only body to NED transformation matrices are considered to be valid. 1164 * 1165 * @param c coordinate transformation matrix to be checked. 1166 * @return true if provided value is valid, false otherwise. 1167 */ 1168 public static boolean isValidCoordinateTransformation(final CoordinateTransformation c) { 1169 return c.getSourceType() == FrameType.BODY_FRAME 1170 && c.getDestinationType() == FrameType.LOCAL_NAVIGATION_FRAME; 1171 } 1172 1173 /** 1174 * Copies this instance data into provided instance. 1175 * 1176 * @param output destination instance where data will be copied to. 1177 */ 1178 public void copyTo(final NEDFrame output) { 1179 output.latitude = latitude; 1180 output.longitude = longitude; 1181 output.height = height; 1182 1183 output.vn = vn; 1184 output.ve = ve; 1185 output.vd = vd; 1186 1187 c.copyTo(output.c); 1188 } 1189 1190 /** 1191 * Copies data of provided instance into this instance. 1192 * 1193 * @param input instance to copy data from. 1194 */ 1195 public void copyFrom(final NEDFrame input) { 1196 latitude = input.latitude; 1197 longitude = input.longitude; 1198 height = input.height; 1199 1200 vn = input.vn; 1201 ve = input.ve; 1202 vd = input.vd; 1203 1204 c.copyFrom(input.c); 1205 } 1206 1207 /** 1208 * Computes and returns hash code for this instance. Hash codes are almost unique 1209 * values that are useful for fast classification and storage of objects in collections. 1210 * 1211 * @return Hash code. 1212 */ 1213 @Override 1214 public int hashCode() { 1215 return Objects.hash(latitude, longitude, height, vn, ve, vd, c); 1216 } 1217 1218 /** 1219 * Checks if provided object is an ECEFFrame having exactly the same contents as 1220 * this instance. 1221 * 1222 * @param obj Object to be compared. 1223 * @return true if both objects are considered to be equal, false otherwise. 1224 */ 1225 @Override 1226 public boolean equals(final Object obj) { 1227 if (obj == null) { 1228 return false; 1229 } 1230 if (obj == this) { 1231 return true; 1232 } 1233 if (!(obj instanceof NEDFrame)) { 1234 return false; 1235 } 1236 1237 final NEDFrame other = (NEDFrame) obj; 1238 return equals(other); 1239 } 1240 1241 /** 1242 * Checks if provided instance has exactly the same contents as this instance. 1243 * 1244 * @param other instance to be compared. 1245 * @return true if both instances are considered to be equal, false otherwise. 1246 */ 1247 public boolean equals(final NEDFrame other) { 1248 return equals(other, 0.0); 1249 } 1250 1251 /** 1252 * Checks if provided instance has contents similar to this instance up to provided 1253 * threshold value. 1254 * 1255 * @param other instance to be compared. 1256 * @param threshold maximum difference allowed between position, velocity and coordinate transformation matrix. 1257 * @return true if both instances are considered to be equal (up to provided threshold), false otherwise. 1258 */ 1259 public boolean equals(final NEDFrame other, final double threshold) { 1260 if (other == null) { 1261 return false; 1262 } 1263 1264 return Math.abs(latitude - other.latitude) <= threshold 1265 && Math.abs(longitude - other.longitude) <= threshold 1266 && Math.abs(height - other.height) <= threshold 1267 && Math.abs(vn - other.vn) <= threshold 1268 && Math.abs(ve - other.ve) <= threshold 1269 && Math.abs(vd - other.vd) <= threshold 1270 && c.equals(other.c, threshold); 1271 } 1272 1273 /** 1274 * Makes a copy of this instance. 1275 * 1276 * @return a copy of this instance. 1277 * @throws CloneNotSupportedException if clone fails for some reason. 1278 */ 1279 @Override 1280 protected Object clone() throws CloneNotSupportedException { 1281 final var result = (NEDFrame)super.clone(); 1282 copyTo(result); 1283 return result; 1284 } 1285 }