1   /* Copyright 2022-2025 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.hipparchus.geometry.euclidean.threed.Vector3D;
20  import org.orekit.frames.StaticTransform;
21  import org.orekit.gnss.antenna.FrequencyPattern;
22  
23  /** Compute phase centers offset on an emitter-receiver link.
24   * @author Luc Maisonobe
25   * @since 12.0
26   */
27  public class PhaseCentersOffsetComputer {
28  
29      /** Emitter pattern. */
30      private final FrequencyPattern emitterPattern;
31  
32      /** Receiver pattern. */
33      private final FrequencyPattern receiverPattern;
34  
35      /** Simple constructor.
36       * @param emitterPattern emitter pattern
37       * @param receiverPattern receiver pattern
38       */
39      public PhaseCentersOffsetComputer(final FrequencyPattern emitterPattern,
40                                        final FrequencyPattern receiverPattern) {
41          this.emitterPattern  = emitterPattern;
42          this.receiverPattern = receiverPattern;
43      }
44  
45      /** Compute distance offset to be added to the distance between antennas reference points.
46       * @param emitterToInert transform from emitter to inertial frame at emission date
47       * @param receiverToInert transform from receiver to inertial frame at reception date
48       * @return offset to be added to distance between origins, in order to get distance between phase centers
49       */
50      public double offset(final StaticTransform emitterToInert, final StaticTransform receiverToInert) {
51  
52          // compute the relative positions of frames origins
53          final Vector3D emitterOrigin  = emitterToInert.transformPosition(Vector3D.ZERO);
54          final Vector3D receiverOrigin = receiverToInert.transformPosition(Vector3D.ZERO);
55          final Vector3D deltaOrigins   = receiverOrigin.subtract(emitterOrigin);
56  
57          // compute the relative positions of mean phase centers
58          final Vector3D emitterMean    = emitterToInert.transformPosition(emitterPattern.getEccentricities());
59          final Vector3D receiverMean   = receiverToInert.transformPosition(receiverPattern.getEccentricities());
60          final Vector3D deltaMeans     = receiverMean.subtract(emitterMean);
61  
62          // compute the phase variation at emission
63          final Vector3D emitterLos = emitterToInert.getRotation().applyInverseTo(deltaMeans);
64          final double   emitterPCV = emitterPattern.getPhaseCenterVariation(emitterLos);
65  
66          // compute the phase variation at reception
67          final Vector3D receiverLos = receiverToInert.getRotation().applyInverseTo(deltaMeans.negate());
68          final double   receiverPCV = receiverPattern.getPhaseCenterVariation(receiverLos);
69  
70          // compute the total offset resulting from both antennas phase centers
71          return deltaMeans.getNorm() - deltaOrigins.getNorm() + emitterPCV + receiverPCV;
72  
73      }
74  
75  }