1   /* Copyright 2002-2021 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.hipparchus.util.MathUtils;
27  import org.orekit.estimation.Context;
28  import org.orekit.frames.Frame;
29  import org.orekit.frames.Transform;
30  import org.orekit.propagation.SpacecraftState;
31  import org.orekit.time.AbsoluteDate;
32  import org.orekit.utils.Constants;
33  import org.orekit.utils.ParameterDriver;
34  
35  public class AngularRaDecMeasurementCreator extends MeasurementCreator {
36  
37      private final Context context;
38      private final ObservableSatellite satellite;
39  
40      public AngularRaDecMeasurementCreator(final Context context) {
41          this.context   = context;
42          this.satellite = new ObservableSatellite(0);
43      }
44  
45      public void init(SpacecraftState s0, AbsoluteDate t, double step) {
46          for (final GroundStation station : context.stations) {
47              for (ParameterDriver driver : Arrays.asList(station.getClockOffsetDriver(),
48                                                          station.getEastOffsetDriver(),
49                                                          station.getNorthOffsetDriver(),
50                                                          station.getZenithOffsetDriver(),
51                                                          station.getPrimeMeridianOffsetDriver(),
52                                                          station.getPrimeMeridianDriftDriver(),
53                                                          station.getPolarOffsetXDriver(),
54                                                          station.getPolarDriftXDriver(),
55                                                          station.getPolarOffsetYDriver(),
56                                                          station.getPolarDriftYDriver())) {
57                  if (driver.getReferenceDate() == null) {
58                      driver.setReferenceDate(s0.getDate());
59                  }
60              }
61  
62          }
63      }
64  
65      public void handleStep(final SpacecraftState currentState) {
66          for (final GroundStation station : context.stations) {
67  
68              final AbsoluteDate     date      = currentState.getDate();
69              final Frame            inertial  = currentState.getFrame();
70              final Vector3D         position  = currentState.getPVCoordinates().getPosition();
71  
72              if (station.getBaseFrame().getElevation(position, inertial, date) > FastMath.toRadians(30.0)) {
73                  final UnivariateSolver solver = new BracketingNthOrderBrentSolver(1.0e-12, 5);
74  
75                  final double downLinkDelay  = solver.solve(1000, new UnivariateFunction() {
76                      public double value(final double x) {
77                          final Transform t = station.getOffsetToInertial(inertial, date.shiftedBy(x));
78                          final double d = Vector3D.distance(position, t.transformPosition(Vector3D.ZERO));
79                          return d - x * Constants.SPEED_OF_LIGHT;
80                      }
81                  }, -1.0, 1.0);
82  
83                  // Satellite position at signal departure
84                  final Vector3D satelliteAtDeparture = currentState.shiftedBy(-downLinkDelay).getPVCoordinates().getPosition();
85  
86                  // Initialize measurement
87                  final double[] angular = new double[2];
88                  final double[] sigma = {1.0, 1.0};
89                  final double[] baseweight = {10.0, 10.0};
90                  
91                  // Inertial frame used
92                  final Frame inertialFrame = context.initialOrbit.getFrame();
93                  
94                  // Station position at signal arrival
95                  // Set the reference date of offset drivers arbitrarily to avoid exception
96                  station.getPrimeMeridianOffsetDriver().setReferenceDate(date);
97                  station.getPolarOffsetXDriver().setReferenceDate(date);
98                  station.getPolarOffsetYDriver().setReferenceDate(date);
99                  final Transform offsetToInertialArrival = station.getOffsetToInertial(inertialFrame, date);
100                 final Vector3D  stationPArrival = offsetToInertialArrival.transformPosition(Vector3D.ZERO);
101                 
102                 // Vector station position at signal arrival - satellite at signal departure
103                 // In inertial reference frame
104                 final Vector3D staSat = satelliteAtDeparture.subtract(stationPArrival);
105 
106                 // Compute measurement
107                 // Right ascension
108                 final double baseRightAscension = staSat.getAlpha();
109                 angular[0] = MathUtils.normalizeAngle(baseRightAscension, 0.0);
110 
111                 // Declination
112                 angular[1] = staSat.getDelta();
113 
114                 addMeasurement(new AngularRaDec(station, inertialFrame, date, angular, sigma, baseweight, satellite));
115             }
116 
117         }
118     }
119 
120 }