SensorPixelCrossing.java

  1. /* Copyright 2013-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.rugged.linesensor;

  18. import org.hipparchus.analysis.UnivariateFunction;
  19. import org.hipparchus.analysis.solvers.BracketingNthOrderBrentSolver;
  20. import org.hipparchus.analysis.solvers.UnivariateSolver;
  21. import org.hipparchus.exception.MathIllegalArgumentException;
  22. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  23. import org.hipparchus.util.FastMath;
  24. import org.orekit.rugged.errors.RuggedException;
  25. import org.orekit.rugged.errors.RuggedInternalError;
  26. import org.orekit.time.AbsoluteDate;

  27. /** Class devoted to locate where ground point crosses a sensor line.
  28.  * <p>
  29.  * This class is used in the first stage of inverse location.
  30.  * </p>
  31.  * @author Luc Maisonobe
  32.  */
  33. public class SensorPixelCrossing {

  34.     /** Margin before and after end pixels, in order to avoid search failures near boundaries. */
  35.     private static final double MARGIN = 10.0;

  36.     /** Line sensor. */
  37.     private final LineSensor sensor;

  38.     /** Cross direction in spacecraft frame. */
  39.     private final Vector3D cross;

  40.     /** Maximum number of evaluations. */
  41.     private final int maxEval;

  42.     /** Accuracy to use for finding crossing line number. */
  43.     private final double accuracy;

  44.     /** Simple constructor.
  45.      * @param sensor sensor to consider
  46.      * @param meanNormal mean plane normal of the line sensor
  47.      * @param targetDirection target direction in spacecraft frame
  48.      * @param maxEval maximum number of evaluations
  49.      * @param accuracy accuracy to use for finding crossing line number
  50.      */
  51.     public SensorPixelCrossing(final LineSensor sensor, final Vector3D meanNormal,
  52.                                final Vector3D targetDirection,
  53.                                final int maxEval, final double accuracy) {
  54.         this.sensor   = sensor;
  55.         this.cross    = Vector3D.crossProduct(meanNormal, targetDirection).normalize();
  56.         this.maxEval  = maxEval;
  57.         this.accuracy = accuracy;
  58.     }

  59.     /** Locate pixel along sensor line.
  60.      * @param date current date
  61.      * @return pixel location ({@code Double.NaN} if the first and last
  62.      * pixels of the line do not bracket a location)
  63.      */
  64.     public double locatePixel(final AbsoluteDate date) {
  65.         try {

  66.             // set up function evaluating to 0.0 where target matches pixel
  67.             final UnivariateFunction f = new UnivariateFunction() {
  68.                 /** {@inheritDoc} */
  69.                 @Override
  70.                 public double value(final double x) {
  71.                     try {
  72.                         return Vector3D.angle(cross, getLOS(date, x)) - 0.5 * FastMath.PI;
  73.                     } catch (RuggedException re) {
  74.                         throw new RuggedInternalError(re);
  75.                     }
  76.                 }
  77.             };

  78.             // find the root
  79.             final UnivariateSolver solver =
  80.                     new BracketingNthOrderBrentSolver(0.0, accuracy, 5);
  81.             return solver.solve(maxEval, f, -MARGIN, sensor.getNbPixels() - 1 + MARGIN);

  82.         } catch (MathIllegalArgumentException nbe) {
  83.             // there are no solutions in the search interval
  84.             return Double.NaN;
  85.         }
  86.     }

  87.     /** Interpolate sensor pixels at some pixel index.
  88.      * @param date current date
  89.      * @param x pixel index
  90.      * @return interpolated direction for specified index
  91.      */
  92.     private Vector3D getLOS(final AbsoluteDate date, final double x) {

  93.         // find surrounding pixels
  94.         final int iInf = FastMath.max(0, FastMath.min(sensor.getNbPixels() - 2, (int) FastMath.floor(x)));
  95.         final int iSup = iInf + 1;

  96.         // interpolate
  97.         return new Vector3D(iSup - x, sensor.getLOS(date, iInf),
  98.                             x - iInf, sensor.getLOS(date, iSup)).normalize();

  99.     }

  100. }