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  
28  /** This class logs events detectors events during propagation.
29   *
30   * <p>As {@link FieldEventDetector events detectors} are triggered during
31   * orbit propagation, an event specific {@link
32   * FieldEventHandler#eventOccurred(FieldSpacecraftState, FieldEventDetector, 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 FieldEventDetector
38   * events detectors} before they are registered to the propagator. The
39   * wrapper monitor the calls to {@link
40   * FieldEventHandler#eventOccurred(FieldSpacecraftState, FieldEventDetector, boolean) eventOccurred}
41   * and store the corresponding events as {@link FieldLoggedEvent} 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   * @param <T> type of the field elements
47   */
48  public class FieldEventsLogger<T extends CalculusFieldElement<T>> {
49  
50      /** List of occurred events. */
51      private final List<FieldLoggedEvent<T>> log;
52  
53      /** Simple constructor.
54       * <p>
55       * Build an empty logger for events detectors.
56       * </p>
57       */
58      public FieldEventsLogger() {
59          log = new ArrayList<>();
60      }
61  
62      /** Monitor an event detector.
63       * <p>
64       * In order to monitor an event detector, it must be wrapped thanks to
65       * this method as follows:
66       * </p>
67       * <pre>
68       * Propagator propagator = new XyzPropagator(...);
69       * EventsLogger logger = new EventsLogger();
70       * FieldEventDetector&lt;T&gt; detector = new UvwDetector(...);
71       * propagator.addEventDetector(logger.monitorDetector(detector));
72       * </pre>
73       * <p>
74       * Note that the event detector returned by the {@link
75       * FieldLoggedEvent#getEventDetector() getEventDetector} method in
76       * {@link FieldLoggedEvent FieldLoggedEvent} instances returned by {@link
77       * #getLoggedEvents()} are the {@code monitoredDetector} instances
78       * themselves, not the wrapping detector returned by this method.
79       * </p>
80       * @param monitoredDetector event detector to monitor
81       * @return the wrapping detector to add to the propagator
82       */
83      public FieldEventDetector<T> monitorDetector(final FieldEventDetector<T> monitoredDetector) {
84          return new FieldLoggingWrapper(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<FieldLoggedEvent<T>> getLoggedEvents() {
102         return new ArrayList<>(log);
103     }
104 
105     /** Class for logged events entries.
106      * @param <T> type of the field elements
107      */
108     public static class FieldLoggedEvent <T extends CalculusFieldElement<T>> {
109 
110         /** Event detector triggered. */
111         private final FieldEventDetector<T> detector;
112 
113         /** Triggering state. */
114         private final FieldSpacecraftState<T> state;
115 
116         /** Increasing/decreasing status. */
117         private final boolean increasing;
118 
119         /** Simple constructor.
120          * @param detectorN detector for event that was triggered
121          * @param stateN state at event trigger date
122          * @param increasingN indicator if the event switching function was increasing
123          * or decreasing at event occurrence date
124          */
125         private FieldLoggedEvent(final FieldEventDetector<T> detectorN, final FieldSpacecraftState<T> stateN,
126                                  final boolean increasingN) {
127             detector   = detectorN;
128             state      = stateN;
129             increasing = increasingN;
130         }
131 
132         /** Get the event detector triggered.
133          * @return event detector triggered
134          */
135         public FieldEventDetector<T> getEventDetector() {
136             return detector;
137         }
138 
139         /** Get the triggering state.
140          * @return triggering state
141          * @see FieldEventHandler#eventOccurred(FieldSpacecraftState, FieldEventDetector, boolean)
142          */
143         public FieldSpacecraftState<T> getState() {
144             return state;
145         }
146 
147         /** Get the Increasing/decreasing status of the event.
148          * @return increasing/decreasing status of the event
149          * @see FieldEventHandler#eventOccurred(FieldSpacecraftState, FieldEventDetector, boolean)
150          */
151         public boolean isIncreasing() {
152             return increasing;
153         }
154 
155     }
156 
157     /** Internal wrapper for events detectors. */
158     private class FieldLoggingWrapper implements FieldDetectorModifier<T> {
159 
160         /** Wrapped detector. */
161         private final FieldEventDetector<T> detector;
162 
163         /** Simple constructor.
164          * @param detector events detector to wrap
165          */
166         FieldLoggingWrapper(final FieldEventDetector<T> detector) {
167             this.detector = detector;
168         }
169 
170         @Override
171         public FieldEventDetector<T> getDetector() {
172             return detector;
173         }
174 
175         /** Log an event.
176          * @param state state at event trigger date
177          * @param increasing indicator if the event switching function was increasing
178          */
179         public void logEvent(final FieldSpacecraftState<T> state, final boolean increasing) {
180             log.add(new FieldLoggedEvent<>(getDetector(), state, increasing));
181         }
182 
183         /** {@inheritDoc} */
184         @Override
185         public FieldEventHandler<T> getHandler() {
186 
187             final FieldEventHandler<T> handler = getDetector().getHandler();
188 
189             return new FieldEventHandler<T>() {
190 
191                 /** {@inheritDoc} */
192                 public Action eventOccurred(final FieldSpacecraftState<T> s,
193                                             final FieldEventDetector<T> d,
194                                             final boolean increasing) {
195                     logEvent(s, increasing);
196                     return handler.eventOccurred(s, getDetector(), increasing);
197                 }
198 
199                 /** {@inheritDoc} */
200                 @Override
201                 public FieldSpacecraftState<T> resetState(final FieldEventDetector<T> d,
202                                                           final FieldSpacecraftState<T> oldState) {
203                     return handler.resetState(getDetector(), oldState);
204                 }
205 
206             };
207         }
208 
209     }
210 
211 }