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