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
20 import java.util.ArrayList;
21 import java.util.List;
22
23 import org.hipparchus.CalculusFieldElement;
24 import org.hipparchus.ode.events.Action;
25 import org.orekit.propagation.FieldSpacecraftState;
26 import org.orekit.propagation.events.handlers.FieldEventHandler;
27 import org.orekit.time.FieldAbsoluteDate;
28
29 /** This class logs events detectors events during propagation.
30 *
31 * <p>As {@link FieldEventDetector events detectors} are triggered during
32 * orbit propagation, an event specific {@link
33 * FieldEventHandler#eventOccurred(FieldSpacecraftState, FieldEventDetector, boolean) eventOccurred}
34 * method is called. This class can be used to add a global logging
35 * feature registering all events with their corresponding states in
36 * a chronological sequence (or reverse-chronological if propagation
37 * occurs backward).
38 * <p>This class works by wrapping user-provided {@link FieldEventDetector
39 * events detectors} before they are registered to the propagator. The
40 * wrapper monitor the calls to {@link
41 * FieldEventHandler#eventOccurred(FieldSpacecraftState, FieldEventDetector, boolean) eventOccurred}
42 * and store the corresponding events as {@link FieldLoggedEvent} instances.
43 * After propagation is complete, the user can retrieve all the events
44 * that have occurred at once by calling method {@link #getLoggedEvents()}.</p>
45 *
46 * @author Luc Maisonobe
47 * @param <T> type of the field elements
48 */
49 public class FieldEventsLogger<T extends CalculusFieldElement<T>> {
50
51 /** List of occurred events. */
52 private final List<FieldLoggedEvent<T>> log;
53
54 /** Simple constructor.
55 * <p>
56 * Build an empty logger for events detectors.
57 * </p>
58 */
59 public FieldEventsLogger() {
60 log = new ArrayList<>();
61 }
62
63 /** Monitor an event detector.
64 * <p>
65 * In order to monitor an event detector, it must be wrapped thanks to
66 * this method as follows:
67 * </p>
68 * <pre>
69 * Propagator propagator = new XyzPropagator(...);
70 * EventsLogger logger = new EventsLogger();
71 * FieldEventDetector<T> detector = new UvwDetector(...);
72 * propagator.addEventDetector(logger.monitorDetector(detector));
73 * </pre>
74 * <p>
75 * Note that the event detector returned by the {@link
76 * FieldLoggedEvent#getEventDetector() getEventDetector} method in
77 * {@link FieldLoggedEvent FieldLoggedEvent} instances returned by {@link
78 * #getLoggedEvents()} are the {@code monitoredDetector} instances
79 * themselves, not the wrapping detector returned by this method.
80 * </p>
81 * @param monitoredDetector event detector to monitor
82 * @return the wrapping detector to add to the propagator
83 */
84 public FieldEventDetector<T> monitorDetector(final FieldEventDetector<T> monitoredDetector) {
85 return new FieldLoggingWrapper(monitoredDetector);
86 }
87
88 /** Clear the logged events.
89 */
90 public void clearLoggedEvents() {
91 log.clear();
92 }
93
94 /** Get an immutable copy of the logged events.
95 * <p>
96 * The copy is independent of the logger. It is preserved
97 * event if the {@link #clearLoggedEvents() clearLoggedEvents} method
98 * is called and the logger reused in another propagation.
99 * </p>
100 * @return an immutable copy of the logged events
101 */
102 public List<FieldLoggedEvent<T>> getLoggedEvents() {
103 return new ArrayList<>(log);
104 }
105
106 /** Class for logged events entries.
107 * @param <T> type of the field elements
108 */
109 public static class FieldLoggedEvent <T extends CalculusFieldElement<T>> {
110
111 /** Event detector triggered. */
112 private final FieldEventDetector<T> detector;
113
114 /** Triggering state. */
115 private final FieldSpacecraftState<T> state;
116
117 /** Increasing/decreasing status. */
118 private final boolean increasing;
119
120 /** Reset state if any, otherwise event state. */
121 private final FieldSpacecraftState<T> resetState;
122
123 /** Constructor.
124 * @param detectorN detector for event that was triggered
125 * @param stateN state at event trigger date
126 * @param resetStateN reset state if any, otherwise same as event state
127 * @param increasingN indicator if the event switching function was increasing
128 * or decreasing at event occurrence date
129 * @since 13.1
130 */
131 private FieldLoggedEvent(final FieldEventDetector<T> detectorN, final FieldSpacecraftState<T> stateN,
132 final FieldSpacecraftState<T> resetStateN, final boolean increasingN) {
133 detector = detectorN;
134 state = stateN;
135 resetState = resetStateN;
136 increasing = increasingN;
137 }
138
139 /** Get the event detector triggered.
140 * @return event detector triggered
141 */
142 public FieldEventDetector<T> getEventDetector() {
143 return detector;
144 }
145
146 /** Get the triggering state.
147 * @return triggering state
148 * @see FieldEventHandler#eventOccurred(FieldSpacecraftState, FieldEventDetector, boolean)
149 */
150 public FieldSpacecraftState<T> getState() {
151 return state;
152 }
153
154 /**
155 * Get the reset state.
156 * @return reset state
157 * @since 13.1
158 */
159 public FieldSpacecraftState<T> getResetState() {
160 return resetState;
161 }
162
163 /** Get the Increasing/decreasing status of the event.
164 * @return increasing/decreasing status of the event
165 * @see FieldEventHandler#eventOccurred(FieldSpacecraftState, FieldEventDetector, boolean)
166 */
167 public boolean isIncreasing() {
168 return increasing;
169 }
170
171 }
172
173 /** Internal wrapper for events detectors. */
174 private class FieldLoggingWrapper implements FieldDetectorModifier<T> {
175
176 /** Wrapped detector. */
177 private final FieldEventDetector<T> wrappedDetector;
178
179 /** Simple constructor.
180 * @param detector events detector to wrap
181 */
182 FieldLoggingWrapper(final FieldEventDetector<T> detector) {
183 this.wrappedDetector = detector;
184 }
185
186 @Override
187 public FieldEventDetector<T> getDetector() {
188 return wrappedDetector;
189 }
190
191 /** Log an event.
192 * @param state state at event trigger date
193 * @param resetState reset state if any, otherwise same as event state
194 * @param increasing indicator if the event switching function was increasing
195 */
196 void logEvent(final FieldSpacecraftState<T> state, final FieldSpacecraftState<T> resetState,
197 final boolean increasing) {
198 log.add(new FieldLoggedEvent<>(getDetector(), state, resetState, increasing));
199 }
200
201 /** {@inheritDoc} */
202 @Override
203 public FieldEventHandler<T> getHandler() {
204
205 final FieldEventHandler<T> handler = getDetector().getHandler();
206
207 return new FieldEventHandler<T>() {
208
209 private FieldSpacecraftState<T> lastTriggeringState = null;
210 private FieldSpacecraftState<T> lastResetState = null;
211
212 @Override
213 public void init(final FieldSpacecraftState<T> initialState, final FieldAbsoluteDate<T> target,
214 final FieldEventDetector<T> detector) {
215 FieldEventHandler.super.init(initialState, target, detector);
216 lastResetState = null;
217 lastTriggeringState = null;
218 }
219
220 /** {@inheritDoc} */
221 @Override
222 public Action eventOccurred(final FieldSpacecraftState<T> s,
223 final FieldEventDetector<T> d,
224 final boolean increasing) {
225 final Action action = handler.eventOccurred(s, getDetector(), increasing);
226 if (action == Action.RESET_STATE) {
227 lastResetState = resetState(getDetector(), s);
228 } else {
229 lastResetState = s;
230 }
231 lastTriggeringState = s;
232 logEvent(s, lastResetState, increasing);
233 return action;
234 }
235
236 /** {@inheritDoc} */
237 @Override
238 public FieldSpacecraftState<T> resetState(final FieldEventDetector<T> d,
239 final FieldSpacecraftState<T> oldState) {
240 if (lastTriggeringState != oldState) {
241 lastTriggeringState = oldState;
242 lastResetState = handler.resetState(getDetector(), oldState);
243 }
244 return lastResetState;
245 }
246
247 };
248 }
249
250 }
251
252 }