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.propagation.analytical.gnss;
18
19 import org.hipparchus.analysis.differentiation.UnivariateDerivative2;
20 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
21 import org.hipparchus.geometry.euclidean.threed.Vector3D;
22 import org.orekit.attitudes.AttitudeProvider;
23 import org.orekit.errors.OrekitException;
24 import org.orekit.errors.OrekitMessages;
25 import org.orekit.frames.Frame;
26 import org.orekit.orbits.CartesianOrbit;
27 import org.orekit.orbits.Orbit;
28 import org.orekit.propagation.SpacecraftState;
29 import org.orekit.propagation.analytical.AbstractAnalyticalPropagator;
30 import org.orekit.propagation.analytical.gnss.data.SBASOrbitalElements;
31 import org.orekit.time.AbsoluteDate;
32 import org.orekit.utils.PVCoordinates;
33
34 /**
35 * This class aims at propagating a SBAS orbit from {@link SBASOrbitalElements}.
36 *
37 * @see "Tyler Reid, Todd Walker, Per Enge, L1/L5 SBAS MOPS Ephemeris Message to
38 * Support Multiple Orbit Classes, ION ITM, 2013"
39 *
40 * @author Bryan Cazabonne
41 * @since 10.1
42 *
43 */
44 public class SBASPropagator extends AbstractAnalyticalPropagator {
45
46 /** The SBAS orbital elements used. */
47 private final SBASOrbitalElements sbasOrbit;
48
49 /** The spacecraft mass (kg). */
50 private final double mass;
51
52 /** The Earth gravity coefficient used for SBAS propagation. */
53 private final double mu;
54
55 /** The ECI frame used for SBAS propagation. */
56 private final Frame eci;
57
58 /** The ECEF frame used for SBAS propagation. */
59 private final Frame ecef;
60
61 /**
62 * Private constructor.
63 * @param sbasOrbit Glonass orbital elements
64 * @param eci Earth Centered Inertial frame
65 * @param ecef Earth Centered Earth Fixed frame
66 * @param provider Attitude provider
67 * @param mass Satellite mass (kg)
68 * @param mu Earth's gravity coefficient used for SBAS propagation
69 */
70 SBASPropagator(final SBASOrbitalElements sbasOrbit, final Frame eci,
71 final Frame ecef, final AttitudeProvider provider,
72 final double mass, final double mu) {
73 super(provider);
74 // Stores the SBAS orbital elements
75 this.sbasOrbit = sbasOrbit;
76 // Sets the start date as the date of the orbital elements
77 setStartDate(sbasOrbit.getDate());
78 // Sets the mu
79 this.mu = mu;
80 // Sets the mass
81 this.mass = mass;
82 // Sets the Earth Centered Inertial frame
83 this.eci = eci;
84 // Sets the Earth Centered Earth Fixed frame
85 this.ecef = ecef;
86 }
87
88 /**
89 * Gets the PVCoordinates of the GNSS SV in {@link #getECEF() ECEF frame}.
90 *
91 * <p>The algorithm uses automatic differentiation to compute velocity and
92 * acceleration.</p>
93 *
94 * @param date the computation date
95 * @return the GNSS SV PVCoordinates in {@link #getECEF() ECEF frame}
96 */
97 public PVCoordinates propagateInEcef(final AbsoluteDate date) {
98 // Duration from SBAS ephemeris Reference date
99 final UnivariateDerivative2 dt = new UnivariateDerivative2(getDT(date), 1.0, 0.0);
100 // Satellite coordinates
101 final UnivariateDerivative2 x = dt.multiply(dt.multiply(0.5 * sbasOrbit.getXDotDot()).add(sbasOrbit.getXDot())).add(sbasOrbit.getX());
102 final UnivariateDerivative2 y = dt.multiply(dt.multiply(0.5 * sbasOrbit.getYDotDot()).add(sbasOrbit.getYDot())).add(sbasOrbit.getY());
103 final UnivariateDerivative2 z = dt.multiply(dt.multiply(0.5 * sbasOrbit.getZDotDot()).add(sbasOrbit.getZDot())).add(sbasOrbit.getZ());
104 // Returns the Earth-fixed coordinates
105 final FieldVector3D<UnivariateDerivative2> positionwithDerivatives =
106 new FieldVector3D<>(x, y, z);
107 return new PVCoordinates(new Vector3D(positionwithDerivatives.getX().getValue(),
108 positionwithDerivatives.getY().getValue(),
109 positionwithDerivatives.getZ().getValue()),
110 new Vector3D(positionwithDerivatives.getX().getFirstDerivative(),
111 positionwithDerivatives.getY().getFirstDerivative(),
112 positionwithDerivatives.getZ().getFirstDerivative()),
113 new Vector3D(positionwithDerivatives.getX().getSecondDerivative(),
114 positionwithDerivatives.getY().getSecondDerivative(),
115 positionwithDerivatives.getZ().getSecondDerivative()));
116 }
117
118 /** {@inheritDoc} */
119 protected Orbit propagateOrbit(final AbsoluteDate date) {
120 // Gets the PVCoordinates in ECEF frame
121 final PVCoordinates pvaInECEF = propagateInEcef(date);
122 // Transforms the PVCoordinates to ECI frame
123 final PVCoordinates pvaInECI = ecef.getTransformTo(eci, date).transformPVCoordinates(pvaInECEF);
124 // Returns the Cartesian orbit
125 return new CartesianOrbit(pvaInECI, eci, date, mu);
126 }
127
128 /**
129 * Get the Earth gravity coefficient used for SBAS propagation.
130 * @return the Earth gravity coefficient.
131 */
132 public double getMU() {
133 return mu;
134 }
135
136 /**
137 * Gets the Earth Centered Inertial frame used to propagate the orbit.
138 *
139 * @return the ECI frame
140 */
141 public Frame getECI() {
142 return eci;
143 }
144
145 /**
146 * Gets the Earth Centered Earth Fixed frame used to propagate GNSS orbits.
147 *
148 * @return the ECEF frame
149 */
150 public Frame getECEF() {
151 return ecef;
152 }
153
154 /**
155 * Get the underlying SBAS orbital elements.
156 *
157 * @return the underlying SBAS orbital elements
158 */
159 public SBASOrbitalElements getSBASOrbitalElements() {
160 return sbasOrbit;
161 }
162
163 /** {@inheritDoc} */
164 public Frame getFrame() {
165 return eci;
166 }
167
168 /** {@inheritDoc} */
169 public void resetInitialState(final SpacecraftState state) {
170 throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
171 }
172
173 /** {@inheritDoc} */
174 protected double getMass(final AbsoluteDate date) {
175 return mass;
176 }
177
178 /** {@inheritDoc} */
179 protected void resetIntermediateState(final SpacecraftState state, final boolean forward) {
180 throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
181 }
182
183 /** Get the duration from SBAS Reference epoch.
184 * @param date the considered date
185 * @return the duration from SBAS orbit Reference epoch (s)
186 */
187 private double getDT(final AbsoluteDate date) {
188 // Time from ephemeris reference epoch
189 return date.durationFrom(sbasOrbit.getDate());
190 }
191
192 }