1   /* Copyright 2002-2023 Andrew Goetz
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.stk;
18  
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Locale;
24  import java.util.Map;
25  import java.util.Objects;
26  
27  import org.orekit.errors.OrekitException;
28  import org.orekit.errors.OrekitMessages;
29  import org.orekit.files.general.EphemerisFile;
30  import org.orekit.files.stk.STKEphemerisFile.STKEphemerisSegment;
31  import org.orekit.frames.Frame;
32  import org.orekit.time.AbsoluteDate;
33  import org.orekit.utils.CartesianDerivativesFilter;
34  import org.orekit.utils.TimeStampedPVCoordinates;
35  
36  /**
37   * STK ephemeris file.
38   *
39   * @author Andrew Goetz
40   * @since 12.0
41   */
42  public class STKEphemerisFile implements EphemerisFile<TimeStampedPVCoordinates, STKEphemerisSegment> {
43  
44      /** STK version. */
45      private final String stkVersion;
46  
47      /** Unmodifiable mapping with a single key-value pair from satellite id to ephemeris. */
48      private final Map<String, STKEphemeris> satellites;
49  
50      /**
51       * Constructs a {@link STKEphemerisFile} instance.
52       * @param stkVersion STK version string (example: "stk.v.11.0")
53       * @param satelliteId satellite id
54       * @param ephemeris ephemeris
55       */
56      public STKEphemerisFile(final String stkVersion, final String satelliteId, final STKEphemeris ephemeris) {
57          this.stkVersion = Objects.requireNonNull(stkVersion);
58          final Map<String, STKEphemeris> tempMap = new HashMap<>();
59          tempMap.put(satelliteId, ephemeris);
60          this.satellites = Collections.unmodifiableMap(tempMap);
61      }
62  
63      /**
64       * Returns the STK version string.
65       * @return STK version string
66       */
67      public String getSTKVersion() {
68          return stkVersion;
69      }
70  
71      /**
72       * {@inheritDoc}
73       * <p>
74       * STK ephemeris files define ephemeris for a single satellite, so the returned
75       * map will have a single entry.
76       * </p>
77       */
78      @Override
79      public Map<String, STKEphemeris> getSatellites() {
80          return satellites;
81      }
82  
83      /**
84       * Ephemeris segment from an STK ephemeris file.
85       */
86      public static class STKEphemerisSegment implements EphemerisFile.EphemerisSegment<TimeStampedPVCoordinates> {
87  
88          /** Gravitational parameter (m^3/s^2). */
89          private final double mu;
90  
91          /** Reference frame. */
92          private final Frame frame;
93  
94          /** Number of samples to use in interpolation. */
95          private final int interpolationSamples;
96  
97          /** Cartesian derivatives filter. */
98          private final CartesianDerivativesFilter cartesianDerivativesFilter;
99  
100         /** Time-sorted time/position/velocity data. */
101         private final List<TimeStampedPVCoordinates> timeStampedPVCoordinates;
102 
103         /**
104          * Constructs a {@link STKEphemerisSegment} instance.
105          * @param mu gravitational parameter (m^3/s^2)
106          * @param frame frame
107          * @param interpolationSamples number of samples to use in interpolation
108          * @param cartesianDerivativesFilter Cartesian derivatives filter
109          * @param timeStampedPVCoordinates time-sorted time/position/velocity data
110          */
111         public STKEphemerisSegment(final double mu, final Frame frame, final int interpolationSamples,
112                 final CartesianDerivativesFilter cartesianDerivativesFilter,
113                 final List<TimeStampedPVCoordinates> timeStampedPVCoordinates) {
114             this.mu = mu;
115             this.frame = Objects.requireNonNull(frame);
116             this.interpolationSamples = interpolationSamples;
117             this.cartesianDerivativesFilter = Objects.requireNonNull(cartesianDerivativesFilter);
118             this.timeStampedPVCoordinates = Collections.unmodifiableList(new ArrayList<>(timeStampedPVCoordinates));
119         }
120 
121         @Override
122         public double getMu() {
123             return mu;
124         }
125 
126         @Override
127         public Frame getFrame() {
128             return frame;
129         }
130 
131         @Override
132         public int getInterpolationSamples() {
133             return interpolationSamples;
134         }
135 
136         @Override
137         public CartesianDerivativesFilter getAvailableDerivatives() {
138             return cartesianDerivativesFilter;
139         }
140 
141         @Override
142         public List<TimeStampedPVCoordinates> getCoordinates() {
143             return timeStampedPVCoordinates;
144         }
145 
146         @Override
147         public AbsoluteDate getStart() {
148             return timeStampedPVCoordinates.get(0).getDate();
149         }
150 
151         @Override
152         public AbsoluteDate getStop() {
153             return timeStampedPVCoordinates.get(timeStampedPVCoordinates.size() - 1).getDate();
154         }
155 
156     }
157 
158     /**
159      * Ephemeris from an STK ephemeris file.
160      */
161     public static class STKEphemeris implements SatelliteEphemeris<TimeStampedPVCoordinates, STKEphemerisSegment> {
162 
163         /** Satellite id.*/
164         private final String satelliteId;
165 
166         /** Gravitational parameter (m^3/s^2). */
167         private final double mu;
168 
169         /** Unmodifiable list of ephemeris segments. */
170         private final List<STKEphemerisSegment> segments;
171 
172         /**
173          * Constructs a {@link STKEphemeris} instance. This constructor shallowly copies the list of segments provided.
174          * @param satelliteId satellite id
175          * @param mu gravitational parameter (m^3/s^2)
176          * @param segments ephemeris segments
177          */
178         public STKEphemeris(final String satelliteId, final double mu, final List<STKEphemerisSegment> segments) {
179             this.satelliteId = Objects.requireNonNull(satelliteId);
180             this.mu = mu;
181             this.segments = Collections.unmodifiableList(new ArrayList<>(segments));
182         }
183 
184         @Override
185         public String getId() {
186             return satelliteId;
187         }
188 
189         @Override
190         public double getMu() {
191             return mu;
192         }
193 
194         @Override
195         public List<STKEphemerisSegment> getSegments() {
196             return segments;
197         }
198 
199         @Override
200         public AbsoluteDate getStart() {
201             return segments.get(0).getStart();
202         }
203 
204         @Override
205         public AbsoluteDate getStop() {
206             return segments.get(segments.size() - 1).getStop();
207         }
208 
209     }
210 
211     /**
212      * STK coordinate system.
213      * <p>
214      * Currently, only Earth-centered coordinate systems are supported.
215      * </p>
216      */
217     public enum STKCoordinateSystem {
218 
219         /** International Celestial Reference Frame. */
220         ICRF,
221 
222         /** Mean equator and mean equinox of the J2000 epoch. */
223         J2000,
224 
225         /** Central-body-dependent inertial frame, equivalent to ICRF for Earth. */
226         INERTIAL,
227 
228         /** Fixed frame. */
229         FIXED,
230 
231         /** True equator and true equinox of date. */
232         TRUE_OF_DATE,
233 
234         /** Mean equator and mean equinox of date. */
235         MEAN_OF_DATE,
236 
237         /** True equator and mean equinox of date. */
238         TEME_OF_DATE;
239 
240         /**
241          * Parses a coordinate system from a string.
242          * @param s string
243          * @return coordinate system
244          */
245         public static STKCoordinateSystem parse(final String s) {
246             final String sUpper = s.toUpperCase(Locale.US);
247             switch (sUpper) {
248                 case "ICRF":
249                     return ICRF;
250                 case "J2000":
251                     return J2000;
252                 case "INERTIAL":
253                     return INERTIAL;
254                 case "FIXED":
255                     return FIXED;
256                 case "TRUEOFDATE":
257                     return TRUE_OF_DATE;
258                 case "MEANOFDATE":
259                     return MEAN_OF_DATE;
260                 case "TEMEOFDATE":
261                     return TEME_OF_DATE;
262                 default:
263                     throw new OrekitException(OrekitMessages.STK_INVALID_OR_UNSUPPORTED_COORDINATE_SYSTEM, s);
264             }
265         }
266 
267     }
268 
269 }