TrajectoryStateHistoryMetadata.java

  1. /* Copyright 2002-2025 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.ndm.odm.ocm;

  18. import java.util.List;

  19. import org.orekit.data.DataContext;
  20. import org.orekit.errors.OrekitException;
  21. import org.orekit.errors.OrekitMessages;
  22. import org.orekit.files.ccsds.definitions.BodyFacade;
  23. import org.orekit.files.ccsds.definitions.CelestialBodyFrame;
  24. import org.orekit.files.ccsds.definitions.FrameFacade;
  25. import org.orekit.files.ccsds.ndm.odm.oem.InterpolationMethod;
  26. import org.orekit.files.ccsds.section.CommentsContainer;
  27. import org.orekit.time.AbsoluteDate;
  28. import org.orekit.utils.units.Unit;

  29. /** Metadata for trajectory state history.
  30.  * <p>
  31.  * Beware that the Orekit getters and setters all rely on SI units. The parsers
  32.  * and writers take care of converting these SI units into CCSDS mandatory units.
  33.  * The {@link org.orekit.utils.units.Unit Unit} class provides useful
  34.  * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
  35.  * {@link org.orekit.utils.units.Unit#toSI(double) toSI} methods in case the callers
  36.  * already use CCSDS units instead of the API SI units. The general-purpose
  37.  * {@link org.orekit.utils.units.Unit Unit} class (without an 's') and the
  38.  * CCSDS-specific {@link org.orekit.files.ccsds.definitions.Units Units} class
  39.  * (with an 's') also provide some predefined units. These predefined units and the
  40.  * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
  41.  * {@link org.orekit.utils.units.Unit#toSI(double) toSI} conversion methods are indeed
  42.  * what the parsers and writers use for the conversions.
  43.  * </p>
  44.  * @author Luc Maisonobe
  45.  * @since 11.0
  46.  */
  47. public class TrajectoryStateHistoryMetadata extends CommentsContainer {

  48.     /** Default interpolation method.
  49.      * @since 12.0
  50.      */
  51.     public static final InterpolationMethod DEFAULT_INTERPOLATION_METHOD = InterpolationMethod.HERMITE;

  52.     /** Default interpolation degree.
  53.      * @since 12.0
  54.      */
  55.     public static final int DEFAULT_INTERPOLATION_DEGREE = 3;

  56.     /** Trajectory identification number. */
  57.     private String trajID;

  58.     /** Identification number of previous trajectory. */
  59.     private String trajPrevID;

  60.     /** Identification number of next trajectory. */
  61.     private String trajNextID;

  62.     /** Basis of this trajectory state time history data. */
  63.     private String trajBasis;

  64.     /** Identification number of the orbit determination or simulation upon which this trajectory is based. */
  65.     private String trajBasisID;

  66.     /** Interpolation method. */
  67.     private InterpolationMethod interpolationMethod;

  68.     /** Interpolation degree. */
  69.     private int interpolationDegree;

  70.     /** Orbit propagator used to generate this trajectory.
  71.      * @since 11.2
  72.      */
  73.     private String propagator;

  74.     /** Origin of reference frame. */
  75.     private BodyFacade center;

  76.     /** Reference frame of the trajectory. */
  77.     private FrameFacade trajReferenceFrame;

  78.     /** Epoch of the trajectory reference frame. */
  79.     private AbsoluteDate trajFrameEpoch;

  80.     /** Start of useable time span covered by ephemerides data, it may be
  81.      * necessary to allow for proper interpolation. */
  82.     private AbsoluteDate useableStartTime;

  83.     /** End of useable time span covered by ephemerides data, it may be
  84.      * necessary to allow for proper interpolation. */
  85.     private AbsoluteDate useableStopTime;

  86.     /** Integer orbit revolution number. */
  87.     private int orbRevNum;

  88.     /** Basis for orbit revolution counter (i.e is first launch/deployment on orbit 0 or 1). */
  89.     private int orbRevNumBasis;

  90.     /** Trajectory element set type. */
  91.     private OrbitElementsType trajType;

  92.     /** Type of averaging (Osculating, mean Brouwer, other...). */
  93.     private String orbAveraging;

  94.     /** Units of trajectory element set. */
  95.     private List<Unit> trajUnits;

  96.     /** Data context.
  97.      * @since 12.0
  98.      */
  99.     private final DataContext dataContext;

  100.     /** Simple constructor.
  101.      * @param epochT0 T0 epoch from file metadata
  102.      * @param dataContext data context
  103.      */
  104.     public TrajectoryStateHistoryMetadata(final AbsoluteDate epochT0, final DataContext dataContext) {
  105.         // we don't call the setXxx() methods in order to avoid
  106.         // calling refuseFurtherComments as a side effect
  107.         trajBasis           = null;
  108.         interpolationMethod = DEFAULT_INTERPOLATION_METHOD;
  109.         interpolationDegree = DEFAULT_INTERPOLATION_DEGREE;
  110.         orbAveraging        = "OSCULATING";
  111.         center              = new BodyFacade("EARTH",
  112.                                              dataContext.getCelestialBodies().getEarth());
  113.         trajReferenceFrame  = new FrameFacade(dataContext.getFrames().getICRF(),
  114.                                               CelestialBodyFrame.ICRF, null, null,
  115.                                               CelestialBodyFrame.ICRF.name());
  116.         trajFrameEpoch      = epochT0;
  117.         trajType            = OrbitElementsType.CARTPV;
  118.         orbRevNum           = -1;
  119.         orbRevNumBasis      = -1;

  120.         this.dataContext    = dataContext;

  121.     }

  122.     /** {@inheritDoc} */
  123.     @Override
  124.     public void validate(final double version) {
  125.         checkMandatoryEntriesExceptOrbitsCounter(version);
  126.         if (orbRevNum >= 0 && orbRevNumBasis < 0) {
  127.             throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY,
  128.                                       TrajectoryStateHistoryMetadataKey.ORB_REVNUM_BASIS.name());
  129.         }
  130.     }

  131.     /** Check is mandatory entries EXCEPT orbits counters have been initialized.
  132.      * <p>
  133.      * This method should throw an exception if some mandatory entry is missing
  134.      * </p>
  135.      * @param version format version
  136.      */
  137.     private void checkMandatoryEntriesExceptOrbitsCounter(final double version) {
  138.         super.validate(version);
  139.         if (trajType != OrbitElementsType.CARTP   &&
  140.             trajType != OrbitElementsType.CARTPV  &&
  141.             trajType != OrbitElementsType.CARTPVA) {
  142.             checkNotNull(orbAveraging, TrajectoryStateHistoryMetadataKey.ORB_AVERAGING.name());
  143.         }
  144.         if (trajUnits != null) {
  145.             Unit.ensureCompatible(trajType.toString(), trajType.getUnits(), false, trajUnits);
  146.         }
  147.     }

  148.     /** Increments a trajectory ID.
  149.      * <p>
  150.      * The trajectory blocks metadata contains three identifiers ({@code TRAJ_ID},
  151.      * {@code TRAJ_PREV_ID}, {@code TRAJ_NEXT_ID}) that link the various blocks together.
  152.      * This helper method allows to update one identifier based on the value of another
  153.      * identifier. The update is performed by looking for an integer suffix at the end
  154.      * of the {@code original} identifier and incrementing it by one, taking care to use
  155.      * at least the same number of digits. If for example the original identifier is set
  156.      * to {@code trajectory 037}, then the updated identifier will be {@code trajectory 038}.
  157.      * </p>
  158.      * <p>
  159.      * This helper function is intended to be used by ephemeris generators like {@link EphemerisOcmWriter}
  160.      * and {@link StreamingOcmWriter}, allowing users to call only {@link #setTrajBasisID(String)}
  161.      * in the trajectory metadata template. The ephemeris generators call {@code
  162.      * template.setTrajNextID(TrajectoryStateHistoryMetadata.incrementTrajID(template.getTrajID()))}
  163.      * before generating each trajectory block and call both {@code template.setTrajPrevID(template.getTrajID()))}
  164.      * and {@code template.setTrajID(template.getTrajNextID()))} after having generated each block.
  165.      * </p>
  166.      * @param original original ID (may be null)
  167.      * @return incremented ID, or null if original was null
  168.      */
  169.     public static String incrementTrajID(final String original) {

  170.         if (original == null) {
  171.             // no trajectory ID at all
  172.             return null;
  173.         }

  174.         // split the ID into prefix and numerical index
  175.         int end = original.length();
  176.         while (end > 0 && Character.isDigit(original.charAt(end - 1))) {
  177.             --end;
  178.         }
  179.         final String prefix   = original.substring(0, end);
  180.         final int    index    = end < original.length() ? Integer.parseInt(original.substring(end)) : 0;

  181.         // build offset index, taking care to use at least the same number of digits
  182.         final String newIndex = String.format(String.format("%%0%dd", original.length() - end),
  183.                                               index + 1);

  184.         return prefix + newIndex;

  185.     }

  186.     /** Get trajectory identification number.
  187.      * @return trajectory identification number
  188.      */
  189.     public String getTrajID() {
  190.         return trajID;
  191.     }

  192.     /** Set trajectory identification number.
  193.      * @param trajID trajectory identification number
  194.      */
  195.     public void setTrajID(final String trajID) {
  196.         refuseFurtherComments();
  197.         this.trajID = trajID;
  198.     }

  199.     /** Get identification number of previous trajectory.
  200.      * @return identification number of previous trajectory
  201.      */
  202.     public String getTrajPrevID() {
  203.         return trajPrevID;
  204.     }

  205.     /** Set identification number of previous trajectory.
  206.      * @param trajPrevID identification number of previous trajectory
  207.      */
  208.     public void setTrajPrevID(final String trajPrevID) {
  209.         refuseFurtherComments();
  210.         this.trajPrevID = trajPrevID;
  211.     }

  212.     /** Get identification number of next trajectory.
  213.      * @return identification number of next trajectory
  214.      */
  215.     public String getTrajNextID() {
  216.         return trajNextID;
  217.     }

  218.     /** Set identification number of next trajectory.
  219.      * @param trajNextID identification number of next trajectory
  220.      */
  221.     public void setTrajNextID(final String trajNextID) {
  222.         refuseFurtherComments();
  223.         this.trajNextID = trajNextID;
  224.     }

  225.     /** Get basis of this trajectory state time history data.
  226.      * @return basis of this trajectory state time history data
  227.      */
  228.     public String getTrajBasis() {
  229.         return trajBasis;
  230.     }

  231.     /** Set basis of this trajectory state time history data.
  232.      * @param trajBasis basis of this trajectory state time history data
  233.      */
  234.     public void setTrajBasis(final String trajBasis) {
  235.         refuseFurtherComments();
  236.         this.trajBasis = trajBasis;
  237.     }

  238.     /** Get identification number of the orbit determination or simulation upon which this trajectory is based.
  239.      * @return identification number of the orbit determination or simulation upon which this trajectory is based
  240.      */
  241.     public String getTrajBasisID() {
  242.         return trajBasisID;
  243.     }

  244.     /** Set identification number of the orbit determination or simulation upon which this trajectory is based.
  245.      * @param trajBasisID identification number of the orbit determination or simulation upon which this trajectory is based
  246.      */
  247.     public void setTrajBasisID(final String trajBasisID) {
  248.         refuseFurtherComments();
  249.         this.trajBasisID = trajBasisID;
  250.     }

  251.     /** Get the interpolation method to be used.
  252.      * @return the interpolation method
  253.      */
  254.     public InterpolationMethod getInterpolationMethod() {
  255.         return interpolationMethod;
  256.     }

  257.     /** Set the interpolation method to be used.
  258.      * @param interpolationMethod the interpolation method to be set
  259.      */
  260.     public void setInterpolationMethod(final InterpolationMethod interpolationMethod) {
  261.         refuseFurtherComments();
  262.         this.interpolationMethod = interpolationMethod;
  263.     }

  264.     /** Get the interpolation degree.
  265.      * @return the interpolation degree
  266.      */
  267.     public int getInterpolationDegree() {
  268.         return interpolationDegree;
  269.     }

  270.     /** Set the interpolation degree.
  271.      * @param interpolationDegree the interpolation degree to be set
  272.      */
  273.     public void setInterpolationDegree(final int interpolationDegree) {
  274.         refuseFurtherComments();
  275.         this.interpolationDegree = interpolationDegree;
  276.     }

  277.     /** Get the orbit propagator used to generate this trajectory.
  278.      * @return orbit propagator used to generate this trajectory
  279.      * @since 11.2
  280.      */
  281.     public String getPropagator() {
  282.         return propagator;
  283.     }

  284.     /** Set the orbit propagator used to generate this trajectory.
  285.      * @param propagator orbit propagator used to generate this trajectory
  286.      * @since 11.2
  287.      */
  288.     public void setPropagator(final String propagator) {
  289.         refuseFurtherComments();
  290.         this.propagator = propagator;
  291.     }

  292.     /** Get the origin of reference frame.
  293.      * @return the origin of reference frame.
  294.      */
  295.     public BodyFacade getCenter() {
  296.         return center;
  297.     }

  298.     /** Set the origin of reference frame.
  299.      * @param center origin of reference frame to be set
  300.      */
  301.     public void setCenter(final BodyFacade center) {
  302.         refuseFurtherComments();
  303.         this.center = center;
  304.     }

  305.     /** Get reference frame of the trajectory.
  306.      * @return reference frame of the trajectory
  307.      */
  308.     public FrameFacade getTrajReferenceFrame() {
  309.         return trajReferenceFrame;
  310.     }

  311.     /** Set reference frame of the trajectory.
  312.      * @param trajReferenceFrame the reference frame to be set
  313.      */
  314.     public void setTrajReferenceFrame(final FrameFacade trajReferenceFrame) {
  315.         refuseFurtherComments();
  316.         this.trajReferenceFrame = trajReferenceFrame;
  317.     }

  318.     /** Get epoch of the {@link #getTrajReferenceFrame() trajectory reference frame}.
  319.      * @return epoch of the {@link #getTrajReferenceFrame() trajectory reference frame}
  320.      */
  321.     public AbsoluteDate getTrajFrameEpoch() {
  322.         return trajFrameEpoch;
  323.     }

  324.     /** Set epoch of the {@link #getTrajReferenceFrame() trajectory reference frame}.
  325.      * @param trajFrameEpoch epoch of the {@link #getTrajReferenceFrame() trajectory reference frame}
  326.      */
  327.     public void setTrajFrameEpoch(final AbsoluteDate trajFrameEpoch) {
  328.         refuseFurtherComments();
  329.         this.trajFrameEpoch = trajFrameEpoch;
  330.     }

  331.     /** Get start of useable time span covered by ephemerides data, it may be
  332.      * necessary to allow for proper interpolation.
  333.      * @return the useable start time
  334.      */
  335.     public AbsoluteDate getUseableStartTime() {
  336.         return useableStartTime;
  337.     }

  338.     /** Set start of useable time span covered by ephemerides data, it may be
  339.      * necessary to allow for proper interpolation.
  340.      * @param useableStartTime the time to be set
  341.      */
  342.     public void setUseableStartTime(final AbsoluteDate useableStartTime) {
  343.         refuseFurtherComments();
  344.         this.useableStartTime = useableStartTime;
  345.     }

  346.     /** Get end of useable time span covered by ephemerides data, it may be
  347.      * necessary to allow for proper interpolation.
  348.      * @return the useable stop time
  349.      */
  350.     public AbsoluteDate getUseableStopTime() {
  351.         return useableStopTime;
  352.     }

  353.     /** Set end of useable time span covered by ephemerides data, it may be
  354.      * necessary to allow for proper interpolation.
  355.      * @param useableStopTime the time to be set
  356.      */
  357.     public void setUseableStopTime(final AbsoluteDate useableStopTime) {
  358.         refuseFurtherComments();
  359.         this.useableStopTime = useableStopTime;
  360.     }

  361.     /** Get the integer orbit revolution number.
  362.      * @return integer orbit revolution number (-1 if not set)
  363.      */
  364.     public int getOrbRevNum() {
  365.         return orbRevNum;
  366.     }

  367.     /** Set the integer orbit revolution number.
  368.      * @param orbRevNum integer orbit revolution number
  369.      */
  370.     public void setOrbRevNum(final int orbRevNum) {
  371.         this.orbRevNum = orbRevNum;
  372.     }

  373.     /** Get the basis for orbit revolution number.
  374.      * <p>
  375.      * This specifies if first launch/deployment is on orbit 0 or 1.
  376.      * </p>
  377.      * @return basis for orbit revolution number (-1 if not set)
  378.      */
  379.     public int getOrbRevNumBasis() {
  380.         return orbRevNumBasis;
  381.     }

  382.     /** Set the basis for orbit revolution number.
  383.      * <p>
  384.      * This specifies if first launch/deployment is on orbit 0 or 1.
  385.      * </p>
  386.      * @param orbRevNumBasis basis for orbit revolution number
  387.      */
  388.     public void setOrbRevNumBasis(final int orbRevNumBasis) {
  389.         this.orbRevNumBasis = orbRevNumBasis;
  390.     }

  391.     /** Get type of averaging (Osculating, mean Brouwer, other.
  392.      * @return type of averaging (Osculating, mean Brouwer, other)
  393.      */
  394.     public String getOrbAveraging() {
  395.         return orbAveraging;
  396.     }

  397.     /** Set type of averaging (Osculating, mean Brouwer, other.
  398.      * @param orbAveraging type of averaging (Osculating, mean Brouwer, other).
  399.      */
  400.     public void setOrbAveraging(final String orbAveraging) {
  401.         refuseFurtherComments();
  402.         this.orbAveraging = orbAveraging;
  403.     }

  404.     /** Get trajectory element set type.
  405.      * @return trajectory element set type
  406.      */
  407.     public OrbitElementsType getTrajType() {
  408.         return trajType;
  409.     }

  410.     /** Set trajectory element set type.
  411.      * @param trajType trajectory element set type
  412.      */
  413.     public void setTrajType(final OrbitElementsType trajType) {
  414.         refuseFurtherComments();
  415.         this.trajType = trajType;
  416.     }

  417.     /** Get trajectory element set units.
  418.      * @return trajectory element set units
  419.      */
  420.     public List<Unit> getTrajUnits() {
  421.         return trajUnits;
  422.     }

  423.     /** Set trajectory element set units.
  424.      * @param trajUnits trajectory element set units
  425.      */
  426.     public void setTrajUnits(final List<Unit> trajUnits) {
  427.         refuseFurtherComments();
  428.         this.trajUnits = trajUnits;
  429.     }

  430.     /** Copy the instance, making sure mandatory fields have been initialized.
  431.      * <p>
  432.      * Dates and orbit counter are not copied.
  433.      * </p>
  434.      * @param version format version
  435.      * @return a new copy
  436.      * @since 12.0
  437.      */
  438.     public TrajectoryStateHistoryMetadata copy(final double version) {

  439.         checkMandatoryEntriesExceptOrbitsCounter(version);

  440.         // allocate new instance
  441.         final TrajectoryStateHistoryMetadata copy = new TrajectoryStateHistoryMetadata(trajFrameEpoch, dataContext);

  442.         // copy comments
  443.         for (String comment : getComments()) {
  444.             copy.addComment(comment);
  445.         }

  446.         // copy metadata
  447.         copy.setTrajPrevID(getTrajPrevID());
  448.         copy.setTrajID(getTrajID());
  449.         copy.setTrajNextID(getTrajNextID());
  450.         copy.setTrajBasis(getTrajBasis());
  451.         copy.setTrajBasisID(getTrajBasisID());
  452.         copy.setInterpolationMethod(getInterpolationMethod());
  453.         copy.setInterpolationDegree(getInterpolationDegree());
  454.         copy.setPropagator(getPropagator());
  455.         copy.setCenter(getCenter());
  456.         copy.setTrajReferenceFrame(getTrajReferenceFrame());
  457.         copy.setTrajFrameEpoch(getTrajFrameEpoch());
  458.         copy.setOrbRevNumBasis(getOrbRevNumBasis());
  459.         copy.setOrbAveraging(getOrbAveraging());
  460.         copy.setTrajType(getTrajType());
  461.         copy.setTrajUnits(getTrajUnits());

  462.         return copy;

  463.     }

  464. }