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.Collections;
20  import java.util.List;
21  
22  import org.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.orekit.estimation.measurements.EstimatedMeasurementBase;
24  import org.orekit.estimation.measurements.EstimationModifier;
25  import org.orekit.estimation.measurements.TurnAroundRange;
26  import org.orekit.frames.StaticTransform;
27  import org.orekit.propagation.SpacecraftState;
28  import org.orekit.time.AbsoluteDate;
29  import org.orekit.utils.ParameterDriver;
30  import org.orekit.utils.TimeStampedPVCoordinates;
31  
32  /** On-board antenna offset effect on turn around range measurements.
33   * @author Luc Maisonobe
34   * @since 9.0
35   */
36  public class OnBoardAntennaTurnAroundRangeModifier implements EstimationModifier<TurnAroundRange> {
37  
38      /** Position of the Antenna Phase Center in satellite frame. */
39      private final Vector3D antennaPhaseCenter;
40  
41      /** Simple constructor.
42       * @param antennaPhaseCenter position of the Antenna Phase Center in satellite frame
43       */
44      public OnBoardAntennaTurnAroundRangeModifier(final Vector3D antennaPhaseCenter) {
45          this.antennaPhaseCenter = antennaPhaseCenter;
46      }
47  
48      /** {@inheritDoc} */
49      @Override
50      public List<ParameterDriver> getParametersDrivers() {
51          return Collections.emptyList();
52      }
53  
54      /** {@inheritDoc} */
55      @Override
56      public void modifyWithoutDerivatives(final EstimatedMeasurementBase<TurnAroundRange> estimated) {
57  
58          // the participants are primary station at emission, spacecraft during leg 1,
59          // secondary station at rebound, spacecraft during leg 2, primary station at reception
60          final TimeStampedPVCoordinates[] participants      = estimated.getParticipants();
61          final Vector3D                   pPrimaryEmission  = participants[0].getPosition();
62          final AbsoluteDate               transitDateLeg1   = participants[1].getDate();
63          final Vector3D                   pSecondaryRebound = participants[2].getPosition();
64          final AbsoluteDate               transitDateLeg2   = participants[3].getDate();
65          final Vector3D                   pPrimaryReception = participants[4].getPosition();
66  
67          // transforms from spacecraft to inertial frame at transit dates
68          final SpacecraftState refState              = estimated.getStates()[0];
69          final SpacecraftState transitStateLeg1      = refState.shiftedBy(transitDateLeg1.durationFrom(refState.getDate()));
70          final StaticTransform spacecraftToInertLeg1 = transitStateLeg1.toStaticTransform().getInverse();
71          final SpacecraftState transitStateLeg2      = refState.shiftedBy(transitDateLeg2.durationFrom(refState.getDate()));
72          final StaticTransform spacecraftToInertLeg2 = transitStateLeg2.toStaticTransform().getInverse();
73  
74          // compute the geometrical value of the turn-around range directly from participants positions.
75          // Note that this may be different from the value returned by estimated.getEstimatedValue(),
76          // because other modifiers may already have been taken into account
77          final Vector3D pSpacecraftLeg1 = spacecraftToInertLeg1.transformPosition(Vector3D.ZERO);
78          final Vector3D pSpacecraftLeg2 = spacecraftToInertLeg2.transformPosition(Vector3D.ZERO);
79          final double turnAroundRangeUsingSpacecraftCenter =
80                          0.5 * (Vector3D.distance(pPrimaryEmission,  pSpacecraftLeg1) +
81                                 Vector3D.distance(pSpacecraftLeg1,   pSecondaryRebound)   +
82                                 Vector3D.distance(pSecondaryRebound, pSpacecraftLeg2) +
83                                 Vector3D.distance(pSpacecraftLeg2,   pPrimaryReception));
84  
85          // compute the geometrical value of the range replacing
86          // the spacecraft positions with antenna phase center positions
87          final Vector3D pAPCLeg1 = spacecraftToInertLeg1.transformPosition(antennaPhaseCenter);
88          final Vector3D pAPCLeg2 = spacecraftToInertLeg2.transformPosition(antennaPhaseCenter);
89          final double turnAroundRangeUsingAntennaPhaseCenter =
90                          0.5 * (Vector3D.distance(pPrimaryEmission,  pAPCLeg1)          +
91                                 Vector3D.distance(pAPCLeg1,          pSecondaryRebound) +
92                                 Vector3D.distance(pSecondaryRebound, pAPCLeg2)          +
93                                 Vector3D.distance(pAPCLeg2,          pPrimaryReception));
94  
95          // get the estimated value before this modifier is applied
96          final double[] value = estimated.getEstimatedValue();
97  
98          // modify the value
99          value[0] += turnAroundRangeUsingAntennaPhaseCenter - turnAroundRangeUsingSpacecraftCenter;
100         estimated.modifyEstimatedValue(this, value);
101 
102     }
103 
104 }