1   /* Copyright 2002-2024 Luc Maisonobe
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 org.orekit.estimation.measurements.EstimatedMeasurementBase;
20  import org.orekit.estimation.measurements.GroundReceiverMeasurement;
21  import org.orekit.estimation.measurements.GroundStation;
22  import org.orekit.frames.Frame;
23  import org.orekit.frames.Transform;
24  import org.orekit.gnss.antenna.FrequencyPattern;
25  import org.orekit.propagation.SpacecraftState;
26  import org.orekit.time.AbsoluteDate;
27  import org.orekit.utils.TimeStampedPVCoordinates;
28  
29  /** Ground and on-board antennas offsets effect on range measurements.
30   * @param <T> the type of the measurement
31   * @author Luc Maisonobe
32   * @since 12.0
33   */
34  public class PhaseCentersGroundReceiverBaseModifier<T extends GroundReceiverMeasurement<T>> {
35  
36      /** Uplink offset model. */
37      private final PhaseCentersOffsetComputer uplink;
38  
39      /** Downlink offset model. */
40      private final PhaseCentersOffsetComputer downlink;
41  
42      /** Simple constructor.
43       * @param stationPattern station pattern
44       * @param satellitePattern satellite pattern
45       */
46      public PhaseCentersGroundReceiverBaseModifier(final FrequencyPattern stationPattern,
47                                                    final FrequencyPattern satellitePattern) {
48          this.uplink   = new PhaseCentersOffsetComputer(stationPattern, satellitePattern);
49          this.downlink = new PhaseCentersOffsetComputer(satellitePattern, stationPattern);
50      }
51  
52      /** Compute distance modification for one way measurement.
53       * @param estimated estimated measurement to modify
54       * @return distance modification to add to raw measurement
55       */
56      public double oneWayDistanceModification(final EstimatedMeasurementBase<T> estimated) {
57  
58          // get all participants
59          // note that clock offset is compensated in participants,
60          // so the dates included there are more accurate than the measurement date
61          final TimeStampedPVCoordinates[] participants = estimated.getParticipants();
62  
63          // station at reception date
64          final Frame         inertial       = estimated.getStates()[0].getFrame();
65          final GroundStation station        = estimated.getObservedMeasurement().getStation();
66          final AbsoluteDate  receptionDate  = participants[1].getDate();
67          final Transform     stationToInert = station.getOffsetToInertial(inertial, receptionDate, false);
68  
69          // spacecraft at emission date
70          final AbsoluteDate    emissionDate      = participants[0].getDate();
71          final SpacecraftState refState          = estimated.getStates()[0];
72          final SpacecraftState emissionState     = refState.shiftedBy(emissionDate.durationFrom(refState.getDate()));
73          final Transform       spacecraftToInert = emissionState.toTransform().getInverse();
74  
75          // compute offset due to phase centers
76          return downlink.offset(spacecraftToInert, stationToInert);
77  
78      }
79  
80      /** Apply a modifier to a two-way range measurement.
81       * @param estimated estimated measurement to modify
82       * @return distance modification to add to raw measurement
83       */
84      public double twoWayDistanceModification(final EstimatedMeasurementBase<T> estimated) {
85  
86          // get all participants
87          // note that clock offset is compensated in participants,
88          // so the dates included there are more accurate than the measurement date
89          final TimeStampedPVCoordinates[] participants = estimated.getParticipants();
90  
91          // station at reception date
92          final Frame         inertial                = estimated.getStates()[0].getFrame();
93          final GroundStation station                 = estimated.getObservedMeasurement().getStation();
94          final AbsoluteDate  receptionDate           = participants[2].getDate();
95          final Transform     stationToInertReception = station.getOffsetToInertial(inertial, receptionDate, false);
96  
97          // transform from spacecraft to inertial frame at transit date
98          final AbsoluteDate    transitDate           = participants[1].getDate();
99          final SpacecraftState refState              = estimated.getStates()[0];
100         final SpacecraftState transitState          = refState.shiftedBy(transitDate.durationFrom(refState.getDate()));
101         final Transform       spacecraftToInert     = transitState.toTransform().getInverse();
102 
103         // station at emission date
104         final AbsoluteDate emissionDate             = participants[0].getDate();
105         final Transform    stationToInertEmission   = station.getOffsetToInertial(inertial, emissionDate, true);
106 
107         // compute offsets due to phase centers
108         final double uplinkOffset   = uplink.offset(stationToInertEmission, spacecraftToInert);
109         final double downlinkOffset = downlink.offset(spacecraftToInert, stationToInertReception);
110 
111         return 0.5 * (uplinkOffset + downlinkOffset);
112 
113     }
114 
115 }