From 6535441575044b813c14972a3347c648aa503d72 Mon Sep 17 00:00:00 2001 From: Luc Maisonobe <luc@orekit.org> Date: Fri, 7 Dec 2018 18:08:09 +0100 Subject: [PATCH] Moved the propagator from generator to schedulers. --- ...measurements-generation-class-diagram.puml | 6 +- .../generation/AbstractScheduler.java | 44 +++++++- .../generation/EventBasedScheduler.java | 106 ++++++++++++++++-- .../measurements/generation/Generator.java | 72 +++++++++++- .../measurements/generation/Scheduler.java | 22 +++- 5 files changed, 232 insertions(+), 18 deletions(-) diff --git a/src/design/measurements-generation-class-diagram.puml b/src/design/measurements-generation-class-diagram.puml index 07d88ac469..daf50183ca 100644 --- a/src/design/measurements-generation-class-diagram.puml +++ b/src/design/measurements-generation-class-diagram.puml @@ -59,7 +59,7 @@ class Generator { +addScheduler(Scheduler) - +SortedSet<ObservedMeasurements> generate(startDate, endDate, propagators) + +SortedSet<ObservedMeasurements> generate(startDate, endDate) } enum SignSemantic { @@ -69,6 +69,7 @@ class "EventBasedScheduler<T>" as EventBasedScheduler_T_ interface "Scheduler<T>" as Scheduler_T_ { + +Propagator getPropagator() +SortedSet<T> generate(interpolators) } @@ -101,10 +102,13 @@ package propagation #DDEBD8 { + interface Propagator class PropagatorsParallelizer { propagate() } Generator --> PropagatorsParallelizer + Scheduler_T_ *--> "1" Propagator + Propagator <-- PropagatorsParallelizer } package time #DDEBD8 { diff --git a/src/main/java/org/orekit/estimation/measurements/generation/AbstractScheduler.java b/src/main/java/org/orekit/estimation/measurements/generation/AbstractScheduler.java index dbba30a899..87372e929c 100644 --- a/src/main/java/org/orekit/estimation/measurements/generation/AbstractScheduler.java +++ b/src/main/java/org/orekit/estimation/measurements/generation/AbstractScheduler.java @@ -17,6 +17,8 @@ package org.orekit.estimation.measurements.generation; import org.orekit.estimation.measurements.ObservedMeasurement; +import org.orekit.propagation.Propagator; +import org.orekit.time.AbsoluteDate; import org.orekit.time.DatesSelector; @@ -33,14 +35,50 @@ public abstract class AbstractScheduler<T extends ObservedMeasurement<T>> implem /** Selector for dates. */ private final DatesSelector selector; + /** Propagator associated with this scheduler. */ + private final Propagator propagator; + /** Simple constructor. * @param builder builder for individual measurements * @param selector selector for dates + * @param propagator propagator associated with this scheduler */ protected AbstractScheduler(final MeasurementBuilder<T> builder, - final DatesSelector selector) { - this.builder = builder; - this.selector = selector; + final DatesSelector selector, + final Propagator propagator) { + this.builder = builder; + this.selector = selector; + this.propagator = propagator; + } + + /** {@inheritDoc} + * <p> + * This implementation initialize the measurement builder. + * </p> + */ + @Override + public void init(final AbsoluteDate start, final AbsoluteDate end) { + builder.init(start, end); + } + + /** Get the measurements builder. + * @return measurements builder + */ + public MeasurementBuilder<T> getBuilder() { + return builder; + } + + /** Get the dates selector. + * @return dates selector + */ + public DatesSelector getSelector() { + return selector; + } + + /** {@inheritDoc} */ + @Override + public Propagator getPropagator() { + return propagator; } } diff --git a/src/main/java/org/orekit/estimation/measurements/generation/EventBasedScheduler.java b/src/main/java/org/orekit/estimation/measurements/generation/EventBasedScheduler.java index 072445073e..ebf67bd83b 100644 --- a/src/main/java/org/orekit/estimation/measurements/generation/EventBasedScheduler.java +++ b/src/main/java/org/orekit/estimation/measurements/generation/EventBasedScheduler.java @@ -16,12 +16,20 @@ */ package org.orekit.estimation.measurements.generation; +import java.util.List; import java.util.SortedSet; +import java.util.TreeSet; import org.orekit.estimation.measurements.ObservedMeasurement; +import org.orekit.propagation.Propagator; +import org.orekit.propagation.SpacecraftState; +import org.orekit.propagation.events.AdapterDetector; import org.orekit.propagation.events.EventDetector; +import org.orekit.propagation.events.handlers.EventHandler.Action; import org.orekit.propagation.sampling.OrekitStepInterpolator; +import org.orekit.time.AbsoluteDate; import org.orekit.time.DatesSelector; +import org.orekit.utils.TimeSpanMap; /** {@link Scheduler} based on {@link EventDetector} for generating measurements sequences. @@ -51,30 +59,112 @@ import org.orekit.time.DatesSelector; */ public class EventBasedScheduler<T extends ObservedMeasurement<T>> extends AbstractScheduler<T> { - /** Detector for checking measurements feasibility. */ - private final EventDetector detector; - /** Semantic of the detector g function sign to use. */ private final SignSemantic signSemantic; + /** Feasibility status. */ + private TimeSpanMap<Boolean> feasibility; + + /** Propagation direction. */ + private boolean forward; + /** Simple constructor. + * <p> + * The event detector instance should <em>not</em> be already bound to the propagator. + * It will be wrapped in an {@link AdapterDetector adapter} in order to manage time + * ranges when measurements are feasible. The wrapping adapter will be automatically + * {@link Propagator#addEventDetector(EventDetector) added} to the propagator by this + * constructor. + * </p> * @param builder builder for individual measurements * @param selector selector for dates + * @param propagator propagator associated with this scheduler * @param detector detector for checking measurements feasibility * @param signSemantic semantic of the detector g function sign to use */ public EventBasedScheduler(final MeasurementBuilder<T> builder, final DatesSelector selector, + final Propagator propagator, final EventDetector detector, final SignSemantic signSemantic) { - super(builder, selector); - this.detector = detector; + super(builder, selector, propagator); this.signSemantic = signSemantic; + this.feasibility = new TimeSpanMap<Boolean>(Boolean.FALSE); + this.forward = true; + propagator.addEventDetector(new FeasibilityAdapter(detector)); } /** {@inheritDoc} */ @Override - public SortedSet<T> generate(final OrekitStepInterpolator... interpolators) { - // TODO - return null; + public SortedSet<T> generate(final List<OrekitStepInterpolator> interpolators) { + + // select dates in the current step, using arbitrarily interpolator 0 + // as all interpolators cover the same range + final List<AbsoluteDate> dates = getSelector().selectDates(interpolators.get(0).getPreviousState().getDate(), + interpolators.get(0).getCurrentState().getDate()); + + // generate measurements when feasible + final SortedSet<T> measurements = new TreeSet<>(); + for (final AbsoluteDate date : dates) { + if (feasibility.get(date)) { + // a measurement is feasible at this date + + // interpolate states at measurement date + final SpacecraftState[] states = new SpacecraftState[interpolators.size()]; + for (int i = 0; i < states.length; ++i) { + states[i] = interpolators.get(i).getInterpolatedState(date); + } + + // generate measurement + measurements.add(getBuilder().build(states)); + + } + } + + return measurements; + + } + + /** Adapter for managing feasibility status changes. */ + private class FeasibilityAdapter extends AdapterDetector { + + /** Serializable UID. */ + private static final long serialVersionUID = 20181206L; + + /** Build an adaptor wrapping an existing detector. + * @param detector detector to wrap + */ + FeasibilityAdapter(final EventDetector detector) { + super(detector); + } + + /** {@inheritDoc} */ + @Override + public void init(final SpacecraftState s0, final AbsoluteDate t) { + super.init(s0, t); + forward = t.compareTo(s0.getDate()) > 0; + feasibility = new TimeSpanMap<Boolean>(signSemantic.measurementIsFeasible(g(s0))); + } + + /** {@inheritDoc} */ + @Override + public Action eventOccurred(final SpacecraftState s, final boolean increasing) { + + // find the feasibility status AFTER the current date + final boolean statusAfter = signSemantic.measurementIsFeasible(increasing ? +1 : -1); + + // store either status or its opposite according to propagation direction + if (forward) { + // forward propagation + feasibility.addValidAfter(statusAfter, s.getDate()); + } else { + // backward propagation + feasibility.addValidBefore(!statusAfter, s.getDate()); + } + + // delegate to wrapped detector + return super.eventOccurred(s, increasing); + + } + } } diff --git a/src/main/java/org/orekit/estimation/measurements/generation/Generator.java b/src/main/java/org/orekit/estimation/measurements/generation/Generator.java index 95a671a991..7e6b6b034a 100644 --- a/src/main/java/org/orekit/estimation/measurements/generation/Generator.java +++ b/src/main/java/org/orekit/estimation/measurements/generation/Generator.java @@ -19,9 +19,14 @@ package org.orekit.estimation.measurements.generation; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; +import java.util.TreeSet; import org.orekit.estimation.measurements.ObservedMeasurement; import org.orekit.propagation.Propagator; +import org.orekit.propagation.PropagatorsParallelizer; +import org.orekit.propagation.SpacecraftState; +import org.orekit.propagation.sampling.MultiSatStepHandler; +import org.orekit.propagation.sampling.OrekitStepInterpolator; import org.orekit.time.AbsoluteDate; @@ -51,13 +56,70 @@ public class Generator { /** Generate measurements. * @param start start of the measurements time span * @param end end of the measurements time span - * @param propagators propagators to use * @return generated measurements */ - public SortedSet<ObservedMeasurement<?>> generate(final AbsoluteDate start, final AbsoluteDate end, - final Propagator... propagators) { - // TODO - return null; + public SortedSet<ObservedMeasurement<?>> generate(final AbsoluteDate start, final AbsoluteDate end) { + + // initialize schedulers + for (final Scheduler<?> scheduler : schedulers) { + scheduler.init(start, end); + } + + // set up parallelized propagators + final List<Propagator> propagators = new ArrayList<>(schedulers.size()); + for (final Scheduler<?> scheduler : schedulers) { + propagators.add(scheduler.getPropagator()); + } + final GeneratorHandler handler = new GeneratorHandler(schedulers); + final PropagatorsParallelizer parallelizer = new PropagatorsParallelizer(propagators, handler); + + // generate the measurements + parallelizer.propagate(start, end); + + return handler.getMeasurements(); + + } + + /** Handler for measurements generation steps. */ + private static class GeneratorHandler implements MultiSatStepHandler { + + /** Sequences generators. */ + private final List<Scheduler<?>> schedulers; + + /** Set for holding measurements. */ + private final SortedSet<ObservedMeasurement<?>> measurements; + + /** Simple constructor. + * @param schedulers sequences generators + */ + GeneratorHandler(final List<Scheduler<?>> schedulers) { + this.schedulers = schedulers; + this.measurements = new TreeSet<>(); + } + + /** {@inheritDoc} */ + @Override + public void init(final List<SpacecraftState> states0, final AbsoluteDate t) { + for (final Scheduler<?> scheduler : schedulers) { + scheduler.init(states0.get(0).getDate(), t); + } + } + + /** {@inheritDoc} */ + @Override + public void handleStep(final List<OrekitStepInterpolator> interpolators, final boolean isLast) { + for (final Scheduler<?> scheduler : schedulers) { + scheduler.generate(interpolators); + } + } + + /** Get the generated measurements. + * @return generated measurements + */ + public SortedSet<ObservedMeasurement<?>> getMeasurements() { + return measurements; + } + } } diff --git a/src/main/java/org/orekit/estimation/measurements/generation/Scheduler.java b/src/main/java/org/orekit/estimation/measurements/generation/Scheduler.java index 2b7e419e5d..007ec8a287 100644 --- a/src/main/java/org/orekit/estimation/measurements/generation/Scheduler.java +++ b/src/main/java/org/orekit/estimation/measurements/generation/Scheduler.java @@ -16,10 +16,13 @@ */ package org.orekit.estimation.measurements.generation; +import java.util.List; import java.util.SortedSet; import org.orekit.estimation.measurements.ObservedMeasurement; +import org.orekit.propagation.Propagator; import org.orekit.propagation.sampling.OrekitStepInterpolator; +import org.orekit.time.AbsoluteDate; /** Interface for generating {@link ObservedMeasurements measurements} sequences. @@ -29,10 +32,27 @@ import org.orekit.propagation.sampling.OrekitStepInterpolator; */ public interface Scheduler<T extends ObservedMeasurement<T>> { + /** Initialize scheduler at the start of a measurements generation. + * <p> + * This method is called once at the start of the measurements generation. It + * may be used by the scheduler to initialize some internal data + * if needed, typically {@link MeasurementBuilder#init(AbsoluteDate, AbsoluteDate) + * initializing builders}. + * </p> + * @param start start of the measurements time span + * @param end end of the measurements time span + */ + void init(AbsoluteDate start, AbsoluteDate end); + + /** Get the propagator associated with this scheduler. + * @return propagator associated with this scheduler + */ + Propagator getPropagator(); + /** Generate a sequence of measurements. * @param interpolators interpolators for spacecraft states * @return generated measurements */ - SortedSet<T> generate(OrekitStepInterpolator... interpolators); + SortedSet<T> generate(List<OrekitStepInterpolator> interpolators); } -- GitLab