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 }