TrajectoryStateHistoryMetadata.java

  1. /* Copyright 2002-2024 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.  * @author Luc Maisonobe
  31.  * @since 11.0
  32.  */
  33. public class TrajectoryStateHistoryMetadata extends CommentsContainer {

  34.     /** Default interpolation method.
  35.      * @since 12.0
  36.      */
  37.     public static final InterpolationMethod DEFAULT_INTERPOLATION_METHOD = InterpolationMethod.HERMITE;

  38.     /** Default interpolation degree.
  39.      * @since 12.0
  40.      */
  41.     public static final int DEFAULT_INTERPOLATION_DEGREE = 3;

  42.     /** Trajectory identification number. */
  43.     private String trajID;

  44.     /** Identification number of previous trajectory. */
  45.     private String trajPrevID;

  46.     /** Identification number of next trajectory. */
  47.     private String trajNextID;

  48.     /** Basis of this trajectory state time history data. */
  49.     private String trajBasis;

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

  52.     /** Interpolation method. */
  53.     private InterpolationMethod interpolationMethod;

  54.     /** Interpolation degree. */
  55.     private int interpolationDegree;

  56.     /** Orbit propagator used to generate this trajectory.
  57.      * @since 11.2
  58.      */
  59.     private String propagator;

  60.     /** Origin of reference frame. */
  61.     private BodyFacade center;

  62.     /** Reference frame of the trajectory. */
  63.     private FrameFacade trajReferenceFrame;

  64.     /** Epoch of the trajectory reference frame. */
  65.     private AbsoluteDate trajFrameEpoch;

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

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

  72.     /** Integer orbit revolution number. */
  73.     private int orbRevNum;

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

  76.     /** Trajectory element set type. */
  77.     private OrbitElementsType trajType;

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

  80.     /** Units of trajectory element set. */
  81.     private List<Unit> trajUnits;

  82.     /** Data context.
  83.      * @since 12.0
  84.      */
  85.     private final DataContext dataContext;

  86.     /** Simple constructor.
  87.      * @param epochT0 T0 epoch from file metadata
  88.      * @param dataContext data context
  89.      */
  90.     public TrajectoryStateHistoryMetadata(final AbsoluteDate epochT0, final DataContext dataContext) {
  91.         // we don't call the setXxx() methods in order to avoid
  92.         // calling refuseFurtherComments as a side effect
  93.         trajBasis           = "PREDICTED";
  94.         interpolationMethod = DEFAULT_INTERPOLATION_METHOD;
  95.         interpolationDegree = DEFAULT_INTERPOLATION_DEGREE;
  96.         orbAveraging        = "OSCULATING";
  97.         center              = new BodyFacade("EARTH",
  98.                                              dataContext.getCelestialBodies().getEarth());
  99.         trajReferenceFrame  = new FrameFacade(dataContext.getFrames().getICRF(),
  100.                                               CelestialBodyFrame.ICRF, null, null,
  101.                                               CelestialBodyFrame.ICRF.name());
  102.         trajFrameEpoch      = epochT0;
  103.         trajType            = OrbitElementsType.CARTPV;
  104.         orbRevNum           = -1;
  105.         orbRevNumBasis      = -1;

  106.         this.dataContext    = dataContext;

  107.     }

  108.     /** {@inheritDoc} */
  109.     @Override
  110.     public void validate(final double version) {
  111.         checkMandatoryEntriesExceptOrbitsCounter(version);
  112.         if (orbRevNum >= 0 && orbRevNumBasis < 0) {
  113.             throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY,
  114.                                       TrajectoryStateHistoryMetadataKey.ORB_REVNUM_BASIS.name());
  115.         }
  116.     }

  117.     /** Check is mandatory entries EXCEPT orbits counters have been initialized.
  118.      * <p>
  119.      * This method should throw an exception if some mandatory entry is missing
  120.      * </p>
  121.      * @param version format version
  122.      */
  123.     private void checkMandatoryEntriesExceptOrbitsCounter(final double version) {
  124.         super.validate(version);
  125.         if (trajType != OrbitElementsType.CARTP   &&
  126.             trajType != OrbitElementsType.CARTPV  &&
  127.             trajType != OrbitElementsType.CARTPVA) {
  128.             checkNotNull(orbAveraging, TrajectoryStateHistoryMetadataKey.ORB_AVERAGING.name());
  129.         }
  130.         if (trajUnits != null) {
  131.             Unit.ensureCompatible(trajType.toString(), trajType.getUnits(), false, trajUnits);
  132.         }
  133.     }

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

  156.         if (original == null) {
  157.             // no trajectory ID at all
  158.             return null;
  159.         }

  160.         // split the ID into prefix and numerical index
  161.         int end = original.length();
  162.         while (end > 0 && Character.isDigit(original.charAt(end - 1))) {
  163.             --end;
  164.         }
  165.         final String prefix   = original.substring(0, end);
  166.         final int    index    = end < original.length() ? Integer.parseInt(original.substring(end)) : 0;

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

  170.         return prefix + newIndex;

  171.     }

  172.     /** Get trajectory identification number.
  173.      * @return trajectory identification number
  174.      */
  175.     public String getTrajID() {
  176.         return trajID;
  177.     }

  178.     /** Set trajectory identification number.
  179.      * @param trajID trajectory identification number
  180.      */
  181.     public void setTrajID(final String trajID) {
  182.         refuseFurtherComments();
  183.         this.trajID = trajID;
  184.     }

  185.     /** Get identification number of previous trajectory.
  186.      * @return identification number of previous trajectory
  187.      */
  188.     public String getTrajPrevID() {
  189.         return trajPrevID;
  190.     }

  191.     /** Set identification number of previous trajectory.
  192.      * @param trajPrevID identification number of previous trajectory
  193.      */
  194.     public void setTrajPrevID(final String trajPrevID) {
  195.         refuseFurtherComments();
  196.         this.trajPrevID = trajPrevID;
  197.     }

  198.     /** Get identification number of next trajectory.
  199.      * @return identification number of next trajectory
  200.      */
  201.     public String getTrajNextID() {
  202.         return trajNextID;
  203.     }

  204.     /** Set identification number of next trajectory.
  205.      * @param trajNextID identification number of next trajectory
  206.      */
  207.     public void setTrajNextID(final String trajNextID) {
  208.         refuseFurtherComments();
  209.         this.trajNextID = trajNextID;
  210.     }

  211.     /** Get basis of this trajectory state time history data.
  212.      * @return basis of this trajectory state time history data
  213.      */
  214.     public String getTrajBasis() {
  215.         return trajBasis;
  216.     }

  217.     /** Set basis of this trajectory state time history data.
  218.      * @param trajBasis basis of this trajectory state time history data
  219.      */
  220.     public void setTrajBasis(final String trajBasis) {
  221.         refuseFurtherComments();
  222.         this.trajBasis = trajBasis;
  223.     }

  224.     /** Get identification number of the orbit determination or simulation upon which this trajectory is based.
  225.      * @return identification number of the orbit determination or simulation upon which this trajectory is based
  226.      */
  227.     public String getTrajBasisID() {
  228.         return trajBasisID;
  229.     }

  230.     /** Set identification number of the orbit determination or simulation upon which this trajectory is based.
  231.      * @param trajBasisID identification number of the orbit determination or simulation upon which this trajectory is based
  232.      */
  233.     public void setTrajBasisID(final String trajBasisID) {
  234.         refuseFurtherComments();
  235.         this.trajBasisID = trajBasisID;
  236.     }

  237.     /** Get the interpolation method to be used.
  238.      * @return the interpolation method
  239.      */
  240.     public InterpolationMethod getInterpolationMethod() {
  241.         return interpolationMethod;
  242.     }

  243.     /** Set the interpolation method to be used.
  244.      * @param interpolationMethod the interpolation method to be set
  245.      */
  246.     public void setInterpolationMethod(final InterpolationMethod interpolationMethod) {
  247.         refuseFurtherComments();
  248.         this.interpolationMethod = interpolationMethod;
  249.     }

  250.     /** Get the interpolation degree.
  251.      * @return the interpolation degree
  252.      */
  253.     public int getInterpolationDegree() {
  254.         return interpolationDegree;
  255.     }

  256.     /** Set the interpolation degree.
  257.      * @param interpolationDegree the interpolation degree to be set
  258.      */
  259.     public void setInterpolationDegree(final int interpolationDegree) {
  260.         refuseFurtherComments();
  261.         this.interpolationDegree = interpolationDegree;
  262.     }

  263.     /** Get the orbit propagator used to generate this trajectory.
  264.      * @return orbit propagator used to generate this trajectory
  265.      * @since 11.2
  266.      */
  267.     public String getPropagator() {
  268.         return propagator;
  269.     }

  270.     /** Set the orbit propagator used to generate this trajectory.
  271.      * @param propagator orbit propagator used to generate this trajectory
  272.      * @since 11.2
  273.      */
  274.     public void setPropagator(final String propagator) {
  275.         refuseFurtherComments();
  276.         this.propagator = propagator;
  277.     }

  278.     /** Get the origin of reference frame.
  279.      * @return the origin of reference frame.
  280.      */
  281.     public BodyFacade getCenter() {
  282.         return center;
  283.     }

  284.     /** Set the origin of reference frame.
  285.      * @param center origin of reference frame to be set
  286.      */
  287.     public void setCenter(final BodyFacade center) {
  288.         refuseFurtherComments();
  289.         this.center = center;
  290.     }

  291.     /** Get reference frame of the trajectory.
  292.      * @return reference frame of the trajectory
  293.      */
  294.     public FrameFacade getTrajReferenceFrame() {
  295.         return trajReferenceFrame;
  296.     }

  297.     /** Set reference frame of the trajectory.
  298.      * @param trajReferenceFrame the reference frame to be set
  299.      */
  300.     public void setTrajReferenceFrame(final FrameFacade trajReferenceFrame) {
  301.         refuseFurtherComments();
  302.         this.trajReferenceFrame = trajReferenceFrame;
  303.     }

  304.     /** Get epoch of the {@link #getTrajReferenceFrame() trajectory reference frame}.
  305.      * @return epoch of the {@link #getTrajReferenceFrame() trajectory reference frame}
  306.      */
  307.     public AbsoluteDate getTrajFrameEpoch() {
  308.         return trajFrameEpoch;
  309.     }

  310.     /** Set epoch of the {@link #getTrajReferenceFrame() trajectory reference frame}.
  311.      * @param trajFrameEpoch epoch of the {@link #getTrajReferenceFrame() trajectory reference frame}
  312.      */
  313.     public void setTrajFrameEpoch(final AbsoluteDate trajFrameEpoch) {
  314.         refuseFurtherComments();
  315.         this.trajFrameEpoch = trajFrameEpoch;
  316.     }

  317.     /** Get start of useable time span covered by ephemerides data, it may be
  318.      * necessary to allow for proper interpolation.
  319.      * @return the useable start time
  320.      */
  321.     public AbsoluteDate getUseableStartTime() {
  322.         return useableStartTime;
  323.     }

  324.     /** Set start of useable time span covered by ephemerides data, it may be
  325.      * necessary to allow for proper interpolation.
  326.      * @param useableStartTime the time to be set
  327.      */
  328.     public void setUseableStartTime(final AbsoluteDate useableStartTime) {
  329.         refuseFurtherComments();
  330.         this.useableStartTime = useableStartTime;
  331.     }

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

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

  347.     /** Get the integer orbit revolution number.
  348.      * @return integer orbit revolution number (-1 if not set)
  349.      */
  350.     public int getOrbRevNum() {
  351.         return orbRevNum;
  352.     }

  353.     /** Set the integer orbit revolution number.
  354.      * @param orbRevNum integer orbit revolution number
  355.      */
  356.     public void setOrbRevNum(final int orbRevNum) {
  357.         this.orbRevNum = orbRevNum;
  358.     }

  359.     /** Get the basis for orbit revolution number.
  360.      * <p>
  361.      * This specifies if first launch/deployment is on orbit 0 or 1.
  362.      * </p>
  363.      * @return basis for orbit revolution number (-1 if not set)
  364.      */
  365.     public int getOrbRevNumBasis() {
  366.         return orbRevNumBasis;
  367.     }

  368.     /** Set the basis for orbit revolution number.
  369.      * <p>
  370.      * This specifies if first launch/deployment is on orbit 0 or 1.
  371.      * </p>
  372.      * @param orbRevNumBasis basis for orbit revolution number
  373.      */
  374.     public void setOrbRevNumBasis(final int orbRevNumBasis) {
  375.         this.orbRevNumBasis = orbRevNumBasis;
  376.     }

  377.     /** Get type of averaging (Osculating, mean Brouwer, other.
  378.      * @return type of averaging (Osculating, mean Brouwer, other)
  379.      */
  380.     public String getOrbAveraging() {
  381.         return orbAveraging;
  382.     }

  383.     /** Set type of averaging (Osculating, mean Brouwer, other.
  384.      * @param orbAveraging type of averaging (Osculating, mean Brouwer, other).
  385.      */
  386.     public void setOrbAveraging(final String orbAveraging) {
  387.         refuseFurtherComments();
  388.         this.orbAveraging = orbAveraging;
  389.     }

  390.     /** Get trajectory element set type.
  391.      * @return trajectory element set type
  392.      */
  393.     public OrbitElementsType getTrajType() {
  394.         return trajType;
  395.     }

  396.     /** Set trajectory element set type.
  397.      * @param trajType trajectory element set type
  398.      */
  399.     public void setTrajType(final OrbitElementsType trajType) {
  400.         refuseFurtherComments();
  401.         this.trajType = trajType;
  402.     }

  403.     /** Get trajectory element set units.
  404.      * @return trajectory element set units
  405.      */
  406.     public List<Unit> getTrajUnits() {
  407.         return trajUnits;
  408.     }

  409.     /** Set trajectory element set units.
  410.      * @param trajUnits trajectory element set units
  411.      */
  412.     public void setTrajUnits(final List<Unit> trajUnits) {
  413.         refuseFurtherComments();
  414.         this.trajUnits = trajUnits;
  415.     }

  416.     /** Copy the instance, making sure mandatory fields have been initialized.
  417.      * <p>
  418.      * Dates and orbit counter are not copied.
  419.      * </p>
  420.      * @param version format version
  421.      * @return a new copy
  422.      * @since 12.0
  423.      */
  424.     public TrajectoryStateHistoryMetadata copy(final double version) {

  425.         checkMandatoryEntriesExceptOrbitsCounter(version);

  426.         // allocate new instance
  427.         final TrajectoryStateHistoryMetadata copy = new TrajectoryStateHistoryMetadata(trajFrameEpoch, dataContext);

  428.         // copy comments
  429.         for (String comment : getComments()) {
  430.             copy.addComment(comment);
  431.         }

  432.         // copy metadata
  433.         copy.setTrajPrevID(getTrajPrevID());
  434.         copy.setTrajID(getTrajID());
  435.         copy.setTrajNextID(getTrajNextID());
  436.         copy.setTrajBasis(getTrajBasis());
  437.         copy.setTrajBasisID(getTrajBasisID());
  438.         copy.setInterpolationMethod(getInterpolationMethod());
  439.         copy.setInterpolationDegree(getInterpolationDegree());
  440.         copy.setPropagator(getPropagator());
  441.         copy.setCenter(getCenter());
  442.         copy.setTrajReferenceFrame(getTrajReferenceFrame());
  443.         copy.setTrajFrameEpoch(getTrajFrameEpoch());
  444.         copy.setOrbRevNumBasis(getOrbRevNumBasis());
  445.         copy.setOrbAveraging(getOrbAveraging());
  446.         copy.setTrajType(getTrajType());
  447.         copy.setTrajUnits(getTrajUnits());

  448.         return copy;

  449.     }

  450. }