1   /* Copyright 2002-2024 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  
19  import org.hipparchus.ode.events.Action;
20  import org.orekit.bodies.BodyShape;
21  import org.orekit.bodies.GeodeticPoint;
22  import org.orekit.frames.Frame;
23  import org.orekit.propagation.SpacecraftState;
24  import org.orekit.propagation.events.handlers.EventHandler;
25  import org.orekit.propagation.events.handlers.StopOnDecreasing;
26  
27  /** Finder for satellite altitude crossing events.
28   * <p>This class finds altitude events (i.e. satellite crossing
29   * a predefined altitude level above ground).</p>
30   * <p>The default implementation behavior is to {@link Action#CONTINUE
31   * continue} propagation when ascending and to {@link Action#STOP stop}
32   * propagation when descending. This can be changed by calling
33   * {@link #withHandler(EventHandler)} after construction.</p>
34   * @see org.orekit.propagation.Propagator#addEventDetector(EventDetector)
35   * @author Luc Maisonobe
36   */
37  public class AltitudeDetector extends AbstractDetector<AltitudeDetector> {
38  
39      /** Threshold altitude value (m). */
40      private final double altitude;
41  
42      /** Body shape with respect to which altitude should be evaluated. */
43      private final BodyShape bodyShape;
44  
45      /** Build a new altitude detector.
46       * <p>This simple constructor takes default values for maximal checking
47       *  interval ({@link #DEFAULT_MAXCHECK}) and convergence threshold
48       * ({@link #DEFAULT_THRESHOLD}).</p>
49       * @param altitude threshold altitude value
50       * @param bodyShape body shape with respect to which altitude should be evaluated
51       */
52      public AltitudeDetector(final double altitude, final BodyShape bodyShape) {
53          this(DEFAULT_MAXCHECK, DEFAULT_THRESHOLD, altitude, bodyShape);
54      }
55  
56      /** Build a new altitude detector.
57       * <p>This simple constructor takes default value for convergence threshold
58       * ({@link #DEFAULT_THRESHOLD}).</p>
59       * <p>The maximal interval between altitude checks should
60       * be smaller than the half duration of the minimal pass to handle,
61       * otherwise some short passes could be missed.</p>
62       * @param maxCheck maximal checking interval (s)
63       * @param altitude threshold altitude value (m)
64       * @param bodyShape body shape with respect to which altitude should be evaluated
65       */
66      public AltitudeDetector(final double maxCheck,
67                              final double altitude,
68                              final BodyShape bodyShape) {
69          this(maxCheck, DEFAULT_THRESHOLD, altitude, bodyShape);
70      }
71  
72      /** Build a new altitude detector.
73       * <p>The maximal interval between altitude checks should
74       * be smaller than the half duration of the minimal pass to handle,
75       * otherwise some short passes could be missed.</p>
76       * <p>The maximal interval between altitude checks should
77       * be smaller than the half duration of the minimal pass to handle,
78       * otherwise some short passes could be missed.</p>
79       * @param maxCheck maximal checking interval (s)
80       * @param threshold convergence threshold (s)
81       * @param altitude threshold altitude value (m)
82       * @param bodyShape body shape with respect to which altitude should be evaluated
83       */
84      public AltitudeDetector(final double maxCheck,
85                              final double threshold,
86                              final double altitude,
87                              final BodyShape bodyShape) {
88          this(AdaptableInterval.of(maxCheck), threshold, DEFAULT_MAX_ITER, new StopOnDecreasing(),
89               altitude, bodyShape);
90      }
91  
92      /** Protected constructor with full parameters.
93       * <p>
94       * This constructor is not public as users are expected to use the builder
95       * API with the various {@code withXxx()} methods to set up the instance
96       * in a readable manner without using a huge amount of parameters.
97       * </p>
98       * @param maxCheck maximum checking interval
99       * @param threshold convergence threshold (s)
100      * @param maxIter maximum number of iterations in the event time search
101      * @param handler event handler to call at event occurrences
102      * @param altitude threshold altitude value (m)
103      * @param bodyShape body shape with respect to which altitude should be evaluated
104      * @since 6.1
105      */
106     protected AltitudeDetector(final AdaptableInterval maxCheck, final double threshold,
107                                final int maxIter, final EventHandler handler,
108                                final double altitude,
109                                final BodyShape bodyShape) {
110         super(maxCheck, threshold, maxIter, handler);
111         this.altitude  = altitude;
112         this.bodyShape = bodyShape;
113     }
114 
115     /** {@inheritDoc} */
116     @Override
117     protected AltitudeDetector create(final AdaptableInterval newMaxCheck, final double newThreshold,
118                                       final int newMaxIter, final EventHandler newHandler) {
119         return new AltitudeDetector(newMaxCheck, newThreshold, newMaxIter, newHandler,
120                                     altitude, bodyShape);
121     }
122 
123     /** Get the threshold altitude value.
124      * @return the threshold altitude value (m)
125      */
126     public double getAltitude() {
127         return altitude;
128     }
129 
130     /** Get the body shape.
131      * @return the body shape
132      */
133     public BodyShape getBodyShape() {
134         return bodyShape;
135     }
136 
137     /** Compute the value of the switching function.
138      * This function measures the difference between the current altitude
139      * and the threshold altitude.
140      * @param s the current state information: date, kinematics, attitude
141      * @return value of the switching function
142      */
143     public double g(final SpacecraftState s) {
144         final Frame bodyFrame      = bodyShape.getBodyFrame();
145         final GeodeticPoint point  = bodyShape.transform(s.getPosition(bodyFrame), bodyFrame, s.getDate());
146         return point.getAltitude() - altitude;
147     }
148 
149 }