ElementsType.java

  1. /* Copyright 2002-2022 CS GROUP
  2.  * Licensed to CS GROUP (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.files.ccsds.definitions;

  18. import java.util.List;
  19. import java.util.stream.Collectors;
  20. import java.util.stream.Stream;

  21. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  22. import org.hipparchus.util.Precision;
  23. import org.orekit.annotation.DefaultDataContext;
  24. import org.orekit.errors.OrekitException;
  25. import org.orekit.errors.OrekitMessages;
  26. import org.orekit.files.ccsds.ndm.odm.ocm.Ocm;
  27. import org.orekit.frames.FramesFactory;
  28. import org.orekit.orbits.EquinoctialOrbit;
  29. import org.orekit.orbits.KeplerianOrbit;
  30. import org.orekit.orbits.PositionAngle;
  31. import org.orekit.time.AbsoluteDate;
  32. import org.orekit.utils.TimeStampedPVCoordinates;
  33. import org.orekit.utils.units.Unit;

  34. /** Orbit element set type used in CCSDS {@link Ocm Orbit Comprehensive Messages}.
  35.  * @see <a href="https://sanaregistry.org/r/orbital_elements">SANA registry for orbital elements</a>
  36.  * @author Luc Maisonobe
  37.  * @since 11.0
  38.  */
  39. public enum ElementsType {

  40.     // CHECKSTYLE: stop MultipleStringLiterals check

  41.     /** Spherical 6-element set (α,δ,β,A,r,v). */
  42.     ADBARV("Spherical 6-element set (α,δ,β,A,r,v)",
  43.            "°", "°", "°", "°", "km", "km"),

  44.     /** Cartesian 3-element position (X, Y, Z). */
  45.     CARTP("Cartesian 3-element position (X, Y, Z)",
  46.           "km", "km", "km") {
  47.         /** {@inheritDoc} */
  48.         @Override
  49.         public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements, final double mu) {
  50.             return new TimeStampedPVCoordinates(date,
  51.                                                 new Vector3D(elements[0], elements[1], elements[2]),
  52.                                                 Vector3D.ZERO,
  53.                                                 Vector3D.ZERO);
  54.         }
  55.     },

  56.     /** Cartesian 6-element position and velocity (X, Y, Z, XD, YD, ZD). */
  57.     CARTPV("Cartesian 6-element position and velocity (X, Y, Z, XD, YD, ZD)",
  58.            "km", "km", "km", "km/s", "km/s", "km/s") {
  59.         /** {@inheritDoc} */
  60.         @Override
  61.         public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements, final double mu) {
  62.             return new TimeStampedPVCoordinates(date,
  63.                                                 new Vector3D(elements[0], elements[1], elements[2]),
  64.                                                 new Vector3D(elements[3], elements[4], elements[5]),
  65.                                                 Vector3D.ZERO);
  66.         }
  67.     },

  68.     /** Cartesian 9-element position, velocity and acceleration (X, Y, Z, XD, YD, ZD, XDD, YDD, ZDD). */
  69.     CARTPVA("Cartesian 9-element position, velocity and acceleration (X, Y, Z, XD, YD, ZD, XDD, YDD, ZDD)",
  70.             "km", "km", "km", "km/s", "km/s", "km/s", "km/s²", "km/s²", "km/s²") {
  71.         /** {@inheritDoc} */
  72.         @Override
  73.         public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements, final double mu) {
  74.             return new TimeStampedPVCoordinates(date,
  75.                                                 new Vector3D(elements[0], elements[1], elements[2]),
  76.                                                 new Vector3D(elements[3], elements[4], elements[5]),
  77.                                                 new Vector3D(elements[6], elements[7], elements[8]));
  78.         }
  79.     },

  80.     /** Delaunay elements (L, G, H, l, g, h). */
  81.     DELAUNAY("Delaunay elements (L, G, H, l, g, h)",
  82.              "km²/s", "km²/s", "km²/s", "°", "°", "°"),

  83.     /** Modified Delaunay elements (Lm, Gm, Hm, lm, gm, hm). */
  84.     DELAUNAYMOD("Delaunay elements (Lm, Gm, Hm, lm, gm, hm)",
  85.                 "√km", "√km", "√km", "°", "°", "°"),

  86.     /** 12 elements eigenvalue/eigenvectors (EigMaj, EigMed, EigMin, EigVecMaj, EigVecMed, EigVecMin). */
  87.     EIGVAL3EIGVEC3("12 elements eigenvalue/eigenvectors (EigMaj, EigMed, EigMin, EigVecMaj, EigVecMed, EigVecMin)",
  88.                    "km", "km", "km", "n/a", "n/a", "n/a", "n/a", "n/a", "n/a", "n/a", "n/a", "n/a"),

  89.     /** Equinoctial elements (a, af, ag, L=M+ω+frΩ, χ, ψ, fr). */
  90.     EQUINOCTIAL("Equinoctial elements (a, af, ag, L=M+ω+frΩ, χ, ψ, fr)",
  91.                 "km", "n/a", "n/a", "°", "n/a", "n/a", "n/a") {
  92.         /** {@inheritDoc} */
  93.         @Override
  94.         @DefaultDataContext
  95.         public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements, final double mu) {
  96.             if (elements[6] < 0) {
  97.                 // retrograde
  98.                 throw new OrekitException(OrekitMessages.CCSDS_UNSUPPORTED_RETROGRADE_EQUINOCTIAL,
  99.                                           EQUINOCTIAL.name());
  100.             }
  101.             return new EquinoctialOrbit(elements[0], elements[1], elements[2],
  102.                                         elements[5], elements[4], // BEWARE! the inversion here is intentional
  103.                                         elements[3], PositionAngle.MEAN,
  104.                                         FramesFactory.getGCRF(), date, mu).
  105.                             getPVCoordinates();
  106.         }
  107.     },

  108.     /** Modified equinoctial elements (p=a(1−e²), af, ag, L'=υ+ω+frΩ, χ, ψ, fr). */
  109.     EQUINOCTIALMOD("Modified equinoctial elements (p=a(1−e²), af, ag, L'=υ+ω+frΩ, χ, ψ, fr)",
  110.                    "km", "n/a", "n/a", "°", "n/a", "n/a", "n/a") {
  111.         /** {@inheritDoc} */
  112.         @Override
  113.         @DefaultDataContext
  114.         public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements, final double mu) {
  115.             if (elements[6] < 0) {
  116.                 // retrograde
  117.                 throw new OrekitException(OrekitMessages.CCSDS_UNSUPPORTED_RETROGRADE_EQUINOCTIAL,
  118.                                           EQUINOCTIALMOD.name());
  119.             }
  120.             final double oMe2 = 1.0 - elements[1] * elements[1] - elements[2] * elements[2];
  121.             return new EquinoctialOrbit(elements[0] / oMe2, elements[1], elements[2],
  122.                                         elements[5], elements[4], // BEWARE! the inversion here is intentional
  123.                                         elements[3], PositionAngle.TRUE,
  124.                                         FramesFactory.getGCRF(), date, mu).
  125.                             getPVCoordinates();
  126.         }
  127.     },

  128.     /** Geodetic elements (λ, ΦGD, β, A, h, vre). */
  129.     GEODETIC("Geodetic elements (λ, ΦGD, β, A, h, vre)",
  130.              "°", "°", "°", "°", "km", "km/s"),

  131.     /** Keplerian 6-element classical set (a, e, i, Ω, ω, ν). */
  132.     KEPLERIAN("Keplerian 6-elemnt classical set (a, e, i, Ω, ω, ν)",
  133.               "km", "n/a", "°", "°", "°", "°") {
  134.         /** {@inheritDoc} */
  135.         @Override
  136.         @DefaultDataContext
  137.         public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements, final double mu) {
  138.             return new KeplerianOrbit(elements[0], elements[1], elements[2],
  139.                                       elements[4], elements[3], // BEWARE! the inversion here is intentional
  140.                                       elements[5], PositionAngle.TRUE,
  141.                                       FramesFactory.getGCRF(), date, mu).
  142.                    getPVCoordinates();
  143.         }
  144.     },

  145.     /** Keplerian 6-element classical set (a, e, i, Ω, ω, M). */
  146.     KEPLERIANMEAN("Keplerian 6-elemnt classical set (a, e, i, Ω, ω, M)",
  147.                   "km", "n/a", "°", "°", "°", "°") {
  148.         /** {@inheritDoc} */
  149.         @Override
  150.         @DefaultDataContext
  151.         public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements, final double mu) {
  152.             return new KeplerianOrbit(elements[0], elements[1], elements[2],
  153.                                       elements[4], elements[3], // BEWARE! the inversion here is intentional
  154.                                       elements[5], PositionAngle.MEAN,
  155.                                       FramesFactory.getGCRF(), date, mu).
  156.                    getPVCoordinates();
  157.         }
  158.     },

  159.     /** Modified spherical 6-element set (λ, δ, β, A, r, v). */
  160.     LDBARV("Modified spherical 6-element set (λ, δ, β, A, r, v)",
  161.            "°", "°", "°", "°", "km", "km/s"),

  162.     /** Geosynchronous on-station tailored set (a, ex, ey, ix, iy, λ). */
  163.     ONSTATION("Geosynchronous on-station tailored set (a, ex, ey, ix, iy, λ)",
  164.               "km", "n/a", "n/a", "n/a", "n/a", "°"),

  165.     /** Canonical counterpart of equinoctial 6-element set (λM=M+ω+Ω, gp, hp, Lp, Gp, Hp). */
  166.     POINCARE("Canonical counterpart of equinoctial 6-element set (λM=M+ω+Ω, gp, hp, Lp, Gp, Hp)",
  167.              "°", "km/√s", "km/√s", "km²/s", "km/√s", "km/√s");

  168.     // CHECKSTYLE: resume MultipleStringLiterals check

  169.     /** Description. */
  170.     private final String description;

  171.     /** Elements units. */
  172.     private final List<Unit> units;

  173.     /** Simple constructor.
  174.      * @param description description
  175.      * @param unitsSpecifications elements units specifications
  176.      */
  177.     ElementsType(final String description, final String... unitsSpecifications) {
  178.         this.description = description;
  179.         this.units       = Stream.of(unitsSpecifications).
  180.                            map(s -> Unit.parse(s)).
  181.                            collect(Collectors.toList());
  182.     }

  183.     /** Get the elements units.
  184.      * @return elements units
  185.      */
  186.     public List<Unit> getUnits() {
  187.         return units;
  188.     }

  189.     /** Check if parsed units are compatible with elements types.
  190.      * @param parsedUnits units to check
  191.      */
  192.     public void checkUnits(final List<Unit> parsedUnits) {
  193.         if (parsedUnits.size() != units.size()) {
  194.             throw new OrekitException(OrekitMessages.CCSDS_ELEMENT_SET_WRONG_NB_COMPONENTS,
  195.                                       name(), toString(), units.size());
  196.         }
  197.         for (int i = 0; i < units.size(); ++i) {
  198.             if (!(units.get(i).sameDimension(parsedUnits.get(i)) &&
  199.                   Precision.equals(units.get(i).getScale(), parsedUnits.get(i).getScale(), 1))) {
  200.                 throw new OrekitException(OrekitMessages.INCOMPATIBLE_UNITS,
  201.                                           units.get(i).getName(),
  202.                                           parsedUnits.get(i).getName());
  203.             }
  204.         }
  205.     }

  206.     /** Convert to Cartesian coordinates.
  207.      * @param date elements date
  208.      * @param elements elements values
  209.      * @param mu gravitational parameter in m³/s²
  210.      * @return Cartesian coordinates
  211.      */
  212.     public TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final double[] elements, final double mu) {
  213.         throw new OrekitException(OrekitMessages.CCSDS_UNSUPPORTED_ELEMENT_SET_TYPE, name(), toString());
  214.     }

  215.     /** {@inheritDoc} */
  216.     @Override
  217.     public String toString() {
  218.         return description;
  219.     }

  220. }