1 /* Copyright 2022-2025 Luc Maisonobe
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.estimation.measurements.gnss;
18
19 import java.util.Collections;
20
21 import org.hipparchus.analysis.differentiation.Gradient;
22 import org.orekit.estimation.measurements.ObservableSatellite;
23 import org.orekit.estimation.measurements.ObservedMeasurement;
24 import org.orekit.estimation.measurements.QuadraticClockModel;
25 import org.orekit.propagation.SpacecraftState;
26 import org.orekit.time.AbsoluteDate;
27 import org.orekit.utils.FieldPVCoordinatesProvider;
28 import org.orekit.utils.PVCoordinatesProvider;
29 import org.orekit.utils.TimeStampedFieldPVCoordinates;
30 import org.orekit.utils.TimeStampedPVCoordinates;
31
32 /** Base class for one-way GNSS measurement.
33 * <p>
34 * This class can be used in precise orbit determination applications
35 * for modeling a range measurement between a GNSS satellite (emitter)
36 * and a LEO satellite (receiver).
37 * </p>
38 * <p>
39 * The one-way GNSS range measurement assumes knowledge of the orbit and
40 * the clock offset of the emitting GNSS satellite. For instance, it is
41 * possible to use a SP3 file or a GNSS navigation message to recover
42 * the satellite's orbit and clock.
43 * </p>
44 * <p>
45 * This class is very similar to {@link AbstractInterSatellitesMeasurement} measurement
46 * class. However, using the one-way GNSS range measurement, the orbit and clock
47 * of the emitting GNSS satellite are <b>NOT</b> estimated simultaneously with
48 * LEO satellite coordinates.
49 * </p>
50 *
51 * @param <T> type of the measurement
52 * @author Luc Maisonobe
53 * @since 12.1
54 */
55 public abstract class AbstractOneWayGNSSMeasurement<T extends ObservedMeasurement<T>>
56 extends AbstractOnBoardMeasurement<T> {
57
58 /** Emitting satellite. */
59 private final PVCoordinatesProvider remotePV;
60
61 /** Clock offset of the emitting satellite. */
62 private final QuadraticClockModel remoteClock;
63
64 /** Simple constructor.
65 * @param remotePV provider for GNSS satellite which simply emits the signal
66 * @param remoteClock clock offset of the GNSS satellite
67 * @param date date of the measurement
68 * @param range observed value
69 * @param sigma theoretical standard deviation
70 * @param baseWeight base weight
71 * @param local satellite which receives the signal and perform the measurement
72 */
73 public AbstractOneWayGNSSMeasurement(final PVCoordinatesProvider remotePV,
74 final QuadraticClockModel remoteClock,
75 final AbsoluteDate date,
76 final double range, final double sigma,
77 final double baseWeight, final ObservableSatellite local) {
78 // Call super constructor
79 super(date, range, sigma, baseWeight, Collections.singletonList(local));
80 // The local satellite clock offset affects the measurement
81 addParameterDriver(local.getClockOffsetDriver());
82 addParameterDriver(local.getClockDriftDriver());
83 addParameterDriver(local.getClockAccelerationDriver());
84 // Initialise fields
85 this.remotePV = remotePV;
86 this.remoteClock = remoteClock;
87 }
88
89 /** {@inheritDoc} */
90 @Override
91 protected PVCoordinatesProvider getRemotePV(final SpacecraftState[] states) {
92 return remotePV;
93 }
94
95 /** {@inheritDoc} */
96 @Override
97 protected QuadraticClockModel getRemoteClock() {
98 return remoteClock;
99 }
100
101 /** {@inheritDoc} */
102 @Override
103 protected FieldPVCoordinatesProvider<Gradient> getRemotePV(final SpacecraftState[] states,
104 final int freeParameters) {
105 // convert the PVCoordinatesProvider to a FieldPVCoordinatesProvider<Gradient>
106 return (date, frame) -> {
107
108 // apply the raw (no derivatives) remote provider
109 final AbsoluteDate dateBase = date.toAbsoluteDate();
110 final TimeStampedPVCoordinates pvBase = remotePV.getPVCoordinates(dateBase, frame);
111 final TimeStampedFieldPVCoordinates<Gradient> pvWithoutDerivatives =
112 new TimeStampedFieldPVCoordinates<>(date.getField(), pvBase);
113
114 // add derivatives, using a trick: we shift the date by 0, with derivatives
115 final Gradient zeroWithDerivatives = date.durationFrom(dateBase);
116 return pvWithoutDerivatives.shiftedBy(zeroWithDerivatives);
117
118 };
119 }
120
121 }