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;
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.hipparchus.util.FastMath;
24  import org.orekit.estimation.StationDataProvider;
25  import org.orekit.frames.Frame;
26  import org.orekit.frames.Transform;
27  import org.orekit.propagation.SpacecraftState;
28  import org.orekit.time.AbsoluteDate;
29  import org.orekit.utils.Constants;
30  import org.orekit.utils.ParameterDriver;
31  
32  import java.util.Arrays;
33  
34  public class AngularAzElMeasurementCreator extends MeasurementCreator {
35  
36      private final StationDataProvider context;
37      private final ObservableSatellite satellite;
38      private final double azBias;
39      private final double elBias;
40  
41      public AngularAzElMeasurementCreator(final StationDataProvider context) {
42          this(context, 0., 0.);
43      }
44  
45      public AngularAzElMeasurementCreator(final StationDataProvider context, final double azBias, final double elBias) {
46          this.context   = context;
47          this.satellite = new ObservableSatellite(0);
48          this.azBias    = azBias;
49          this.elBias    = elBias;
50      }
51  
52      public void init(SpacecraftState s0, AbsoluteDate t, double step) {
53          for (final GroundStation station : context.getStations()) {
54              for (ParameterDriver driver : Arrays.asList(station.getClockOffsetDriver(),
55                                                          station.getEastOffsetDriver(),
56                                                          station.getNorthOffsetDriver(),
57                                                          station.getZenithOffsetDriver(),
58                                                          station.getPrimeMeridianOffsetDriver(),
59                                                          station.getPrimeMeridianDriftDriver(),
60                                                          station.getPolarOffsetXDriver(),
61                                                          station.getPolarDriftXDriver(),
62                                                          station.getPolarOffsetYDriver(),
63                                                          station.getPolarDriftYDriver())) {
64                  if (driver.getReferenceDate() == null) {
65                      driver.setReferenceDate(s0.getDate());
66                  }
67              }
68  
69          }
70      }
71  
72      public void handleStep(final SpacecraftState currentState) {
73          for (final GroundStation station : context.getStations()) {
74  
75              final AbsoluteDate     date      = currentState.getDate();
76              final Frame            inertial  = currentState.getFrame();
77              final Vector3D         position  = currentState.getPVCoordinates().getPosition();
78  
79              if (station.getBaseFrame().getElevation(position, inertial, date) > FastMath.toRadians(30.0)) {
80                  final UnivariateSolver solver = new BracketingNthOrderBrentSolver(1.0e-12, 5);
81  
82                  final double downLinkDelay  = solver.solve(1000, new UnivariateFunction() {
83                      public double value(final double x) {
84                          final Transform t = station.getOffsetToInertial(inertial, date.shiftedBy(x));
85                          final double d = Vector3D.distance(position, t.transformPosition(Vector3D.ZERO));
86                          return d - x * Constants.SPEED_OF_LIGHT;
87                      }
88                  }, -1.0, 1.0);
89  
90                  // Satellite position at signal departure
91                  final Vector3D satelliteAtDeparture = currentState.shiftedBy(-downLinkDelay).getPVCoordinates().getPosition();
92  
93                  // Initialize measurement
94                  final double[] angular = new double[2];
95                  final double[] sigma = {1.0, 1.0};
96                  final double[] baseweight = {10.0, 10.0};
97  
98                  // Compute measurement
99                  // Elevation
100                 angular[1] = station.getBaseFrame().getElevation(satelliteAtDeparture,
101                                                                  currentState.getFrame(),
102                                                                  currentState.getDate()) + elBias;
103                 // Azimuth
104                 angular[0] = station.getBaseFrame().getAzimuth(satelliteAtDeparture,
105                                                                currentState.getFrame(),
106                                                                currentState.getDate()) + azBias;
107 
108                 addMeasurement(new AngularAzEl(station, date, angular, sigma, baseweight, satellite));
109             }
110 
111         }
112     }
113 
114 }