OEMWriter.java

  1. /* Copyright 2016 Applied Defense Solutions (ADS)
  2.  * Licensed to CS Systèmes d'Information (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.  * ADS 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;

  18. import java.io.IOException;
  19. import java.util.LinkedHashMap;
  20. import java.util.List;
  21. import java.util.Map;

  22. import org.orekit.errors.OrekitException;
  23. import org.orekit.errors.OrekitIllegalArgumentException;
  24. import org.orekit.errors.OrekitMessages;
  25. import org.orekit.files.ccsds.StreamingOemWriter.Segment;
  26. import org.orekit.files.general.EphemerisFile;
  27. import org.orekit.files.general.EphemerisFile.EphemerisSegment;
  28. import org.orekit.files.general.EphemerisFileWriter;
  29. import org.orekit.time.TimeScale;
  30. import org.orekit.utils.TimeStampedPVCoordinates;

  31. /**
  32.  * An OEM Writer class that can take in a general {@link EphemerisFile} object
  33.  * and export it as a valid OEM file.
  34.  *
  35.  * @author Hank Grabowski
  36.  * @author Evan Ward
  37.  * @since 9.0
  38.  * @see <a href="https://public.ccsds.org/Pubs/502x0b2c1.pdf">CCSDS 502.0-B-2 Orbit Data
  39.  *      Messages</a>
  40.  * @see <a href="https://public.ccsds.org/Pubs/500x0g3.pdf">CCSDS 500.0-G-3 Navigation
  41.  *      Data Definitions and Conventions</a>
  42.  * @see StreamingOemWriter
  43.  */
  44. public class OEMWriter implements EphemerisFileWriter {

  45.     /** Version number implemented. **/
  46.     public static final String CCSDS_OEM_VERS = "2.0";

  47.     /** Default interpolation method if the user specifies none. **/
  48.     public static final InterpolationMethod DEFAULT_INTERPOLATION_METHOD = InterpolationMethod.LAGRANGE;

  49.     /** Default originator field value if user specifies none. **/
  50.     public static final String DEFAULT_ORIGINATOR = "OREKIT";

  51.     /**
  52.      * The space object ID we want to export, or null if we will process
  53.      * whichever space object is in an {@link EphemerisFile} with only one space
  54.      * object in it.
  55.      */
  56.     private final InterpolationMethod interpolationMethod;

  57.     /** Originator name, usually the organization and/or country. **/
  58.     private final String originator;

  59.     /**
  60.      * Space object ID, usually an official international designator such as
  61.      * "1998-067A".
  62.      **/
  63.     private final String spaceObjectId;

  64.     /** Space object name, usually a common name for an object like "ISS". **/
  65.     private final String spaceObjectName;

  66.     /**
  67.      * Standard default constructor that creates a writer with default
  68.      * configurations.
  69.      */
  70.     public OEMWriter() {
  71.         this(DEFAULT_INTERPOLATION_METHOD, DEFAULT_ORIGINATOR, null, null);
  72.     }

  73.     /**
  74.      * Constructor used to create a new OEM writer configured with the necessary
  75.      * parameters to successfully fill in all required fields that aren't part
  76.      * of a standard @{link EphemerisFile} object.
  77.      *
  78.      * @param interpolationMethod
  79.      *            The interpolation method to specify in the OEM file
  80.      * @param originator
  81.      *            The originator field string
  82.      * @param spaceObjectId
  83.      *            The spacecraft ID
  84.      * @param spaceObjectName
  85.      *            The space object common name
  86.      */
  87.     public OEMWriter(final InterpolationMethod interpolationMethod, final String originator, final String spaceObjectId,
  88.             final String spaceObjectName) {
  89.         this.interpolationMethod = interpolationMethod;
  90.         this.originator = originator;
  91.         this.spaceObjectId = spaceObjectId;
  92.         this.spaceObjectName = spaceObjectName;
  93.     }

  94.     /** {@inheritDoc} */
  95.     @Override
  96.     public void write(final Appendable writer, final EphemerisFile ephemerisFile)
  97.             throws OrekitException, IOException {

  98.         if (writer == null) {
  99.             throw new OrekitIllegalArgumentException(OrekitMessages.NULL_ARGUMENT, "writer");
  100.         }

  101.         if (ephemerisFile == null) {
  102.             return;
  103.         }

  104.         final String idToProcess;
  105.         if (spaceObjectId != null) {
  106.             if (ephemerisFile.getSatellites().containsKey(spaceObjectId)) {
  107.                 idToProcess = spaceObjectId;
  108.             } else {
  109.                 throw new OrekitIllegalArgumentException(OrekitMessages.VALUE_NOT_FOUND, spaceObjectId, "ephemerisFile");
  110.             }
  111.         } else if (ephemerisFile.getSatellites().keySet().size() == 1) {
  112.             idToProcess = ephemerisFile.getSatellites().keySet().iterator().next();
  113.         } else {
  114.             throw new OrekitIllegalArgumentException(OrekitMessages.EPHEMERIS_FILE_NO_MULTI_SUPPORT);
  115.         }

  116.         // Get satellite and ephemeris segments to output.
  117.         final EphemerisFile.SatelliteEphemeris satEphem = ephemerisFile.getSatellites().get(idToProcess);
  118.         final List<? extends EphemerisSegment> segments = satEphem.getSegments();
  119.         if (segments.isEmpty()) {
  120.             // no data -> no output
  121.             return;
  122.         }
  123.         final EphemerisSegment firstSegment = segments.get(0);

  124.         final String objectName = this.spaceObjectName == null ?
  125.                 idToProcess : this.spaceObjectName;
  126.         // Only one time scale per OEM file, see Section 5.2.4.5
  127.         final TimeScale timeScale = firstSegment.getTimeScale();
  128.         // metadata that is constant for the whole OEM file
  129.         final Map<Keyword, String> metadata = new LinkedHashMap<>();
  130.         metadata.put(Keyword.TIME_SYSTEM, firstSegment.getTimeScaleString());
  131.         metadata.put(Keyword.ORIGINATOR, this.originator);
  132.         // Only one object in an OEM file, see Section 2.1
  133.         metadata.put(Keyword.OBJECT_ID, idToProcess);
  134.         metadata.put(Keyword.OBJECT_NAME, objectName);
  135.         metadata.put(Keyword.INTERPOLATION, this.interpolationMethod.toString());
  136.         final StreamingOemWriter oemWriter =
  137.                 new StreamingOemWriter(writer, timeScale, metadata);
  138.         oemWriter.writeHeader();

  139.         for (final EphemerisSegment segment : segments) {
  140.             // segment specific metadata
  141.             metadata.clear();
  142.             metadata.put(Keyword.CENTER_NAME, segment.getFrameCenterString());
  143.             metadata.put(Keyword.REF_FRAME, segment.getFrameString());
  144.             metadata.put(Keyword.START_TIME, segment.getStart().toString(timeScale));
  145.             metadata.put(Keyword.STOP_TIME, segment.getStop().toString(timeScale));
  146.             metadata.put(Keyword.INTERPOLATION_DEGREE,
  147.                     String.valueOf(segment.getInterpolationSamples() - 1));
  148.             final Segment segmentWriter = oemWriter.newSegment(null, metadata);
  149.             segmentWriter.writeMetadata();
  150.             for (final TimeStampedPVCoordinates coordinates : segment.getCoordinates()) {
  151.                 segmentWriter.writeEphemerisLine(coordinates);
  152.             }
  153.         }
  154.     }

  155.     /** OEM interpolation method. See Table 5-3. */
  156.     public enum InterpolationMethod {
  157.         /** Hermite interpolation. */
  158.         HERMITE,
  159.         /** Lagrange interpolation. */
  160.         LAGRANGE,
  161.         /** Linear interpolation. */
  162.         LINEAR
  163.     }

  164. }