FieldElevationExtremumDetector.java

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

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

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

  69.     /** Protected constructor with full parameters.
  70.      * <p>
  71.      * This constructor is not public as users are expected to use the builder
  72.      * API with the various {@code withXxx()} methods to set up the instance
  73.      * in a readable manner without using a huge amount of parameters.
  74.      * </p>
  75.      * @param detectionSettings event detection settings
  76.      * @param handler event handler to call at event occurrences
  77.      * @param topo topocentric frame centered on ground point
  78.      */
  79.     protected FieldElevationExtremumDetector(final FieldEventDetectionSettings<T> detectionSettings,
  80.                                              final FieldEventHandler<T> handler,
  81.                                              final TopocentricFrame topo) {
  82.         super(detectionSettings, handler, topo);
  83.     }

  84.     /** {@inheritDoc} */
  85.     @Override
  86.     protected FieldElevationExtremumDetector<T> create(final FieldEventDetectionSettings<T> detectionSettings,
  87.                                                        final FieldEventHandler<T> newHandler) {
  88.         return new FieldElevationExtremumDetector<>(detectionSettings, newHandler, getTopocentricFrame());
  89.     }

  90.     /** Get the elevation value.
  91.      * @param s the current state information: date, kinematics, attitude
  92.      * @return spacecraft elevation
  93.      */
  94.     public T getElevation(final FieldSpacecraftState<T> s) {
  95.         return getTopocentricFrame().getElevation(s.getPosition(), s.getFrame(), s.getDate());
  96.     }

  97.     /** Compute the value of the detection function.
  98.      * <p>
  99.      * The value is the spacecraft elevation first time derivative.
  100.      * </p>
  101.      * @param s the current state information: date, kinematics, attitude
  102.      * @return spacecraft elevation first time derivative
  103.      */
  104.     public T g(final FieldSpacecraftState<T> s) {

  105.         // get position, velocity acceleration of spacecraft in topocentric frame
  106.         final FieldStaticTransform<FieldUnivariateDerivative1<T>> inertToTopo = s.getFrame().getStaticTransformTo(getTopocentricFrame(),
  107.                 s.getDate().toFUD1Field());
  108.         final FieldVector3D<FieldUnivariateDerivative1<T>> positionInert = s.getPVCoordinates().toUnivariateDerivative1Vector();
  109.         final FieldVector3D<FieldUnivariateDerivative1<T>> posTopo = inertToTopo.transformPosition(positionInert);

  110.         // compute elevation and its first time derivative
  111.         final FieldUnivariateDerivative1<T> elevation = posTopo.getDelta();

  112.         // return elevation first time derivative
  113.         return elevation.getFirstDerivative();

  114.     }

  115. }