FieldElevationExtremumDetector.java

  1. /* Copyright 2002-2024 Luc Maisonobe
  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.CalculusFieldElement;
  19. import org.hipparchus.Field;
  20. import org.hipparchus.analysis.differentiation.FieldUnivariateDerivative1;
  21. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  22. import org.hipparchus.ode.events.FieldEventSlopeFilter;
  23. import org.orekit.frames.FieldKinematicTransform;
  24. import org.orekit.frames.TopocentricFrame;
  25. import org.orekit.propagation.FieldSpacecraftState;
  26. import org.orekit.propagation.events.handlers.FieldEventHandler;
  27. import org.orekit.propagation.events.handlers.FieldStopOnIncreasing;
  28. import org.orekit.utils.TimeStampedFieldPVCoordinates;

  29. /** Detector for elevation extremum with respect to a ground point.
  30.  * <p>This detector identifies when a spacecraft reaches its
  31.  * extremum elevation with respect to a ground point.</p>
  32.  * <p>
  33.  * As in most cases only the elevation maximum is needed and the
  34.  * minimum is often irrelevant, this detector is often wrapped into
  35.  * an {@link FieldEventSlopeFilter event slope filter} configured with
  36.  * {@link FilterType#TRIGGER_ONLY_DECREASING_EVENTS} (i.e. when the
  37.  * elevation derivative decreases from positive values to negative values,
  38.  * which correspond to a maximum). Setting up this filter saves some computation
  39.  * time as the elevation minimum occurrences are not even looked at. It is
  40.  * however still often necessary to do an additional filtering
  41.  * </p>
  42.  * @param <T> type of the field element
  43.  * @author Luc Maisonobe
  44.  * @since 12.0
  45.  */
  46. public class FieldElevationExtremumDetector<T extends CalculusFieldElement<T>>
  47.     extends FieldAbstractDetector<FieldElevationExtremumDetector<T>, T> {

  48.     /** Topocentric frame in which elevation should be evaluated. */
  49.     private final TopocentricFrame topo;

  50.     /** Build a new detector.
  51.      * <p>The new instance uses default values for maximal checking interval
  52.      * ({@link #DEFAULT_MAXCHECK}) and convergence threshold ({@link
  53.      * #DEFAULT_THRESHOLD}).</p>
  54.      * @param field field to which elements belong
  55.      * @param topo topocentric frame centered on ground point
  56.      */
  57.     public FieldElevationExtremumDetector(final Field<T> field, final TopocentricFrame topo) {
  58.         this(field.getZero().newInstance(DEFAULT_MAXCHECK),
  59.              field.getZero().newInstance(DEFAULT_THRESHOLD),
  60.              topo);
  61.     }

  62.     /** Build a detector.
  63.      * @param maxCheck maximal checking interval (s)
  64.      * @param threshold convergence threshold (s)
  65.      * @param topo topocentric frame centered on ground point
  66.      */
  67.     public FieldElevationExtremumDetector(final T maxCheck, final T threshold,
  68.                                           final TopocentricFrame topo) {
  69.         this(FieldAdaptableInterval.of(maxCheck.getReal()), threshold, DEFAULT_MAX_ITER, new FieldStopOnIncreasing<>(),
  70.              topo);
  71.     }

  72.     /** Protected constructor with full parameters.
  73.      * <p>
  74.      * This constructor is not public as users are expected to use the builder
  75.      * API with the various {@code withXxx()} methods to set up the instance
  76.      * in a readable manner without using a huge amount of parameters.
  77.      * </p>
  78.      * @param maxCheck maximum checking interval
  79.      * @param threshold convergence threshold (s)
  80.      * @param maxIter maximum number of iterations in the event time search
  81.      * @param handler event handler to call at event occurrences
  82.      * @param topo topocentric frame centered on ground point
  83.      */
  84.     protected FieldElevationExtremumDetector(final FieldAdaptableInterval<T> maxCheck, final T threshold,
  85.                                              final int maxIter, final FieldEventHandler<T> handler,
  86.                                              final TopocentricFrame topo) {
  87.         super(maxCheck, threshold, maxIter, handler);
  88.         this.topo = topo;
  89.     }

  90.     /** {@inheritDoc} */
  91.     @Override
  92.     protected FieldElevationExtremumDetector<T> create(final FieldAdaptableInterval<T> newMaxCheck, final T newThreshold,
  93.                                                        final int newMaxIter,
  94.                                                        final FieldEventHandler<T> newHandler) {
  95.         return new FieldElevationExtremumDetector<>(newMaxCheck, newThreshold, newMaxIter, newHandler, topo);
  96.     }

  97.     /**
  98.      * Returns the topocentric frame centered on ground point.
  99.      * @return topocentric frame centered on ground point
  100.      */
  101.     public TopocentricFrame getTopocentricFrame() {
  102.         return this.topo;
  103.     }

  104.     /** Get the elevation value.
  105.      * @param s the current state information: date, kinematics, attitude
  106.      * @return spacecraft elevation
  107.      */
  108.     public T getElevation(final FieldSpacecraftState<T> s) {
  109.         return topo.getElevation(s.getPosition(), s.getFrame(), s.getDate());
  110.     }

  111.     /** Compute the value of the detection function.
  112.      * <p>
  113.      * The value is the spacecraft elevation first time derivative.
  114.      * </p>
  115.      * @param s the current state information: date, kinematics, attitude
  116.      * @return spacecraft elevation first time derivative
  117.      */
  118.     public T g(final FieldSpacecraftState<T> s) {

  119.         // get position, velocity acceleration of spacecraft in topocentric frame
  120.         final FieldKinematicTransform<T> inertToTopo = s.getFrame().getKinematicTransformTo(topo, s.getDate());
  121.         final TimeStampedFieldPVCoordinates<T> pvTopo = inertToTopo.transformOnlyPV(s.getPVCoordinates());

  122.         // convert the coordinates to UnivariateDerivative1 based vector
  123.         // instead of having vector position, then vector velocity then vector acceleration
  124.         // we get one vector and each coordinate is a DerivativeStructure containing
  125.         // value, first time derivative (we don't need second time derivative here)
  126.         final FieldVector3D<FieldUnivariateDerivative1<T>> pvDS = pvTopo.toUnivariateDerivative1Vector();

  127.         // compute elevation and its first time derivative
  128.         final FieldUnivariateDerivative1<T> elevation = pvDS.getZ().divide(pvDS.getNorm()).asin();

  129.         // return elevation first time derivative
  130.         return elevation.getDerivative(1);

  131.     }

  132. }