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.estimation.measurements.modifiers;
18
19 import java.util.List;
20
21 import org.hipparchus.geometry.euclidean.threed.Vector3D;
22 import org.hipparchus.util.MathUtils;
23 import org.orekit.estimation.measurements.AngularAzEl;
24 import org.orekit.estimation.measurements.EstimatedMeasurementBase;
25 import org.orekit.estimation.measurements.EstimationModifier;
26 import org.orekit.estimation.measurements.GroundStation;
27 import org.orekit.frames.Frame;
28 import org.orekit.frames.TopocentricFrame;
29 import org.orekit.models.earth.ionosphere.IonosphericModel;
30 import org.orekit.propagation.SpacecraftState;
31 import org.orekit.time.AbsoluteDate;
32 import org.orekit.utils.Constants;
33 import org.orekit.utils.ParameterDriver;
34 import org.orekit.utils.TrackingCoordinates;
35
36 /** Class modifying theoretical angular measurement with ionospheric delay.
37 * <p>
38 * The effect of ionospheric correction on the angular measurement is computed
39 * through the computation of the ionospheric delay. The spacecraft state
40 * is shifted by the computed delay time and elevation and azimuth are computed
41 * again with the new spacecraft state.
42 * </p>
43 * <p>
44 * The ionospheric delay depends on the frequency of the signal (GNSS, VLBI, ...).
45 * For optical measurements (e.g. SLR), the ray is not affected by ionosphere charged particles.
46 * </p>
47 * <p>
48 * Since 10.0, state derivatives and ionospheric parameters derivates are computed
49 * using automatic differentiation.
50 * </p>
51 * @author Thierry Ceolin
52 * @since 8.0
53 */
54 public class AngularIonosphericDelayModifier implements EstimationModifier<AngularAzEl> {
55
56 /** Ionospheric delay model. */
57 private final IonosphericModel ionoModel;
58
59 /** Frequency [Hz]. */
60 private final double frequency;
61
62 /** Constructor.
63 *
64 * @param model Ionospheric delay model appropriate for the current angular measurement method.
65 * @param freq frequency of the signal in Hz
66 */
67 public AngularIonosphericDelayModifier(final IonosphericModel model,
68 final double freq) {
69 ionoModel = model;
70 frequency = freq;
71 }
72
73 /** Compute the measurement error due to ionosphere.
74 * @param station station
75 * @param state spacecraft state
76 * @return the measurement error due to ionosphere
77 */
78 private double angularErrorIonosphericModel(final GroundStation station,
79 final SpacecraftState state) {
80 // Base frame associated with the station
81 final TopocentricFrame baseFrame = station.getBaseFrame();
82 // delay in meters
83 return ionoModel.pathDelay(state, baseFrame, frequency, ionoModel.getParameters(state.getDate()));
84 }
85
86 /** {@inheritDoc} */
87 @Override
88 public List<ParameterDriver> getParametersDrivers() {
89 return ionoModel.getParametersDrivers();
90 }
91
92 @Override
93 public void modifyWithoutDerivatives(final EstimatedMeasurementBase<AngularAzEl> estimated) {
94 final AngularAzEl measure = estimated.getObservedMeasurement();
95 final GroundStation station = measure.getStation();
96 final SpacecraftState state = estimated.getStates()[0];
97
98 final double delay = angularErrorIonosphericModel(station, state);
99 // Delay is taken into account to shift the spacecraft position
100 final double dt = delay / Constants.SPEED_OF_LIGHT;
101
102 // Position of the spacecraft shifted of dt
103 final SpacecraftState transitState = state.shiftedBy(-dt);
104
105 // Update estimated value taking into account the ionospheric delay.
106 final AbsoluteDate date = transitState.getDate();
107 final Vector3D position = transitState.getPosition();
108 final Frame inertial = transitState.getFrame();
109
110 // Elevation and azimuth in radians
111 final TrackingCoordinates tc = station.getBaseFrame().getTrackingCoordinates(position, inertial, date);
112 final double twoPiWrap = MathUtils.normalizeAngle(tc.getAzimuth(), measure.getObservedValue()[0]) - tc.getAzimuth();
113 final double azimuth = tc.getAzimuth() + twoPiWrap;
114
115 // Update estimated value taking into account the ionospheric delay.
116 // Azimuth - elevation values
117 estimated.modifyEstimatedValue(this, azimuth, tc.getElevation());
118 }
119
120 }