1   /* Copyright 2002-2022 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.gnss;
18  
19  import org.hipparchus.analysis.UnivariateFunction;
20  import org.hipparchus.analysis.solvers.BracketingNthOrderBrentSolver;
21  import org.hipparchus.analysis.solvers.UnivariateSolver;
22  import org.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.orekit.errors.OrekitException;
24  import org.orekit.estimation.measurements.MeasurementCreator;
25  import org.orekit.estimation.measurements.ObservableSatellite;
26  import org.orekit.estimation.measurements.modifiers.OneWayGNSSPhaseAmbiguityModifier;
27  import org.orekit.gnss.Frequency;
28  import org.orekit.propagation.BoundedPropagator;
29  import org.orekit.propagation.SpacecraftState;
30  import org.orekit.time.AbsoluteDate;
31  import org.orekit.utils.Constants;
32  
33  public class OneWayGNSSPhaseCreator extends MeasurementCreator {
34  
35      private final BoundedPropagator                ephemeris;
36      private final double                           remoteClk;
37      private final double                           wavelength;
38      private final OneWayGNSSPhaseAmbiguityModifier ambiguity;
39      private final Vector3D                         antennaPhaseCenter1;
40      private final Vector3D                         antennaPhaseCenter2;
41      private final ObservableSatellite              local;
42  
43      public OneWayGNSSPhaseCreator(final BoundedPropagator ephemeris,
44                                    final Frequency frequency,
45                                    final int ambiguity, 
46                                    final double localClockOffset,
47                                    final double remoteClockOffset) {
48          this(ephemeris, frequency, ambiguity, localClockOffset, remoteClockOffset, Vector3D.ZERO, Vector3D.ZERO);
49      }
50  
51      public OneWayGNSSPhaseCreator(final BoundedPropagator ephemeris,
52                                    final Frequency frequency,
53                                    final int ambiguity, 
54                                    final double localClockOffset,
55                                    final double remoteClockOffset,
56                                    final Vector3D antennaPhaseCenter1,
57                                    final Vector3D antennaPhaseCenter2) {
58          this.ephemeris           = ephemeris;
59          this.remoteClk           = remoteClockOffset;
60          this.antennaPhaseCenter1 = antennaPhaseCenter1;
61          this.antennaPhaseCenter2 = antennaPhaseCenter2;
62          this.wavelength          = frequency.getWavelength();
63          this.ambiguity           = new OneWayGNSSPhaseAmbiguityModifier(0, ambiguity);
64          this.local               = new ObservableSatellite(0);
65          this.local.getClockOffsetDriver().setValue(localClockOffset);
66      }
67  
68      public ObservableSatellite getLocalSatellite() {
69          return local;
70      }
71  
72      public void init(final SpacecraftState s0, final AbsoluteDate t, final double step) {
73          if (local.getClockOffsetDriver().getReferenceDate() == null) {
74              local.getClockOffsetDriver().setReferenceDate(s0.getDate());
75          }
76      }
77  
78      public void handleStep(final SpacecraftState currentState) {
79          try {
80              final double           n         = ambiguity.getParametersDrivers().get(0).getValue();
81              final double           localClk  = local.getClockOffsetDriver().getValue();
82              final double           deltaD    = Constants.SPEED_OF_LIGHT * (localClk - remoteClk);
83              final AbsoluteDate     date      = currentState.getDate();
84              final Vector3D         position  = currentState.toTransform().getInverse().transformPosition(antennaPhaseCenter1);
85  
86              final UnivariateSolver solver = new BracketingNthOrderBrentSolver(1.0e-12, 5);
87  
88              final double downLinkDelay  = solver.solve(1000, new UnivariateFunction() {
89                  public double value(final double x) {
90                      final Vector3D other = ephemeris.
91                                      propagate(date.shiftedBy(-x)).
92                                      toTransform().
93                                      getInverse().
94                                      transformPosition(antennaPhaseCenter2);
95                      final double d = Vector3D.distance(position, other);
96                      return d - x * Constants.SPEED_OF_LIGHT;
97                  }
98              }, -1.0, 1.0);
99              final AbsoluteDate transitDate = currentState.getDate().shiftedBy(-downLinkDelay);
100             final Vector3D otherAtTransit =
101                             ephemeris.propagate(transitDate).
102                             toTransform().
103                             getInverse().
104                             transformPosition(antennaPhaseCenter2);
105             final double downLinkDistance = Vector3D.distance(position, otherAtTransit);
106 
107             // Generate measurement
108             final OneWayGNSSPhase gnssPhase = new OneWayGNSSPhase(ephemeris, remoteClk, date.shiftedBy(localClk), (downLinkDistance + deltaD) / wavelength + n, wavelength, 1.0, 10.0, local);
109             gnssPhase.addModifier(ambiguity);
110             addMeasurement(gnssPhase);
111 
112         } catch (OrekitException oe) {
113             throw new OrekitException(oe);
114         }
115     }
116 
117 }