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