1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF 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.sampling; 18 19 import org.apache.commons.math3.util.FastMath; 20 import org.orekit.errors.OrekitException; 21 import org.orekit.errors.PropagationException; 22 import org.orekit.propagation.SpacecraftState; 23 import org.orekit.time.AbsoluteDate; 24 25 /** 26 * This class wraps an object implementing {@link OrekitFixedStepHandler} 27 * into a {@link OrekitStepHandler}. 28 29 * <p>It mirrors the <code>StepNormalizer</code> interface from <a 30 * href="http://commons.apache.org/math/">commons-math</a> but 31 * provides a space-dynamics interface to the methods.</p> 32 * @author Luc Maisonobe 33 */ 34 public class OrekitStepNormalizer implements OrekitStepHandler { 35 36 /** Fixed time step. */ 37 private double h; 38 39 /** Underlying step handler. */ 40 private OrekitFixedStepHandler handler; 41 42 /** Last step date. */ 43 private AbsoluteDate lastDate; 44 45 /** Last State vector. */ 46 private SpacecraftState lastState; 47 48 /** Integration direction indicator. */ 49 private boolean forward; 50 51 /** Simple constructor. 52 * @param h fixed time step (sign is not used) 53 * @param handler fixed time step handler to wrap 54 */ 55 public OrekitStepNormalizer(final double h, final OrekitFixedStepHandler handler) { 56 this.h = FastMath.abs(h); 57 this.handler = handler; 58 lastDate = null; 59 lastState = null; 60 forward = true; 61 } 62 63 /** Determines whether this handler needs dense output. 64 * This handler needs dense output in order to provide data at 65 * regularly spaced steps regardless of the steps the propagator 66 * uses, so this method always returns true. 67 * @return always true 68 */ 69 public boolean requiresDenseOutput() { 70 return true; 71 } 72 73 /** {@inheritDoc} */ 74 public void init(final SpacecraftState s0, final AbsoluteDate t) 75 throws PropagationException { 76 lastDate = null; 77 lastState = null; 78 forward = true; 79 handler.init(s0, t); 80 } 81 82 /** 83 * Handle the last accepted step. 84 * @param interpolator interpolator for the last accepted step. For 85 * efficiency purposes, the various propagators reuse the same 86 * object on each call, so if the instance wants to keep it across 87 * all calls (for example to provide at the end of the propagation a 88 * continuous model valid throughout the propagation range), it 89 * should build a local copy using the clone method and store this 90 * copy. 91 * @param isLast true if the step is the last one 92 * @throws PropagationException this exception is propagated to the 93 * caller if the underlying user function triggers one 94 */ 95 public void handleStep(final OrekitStepInterpolator interpolator, final boolean isLast) 96 throws PropagationException { 97 try { 98 99 if (lastState == null) { 100 // initialize lastState in the first step case 101 102 lastDate = interpolator.getPreviousDate(); 103 interpolator.setInterpolatedDate(lastDate); 104 lastState = interpolator.getInterpolatedState(); 105 106 // take the propagation direction into account 107 forward = interpolator.getCurrentDate().compareTo(lastDate) >= 0; 108 if (!forward) { 109 h = -h; 110 } 111 112 } 113 114 // use the interpolator to push fixed steps events to the underlying handler 115 AbsoluteDate nextTime = lastDate.shiftedBy(h); 116 boolean nextInStep = forward ^ (nextTime.compareTo(interpolator.getCurrentDate()) > 0); 117 while (nextInStep) { 118 119 // output the stored previous step 120 handler.handleStep(lastState, false); 121 122 // store the next step 123 lastDate = nextTime; 124 interpolator.setInterpolatedDate(lastDate); 125 lastState = interpolator.getInterpolatedState(); 126 127 // prepare next iteration 128 nextTime = nextTime.shiftedBy(h); 129 nextInStep = forward ^ (nextTime.compareTo(interpolator.getCurrentDate()) > 0); 130 131 } 132 133 if (isLast) { 134 // there will be no more steps, 135 // the stored one should be flagged as being the last 136 handler.handleStep(lastState, true); 137 } 138 139 } catch (OrekitException oe) { 140 141 // recover a possible embedded PropagationException 142 for (Throwable t = oe; t != null; t = t.getCause()) { 143 if (t instanceof PropagationException) { 144 throw (PropagationException) t; 145 } 146 } 147 148 throw new PropagationException(oe); 149 150 } 151 } 152 153 }