1 /* Copyright 2002-2021 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.handlers.EventHandler;
25 import org.orekit.time.AbsoluteDate;
26 import org.orekit.time.TimeStamped;
27
28 /** This class logs events detectors events during propagation.
29 *
30 * <p>As {@link EventDetector events detectors} are triggered during
31 * orbit propagation, an event specific {@link
32 * EventDetector#eventOccurred(SpacecraftState, boolean) eventOccurred}
33 * method is called. This class can be used to add a global logging
34 * feature registering all events with their corresponding states in
35 * a chronological sequence (or reverse-chronological if propagation
36 * occurs backward).
37 * <p>This class works by wrapping user-provided {@link EventDetector
38 * events detectors} before they are registered to the propagator. The
39 * wrapper monitor the calls to {@link
40 * EventDetector#eventOccurred(SpacecraftState, boolean) eventOccurred}
41 * and store the corresponding events as {@link LoggedEvent} instances.
42 * After propagation is complete, the user can retrieve all the events
43 * that have occurred at once by calling method {@link #getLoggedEvents()}.</p>
44 *
45 * @author Luc Maisonobe
46 */
47 public class EventsLogger {
48
49 /** List of occurred events. */
50 private final List<LoggedEvent> log;
51
52 /** Simple constructor.
53 * <p>
54 * Build an empty logger for events detectors.
55 * </p>
56 */
57 public EventsLogger() {
58 log = new ArrayList<EventsLogger.LoggedEvent>();
59 }
60
61 /** Monitor an event detector.
62 * <p>
63 * In order to monitor an event detector, it must be wrapped thanks to
64 * this method as follows:
65 * </p>
66 * <pre>
67 * Propagator propagator = new XyzPropagator(...);
68 * EventsLogger logger = new EventsLogger();
69 * EventDetector detector = new UvwDetector(...);
70 * propagator.addEventDetector(logger.monitorDetector(detector));
71 * </pre>
72 * <p>
73 * Note that the event detector returned by the {@link
74 * LoggedEvent#getEventDetector() getEventDetector} method in
75 * {@link LoggedEvent LoggedEvent} instances returned by {@link
76 * #getLoggedEvents()} are the {@code monitoredDetector} instances
77 * themselves, not the wrapping detector returned by this method.
78 * </p>
79 * @param monitoredDetector event detector to monitor
80 * @return the wrapping detector to add to the propagator
81 * @param <T> class type for the generic version
82 */
83 public <T extends EventDetector> EventDetector monitorDetector(final T monitoredDetector) {
84 return new LoggingWrapper<T>(monitoredDetector);
85 }
86
87 /** Clear the logged events.
88 */
89 public void clearLoggedEvents() {
90 log.clear();
91 }
92
93 /** Get an immutable copy of the logged events.
94 * <p>
95 * The copy is independent of the logger. It is preserved
96 * event if the {@link #clearLoggedEvents() clearLoggedEvents} method
97 * is called and the logger reused in another propagation.
98 * </p>
99 * @return an immutable copy of the logged events
100 */
101 public List<LoggedEvent> getLoggedEvents() {
102 return new ArrayList<EventsLogger.LoggedEvent>(log);
103 }
104
105 /** Class for logged events entries. */
106 public static class LoggedEvent implements TimeStamped {
107
108 /** Event detector triggered. */
109 private final EventDetector detector;
110
111 /** Triggering state. */
112 private final SpacecraftState state;
113
114 /** Increasing/decreasing status. */
115 private final boolean increasing;
116
117 /** Simple constructor.
118 * @param detector detector for event that was triggered
119 * @param state state at event trigger date
120 * @param increasing indicator if the event switching function was increasing
121 * or decreasing at event occurrence date
122 */
123 private LoggedEvent(final EventDetector detector, final SpacecraftState state, final boolean increasing) {
124 this.detector = detector;
125 this.state = state;
126 this.increasing = increasing;
127 }
128
129 /** Get the event detector triggered.
130 * @return event detector triggered
131 */
132 public EventDetector getEventDetector() {
133 return detector;
134 }
135
136 /** {@inheritDoc} */
137 @Override
138 public AbsoluteDate getDate() {
139 return state.getDate();
140 }
141
142 /** Get the triggering state.
143 * @return triggering state
144 * @see EventDetector#eventOccurred(SpacecraftState, boolean)
145 */
146 public SpacecraftState getState() {
147 return state;
148 }
149
150 /** Get the Increasing/decreasing status of the event.
151 * @return increasing/decreasing status of the event
152 * @see EventDetector#eventOccurred(SpacecraftState, boolean)
153 */
154 public boolean isIncreasing() {
155 return increasing;
156 }
157
158 }
159
160 /** Internal wrapper for events detectors.
161 * @param <T> class type for the generic version
162 */
163 private class LoggingWrapper<T extends EventDetector> extends AbstractDetector<LoggingWrapper<T>> {
164
165 /** Wrapped events detector. */
166 private final T detector;
167
168 /** Simple constructor.
169 * @param detector events detector to wrap
170 */
171 LoggingWrapper(final T detector) {
172 this(detector.getMaxCheckInterval(), detector.getThreshold(),
173 detector.getMaxIterationCount(), new LocalHandler<T>(),
174 detector);
175 }
176
177 /** Private constructor with full parameters.
178 * <p>
179 * This constructor is private as users are expected to use the builder
180 * API with the various {@code withXxx()} methods to set up the instance
181 * in a readable manner without using a huge amount of parameters.
182 * </p>
183 * @param maxCheck maximum checking interval (s)
184 * @param threshold convergence threshold (s)
185 * @param maxIter maximum number of iterations in the event time search
186 * @param handler event handler to call at event occurrences
187 * @param detector events detector to wrap
188 * @since 6.1
189 */
190 private LoggingWrapper(final double maxCheck, final double threshold,
191 final int maxIter, final EventHandler<? super LoggingWrapper<T>> handler,
192 final T detector) {
193 super(maxCheck, threshold, maxIter, handler);
194 this.detector = detector;
195 }
196
197 /** {@inheritDoc} */
198 @Override
199 protected LoggingWrapper<T> create(final double newMaxCheck, final double newThreshold,
200 final int newMaxIter, final EventHandler<? super LoggingWrapper<T>> newHandler) {
201 return new LoggingWrapper<T>(newMaxCheck, newThreshold, newMaxIter, newHandler, detector);
202 }
203
204 /** Log an event.
205 * @param state state at event trigger date
206 * @param increasing indicator if the event switching function was increasing
207 */
208 public void logEvent(final SpacecraftState state, final boolean increasing) {
209 log.add(new LoggedEvent(detector, state, increasing));
210 }
211
212 /** {@inheritDoc} */
213 public void init(final SpacecraftState s0,
214 final AbsoluteDate t) {
215 super.init(s0, t);
216 detector.init(s0, t);
217 }
218
219 /** {@inheritDoc} */
220 public double g(final SpacecraftState s) {
221 return detector.g(s);
222 }
223
224 }
225
226 /** Local class for handling events.
227 * @param <T> class type for the generic version
228 */
229 private static class LocalHandler<T extends EventDetector> implements EventHandler<LoggingWrapper<T>> {
230
231 /** {@inheritDoc} */
232 public Action eventOccurred(final SpacecraftState s, final LoggingWrapper<T> wrapper, final boolean increasing) {
233 wrapper.logEvent(s, increasing);
234 return wrapper.detector.eventOccurred(s, increasing);
235 }
236
237 /** {@inheritDoc} */
238 @Override
239 public SpacecraftState resetState(final LoggingWrapper<T> wrapper, final SpacecraftState oldState) {
240 return wrapper.detector.resetState(oldState);
241 }
242
243 }
244
245 }