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.Collections;
20  import java.util.List;
21  
22  import org.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.orekit.estimation.measurements.EstimatedMeasurement;
24  import org.orekit.estimation.measurements.EstimationModifier;
25  import org.orekit.estimation.measurements.Range;
26  import org.orekit.frames.Transform;
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 range measurements.
33   * @author Luc Maisonobe
34   * @since 9.0
35   */
36  public class OnBoardAntennaRangeModifier implements EstimationModifier<Range> {
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 OnBoardAntennaRangeModifier(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 modify(final EstimatedMeasurement<Range> estimated) {
57          if (estimated.getObservedMeasurement().isTwoWay()) {
58              modifyTwoWay(estimated);
59          } else {
60              modifyOneWay(estimated);
61          }
62      }
63  
64      /** Apply a modifier to a one-way range measurement.
65       * @param estimated estimated measurement to modify
66       */
67      private void modifyOneWay(final EstimatedMeasurement<Range> estimated) {
68  
69          // the participants are spacecraft at emission, ground station at reception
70          final TimeStampedPVCoordinates[] participants = estimated.getParticipants();
71          final AbsoluteDate               emissionDate = participants[0].getDate();
72          final Vector3D                   pReception   = participants[1].getPosition();
73  
74          // transform from spacecraft to inertial frame at emission date
75          final SpacecraftState refState          = estimated.getStates()[0];
76          final SpacecraftState emissionState     = refState.shiftedBy(emissionDate.durationFrom(refState.getDate()));
77          final Transform       spacecraftToInert = emissionState.toTransform().getInverse();
78  
79          // compute the geometrical value of the range directly from participants positions.
80          // Note that this may be different from the value returned by estimated.getEstimatedValue(),
81          // because other modifiers may already have been taken into account
82          final Vector3D pSpacecraft = spacecraftToInert.transformPosition(Vector3D.ZERO);
83          final double rangeUsingSpacecraftCenter = Vector3D.distance(pSpacecraft, pReception);
84  
85          // compute the geometrical value of the range replacing
86          // the spacecraft position with antenna phase center position
87          final Vector3D pAPC = spacecraftToInert.transformPosition(antennaPhaseCenter);
88          final double rangeUsingAntennaPhaseCenter = Vector3D.distance(pAPC, pReception);
89  
90          // get the estimated value before this modifier is applied
91          final double[] value = estimated.getEstimatedValue();
92  
93          // modify the value
94          value[0] += rangeUsingAntennaPhaseCenter - rangeUsingSpacecraftCenter;
95          estimated.setEstimatedValue(value);
96  
97      }
98  
99      /** Apply a modifier to a two-way range measurement.
100      * @param estimated estimated measurement to modify
101      */
102     private void modifyTwoWay(final EstimatedMeasurement<Range> estimated) {
103 
104         // the participants are ground station at emission, spacecraft, ground station at reception
105         // or spacecraft, ground station at reception if oneWay
106         final TimeStampedPVCoordinates[] participants = estimated.getParticipants();
107         final Vector3D                   pEmission    = participants[0].getPosition();
108         final AbsoluteDate               transitDate  = participants[1].getDate();
109         final Vector3D                   pReception   = participants[2].getPosition();
110 
111         // transform from spacecraft to inertial frame at transit date
112         final SpacecraftState refState          = estimated.getStates()[0];
113         final SpacecraftState transitState      = refState.shiftedBy(transitDate.durationFrom(refState.getDate()));
114         final Transform       spacecraftToInert = transitState.toTransform().getInverse();
115 
116         // compute the geometrical value of the range directly from participants positions.
117         // Note that this may be different from the value returned by estimated.getEstimatedValue(),
118         // because other modifiers may already have been taken into account
119         final Vector3D pSpacecraft = spacecraftToInert.transformPosition(Vector3D.ZERO);
120         final double rangeUsingSpacecraftCenter =
121                         0.5 * (Vector3D.distance(pEmission, pSpacecraft) + Vector3D.distance(pSpacecraft, pReception));
122 
123         // compute the geometrical value of the range replacing
124         // the spacecraft position with antenna phase center position
125         final Vector3D pAPC = spacecraftToInert.transformPosition(antennaPhaseCenter);
126         final double rangeUsingAntennaPhaseCenter =
127                         0.5 * (Vector3D.distance(pEmission, pAPC) + Vector3D.distance(pAPC, pReception));
128 
129         // get the estimated value before this modifier is applied
130         final double[] value = estimated.getEstimatedValue();
131 
132         // modify the value
133         value[0] += rangeUsingAntennaPhaseCenter - rangeUsingSpacecraftCenter;
134         estimated.setEstimatedValue(value);
135 
136     }
137 
138 }