1   /* Copyright 2002-2021 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.ilrs;
18  
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.concurrent.ConcurrentHashMap;
24  
25  import org.hipparchus.geometry.euclidean.threed.Vector3D;
26  import org.orekit.files.general.EphemerisFile;
27  import org.orekit.frames.Frame;
28  import org.orekit.propagation.BoundedPropagator;
29  import org.orekit.time.AbsoluteDate;
30  import org.orekit.time.TimeScale;
31  import org.orekit.utils.CartesianDerivativesFilter;
32  import org.orekit.utils.TimeStampedPVCoordinates;
33  
34  /**
35   * This class stores all the information of the Consolidated laser ranging Prediction File (CPF) parsed
36   * by CPFParser. It contains the header and a list of ephemeris entry.
37   * @author Bryan Cazabonne
38   * @since 10.3
39   */
40  public class CPF implements EphemerisFile<CPF.CPFCoordinate, CPF.CPFEphemeris> {
41  
42      /** Default satellite ID, used if header is null when initializing the ephemeris. */
43      public static final String DEFAULT_ID = "9999999";
44  
45      /** Gravitational coefficient. */
46      private double mu;
47  
48      /** The interpolation sample. */
49      private int interpolationSample;
50  
51      /** Time scale of dates in the ephemeris file. */
52      private TimeScale timeScale;
53  
54      /** Indicates if data contains velocity or not. */
55      private CartesianDerivativesFilter filter;
56  
57      /** CPF file header. */
58      private CPFHeader header;
59  
60      /** Map containing satellite information. */
61      private Map<String, CPFEphemeris> ephemeris;
62  
63      /** List of comments contained in the file. */
64      private List<String> comments;
65  
66      /**
67       * Constructor.
68       */
69      public CPF() {
70          this.mu        = Double.NaN;
71          this.ephemeris = new ConcurrentHashMap<>();
72          this.header    = new CPFHeader();
73          this.comments  = new ArrayList<>();
74      }
75  
76      /** {@inheritDoc}
77       * First key corresponds to String value of {@link CPFHeader#getIlrsSatelliteId()}
78       */
79      @Override
80      public Map<String, CPFEphemeris> getSatellites() {
81          // Return the map
82          return Collections.unmodifiableMap(ephemeris);
83      }
84  
85      /**
86       * Get the CPF file header.
87       * @return the CPF file header
88       */
89      public CPFHeader getHeader() {
90          return header;
91      }
92  
93      /**
94       * Get the time scale used in CPF file.
95       * @return the time scale used to parse epochs in CPF file.
96       */
97      public TimeScale getTimeScale() {
98          return timeScale;
99      }
100 
101     /**
102      * Get the comments contained in the file.
103      * @return the comments contained in the file
104      */
105     public List<String> getComments() {
106         return comments;
107     }
108 
109     /**
110      * Adds a new P/V coordinate to the satellite.
111      * <p>
112      * If the header has not been read, the {@link #DEFAULT_ID} is used.
113      * </p>
114      * @param coord the P/V coordinate of the satellite
115      * @deprecated as of 11.0.1, replaced by {@link CPF#addSatelliteCoordinate(String, CPFCoordinate)}
116      */
117     @Deprecated
118     public void addSatelliteCoordinate(final CPFCoordinate coord) {
119         addSatelliteCoordinate(DEFAULT_ID, coord);
120     }
121 
122     /**
123      * Adds a set of P/V coordinates to the satellite.
124      * @param id satellite ILRS identifier
125      * @param coord set of coordinates
126      * @since 11.0.1
127      */
128     public void addSatelliteCoordinates(final String id, final List<CPFCoordinate> coord) {
129         createIfNeeded(id);
130         ephemeris.get(id).coordinates.addAll(coord);
131     }
132 
133     /**
134      * Add a new P/V coordinates to the satellite.
135      * @param id satellite ILRS identifier
136      * @param coord the P/V coordinate of the satellite
137      * @since 11.0.1
138      */
139     public void addSatelliteCoordinate(final String id, final CPFCoordinate coord) {
140         createIfNeeded(id);
141         ephemeris.get(id).coordinates.add(coord);
142     }
143 
144     /**
145      * Set the interpolation sample.
146      * @param interpolationSample interpolation sample
147      */
148     public void setInterpolationSample(final int interpolationSample) {
149         this.interpolationSample = interpolationSample;
150     }
151 
152     /**
153      * Set the gravitational coefficient.
154      * @param mu the coefficient to be set
155      */
156     public void setMu(final double mu) {
157         this.mu = mu;
158     }
159 
160     /**
161      * Set the time scale.
162      * @param timeScale use to parse dates in this file.
163      */
164     public void setTimeScale(final TimeScale timeScale) {
165         this.timeScale = timeScale;
166     }
167 
168     /**
169      * Set the derivatives filter.
170      * @param filter that indicates which derivatives of position are available.
171      */
172     public void setFilter(final CartesianDerivativesFilter filter) {
173         this.filter = filter;
174     }
175 
176     /**
177      * Create the satellite ephemeris corresponding to the given ID (if needed).
178      * @param id satellite ILRS identifier
179      */
180     private void createIfNeeded(final String id) {
181         if (ephemeris.get(id) == null) {
182             ephemeris.put(id, new CPFEphemeris(id));
183         }
184     }
185 
186     /** An ephemeris entry  for a single satellite contains in a CPF file. */
187     public class CPFEphemeris
188         implements EphemerisFile.SatelliteEphemeris<CPFCoordinate, CPFEphemeris>,
189                    EphemerisFile.EphemerisSegment<CPFCoordinate> {
190 
191         /** Satellite ID. */
192         private final String id;
193 
194         /** Ephemeris Data. */
195         private final List<CPFCoordinate> coordinates;
196 
197         /**
198          * Constructor.
199          * @deprecated as of 11.0.1, replaced by
200          */
201         @Deprecated
202         public CPFEphemeris() {
203             this(null);
204         }
205 
206         /**
207          * Constructor.
208          * @param id satellite ID
209          */
210         public CPFEphemeris(final String id) {
211             this.id          = id;
212             this.coordinates = new ArrayList<>();
213         }
214 
215 
216         /** {@inheritDoc} */
217         @Override
218         public Frame getFrame() {
219             return header.getRefFrame();
220         }
221 
222         /** {@inheritDoc} */
223         @Override
224         public int getInterpolationSamples() {
225             return interpolationSample;
226         }
227 
228         /** {@inheritDoc} */
229         @Override
230         public CartesianDerivativesFilter getAvailableDerivatives() {
231             return filter;
232         }
233 
234         /** {@inheritDoc} */
235         @Override
236         public List<CPFCoordinate> getCoordinates() {
237             return Collections.unmodifiableList(this.coordinates);
238         }
239 
240         /** {@inheritDoc} */
241         @Override
242         public String getId() {
243             return id == null ? DEFAULT_ID : id;
244         }
245 
246         /** {@inheritDoc} */
247         @Override
248         public double getMu() {
249             return mu;
250         }
251 
252         /** Returns a list containing only {@code this}. */
253         @Override
254         public List<CPFEphemeris> getSegments() {
255             return Collections.singletonList(this);
256         }
257 
258         /** {@inheritDoc} */
259         @Override
260         public AbsoluteDate getStart() {
261             return coordinates.get(0).getDate();
262         }
263 
264         /** {@inheritDoc} */
265         @Override
266         public AbsoluteDate getStop() {
267             return coordinates.get(coordinates.size() - 1).getDate();
268         }
269 
270         /** {@inheritDoc} */
271         @Override
272         public BoundedPropagator getPropagator() {
273             return EphemerisSegment.super.getPropagator();
274         }
275 
276         /** Get the list of Ephemerides data lines.
277          * @return a reference to the internal list of Ephemerides data lines
278          */
279         public List<CPFCoordinate> getEphemeridesDataLines() {
280             return this.coordinates;
281         }
282 
283     }
284 
285     /** A single record of position and possibility velocity in an SP3 file. */
286     public static class CPFCoordinate extends TimeStampedPVCoordinates {
287 
288         /** Serializable UID. */
289         private static final long serialVersionUID = 20201016L;
290 
291         /** Leap second flag. */
292         private final int leap;
293 
294         /**
295          * Constructor with null velocity vector.
296          * @param date date of coordinates validity
297          * @param position position vector
298          * @param leap leap second flag (= 0 or the value of the new leap second)
299          */
300         public CPFCoordinate(final AbsoluteDate date,
301                              final Vector3D position,
302                              final int leap) {
303             this(date, position, Vector3D.ZERO, leap);
304         }
305 
306         /**
307          * Constructor.
308          * @param date date of coordinates validity
309          * @param position position vector
310          * @param velocity velocity vector
311          * @param leap leap second flag (= 0 or the value of the new leap second)
312          */
313         public CPFCoordinate(final AbsoluteDate date,
314                              final Vector3D position,
315                              final Vector3D velocity,
316                              final int leap) {
317             super(date, position, velocity);
318             this.leap = leap;
319         }
320 
321         /**
322          * Get the leap second flag (= 0 or the value of the new leap second).
323          * @return the leap second flag
324          */
325         public int getLeap() {
326             return leap;
327         }
328 
329     }
330 
331 }