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  
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  
52  
53      /** List of occurred events. */
54      private final List<FieldLoggedEvent<T>> log;
55  
56      /** Simple constructor.
57       * <p>
58       * Build an empty logger for events detectors.
59       * </p>
60       */
61      public FieldEventsLogger() {
62          log = new ArrayList<FieldEventsLogger.FieldLoggedEvent<T>>();
63      }
64  
65      /** Monitor an event detector.
66       * <p>
67       * In order to monitor an event detector, it must be wrapped thanks to
68       * this method as follows:
69       * </p>
70       * <pre>
71       * Propagator propagator = new XyzPropagator(...);
72       * EventsLogger logger = new EventsLogger();
73       * FieldEventDetector&lt;T&gt; detector = new UvwDetector(...);
74       * propagator.addEventDetector(logger.monitorDetector(detector));
75       * </pre>
76       * <p>
77       * Note that the event detector returned by the {@link
78       * FieldLoggedEvent#getEventDetector() getEventDetector} method in
79       * {@link FieldLoggedEvent FieldLoggedEvent} instances returned by {@link
80       * #getLoggedEvents()} are the {@code monitoredDetector} instances
81       * themselves, not the wrapping detector returned by this method.
82       * </p>
83       * @param monitoredDetector event detector to monitor
84       * @return the wrapping detector to add to the propagator
85       */
86      public FieldAbstractDetector<FieldLoggingWrapper, T> monitorDetector(final FieldEventDetector<T> monitoredDetector) {
87          return new FieldLoggingWrapper(monitoredDetector);
88      }
89  
90      /** Clear the logged events.
91       */
92      public void clearLoggedEvents() {
93          log.clear();
94      }
95  
96      /** Get an immutable copy of the logged events.
97       * <p>
98       * The copy is independent of the logger. It is preserved
99       * event if the {@link #clearLoggedEvents() clearLoggedEvents} method
100      * is called and the logger reused in another propagation.
101      * </p>
102      * @return an immutable copy of the logged events
103      */
104     public List<FieldLoggedEvent<T>> getLoggedEvents() {
105         return new ArrayList<FieldEventsLogger.FieldLoggedEvent<T>>(log);
106     }
107 
108     /** Class for logged events entries.
109      * @param <T> type of the field elements
110      */
111     public static class FieldLoggedEvent <T extends CalculusFieldElement<T>> {
112 
113         /** Event detector triggered. */
114         private final FieldEventDetector<T> detector;
115 
116         /** Triggering state. */
117         private final FieldSpacecraftState<T> state;
118 
119         /** Increasing/decreasing status. */
120         private final boolean increasing;
121 
122         /** Simple constructor.
123          * @param detectorN detector for event that was triggered
124          * @param stateN state at event trigger date
125          * @param increasingN indicator if the event switching function was increasing
126          * or decreasing at event occurrence date
127          */
128         private FieldLoggedEvent(final FieldEventDetector<T> detectorN, final FieldSpacecraftState<T> stateN, final boolean increasingN) {
129             detector   = detectorN;
130             state      = stateN;
131             increasing = increasingN;
132         }
133 
134         /** Get the event detector triggered.
135          * @return event detector triggered
136          */
137         public FieldEventDetector<T> getEventDetector() {
138             return detector;
139         }
140 
141         /** Get the triggering state.
142          * @return triggering state
143          * @see FieldEventHandler#eventOccurred(FieldSpacecraftState, FieldEventDetector, boolean)
144          */
145         public FieldSpacecraftState<T> getState() {
146             return state;
147         }
148 
149         /** Get the Increasing/decreasing status of the event.
150          * @return increasing/decreasing status of the event
151          * @see FieldEventHandler#eventOccurred(FieldSpacecraftState, FieldEventDetector, boolean)
152          */
153         public boolean isIncreasing() {
154             return increasing;
155         }
156 
157     }
158 
159     /** Internal wrapper for events detectors. */
160     private class FieldLoggingWrapper extends FieldAbstractDetector<FieldLoggingWrapper, T> {
161 
162         /** Wrapped events detector. */
163         private final FieldEventDetector<T> detector;
164 
165         /** Simple constructor.
166          * @param detector events detector to wrap
167          */
168         FieldLoggingWrapper(final FieldEventDetector<T> detector) {
169             this(detector.getMaxCheckInterval(), detector.getThreshold(),
170                  detector.getMaxIterationCount(), null,
171                  detector);
172         }
173 
174         /** Private constructor with full parameters.
175          * <p>
176          * This constructor is private as users are expected to use the builder
177          * API with the various {@code withXxx()} methods to set up the instance
178          * in a readable manner without using a huge amount of parameters.
179          * </p>
180          * @param maxCheck maximum checking interval
181          * @param threshold convergence threshold (s)
182          * @param maxIter maximum number of iterations in the event time search
183          * @param handler event handler to call at event occurrences
184          * @param detector events detector to wrap
185          * @since 6.1
186          */
187         private FieldLoggingWrapper(final FieldAdaptableInterval<T> maxCheck, final T threshold,
188                                     final int maxIter, final FieldEventHandler<T> handler,
189                                     final FieldEventDetector<T> detector) {
190             super(maxCheck, threshold, maxIter, handler);
191             this.detector = detector;
192         }
193 
194         /** {@inheritDoc} */
195         @Override
196         protected FieldLoggingWrapper create(final FieldAdaptableInterval<T> newMaxCheck, final T newThreshold,
197                                              final int newMaxIter, final FieldEventHandler<T> newHandler) {
198             return new FieldLoggingWrapper(newMaxCheck, newThreshold, newMaxIter, newHandler, detector);
199         }
200 
201         /** Log an event.
202          * @param state state at event trigger date
203          * @param increasing indicator if the event switching function was increasing
204          */
205         public void logEvent(final FieldSpacecraftState<T> state, final boolean increasing) {
206             log.add(new FieldLoggedEvent<>(detector, state, increasing));
207         }
208 
209         /** {@inheritDoc} */
210         public void init(final FieldSpacecraftState<T> s0,
211                          final FieldAbsoluteDate<T> t) {
212             super.init(s0, t);
213             detector.init(s0, t);
214         }
215 
216         /** {@inheritDoc} */
217         public T g(final FieldSpacecraftState<T> s) {
218             return detector.g(s);
219         }
220 
221         /** {@inheritDoc} */
222         public FieldEventHandler<T> getHandler() {
223 
224             final FieldEventHandler<T> handler = detector.getHandler();
225 
226             return new FieldEventHandler<T>() {
227 
228                 /** {@inheritDoc} */
229                 public Action eventOccurred(final FieldSpacecraftState<T> s,
230                                             final FieldEventDetector<T> d,
231                                             final boolean increasing) {
232                     logEvent(s, increasing);
233                     return handler.eventOccurred(s, detector, increasing);
234                 }
235 
236                 /** {@inheritDoc} */
237                 @Override
238                 public FieldSpacecraftState<T> resetState(final FieldEventDetector<T> d,
239                                                           final FieldSpacecraftState<T> oldState) {
240                     return handler.resetState(detector, oldState);
241                 }
242 
243             };
244         }
245 
246     }
247 
248 }