1 /* Copyright 2013-2025 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.rugged.refraction;
18
19 import org.hipparchus.analysis.interpolation.BilinearInterpolatingFunction;
20 import org.hipparchus.geometry.euclidean.threed.Vector3D;
21 import org.orekit.rugged.errors.RuggedException;
22 import org.orekit.rugged.errors.RuggedMessages;
23 import org.orekit.rugged.intersection.IntersectionAlgorithm;
24 import org.orekit.rugged.linesensor.LineSensor;
25 import org.orekit.rugged.linesensor.SensorPixel;
26 import org.orekit.rugged.utils.NormalizedGeodeticPoint;
27
28 /**
29 * Base class for atmospheric refraction model.
30 * @author Sergio Esteves
31 * @author Guylaine Prat
32 * @since 2.0
33 */
34 public abstract class AtmosphericRefraction {
35
36 /** Flag to tell if we must compute the correction.
37 * By default: computation is set up.
38 * @since 2.1
39 */
40 private boolean mustBeComputed;
41
42 /** The current atmospheric parameters.
43 * @since 2.1
44 */
45 private AtmosphericComputationParameters atmosphericParams;
46
47 /** Bilinear interpolating function for pixel (used by inverse location).
48 * @since 2.1
49 */
50 private BilinearInterpolatingFunction bifPixel;
51
52 /** Bilinear interpolating function of line (used by inverse location).
53 * @since 2.1
54 */
55 private BilinearInterpolatingFunction bifLine;
56
57 /**
58 * Default constructor.
59 */
60 protected AtmosphericRefraction() {
61 // Set up the atmospheric parameters ... with lazy evaluation of the grid (done only if necessary)
62 this.atmosphericParams = new AtmosphericComputationParameters();
63 this.mustBeComputed = true;
64 this.bifPixel = null;
65 this.bifLine = null;
66 }
67
68 /** Apply correction to the intersected point with an atmospheric refraction model.
69 * @param satPos satellite position, in <em>body frame</em>
70 * @param satLos satellite line of sight, in <em>body frame</em>
71 * @param rawIntersection intersection point before refraction correction
72 * @param algorithm intersection algorithm
73 * @return corrected point with the effect of atmospheric refraction
74 * {@link org.orekit.rugged.utils.ExtendedEllipsoid#pointAtAltitude(Vector3D, Vector3D, double)} or see
75 * {@link org.orekit.rugged.intersection.IntersectionAlgorithm#refineIntersection(org.orekit.rugged.utils.ExtendedEllipsoid, Vector3D, Vector3D, NormalizedGeodeticPoint)}
76 */
77 public abstract NormalizedGeodeticPoint applyCorrection(Vector3D satPos, Vector3D satLos, NormalizedGeodeticPoint rawIntersection,
78 IntersectionAlgorithm algorithm);
79
80 /** Deactivate computation (needed for the inverse location computation).
81 * @since 2.1
82 */
83 public void deactivateComputation() {
84 this.mustBeComputed = false;
85 }
86
87 /** Reactivate computation (needed for the inverse location computation).
88 * @since 2.1
89 */
90 public void reactivateComputation() {
91 this.mustBeComputed = true;
92 }
93
94 /** Tell if the computation must be performed.
95 * @return true if computation must be performed; false otherwise
96 * @since 2.1
97 */
98 public boolean mustBeComputed() {
99 return mustBeComputed;
100 }
101
102 /** Configuration of the interpolation grid. This grid is associated to the given sensor,
103 * with the given min and max lines.
104 * @param sensor line sensor
105 * @param minLine min line defined for the inverse location
106 * @param maxLine max line defined for the inverse location
107 * @since 2.1
108 */
109 public void configureCorrectionGrid(final LineSensor sensor, final int minLine, final int maxLine) {
110
111 atmosphericParams.configureCorrectionGrid(sensor, minLine, maxLine);
112 }
113
114 /** Check if the current atmospheric parameters are the same as the asked ones.
115 * @param sensorName the asked sensor name
116 * @param minLine the asked min line
117 * @param maxLine the asked max line
118 * @return true if same context; false otherwise
119 * @since 2.1
120 */
121 public Boolean isSameContext(final String sensorName, final int minLine, final int maxLine) {
122
123 return Double.compare(atmosphericParams.getMinLineSensor(), minLine) == 0 &&
124 Double.compare(atmosphericParams.getMaxLineSensor(), maxLine) == 0 &&
125 atmosphericParams.getSensorName().compareTo(sensorName) == 0;
126 }
127
128 /** Get the computation parameters.
129 * @return the AtmosphericComputationParameters
130 * @since 2.1
131 */
132 public AtmosphericComputationParameters getComputationParameters() {
133 return atmosphericParams;
134 }
135
136 /** Set the grid steps in pixel and line (used to compute inverse location).
137 * Overwrite the default values, for time optimization for instance.
138 * @param pixelStep pixel step for the inverse location computation
139 * @param lineStep line step for the inverse location computation
140 * @since 2.1
141 */
142 public void setGridSteps(final int pixelStep, final int lineStep) {
143 atmosphericParams.setGridSteps(pixelStep, lineStep);
144 }
145
146 /**
147 * Set the margin for computation of inverse location with atmospheric refraction correction.
148 * Overwrite the default value DEFAULT_INVLOC_MARGIN.
149 * No check is done about this margin. A recommended value is around 1.
150 * @param inverseLocMargin margin in pixel size to compute inverse location with atmospheric refraction correction.
151 * @since 3.0
152 */
153 public void setInverseLocMargin(final double inverseLocMargin) {
154 atmosphericParams.setInverseLocMargin(inverseLocMargin);
155 }
156
157 /** Compute the correction functions for pixel and lines.
158 * The corrections are computed for pixels and lines, on a regular grid at sensor level.
159 * The corrections are based on the difference on grid nodes (where direct loc is known with atmosphere refraction)
160 * and the sensor pixel found by inverse loc without atmosphere refraction.
161 * The bilinear interpolating functions are then computed for pixel and for line.
162 * Need to be computed only once for a given sensor with the same minLine and maxLine.
163 * @param sensorPixelGridInverseWithout inverse location grid WITHOUT atmospheric refraction
164 * @since 2.1
165 */
166 public void computeGridCorrectionFunctions(final SensorPixel[][] sensorPixelGridInverseWithout) {
167
168 final int nbPixelGrid = atmosphericParams.getNbPixelGrid();
169 final int nbLineGrid = atmosphericParams.getNbLineGrid();
170 final double[] pixelGrid = atmosphericParams.getUgrid();
171 final double[] lineGrid = atmosphericParams.getVgrid();
172
173 // Initialize the needed diff functions
174 final double[][] gridDiffPixel = new double[nbPixelGrid][nbLineGrid];
175 final double[][] gridDiffLine = new double[nbPixelGrid][nbLineGrid];
176
177 // Compute the difference between grids nodes WITH - without atmosphere
178 for (int lineIndex = 0; lineIndex < nbLineGrid; lineIndex++) {
179 for (int pixelIndex = 0; pixelIndex < nbPixelGrid; pixelIndex++) {
180
181 if (sensorPixelGridInverseWithout[pixelIndex][lineIndex] != null) {
182 final double diffLine = lineGrid[lineIndex] - sensorPixelGridInverseWithout[pixelIndex][lineIndex].getLineNumber();
183 final double diffPixel = pixelGrid[pixelIndex] - sensorPixelGridInverseWithout[pixelIndex][lineIndex].getPixelNumber();
184 gridDiffPixel[pixelIndex][lineIndex] = diffPixel;
185 gridDiffLine[pixelIndex][lineIndex] = diffLine;
186
187 } else {
188 // Impossible to find the sensor pixel in the given range lines
189 throw new RuggedException(RuggedMessages.SENSOR_PIXEL_NOT_FOUND_IN_RANGE_LINES,
190 atmosphericParams.getMinLineSensor(), atmosphericParams.getMaxLineSensor());
191 }
192 }
193 }
194 // Definition of the interpolating function for pixel and for line
195 this.bifPixel = new BilinearInterpolatingFunction(pixelGrid, lineGrid, gridDiffPixel);
196 this.bifLine = new BilinearInterpolatingFunction(pixelGrid, lineGrid, gridDiffLine);
197 }
198
199 /**
200 * @return the bilinear interpolating function for pixel correction
201 */
202 public BilinearInterpolatingFunction getBifPixel() {
203 return bifPixel;
204 }
205
206 /**
207 * @return the bilinear interpolating function for line correction
208 */
209 public BilinearInterpolatingFunction getBifLine() {
210 return bifLine;
211 }
212 }