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.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(FieldAdaptableInterval.of(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(FieldAdaptableInterval.of(orbit.getKeplerianPeriod().divide(3).getReal()), threshold,
74 DEFAULT_MAX_ITER, new FieldStopOnIncreasing<>());
75 }
76
77 /** Protected constructor with full parameters.
78 * <p>
79 * This constructor is public because otherwise all accessible ones would require an orbit.
80 * </p>
81 * @param maxCheck maximum checking interval
82 * @param threshold convergence threshold (s)
83 * @param maxIter maximum number of iterations in the event time search
84 * @param handler event handler to call at event occurrences
85 */
86 public FieldApsideDetector(final FieldAdaptableInterval<T> maxCheck, final T threshold,
87 final int maxIter, final FieldEventHandler<T> handler) {
88 super(maxCheck, threshold, maxIter, handler);
89 }
90
91 /** {@inheritDoc} */
92 @Override
93 protected FieldApsideDetector<T> create(final FieldAdaptableInterval<T> newMaxCheck, final T newThreshold,
94 final int newMaxIter,
95 final FieldEventHandler<T> newHandler) {
96 return new FieldApsideDetector<>(newMaxCheck, newThreshold, newMaxIter, newHandler);
97 }
98
99 /** Compute the value of the switching function.
100 * This function computes the dot product of the 2 vectors : position.velocity.
101 * @param s the current state information: date, kinematics, attitude
102 * @return value of the switching function
103 */
104 public T g(final FieldSpacecraftState<T> s) {
105 final FieldPVCoordinates<T> pv = s.getPVCoordinates();
106 return FieldVector3D.dotProduct(pv.getPosition(), pv.getVelocity());
107 }
108
109 }