1 /* Copyright 2022-2026 Romain Serra
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.signal;
18
19 import org.hipparchus.geometry.euclidean.threed.Vector3D;
20 import org.hipparchus.optim.ConvergenceChecker;
21 import org.hipparchus.util.FastMath;
22 import org.orekit.frames.Frame;
23 import org.orekit.time.AbsoluteDate;
24 import org.orekit.utils.Constants;
25 import org.orekit.utils.PVCoordinatesProvider;
26
27 /**
28 * Abstract class for computation of signal travel time in vacuum.
29 * @since 14.0
30 * @author Romain Serra
31 * @author Luc Maisonnobe
32 */
33 abstract class AbstractSignalTravelTime {
34
35 /** Reciprocal for light speed. */
36 protected static final double C_RECIPROCAL = 1.0 / Constants.SPEED_OF_LIGHT;
37
38 /** Maximum number of iterations. */
39 protected static final int DEFAULT_MAX_ITER = 10;
40
41 /** Convergence checker. */
42 private final ConvergenceChecker<Double> convergenceChecker;
43
44 /**
45 * Constructor.
46 * @param convergenceChecker convergence checker
47 */
48 protected AbstractSignalTravelTime(final ConvergenceChecker<Double> convergenceChecker) {
49 this.convergenceChecker = convergenceChecker;
50 }
51
52 /**
53 * Get the default convergence checker.
54 * @return checker
55 */
56 static ConvergenceChecker<Double> getDefaultConvergenceChecker() {
57 return (iteration, previous, current) -> iteration != 0 && (iteration > DEFAULT_MAX_ITER ||
58 FastMath.abs(previous - current) <= 2 * FastMath.ulp(current));
59 }
60
61 /**
62 * Getter for the convergence checker.
63 * @return checker
64 */
65 public ConvergenceChecker<Double> getConvergenceChecker() {
66 return convergenceChecker;
67 }
68
69 /** Compute propagation delay on a link leg (typically downlink or uplink).
70 * The max. iteration number and convergence checker can be tweaked to emulate no-delay a.k.a. instantaneous transmission.
71 * @param pvCoordinatesProvider adjustable emitter/receiver
72 * @param initialOffset guess for the time off set
73 * @param fixedPosition fixed receiver/emitter position
74 * @param guessDate guess for emission/reception date
75 * @param frame Inertial frame in which receiver/emitter is defined.
76 * @return <em>positive</em> delay between signal emission and signal reception dates
77 */
78 protected double compute(final PVCoordinatesProvider pvCoordinatesProvider, final double initialOffset,
79 final Vector3D fixedPosition, final AbsoluteDate guessDate, final Frame frame) {
80 double delay = initialOffset;
81
82 // search signal transit date, computing the signal travel in inertial frame
83 double previous = 0.;
84 int count = 0;
85 while (!convergenceChecker.converged(count, previous, delay)) {
86 previous = delay;
87 final double shift = computeShift(initialOffset, delay);
88 final Vector3D pos = pvCoordinatesProvider.getPosition(guessDate.shiftedBy(shift), frame);
89 delay = fixedPosition.distance(pos) * C_RECIPROCAL;
90 count++;
91 }
92
93 return delay;
94
95 }
96
97 /**
98 * Computes the time shift.
99 * @param offset time offset
100 * @param delay time delay
101 * @return time shift to use in computation
102 */
103 protected abstract double computeShift(double offset, double delay);
104
105 }