1   /* Copyright 2002-2025 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.ArrayList;
20  import java.util.List;
21  
22  import org.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.hipparchus.stat.descriptive.DescriptiveStatistics;
24  import org.junit.jupiter.api.Assertions;
25  import org.junit.jupiter.api.Test;
26  import org.orekit.attitudes.LofOffset;
27  import org.orekit.estimation.Context;
28  import org.orekit.estimation.EstimationTestUtils;
29  import org.orekit.estimation.measurements.EstimatedMeasurementBase;
30  import org.orekit.estimation.measurements.EstimationModifier;
31  import org.orekit.estimation.measurements.InterSatellitesRange;
32  import org.orekit.estimation.measurements.InterSatellitesRangeMeasurementCreator;
33  import org.orekit.estimation.measurements.ObservedMeasurement;
34  import org.orekit.frames.LOFType;
35  import org.orekit.orbits.CartesianOrbit;
36  import org.orekit.orbits.Orbit;
37  import org.orekit.orbits.OrbitType;
38  import org.orekit.orbits.PositionAngleType;
39  import org.orekit.propagation.BoundedPropagator;
40  import org.orekit.propagation.EphemerisGenerator;
41  import org.orekit.propagation.Propagator;
42  import org.orekit.propagation.SpacecraftState;
43  import org.orekit.propagation.conversion.NumericalPropagatorBuilder;
44  import org.orekit.utils.TimeStampedPVCoordinates;
45  
46  public class ShapiroInterSatelliteRangeModifierTest {
47  
48      @Test
49      public void testShapiroOneWay() {
50          doTestShapiro(false, 0.000047764, 0.000086953, 0.000164659);
51      }
52  
53      @Test
54      public void testShapiroTwoWay() {
55          doTestShapiro(true, 0.000047764, 0.000086952, 0.000164656);
56      }
57  
58      private void doTestShapiro(final boolean twoWay,
59                                 final double expectedMin, final double expectedMean, final double expectedMax) {
60  
61          Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
62  
63          final NumericalPropagatorBuilder propagatorBuilder =
64                          context.createBuilder(OrbitType.KEPLERIAN, PositionAngleType.TRUE, true,
65                                                1.0e-6, 60.0, 0.001);
66          propagatorBuilder.setAttitudeProvider(new LofOffset(propagatorBuilder.getFrame(), LOFType.LVLH));
67  
68          // create perfect inter-satellites range measurements without antenna offset
69          final TimeStampedPVCoordinates original = context.initialOrbit.getPVCoordinates();
70          final Orbit closeOrbit = new CartesianOrbit(new TimeStampedPVCoordinates(context.initialOrbit.getDate(),
71                                                                                   original.getPosition().add(new Vector3D(1000, 2000, 3000)),
72                                                                                   original.getVelocity().add(new Vector3D(-0.03, 0.01, 0.02))),
73                                                      context.initialOrbit.getFrame(),
74                                                      context.initialOrbit.getMu());
75          final Propagator closePropagator = EstimationTestUtils.createPropagator(closeOrbit,
76                                                                                  propagatorBuilder);
77          final EphemerisGenerator generator = closePropagator.getEphemerisGenerator();
78          closePropagator.propagate(context.initialOrbit.getDate().shiftedBy(3.5 * closeOrbit.getKeplerianPeriod()));
79          final BoundedPropagator ephemeris = generator.getGeneratedEphemeris();
80          final Propagator p1 = EstimationTestUtils.createPropagator(context.initialOrbit,
81                                                                             propagatorBuilder);
82          final double localClockOffset  = 0.137e-6;
83          final double remoteClockOffset = 469.0e-6;
84          List<ObservedMeasurement<?>> measurements =
85                          EstimationTestUtils.createMeasurements(p1,
86                                                                 new InterSatellitesRangeMeasurementCreator(ephemeris,
87                                                                                                            localClockOffset,
88                                                                                                            remoteClockOffset,
89                                                                                                            Vector3D.ZERO,
90                                                                                                            Vector3D.ZERO),
91                                                                 1.0, 3.0, 300.0);
92          if (!twoWay) {
93              // convert default two way measurements to one way measurements
94              final List<ObservedMeasurement<?>> converted = new ArrayList<>();
95              for (final ObservedMeasurement<?> m : measurements) {
96                  final InterSatellitesRange sr = (InterSatellitesRange) m;
97                  converted.add(new InterSatellitesRange(sr.getSatellites().get(0), sr.getSatellites().get(1),
98                                                         false, sr.getDate(),
99                                                         sr.getObservedValue()[0],
100                                                        sr.getTheoreticalStandardDeviation()[0],
101                                                        sr.getBaseWeight()[0]));
102             }
103             measurements = converted;
104         }
105 
106         final ShapiroInterSatelliteRangeModifier modifier = new ShapiroInterSatelliteRangeModifier(context.initialOrbit.getMu());
107         final Propagator p3 = EstimationTestUtils.createPropagator(context.initialOrbit,
108                                                                    propagatorBuilder);
109         DescriptiveStatistics stat = new DescriptiveStatistics();
110         for (int i = 0; i < measurements.size(); ++i) {
111             InterSatellitesRange sr = (InterSatellitesRange) measurements.get(i);
112             SpacecraftState[] states = new SpacecraftState[] {
113                 p3.propagate(sr.getDate()),
114                 ephemeris.propagate(sr.getDate())
115             };
116             EstimatedMeasurementBase<InterSatellitesRange> evalNoMod = sr.estimateWithoutDerivatives(states);
117 
118             // add modifier
119             sr.addModifier(modifier);
120             boolean found = false;
121             for (final EstimationModifier<InterSatellitesRange> existing : sr.getModifiers()) {
122                 found = found || existing == modifier;
123             }
124             Assertions.assertTrue(found);
125             EstimatedMeasurementBase<InterSatellitesRange> eval = sr.estimateWithoutDerivatives(states);
126 
127             stat.addValue(eval.getEstimatedValue()[0] - evalNoMod.getEstimatedValue()[0]);
128             Assertions.assertEquals(1,
129                                     eval.getAppliedEffects().entrySet().stream().
130                                     filter(e -> e.getKey().getEffectName().equals("Shapiro")).count());
131 
132         }
133 
134         Assertions.assertEquals(expectedMin,  stat.getMin(),  1.0e-9);
135         Assertions.assertEquals(expectedMean, stat.getMean(), 1.0e-9);
136         Assertions.assertEquals(expectedMax,  stat.getMax(),  1.0e-9);
137 
138     }
139 
140 }
141 
142