1 /* Copyright 2002-2025 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.CalculusFieldElement;
20 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
21 import org.hipparchus.ode.events.Action;
22 import org.orekit.orbits.FieldOrbit;
23 import org.orekit.propagation.FieldSpacecraftState;
24 import org.orekit.propagation.events.handlers.FieldEventHandler;
25 import org.orekit.propagation.events.handlers.FieldStopOnIncreasing;
26 import org.orekit.utils.FieldPVCoordinates;
27
28 /** Finder for apside crossing events.
29 * <p>This class finds apside crossing events (i.e. apogee or perigee crossing).</p>
30 * <p>The default implementation behavior is to {@link Action#CONTINUE continue}
31 * propagation at apogee crossing and to {@link Action#STOP stop} propagation
32 * at perigee crossing. This can be changed by calling
33 * {@link #withHandler(FieldEventHandler)} after construction.</p>
34 * <p>Beware that apside detection will fail for almost circular orbits. If
35 * for example an apside detector is used to trigger an {@link
36 * org.orekit.forces.maneuvers.ImpulseManeuver ImpulseManeuver} and the maneuver
37 * change the orbit shape to circular, then the detector may completely fail just
38 * after the maneuver has been performed!</p>
39 * @see org.orekit.propagation.FieldPropagator#addEventDetector(FieldEventDetector)
40 * @author Luc Maisonobe
41 * @param <T> type of the field elements
42 */
43 public class FieldApsideDetector<T extends CalculusFieldElement<T>> extends FieldAbstractDetector<FieldApsideDetector<T>, T> {
44
45 /** Build a new instance.
46 * <p>The Keplerian period is used only to set an upper bound for the
47 * max check interval to period/3 and to set the convergence threshold.</p>
48 * @param keplerianPeriod estimate of the Keplerian period
49 * @since 12.1
50 */
51 public FieldApsideDetector(final T keplerianPeriod) {
52 super(new FieldEventDetectionSettings<>(keplerianPeriod.divide(3).getReal(), keplerianPeriod.multiply(1e-13),
53 DEFAULT_MAX_ITER), new FieldStopOnIncreasing<>());
54 }
55
56 /** Build a new instance.
57 * <p>The orbit is used only to set an upper bound for the
58 * max check interval to period/3 and to set the convergence
59 * threshold according to orbit size</p>
60 * @param orbit initial orbit
61 */
62 public FieldApsideDetector(final FieldOrbit<T> orbit) {
63 this(orbit.getKeplerianPeriod());
64 }
65
66 /** Build a new instance.
67 * <p>The orbit is used only to set an upper bound for the
68 * max check interval to period/3</p>
69 * @param threshold convergence threshold (s)
70 * @param orbit initial orbit
71 */
72 public FieldApsideDetector(final T threshold, final FieldOrbit<T> orbit) {
73 super(new FieldEventDetectionSettings<>(orbit.getKeplerianPeriod().divide(3).getReal(), threshold,
74 DEFAULT_MAX_ITER), new FieldStopOnIncreasing<>());
75 }
76
77 /** Constructor with full parameters.
78 * <p>
79 * This constructor is public because otherwise all accessible ones would require an orbit.
80 * </p>
81 * @param detectionSettings event detection settings
82 * @param handler event handler to call at event occurrences
83 * @since 13.0
84 */
85 public FieldApsideDetector(final FieldEventDetectionSettings<T> detectionSettings,
86 final FieldEventHandler<T> handler) {
87 super(detectionSettings, handler);
88 }
89
90 /** {@inheritDoc} */
91 @Override
92 protected FieldApsideDetector<T> create(final FieldEventDetectionSettings<T> detectionSettings,
93 final FieldEventHandler<T> newHandler) {
94 return new FieldApsideDetector<>(detectionSettings, newHandler);
95 }
96
97 /** Compute the value of the switching function.
98 * This function computes the dot product of the 2 vectors : position.velocity.
99 * @param s the current state information: date, kinematics, attitude
100 * @return value of the switching function
101 */
102 public T g(final FieldSpacecraftState<T> s) {
103 final FieldPVCoordinates<T> pv = s.getPVCoordinates();
104 return FieldVector3D.dotProduct(pv.getPosition(), pv.getVelocity());
105 }
106
107 }