CPF.java
/* Copyright 2002-2024 CS GROUP
* Licensed to CS GROUP (CS) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* CS licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.orekit.files.ilrs;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.orekit.attitudes.AttitudeProvider;
import org.orekit.files.general.EphemerisFile;
import org.orekit.frames.Frame;
import org.orekit.propagation.BoundedPropagator;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeScale;
import org.orekit.utils.CartesianDerivativesFilter;
import org.orekit.utils.TimeStampedPVCoordinates;
/**
* This class stores all the information of the Consolidated laser ranging Prediction File (CPF) parsed
* by CPFParser. It contains the header and a list of ephemeris entry.
* @author Bryan Cazabonne
* @since 10.3
*/
public class CPF implements EphemerisFile<CPF.CPFCoordinate, CPF.CPFEphemeris> {
/** Default satellite ID, used if header is null when initializing the ephemeris. */
public static final String DEFAULT_ID = "9999999";
/** Gravitational coefficient. */
private double mu;
/** The interpolation sample. */
private int interpolationSample;
/** Time scale of dates in the ephemeris file. */
private TimeScale timeScale;
/** Indicates if data contains velocity or not. */
private CartesianDerivativesFilter filter;
/** CPF file header. */
private CPFHeader header;
/** Map containing satellite information. */
private Map<String, CPFEphemeris> ephemeris;
/** List of comments contained in the file. */
private List<String> comments;
/**
* Constructor.
*/
public CPF() {
this.mu = Double.NaN;
this.ephemeris = new ConcurrentHashMap<>();
this.header = new CPFHeader();
this.comments = new ArrayList<>();
}
/** {@inheritDoc}
* First key corresponds to String value of {@link CPFHeader#getIlrsSatelliteId()}
*/
@Override
public Map<String, CPFEphemeris> getSatellites() {
// Return the map
return Collections.unmodifiableMap(ephemeris);
}
/**
* Get the CPF file header.
* @return the CPF file header
*/
public CPFHeader getHeader() {
return header;
}
/**
* Get the time scale used in CPF file.
* @return the time scale used to parse epochs in CPF file.
*/
public TimeScale getTimeScale() {
return timeScale;
}
/**
* Get the comments contained in the file.
* @return the comments contained in the file
*/
public List<String> getComments() {
return comments;
}
/**
* Adds a set of P/V coordinates to the satellite.
* @param id satellite ILRS identifier
* @param coord set of coordinates
* @since 11.0.1
*/
public void addSatelliteCoordinates(final String id, final List<CPFCoordinate> coord) {
createIfNeeded(id);
ephemeris.get(id).coordinates.addAll(coord);
}
/**
* Add a new P/V coordinates to the satellite.
* @param id satellite ILRS identifier
* @param coord the P/V coordinate of the satellite
* @since 11.0.1
*/
public void addSatelliteCoordinate(final String id, final CPFCoordinate coord) {
createIfNeeded(id);
ephemeris.get(id).coordinates.add(coord);
}
/**
* Add the velocity to the last CPF coordinate entry.
* @param id satellite ILRS identifier
* @param velocity the velocity vector of the satellite
* @since 11.2
*/
public void addSatelliteVelocityToCPFCoordinate(final String id, final Vector3D velocity) {
// Get the last coordinate entry, which contains the position vector
final CPFCoordinate lastCoordinate = ephemeris.get(id).coordinates.get(ephemeris.get(id).coordinates.size() - 1);
// Create a new CPFCoordinate object with both position and velocity information
final CPFCoordinate CPFCoordUpdated = new CPFCoordinate(lastCoordinate.getDate(),
lastCoordinate.getPosition(),
velocity,
lastCoordinate.getLeap());
// Patch the last record
ephemeris.get(id).coordinates.set(ephemeris.get(id).coordinates.size() - 1, CPFCoordUpdated);
}
/**
* Set the interpolation sample.
* @param interpolationSample interpolation sample
*/
public void setInterpolationSample(final int interpolationSample) {
this.interpolationSample = interpolationSample;
}
/**
* Set the gravitational coefficient.
* @param mu the coefficient to be set
*/
public void setMu(final double mu) {
this.mu = mu;
}
/**
* Set the time scale.
* @param timeScale use to parse dates in this file.
*/
public void setTimeScale(final TimeScale timeScale) {
this.timeScale = timeScale;
}
/**
* Set the derivatives filter.
* @param filter that indicates which derivatives of position are available.
*/
public void setFilter(final CartesianDerivativesFilter filter) {
this.filter = filter;
}
/**
* Create the satellite ephemeris corresponding to the given ID (if needed).
* @param id satellite ILRS identifier
*/
private void createIfNeeded(final String id) {
if (ephemeris.get(id) == null) {
ephemeris.put(id, new CPFEphemeris(id));
}
}
/** An ephemeris entry for a single satellite contains in a CPF file. */
public class CPFEphemeris
implements EphemerisFile.SatelliteEphemeris<CPFCoordinate, CPFEphemeris>,
EphemerisFile.EphemerisSegment<CPFCoordinate> {
/** Satellite ID. */
private final String id;
/** Ephemeris Data. */
private final List<CPFCoordinate> coordinates;
/**
* Constructor.
* @param id satellite ID
*/
public CPFEphemeris(final String id) {
this.id = id;
this.coordinates = new ArrayList<>();
}
/** {@inheritDoc} */
@Override
public Frame getFrame() {
return header.getRefFrame();
}
/** {@inheritDoc} */
@Override
public int getInterpolationSamples() {
return interpolationSample;
}
/** {@inheritDoc} */
@Override
public CartesianDerivativesFilter getAvailableDerivatives() {
return filter;
}
/** {@inheritDoc} */
@Override
public List<CPFCoordinate> getCoordinates() {
return Collections.unmodifiableList(this.coordinates);
}
/** {@inheritDoc} */
@Override
public String getId() {
return id == null ? DEFAULT_ID : id;
}
/** {@inheritDoc} */
@Override
public double getMu() {
return mu;
}
/** Returns a list containing only {@code this}. */
@Override
public List<CPFEphemeris> getSegments() {
return Collections.singletonList(this);
}
/** {@inheritDoc} */
@Override
public AbsoluteDate getStart() {
return coordinates.get(0).getDate();
}
/** {@inheritDoc} */
@Override
public AbsoluteDate getStop() {
return coordinates.get(coordinates.size() - 1).getDate();
}
/** {@inheritDoc} */
@Override
public BoundedPropagator getPropagator() {
return EphemerisSegment.super.getPropagator();
}
/** {@inheritDoc} */
@Override
public BoundedPropagator getPropagator(final AttitudeProvider attitudeProvider) {
return EphemerisSegment.super.getPropagator(attitudeProvider);
}
/** Get the list of Ephemerides data lines.
* @return a reference to the internal list of Ephemerides data lines
*/
public List<CPFCoordinate> getEphemeridesDataLines() {
return this.coordinates;
}
}
/** A single record of position and possibility velocity in an SP3 file. */
public static class CPFCoordinate extends TimeStampedPVCoordinates {
/** Serializable UID. */
private static final long serialVersionUID = 20201016L;
/** Leap second flag. */
private final int leap;
/**
* Constructor with null velocity vector.
* @param date date of coordinates validity
* @param position position vector
* @param leap leap second flag (= 0 or the value of the new leap second)
*/
public CPFCoordinate(final AbsoluteDate date,
final Vector3D position,
final int leap) {
this(date, position, Vector3D.ZERO, leap);
}
/**
* Constructor.
* @param date date of coordinates validity
* @param position position vector
* @param velocity velocity vector
* @param leap leap second flag (= 0 or the value of the new leap second)
*/
public CPFCoordinate(final AbsoluteDate date,
final Vector3D position,
final Vector3D velocity,
final int leap) {
super(date, position, velocity);
this.leap = leap;
}
/**
* Get the leap second flag (= 0 or the value of the new leap second).
* @return the leap second flag
*/
public int getLeap() {
return leap;
}
}
}