SensorPixelCrossing.java

  1. /* Copyright 2013-2017 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (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.RuggedExceptionWrapper;
  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.      * @exception RuggedException if the maximum number of evaluations is exceeded
  64.      */
  65.     public double locatePixel(final AbsoluteDate date) throws RuggedException {
  66.         try {

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

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

  83.         } catch (MathIllegalArgumentException nbe) {
  84.             // there are no solutions in the search interval
  85.             return Double.NaN;
  86.         } catch (RuggedExceptionWrapper rew) {
  87.             throw rew.getException();
  88.         }
  89.     }

  90.     /** Interpolate sensor pixels at some pixel index.
  91.      * @param date current date
  92.      * @param x pixel index
  93.      * @return interpolated direction for specified index
  94.      * @exception RuggedException if date cannot be handled
  95.      */
  96.     private Vector3D getLOS(final AbsoluteDate date, final double x)
  97.         throws RuggedException {

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

  101.         // interpolate
  102.         return new Vector3D(iSup - x, sensor.getLOS(date, iInf),
  103.                             x - iInf, sensor.getLOS(date, iSup)).normalize();

  104.     }

  105. }