FieldOfViewDetector.java

  1. /* Copyright 2002-2023 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.propagation.events;

  18. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  19. import org.hipparchus.ode.events.Action;
  20. import org.hipparchus.util.FastMath;
  21. import org.orekit.geometry.fov.FieldOfView;
  22. import org.orekit.propagation.SpacecraftState;
  23. import org.orekit.propagation.events.handlers.EventHandler;
  24. import org.orekit.propagation.events.handlers.StopOnIncreasing;
  25. import org.orekit.utils.PVCoordinatesProvider;

  26. /** Finder for target entry/exit events with respect to a satellite sensor
  27.  * {@link FieldOfView Field Of View}.
  28.  * <p>Beware that this detector is unaware of any bodies occluding line-of-sight to
  29.  * the target. It can be therefore used for many contexts from Earth Observation to
  30.  * interplanetary mission design. For instance, in an Earth Observation context,
  31.  * it can be easily combined to an {@link ElevationDetector} using
  32.  * {@link BooleanDetector#andCombine(java.util.Collection)} to calculate station
  33.  * visibility opportunities within the satellite's field of view.
  34.  * <p>The default implementation behavior is to {@link Action#CONTINUE continue}
  35.  * propagation at FOV entry and to {@link Action#STOP stop} propagation
  36.  * at FOV exit. This can be changed by calling
  37.  * {@link #withHandler(EventHandler)} after construction.</p>
  38.  * @see org.orekit.propagation.Propagator#addEventDetector(EventDetector)
  39.  * @see FootprintOverlapDetector
  40.  * @see VisibilityTrigger
  41.  * @author Luc Maisonobe
  42.  * @since 7.1
  43.  */
  44. public class FieldOfViewDetector extends AbstractDetector<FieldOfViewDetector> {

  45.     /** Position/velocity provider of the considered target. */
  46.     private final PVCoordinatesProvider targetPVProvider;

  47.     /** Radius of the target, considered to be a spherical body (m). */
  48.     private final double radiusTarget;

  49.     /** Visibility trigger for spherical bodies. */
  50.     private final VisibilityTrigger trigger;

  51.     /** Field of view. */
  52.     private final FieldOfView fov;

  53.     /** Build a new instance.
  54.      * <p>The maximal interval between distance to FOV boundary checks should
  55.      * be smaller than the half duration of the minimal pass to handle,
  56.      * otherwise some short passes could be missed.</p>
  57.      * @param pvTarget Position/velocity provider of the considered target
  58.      * @param fov Field Of View
  59.      * @since 10.1
  60.      */
  61.     public FieldOfViewDetector(final PVCoordinatesProvider pvTarget, final FieldOfView fov) {
  62.         this(pvTarget, 0.0, VisibilityTrigger.VISIBLE_AS_SOON_AS_PARTIALLY_IN_FOV, fov);
  63.     }

  64.     /** Build a new instance.
  65.      * <p>The maximal interval between distance to FOV boundary checks should
  66.      * be smaller than the half duration of the minimal pass to handle,
  67.      * otherwise some short passes could be missed.</p>
  68.      * @param pvTarget Position/velocity provider of the considered target
  69.      * @param radiusTarget radius of the target, considered to be a spherical body (m)
  70.      * @param trigger visibility trigger for spherical bodies
  71.      * @param fov Field Of View
  72.      * @since 10.1
  73.      */
  74.     public FieldOfViewDetector(final PVCoordinatesProvider pvTarget, final double radiusTarget,
  75.                                final VisibilityTrigger trigger, final FieldOfView fov) {
  76.         this(s -> DEFAULT_MAXCHECK, DEFAULT_THRESHOLD, DEFAULT_MAX_ITER,
  77.              new StopOnIncreasing(),
  78.              pvTarget, radiusTarget, trigger, fov);
  79.     }

  80.     /** Protected constructor with full parameters.
  81.      * <p>
  82.      * This constructor is not public as users are expected to use the builder
  83.      * API with the various {@code withXxx()} methods to set up the instance
  84.      * in a readable manner without using a huge amount of parameters.
  85.      * </p>
  86.      * @param maxCheck maximum checking interval
  87.      * @param threshold convergence threshold (s)
  88.      * @param maxIter maximum number of iterations in the event time search
  89.      * @param handler event handler to call at event occurrences
  90.      * @param pvTarget Position/velocity provider of the considered target
  91.      * @param radiusTarget radius of the target, considered to be a spherical body (m)
  92.      * @param trigger visibility trigger for spherical bodies
  93.      * @param fov Field Of View
  94.      */
  95.     protected FieldOfViewDetector(final AdaptableInterval maxCheck, final double threshold, final int maxIter,
  96.                                   final EventHandler handler,
  97.                                   final PVCoordinatesProvider pvTarget, final double radiusTarget,
  98.                                   final VisibilityTrigger trigger, final FieldOfView fov) {
  99.         super(maxCheck, threshold, maxIter, handler);
  100.         this.targetPVProvider = pvTarget;
  101.         this.radiusTarget     = radiusTarget;
  102.         this.trigger          = trigger;
  103.         this.fov              = fov;
  104.     }

  105.     /** {@inheritDoc} */
  106.     @Override
  107.     protected FieldOfViewDetector create(final AdaptableInterval newMaxCheck, final double newThreshold,
  108.                                          final int newMaxIter,
  109.                                          final EventHandler newHandler) {
  110.         return new FieldOfViewDetector(newMaxCheck, newThreshold, newMaxIter, newHandler,
  111.                                        targetPVProvider, radiusTarget, trigger, fov);
  112.     }

  113.     /** Get the position/velocity provider of the target .
  114.      * @return the position/velocity provider of the target
  115.      */
  116.     public PVCoordinatesProvider getPVTarget() {
  117.         return targetPVProvider;
  118.     }

  119.     /** Get the Field Of View.
  120.      * @return Field Of View
  121.      * @since 10.1
  122.      */
  123.     public FieldOfView getFOV() {
  124.         return fov;
  125.     }

  126.     /** {@inheritDoc}
  127.      * <p>
  128.      * The g function value is the angular offset between the
  129.      * target center and the {@link FieldOfView#offsetFromBoundary(Vector3D,
  130.      * double, VisibilityTrigger) Field Of View boundary}, plus or minus the
  131.      * target angular radius depending on the {@link VisibilityTrigger}, minus
  132.      * the {@link FieldOfView#getMargin() Field Of View margin}. It is therefore
  133.      * negative if the target is visible within the Field Of View and positive
  134.      * if it is outside of the Field Of View.
  135.      * </p>
  136.      * <p>
  137.      * As per the previous definition, when the target enters the Field Of
  138.      * View, a decreasing event is generated, and when the target leaves
  139.      * the Field Of View, an increasing event is generated.
  140.      * </p>
  141.      */
  142.     public double g(final SpacecraftState s) {

  143.         // get line of sight in spacecraft frame
  144.         final Vector3D targetPosInert =
  145.                 targetPVProvider.getPosition(s.getDate(), s.getFrame());
  146.         final Vector3D lineOfSightSC = s.toTransform().transformPosition(targetPosInert);

  147.         final double angularRadius = FastMath.asin(radiusTarget / lineOfSightSC.getNorm());
  148.         return fov.offsetFromBoundary(lineOfSightSC, angularRadius, trigger);

  149.     }

  150. }