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 org.hipparchus.ode.events.Action;
20 import org.hipparchus.util.FastMath;
21 import org.orekit.propagation.SpacecraftState;
22 import org.orekit.propagation.events.handlers.EventHandler;
23 import org.orekit.time.AbsoluteDate;
24
25 /** Wrapper shifting events occurrences times.
26 * <p>This class wraps an {@link EventDetector event detector} to slightly
27 * shift the events occurrences times. A typical use case is for handling
28 * operational delays before or after some physical event really occurs.</p>
29 * <p>For example, the satellite attitude mode may be switched from sun pointed
30 * to spin-stabilized a few minutes before eclipse entry, and switched back
31 * to sun pointed a few minutes after eclipse exit. This behavior is handled
32 * by wrapping an {@link EclipseDetector eclipse detector} into an instance
33 * of this class with a positive times shift for increasing events (eclipse exit)
34 * and a negative times shift for decreasing events (eclipse entry).</p>
35 * @see org.orekit.propagation.Propagator#addEventDetector(EventDetector)
36 * @see EventDetector
37 * @param <T> class type for the generic version
38 * @author Luc Maisonobe
39 */
40 public class EventShifter<T extends EventDetector> extends AbstractDetector<EventShifter<T>> {
41
42 /** Event detector for the raw unshifted event. */
43 private final T detector;
44
45 /** Indicator for using shifted or unshifted states at event occurrence. */
46 private final boolean useShiftedStates;
47
48 /** Offset to apply to find increasing events. */
49 private final double increasingOffset;
50
51 /** Offset to apply to find decreasing events. */
52 private final double decreasingOffset;
53
54 /** Build a new instance.
55 * <p>The {@link #getMaxCheckInterval() max check interval}, the
56 * {@link #getThreshold() convergence threshold} of the raw unshifted
57 * events will be used for the shifted event. When an event occurs,
58 * the {@link #eventOccurred(SpacecraftState, boolean) eventOccurred}
59 * method of the raw unshifted events will be called (with spacecraft
60 * state at either the shifted or the unshifted event date depending
61 * on the <code>useShiftedStates</code> parameter).</p>
62 * @param detector event detector for the raw unshifted event
63 * @param useShiftedStates if true, the state provided to {@link
64 * #eventOccurred(SpacecraftState, boolean) eventOccurred} method of
65 * the <code>detector</code> will remain shifted, otherwise it will
66 * be <i>unshifted</i> to correspond to the underlying raw event.
67 * @param increasingTimeShift increasing events time shift.
68 * @param decreasingTimeShift decreasing events time shift.
69 */
70 public EventShifter(final T detector, final boolean useShiftedStates,
71 final double increasingTimeShift, final double decreasingTimeShift) {
72 this(detector.getMaxCheckInterval(), detector.getThreshold(),
73 detector.getMaxIterationCount(), new LocalHandler<T>(),
74 detector, useShiftedStates, increasingTimeShift, decreasingTimeShift);
75 }
76
77 /** Private constructor with full parameters.
78 * <p>
79 * This constructor is private as users are expected to use the builder
80 * API with the various {@code withXxx()} methods to set up the instance
81 * in a readable manner without using a huge amount of parameters.
82 * </p>
83 * @param maxCheck maximum checking interval (s)
84 * @param threshold convergence threshold (s)
85 * @param maxIter maximum number of iterations in the event time search
86 * @param handler event handler to call at event occurrences
87 * @param detector event detector for the raw unshifted event
88 * @param useShiftedStates if true, the state provided to {@link
89 * #eventOccurred(SpacecraftState, boolean) eventOccurred} method of
90 * the <code>detector</code> will remain shifted, otherwise it will
91 * be <i>unshifted</i> to correspond to the underlying raw event.
92 * @param increasingTimeShift increasing events time shift.
93 * @param decreasingTimeShift decreasing events time shift.
94 * @since 6.1
95 */
96 private EventShifter(final double maxCheck, final double threshold,
97 final int maxIter, final EventHandler<? super EventShifter<T>> handler,
98 final T detector, final boolean useShiftedStates,
99 final double increasingTimeShift, final double decreasingTimeShift) {
100 super(maxCheck, threshold, maxIter, handler);
101 this.detector = detector;
102 this.useShiftedStates = useShiftedStates;
103 this.increasingOffset = -increasingTimeShift;
104 this.decreasingOffset = -decreasingTimeShift;
105 }
106
107 /** {@inheritDoc} */
108 @Override
109 protected EventShifter<T> create(final double newMaxCheck, final double newThreshold,
110 final int newMaxIter, final EventHandler<? super EventShifter<T>> newHandler) {
111 return new EventShifter<T>(newMaxCheck, newThreshold, newMaxIter, newHandler,
112 detector, useShiftedStates, -increasingOffset, -decreasingOffset);
113 }
114
115 /** Get the increasing events time shift.
116 * @return increasing events time shift
117 */
118 public double getIncreasingTimeShift() {
119 return -increasingOffset;
120 }
121
122 /** Get the decreasing events time shift.
123 * @return decreasing events time shift
124 */
125 public double getDecreasingTimeShift() {
126 return -decreasingOffset;
127 }
128
129 /** {@inheritDoc} */
130 public void init(final SpacecraftState s0,
131 final AbsoluteDate t) {
132 super.init(s0, t);
133 detector.init(s0, t);
134 }
135
136 /** {@inheritDoc} */
137 public double g(final SpacecraftState s) {
138 final double incShiftedG = detector.g(s.shiftedBy(increasingOffset));
139 final double decShiftedG = detector.g(s.shiftedBy(decreasingOffset));
140 return (increasingOffset >= decreasingOffset) ?
141 FastMath.max(incShiftedG, decShiftedG) : FastMath.min(incShiftedG, decShiftedG);
142 }
143
144 /** Local class for handling events. */
145 private static class LocalHandler<T extends EventDetector> implements EventHandler<EventShifter<T>> {
146
147 /** Shifted state at even occurrence. */
148 private SpacecraftState shiftedState;
149
150 /** {@inheritDoc} */
151 public Action eventOccurred(final SpacecraftState s, final EventShifter<T> shifter, final boolean increasing) {
152
153 if (shifter.useShiftedStates) {
154 // the state provided by the caller already includes the time shift
155 shiftedState = s;
156 } else {
157 // we need to "unshift" the state
158 final double offset = increasing ? shifter.increasingOffset : shifter.decreasingOffset;
159 shiftedState = s.shiftedBy(offset);
160 }
161
162 return shifter.detector.eventOccurred(shiftedState, increasing);
163
164 }
165
166 /** {@inheritDoc} */
167 @Override
168 public SpacecraftState resetState(final EventShifter<T> shifter, final SpacecraftState oldState) {
169 return shifter.detector.resetState(shiftedState);
170 }
171
172 }
173
174 }