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