1 /* Copyright 2002-2026 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 java.util.ArrayList;
20 import java.util.List;
21
22 import org.hipparchus.ode.events.Action;
23 import org.orekit.propagation.SpacecraftState;
24 import org.orekit.propagation.events.functions.BooleanEventFunction;
25 import org.orekit.propagation.events.functions.EventFunction;
26 import org.orekit.propagation.events.functions.ShiftedEventFunction;
27 import org.orekit.propagation.events.handlers.EventHandler;
28
29 /** Wrapper shifting events occurrences times.
30 * <p>This class wraps an {@link EventDetector event detector} to slightly
31 * shift the events occurrences times. A typical use case is for handling
32 * operational delays before or after some physical event really occurs.</p>
33 * <p>For example, the satellite attitude mode may be switched from sun pointed
34 * to spin-stabilized a few minutes before eclipse entry, and switched back
35 * to sun pointed a few minutes after eclipse exit. This behavior is handled
36 * by wrapping an {@link EclipseDetector eclipse detector} into an instance
37 * of this class with a positive times shift for increasing events (eclipse exit)
38 * and a negative times shift for decreasing events (eclipse entry).</p>
39 * @see org.orekit.propagation.Propagator#addEventDetector(EventDetector)
40 * @see EventDetector
41 * @author Luc Maisonobe
42 */
43 public class EventShifter implements DetectorModifier {
44
45 /** Event detector for the raw unshifted event. */
46 private final EventDetector detector;
47
48 /** Indicator for using shifted or unshifted states at event occurrence. */
49 private final boolean useShiftedStates;
50
51 /** Offset to apply to find increasing events. */
52 private final double increasingOffset;
53
54 /** Offset to apply to find decreasing events. */
55 private final double decreasingOffset;
56
57 /** Event detection settings. */
58 private final EventDetectionSettings detectionSettings;
59
60 /** Specialized event handler. */
61 private final LocalHandler handler;
62
63 /** Event function. */
64 private final EventFunction eventFunction;
65
66 /** Build a new instance.
67 * <p>The {@link #getMaxCheckInterval() max check interval}, the
68 * {@link #getThreshold() convergence threshold} of the raw unshifted
69 * events will be used for the shifted event. When an event occurs,
70 * the {@link EventHandler#eventOccurred(SpacecraftState, EventDetector, boolean) eventOccurred}
71 * method of the raw unshifted events will be called (with spacecraft
72 * state at either the shifted or the unshifted event date depending
73 * on the <code>useShiftedStates</code> parameter).</p>
74 * @param detector event detector for the raw unshifted event
75 * @param useShiftedStates if true, the state provided to {@link
76 * EventHandler#eventOccurred(SpacecraftState, EventDetector, boolean) eventOccurred} method of
77 * the associated {@code handler} will remain shifted, otherwise it will
78 * be <i>unshifted</i> to correspond to the underlying raw event.
79 * @param increasingTimeShift increasing events time shift.
80 * @param decreasingTimeShift decreasing events time shift.
81 */
82 public EventShifter(final EventDetector detector, final boolean useShiftedStates,
83 final double increasingTimeShift, final double decreasingTimeShift) {
84 this(detector.getDetectionSettings(), detector, useShiftedStates, increasingTimeShift, decreasingTimeShift);
85 }
86
87 /** Constructor with full parameters.
88 * @param detectionSettings event detection settings
89 * @param detector event detector for the raw unshifted event
90 * @param useShiftedStates if true, the state provided to {@link
91 * EventHandler#eventOccurred(SpacecraftState, EventDetector, boolean) eventOccurred} method of
92 * the <code>detector</code> will remain shifted, otherwise it will
93 * be <i>unshifted</i> to correspond to the underlying raw event.
94 * @param increasingTimeShift increasing events time shift.
95 * @param decreasingTimeShift decreasing events time shift.
96 * @since 13.0
97 */
98 public EventShifter(final EventDetectionSettings detectionSettings,
99 final EventDetector detector, final boolean useShiftedStates,
100 final double increasingTimeShift, final double decreasingTimeShift) {
101 this.detectionSettings = detectionSettings;
102 this.handler = new LocalHandler();
103 this.detector = detector;
104 this.useShiftedStates = useShiftedStates;
105 this.increasingOffset = -increasingTimeShift;
106 this.decreasingOffset = -decreasingTimeShift;
107 final ShiftedEventFunction increasingShifted = new ShiftedEventFunction(detector.getEventFunction(), increasingOffset);
108 final ShiftedEventFunction decreasingShifted = new ShiftedEventFunction(detector.getEventFunction(), decreasingOffset);
109 final List<EventFunction> eventFunctionList = new ArrayList<>();
110 eventFunctionList.add(increasingShifted);
111 eventFunctionList.add(decreasingShifted);
112 this.eventFunction = (increasingOffset >= decreasingOffset) ? BooleanEventFunction.orCombine(eventFunctionList) :
113 BooleanEventFunction.andCombine(eventFunctionList);
114 }
115
116 /** {@inheritDoc} */
117 @Override
118 public EventHandler getHandler() {
119 return handler;
120 }
121
122 /** {@inheritDoc} */
123 @Override
124 public EventFunction getEventFunction() {
125 return eventFunction;
126 }
127
128 /** {@inheritDoc} */
129 @Override
130 public EventDetectionSettings getDetectionSettings() {
131 return detectionSettings;
132 }
133
134 /**
135 * Get the detector for the raw unshifted event.
136 * @return the detector for the raw unshifted event
137 * @since 11.1
138 */
139 public EventDetector getDetector() {
140 return detector;
141 }
142
143 /** Get the increasing events time shift.
144 * @return increasing events time shift
145 */
146 public double getIncreasingTimeShift() {
147 return -increasingOffset;
148 }
149
150 /** Get the decreasing events time shift.
151 * @return decreasing events time shift
152 */
153 public double getDecreasingTimeShift() {
154 return -decreasingOffset;
155 }
156
157 /**
158 * Getter for shifted states in handler flag.
159 * @return flag
160 * @since 14.0
161 */
162 public boolean isUseShiftedStates() {
163 return useShiftedStates;
164 }
165
166 /**
167 * Builds a new instance from the input detection settings.
168 * @param settings event detection settings to be used
169 * @return a new detector
170 */
171 public EventShifter withDetectionSettings(final EventDetectionSettings settings) {
172 return new EventShifter(settings, detector, useShiftedStates, getIncreasingTimeShift(), getDecreasingTimeShift());
173 }
174
175 /** Local class for handling events. */
176 private static class LocalHandler implements EventHandler {
177
178 /** Shifted state at even occurrence. */
179 private SpacecraftState shiftedState;
180
181 /** {@inheritDoc} */
182 public Action eventOccurred(final SpacecraftState s, final EventDetector detector, final boolean increasing) {
183
184 final EventShifter shifter = (EventShifter) detector;
185 if (shifter.useShiftedStates) {
186 // the state provided by the caller already includes the time shift
187 shiftedState = s;
188 } else {
189 // we need to "unshift" the state
190 final double offset = increasing ? shifter.increasingOffset : shifter.decreasingOffset;
191 shiftedState = s.shiftedBy(offset);
192 }
193
194 return shifter.detector.getHandler().eventOccurred(shiftedState, shifter.detector, increasing);
195
196 }
197
198 /** {@inheritDoc} */
199 @Override
200 public SpacecraftState resetState(final EventDetector detector, final SpacecraftState oldState) {
201 final EventShifter shifter = (EventShifter) detector;
202 return shifter.detector.getHandler().resetState(shifter.detector, shiftedState);
203 }
204
205 }
206
207 }