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