ParameterDriver.java
- /* Copyright 2002-2024 CS GROUP
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.orekit.utils;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
- import org.hipparchus.analysis.differentiation.Gradient;
- import org.hipparchus.util.FastMath;
- import org.hipparchus.util.Precision;
- import org.orekit.errors.OrekitException;
- import org.orekit.errors.OrekitIllegalStateException;
- import org.orekit.errors.OrekitMessages;
- import org.orekit.propagation.events.ParameterDrivenDateIntervalDetector;
- import org.orekit.time.AbsoluteDate;
- import org.orekit.utils.TimeSpanMap.Span;
- import org.orekit.utils.TimeSpanMap.Transition;
- /** Class allowing to drive the value of a parameter.
- * <p>
- * This class is typically used as a bridge between an estimation
- * algorithm (typically orbit determination or optimizer) and an
- * internal parameter in a physical model that needs to be tuned,
- * or a bridge between a finite differences algorithm and an
- * internal parameter in a physical model that needs to be slightly
- * offset. The physical model will expose to the algorithm a
- * set of instances of this class so the algorithm can call the
- * {@link #setValue(double, AbsoluteDate)} method to update the
- * parameter value at a given date. Some parameters driver only have 1 value estimated/driven
- * over the all period (constructor by default). Some others have several
- * values estimated/driven on several periods/intervals. For example if the time period is 3 days
- * for a drag parameter estimated all days then 3 values would be estimated, one for
- * each time period. In order to allow several values to be estimated, the PDriver has
- * a name and a value {@link TimeSpanMap} as attribute. In order,
- * to cut the time span map there are 2 options :
- * </p>
- * <ul>
- * <li>Passive cut calling the {@link #addSpans(AbsoluteDate, AbsoluteDate, double)} method.
- * Given a start date, an end date and and a validity period (in sec)
- * for the driver, the {@link #addSpans} method will cut the interval of name and value time span map
- * from start date to date end in several interval of validity period duration. This method should not
- * be called on orbital drivers and must be called only once at beginning of the process (for example
- * beginning of orbit determination). <b>WARNING : In order to ensure converge for orbit determination,
- * the start, end date and driver periodicity must be wisely choosen </b>. There must be enough measurements
- * on each interval or convergence won't reach or singular matrixes will appear. </li>
- * <li> Active cut calling the {@link #addSpanAtDate(AbsoluteDate)} method.
- * Given a date, the method will cut the value and name time span name, in order to have a new span starting at
- * the given date. Can be called several time to cut the time map as wished. <b>WARNING : In order to ensure
- * converge for orbit determination, if the method is called several time, the start date must be wisely choosen </b>.
- * There must be enough measurements on each interval or convergence won't reach or singular matrixes will appear. </li>
- * </ul>
- * <p>
- * Several ways exist in order to get a ParameterDriver value at a certain
- * date for parameters having several values on several intervals.
- * </p>
- * <ul>
- * <li>First of all, the step estimation, that is to say, if a value wants
- * to be known at a certain date, the value returned is the one of span
- * beginning corresponding to the date. With this definition a value
- * will be kept all along the span duration and will be the value of the span
- * start.</li>
- * <li> The continuous estimation, that is to say, when a value wants be to
- * known at a date t, the value returned would be a linear interpolation between
- * the value at the beginning of the span corresponding to date t and end this span
- * (which is also the beginning of next span). NOT IMPLEMENTED FOR NOW
- * </li>
- * </ul>
- * Each time the value is set, the physical model
- * will be notified as it will register a {@link ParameterObserver
- * ParameterObserver} for this purpose.
- * <p>
- * This design has two major goals. First, it allows an external
- * algorithm to drive internal parameters almost anonymously, as it only
- * needs to get a list of instances of this class, without knowing
- * what they really drive. Second, it allows the physical model to
- * not expose directly setters methods for its parameters. In order
- * to be able to modify the parameter value, the algorithm
- * <em>must</em> retrieve a parameter driver.
- * </p>
- * @see ParameterObserver
- * @author Luc Maisonobe
- * @author Melina Vanel
- * @since 8.0
- */
- public class ParameterDriver {
- /** Name of the parameter.*/
- public static final String SPAN = "Span";
- /** Name of the parameter. */
- private String name;
- /** TimeSpan for period names.
- * @since 12.0
- */
- private TimeSpanMap<String> nameSpanMap;
- /** Reference value. */
- private double referenceValue;
- /** Scaling factor. */
- private double scale;
- /** Minimum value. */
- private double minValue;
- /** Maximum value. */
- private double maxValue;
- /** Reference date.
- * @since 9.0
- */
- private AbsoluteDate referenceDate;
- /** Flag to choose estimation method. If estimationContinuous
- * is true then when a value wants to be known an interpolation
- * is performed between given date span start and end (start of
- * next span) otherwise the value returned is the value of span start
- * @since 12.0
- */
- private boolean isEstimationContinuous;
- /** Value time span map.
- * @since 12.0
- */
- private TimeSpanMap<Double> valueSpanMap;
- /** Selection status.
- * <p>
- * Selection is used for estimated parameters in orbit determination,
- * or to compute the Jacobian matrix in partial derivatives computation.
- * </p>
- */
- private boolean selected;
- /** Observers observing this driver. */
- private final List<ParameterObserver> observers;
- /** Create a new instance from another parameterDriver informations
- * for example (useful for {@link ParameterDriversList.DelegatingDriver}))
- * At construction, the parameter new is configured as <em>not</em> selected,
- * the reference date is set to {@code null}. validityPeriod, namesSpanMap and
- * valueSpanMap.
- * @param name general name of the parameter
- * @param namesSpanMap name time span map. WARNING, number of Span must be coherent with
- * validityPeriod and valueSpanMap (same number of Span with same transitions
- * dates)
- * @param valuesSpanMap values time span map
- * @param referenceValue reference value of the parameter
- * @param scale scaling factor to convert the parameters value to
- * non-dimensional (typically set to the expected standard deviation of the
- * parameter), it must be non-zero
- * @param minValue minimum value allowed
- * @param maxValue maximum value allowed
- * @since 12.0
- */
- public ParameterDriver(final String name, final TimeSpanMap<String> namesSpanMap,
- final TimeSpanMap<Double> valuesSpanMap, final double referenceValue,
- final double scale, final double minValue, final double maxValue) {
- if (FastMath.abs(scale) <= Precision.SAFE_MIN) {
- throw new OrekitException(OrekitMessages.TOO_SMALL_SCALE_FOR_PARAMETER,
- name, scale);
- }
- this.name = name;
- this.nameSpanMap = namesSpanMap;
- this.referenceValue = referenceValue;
- this.scale = scale;
- this.minValue = minValue;
- this.maxValue = maxValue;
- this.referenceDate = null;
- this.valueSpanMap = valuesSpanMap;
- this.selected = false;
- this.observers = new ArrayList<>();
- this.isEstimationContinuous = false;
- }
- /** Simple constructor.
- * <p>
- * At construction, the parameter is configured as <em>not</em> selected,
- * the reference date is set to {@code null}, the value is set to the
- * {@code referenceValue}, the validity period is set to 0 so by default
- * the parameterDriver will be estimated on only 1 interval from -INF to
- * +INF. To change the validity period the
- * {@link ParameterDriver#addSpans(AbsoluteDate, AbsoluteDate, double)}
- * method must be called.
- * </p>
- * @param name name of the parameter
- * @param referenceValue reference value of the parameter
- * @param scale scaling factor to convert the parameters value to
- * non-dimensional (typically set to the expected standard deviation of the
- * parameter), it must be non-zero
- * @param minValue minimum value allowed
- * @param maxValue maximum value allowed
- */
- public ParameterDriver(final String name,
- final double referenceValue, final double scale,
- final double minValue, final double maxValue) {
- if (FastMath.abs(scale) <= Precision.SAFE_MIN) {
- throw new OrekitException(OrekitMessages.TOO_SMALL_SCALE_FOR_PARAMETER,
- name, scale);
- }
- this.name = name;
- this.nameSpanMap = new TimeSpanMap<>(SPAN + name + Integer.toString(0));
- this.referenceValue = referenceValue;
- this.scale = scale;
- this.minValue = minValue;
- this.maxValue = maxValue;
- this.referenceDate = null;
- // at construction the parameter driver
- // will be consider with only 1 estimated value over the all orbit
- // determination
- this.valueSpanMap = new TimeSpanMap<>(referenceValue);
- this.selected = false;
- this.observers = new ArrayList<>();
- this.isEstimationContinuous = false;
- }
- /** Get current name span map of the parameterDriver, cut in interval
- * in accordance with value span map and validity period.
- * @return current name span map
- * @since 12.0
- */
- public TimeSpanMap<String> getNamesSpanMap() {
- return nameSpanMap;
- }
- /** Get value time span map for parameterDriver.
- * @return value time span map
- * @since 12.0
- */
- public TimeSpanMap<Double> getValueSpanMap() {
- return valueSpanMap;
- }
- /** Set current parameter value span map to match another driver. In order to keep
- * consistency, the validity period and name span map are updated.
- * @param driver for which the value span map wants to be copied for the
- * current driver
- * @since 12.0
- */
- public void setValueSpanMap(final ParameterDriver driver) {
- final TimeSpanMap<Double> previousValueSpanMap = driver.getValueSpanMap();
- valueSpanMap = driver.getValueSpanMap();
- nameSpanMap = driver.getNamesSpanMap();
- for (final ParameterObserver observer : observers) {
- observer.valueSpanMapChanged(previousValueSpanMap, this);
- }
- }
- /** Get the number of values to estimate that is to say the number.
- * of Span present in valueSpanMap
- * @return int the number of values to estimate
- * @since 12.0
- */
- public int getNbOfValues() {
- return valueSpanMap.getSpansNumber();
- }
- /** Get the dates of the transitions for the drag sensitive models {@link TimeSpanMap}.
- * @return dates of the transitions for the drag sensitive models {@link TimeSpanMap}
- * @since 12.0
- */
- public AbsoluteDate[] getTransitionDates() {
- // Get all transitions
- final List<AbsoluteDate> listDates = new ArrayList<>();
- // Extract all the transitions' dates
- for (Transition<Double> transition = getValueSpanMap().getFirstSpan().getEndTransition(); transition != null; transition = transition.next()) {
- listDates.add(transition.getDate());
- }
- // Return the array of transition dates
- return listDates.toArray(new AbsoluteDate[0]);
- }
- /** Get all values of the valueSpanMap in the chronological order.
- * @return double[] containing values of the valueSpanMap in the chronological order
- */
- public double[] getValues() {
- final double[] chronologicalValues = new double[getNbOfValues()];
- Span<Double> currentSpan = valueSpanMap.getFirstSpan();
- for (int i = 0; i < getNbOfValues() - 1; i++) {
- chronologicalValues[i] = currentSpan.getData();
- currentSpan = currentSpan.next();
- }
- chronologicalValues[getNbOfValues() - 1 ] = currentSpan.getData();
- return chronologicalValues;
- }
- /** Add an observer for this driver.
- * <p>
- * The observer {@link ParameterObserver#valueSpanMapChanged(TimeSpanMap, ParameterDriver)
- * valueSpanMapChanged} method is called once automatically when the
- * observer is added, and then called at each value change.
- * </p>
- * @param observer observer to add
- * while being updated
- */
- public void addObserver(final ParameterObserver observer) {
- observers.add(observer);
- observer.valueSpanMapChanged(getValueSpanMap(), this);
- }
- /** Remove an observer.
- * @param observer observer to remove
- * @since 9.1
- */
- public void removeObserver(final ParameterObserver observer) {
- for (final Iterator<ParameterObserver> iterator = observers.iterator(); iterator.hasNext();) {
- if (iterator.next() == observer) {
- iterator.remove();
- return;
- }
- }
- }
- /** Replace an observer.
- * @param oldObserver observer to replace
- * @param newObserver new observer to use
- * @since 10.1
- */
- public void replaceObserver(final ParameterObserver oldObserver, final ParameterObserver newObserver) {
- for (int i = 0; i < observers.size(); ++i) {
- if (observers.get(i) == oldObserver) {
- observers.set(i, newObserver);
- }
- }
- }
- /** Get the observers for this driver.
- * @return an unmodifiable view of the observers for this driver
- * @since 9.1
- */
- public List<ParameterObserver> getObservers() {
- return Collections.unmodifiableList(observers);
- }
- /** Get parameter driver general name.
- * @return name
- */
- public String getName() {
- return name;
- }
- /** Get name of the parameter span for a specific date.
- * @param date date at which the name of the span wants to be known
- * @return name data of the name time span map at date
- */
- public String getNameSpan(final AbsoluteDate date) {
- return nameSpanMap.get(date);
- }
- /** Change the general name of this parameter driver.
- * @param name new name
- */
- public void setName(final String name) {
- final String previousName = this.name;
- this.name = name;
- for (final ParameterObserver observer : observers) {
- observer.nameChanged(previousName, this);
- }
- // the names time span map must also be updated with the new name
- if (nameSpanMap.getSpansNumber() > 1) {
- Span<String> currentNameSpan = nameSpanMap.getFirstSpan();
- nameSpanMap.addValidBefore(SPAN + name + Integer.toString(0), currentNameSpan.getEnd(), false);
- for (int spanNumber = 1; spanNumber < nameSpanMap.getSpansNumber(); ++spanNumber) {
- currentNameSpan = nameSpanMap.getSpan(currentNameSpan.getEnd());
- nameSpanMap.addValidAfter(SPAN + name + Integer.toString(spanNumber), currentNameSpan.getStart(), false);
- }
- } else {
- nameSpanMap = new TimeSpanMap<>(SPAN + name + Integer.toString(0));
- }
- }
- /** Cut values and names time span map given orbit determination start and end and driver
- * periodicity.
- * <p>
- * For example for a drag coefficient the validity period would be
- * 1 days = 86400sec. To be called after constructor to cut the temporal axis with
- * the wanted parameter driver temporality for estimations on the wanted interval.
- * </p>
- * <p>
- * Must be called only once at the beginning of orbit
- * determination for example. If called several times, will throw exception. If parameter
- * estimations intervals must be changed then a new ParameterDriver must be created or the
- * function {@link #addSpanAtDate} should be used.
- * </p>
- * <p>
- * This function should not be called on {@link DateDriver} and
- * any of {@link ParameterDrivenDateIntervalDetector} attribute, because there is no sense to
- * estimate several values for dateDriver.
- * </p>
- * <p>
- * The choice of {@code orbitDeterminationStartDate}, {@code orbitDeterminationEndDate} and
- * {@code validityPeriodForDriver} in a case of orbit determination must be done carefully,
- * indeed, enough measurement should be available for each time interval or
- * the orbit determination won't converge.
- * </p>
- * @param orbitDeterminationStartDate start date for which the parameter driver
- * starts to be estimated.
- * @param orbitDeterminationEndDate end date for which the parameter driver
- * stops to be estimated.
- * @param validityPeriodForDriver validity period for which the parameter value
- * is effective (for example 1 day for drag coefficient). Warning, validityPeriod
- * should not be too short or the orbit determination won't converge.
- * @since 12.0
- */
- public void addSpans(final AbsoluteDate orbitDeterminationStartDate,
- final AbsoluteDate orbitDeterminationEndDate,
- final double validityPeriodForDriver) {
- // by convention 0 is when the parameter needs to be drived only on 1
- // interval from -INF to +INF time period
- if (getNbOfValues() != 1) {
- // throw exception if called several time, must be called only once at the beginning of orbit
- // determination, if the periods wants to be changed a new parameter must be created
- throw new OrekitIllegalStateException(OrekitMessages.PARAMETER_PERIODS_HAS_ALREADY_BEEN_SET, name);
- } else {
- int spanNumber = 1;
- AbsoluteDate currentDate = orbitDeterminationStartDate.shiftedBy(validityPeriodForDriver);
- //splitting the names and values span map accordingly with start and end of orbit determination
- //and validity period. A security is added to avoid having to few measurements point for a span
- //in order to assure orbit determination convergence
- while (currentDate.isBefore(orbitDeterminationEndDate) && orbitDeterminationEndDate.durationFrom(currentDate) > validityPeriodForDriver / 3.0) {
- valueSpanMap.addValidAfter(getValue(currentDate), currentDate, false);
- nameSpanMap.addValidAfter(SPAN + getName() + Integer.toString(spanNumber++), currentDate, false);
- currentDate = currentDate.shiftedBy(validityPeriodForDriver);
- }
- }
- }
- /** Create a new span in values and names time span map given a start date.
- * <b> One must be aware of the importance of choosing wise dates if this function is called
- * several times to create several span at wanted times. Indeed, if orbit determination is performed
- * it might not converge or find singular matrix if the spans are too short and contains to few measurements.
- * Must be called before any computation (for example before
- * orbit determination).</b>
- * @param spanStartDate wanted start date for parameter value interval
- * starts to be estimated.
- * @since 12.0
- */
- public void addSpanAtDate(final AbsoluteDate spanStartDate) {
- // Split value span map with new interval having for start date spanStartDate and end
- // date next span start date of +INF if no span is present after
- valueSpanMap.addValidAfter(getValue(spanStartDate), spanStartDate, false);
- nameSpanMap.addValidAfter(name, spanStartDate, false);
- // Rename spans recursively
- Span<String> currentNameSpan = nameSpanMap.getFirstSpan();
- nameSpanMap.addValidBefore(SPAN + name + Integer.toString(0), currentNameSpan.getEnd(), false);
- for (int spanNumber = 1; spanNumber < nameSpanMap.getSpansNumber(); spanNumber++) {
- currentNameSpan = nameSpanMap.getSpan(currentNameSpan.getEnd());
- nameSpanMap.addValidAfter(SPAN + name + Integer.toString(spanNumber), currentNameSpan.getStart(), false);
- }
- }
- /** Get reference parameter value.
- * @return reference parameter value
- */
- public double getReferenceValue() {
- return referenceValue;
- }
- /** Set reference parameter value.
- * @since 9.3
- * @param referenceValue the reference value to set.
- */
- public void setReferenceValue(final double referenceValue) {
- final double previousReferenceValue = this.referenceValue;
- this.referenceValue = referenceValue;
- for (final ParameterObserver observer : observers) {
- observer.referenceValueChanged(previousReferenceValue, this);
- }
- }
- /** Get minimum parameter value.
- * @return minimum parameter value
- */
- public double getMinValue() {
- return minValue;
- }
- /** Set minimum parameter value.
- * @since 9.3
- * @param minValue the minimum value to set.
- */
- public void setMinValue(final double minValue) {
- final double previousMinValue = this.minValue;
- this.minValue = minValue;
- for (final ParameterObserver observer : observers) {
- observer.minValueChanged(previousMinValue, this);
- }
- // Check if all values are still not out of min/max range
- for (Span<Double> span = valueSpanMap.getFirstSpan(); span != null; span = span.next()) {
- setValue(getValue(span.getStart()), span.getStart());
- }
- }
- /** Get maximum parameter value.
- * @return maximum parameter value
- */
- public double getMaxValue() {
- return maxValue;
- }
- /** Set maximum parameter value.
- * @since 9.3
- * @param maxValue the maximum value to set.
- */
- public void setMaxValue(final double maxValue) {
- final double previousMaxValue = this.maxValue;
- this.maxValue = maxValue;
- for (final ParameterObserver observer : observers) {
- observer.maxValueChanged(previousMaxValue, this);
- }
- // Check if all values are still not out of min/max range
- for (Span<Double> span = valueSpanMap.getFirstSpan(); span != null; span = span.next()) {
- setValue(getValue(span.getStart()), span.getStart());
- }
- }
- /** Get scale.
- * @return scale
- */
- public double getScale() {
- return scale;
- }
- /** Set scale.
- * @since 9.3
- * @param scale the scale to set.
- */
- public void setScale(final double scale) {
- final double previousScale = this.scale;
- this.scale = scale;
- for (final ParameterObserver observer : observers) {
- observer.scaleChanged(previousScale, this);
- }
- }
- /** Get normalized value at specific date.
- * <p>
- * The normalized value is a non-dimensional value
- * suitable for use as part of a vector in an optimization
- * process. It is computed as {@code (current - reference)/scale}.
- * </p>
- * @param date date for which the normalized value wants to be known
- * @return normalized value
- */
- public double getNormalizedValue(final AbsoluteDate date) {
- return (getValue(date) - getReferenceValue()) / scale;
- }
- /** Get normalized value. Only useable on ParameterDriver
- * which have only 1 span on their TimeSpanMap value (that is
- * to say for which the setPeriod method wasn't called) otherwise
- * it will throw an exception.
- * <p>
- * The normalized value is a non-dimensional value
- * suitable for use as part of a vector in an optimization
- * process. It is computed as {@code (current - reference)/scale}.
- * </p>
- * @return normalized value
- */
- public double getNormalizedValue() {
- return (getValue() - getReferenceValue()) / scale;
- }
- /** Set normalized value at specific date.
- * <p>
- * The normalized value is a non-dimensional value
- * suitable for use as part of a vector in an optimization
- * process. It is computed as {@code (current - reference)/scale}.
- * </p>
- * @param date date for which the normalized value wants to be set
- * @param normalized value
- */
- public void setNormalizedValue(final double normalized, final AbsoluteDate date) {
- setValue(getReferenceValue() + scale * normalized, date);
- }
- /** Set normalized value at specific date. Only useable on ParameterDriver
- * which have only 1 span on their TimeSpanMap value (that is
- * to say for which the setPeriod method wasn't called) otherwise
- * it will throw an exception.
- * <p>
- * The normalized value is a non-dimensional value
- * suitable for use as part of a vector in an optimization
- * process. It is computed as {@code (current - reference)/scale}.
- * </p>
- * @param normalized value
- */
- public void setNormalizedValue(final double normalized) {
- setValue(getReferenceValue() + scale * normalized);
- }
- /** Get current reference date.
- * @return current reference date (null if it was never set)
- * @since 9.0
- */
- public AbsoluteDate getReferenceDate() {
- return referenceDate;
- }
- /** Set reference date.
- * @param newReferenceDate new reference date
- * @since 9.0
- */
- public void setReferenceDate(final AbsoluteDate newReferenceDate) {
- final AbsoluteDate previousReferenceDate = getReferenceDate();
- referenceDate = newReferenceDate;
- for (final ParameterObserver observer : observers) {
- observer.referenceDateChanged(previousReferenceDate, this);
- }
- }
- /** Get current parameter value. Only usable on ParameterDriver
- * which have only 1 span on their TimeSpanMap value (that is
- * to say for which the setPeriod method wasn't called)
- * @return current parameter value
- */
- public double getValue() {
- if (getNbOfValues() > 1) {
- throw new OrekitIllegalStateException(OrekitMessages.PARAMETER_WITH_SEVERAL_ESTIMATED_VALUES, name, "getValue(date)");
- }
- // Attention voir si qlqchose est retourné si une exception est levée
- return valueSpanMap.getFirstSpan().getData();
- }
- /** Get current parameter value at specific date, depending on isContinuousEstimation
- * value, the value returned will be obtained by step estimation or continuous estimation.
- * @param date date for which the value wants to be known. Only if
- * parameter driver has 1 value estimated over the all orbit determination
- * period (not validity period intervals for estimation), the date value can
- * be <em>{@code null}</em> and then the only estimated value will be
- * returned, in this case the date can also be whatever the value returned would
- * be the same. Moreover in this particular case one can also call the {@link #getValue()}.
- * @return current parameter value at date date, or for the all period if
- * no validity period (= 1 value estimated over the all orbit determination
- * period)
- */
- public double getValue(final AbsoluteDate date) {
- return isEstimationContinuous ? getValueContinuousEstimation(date) : getValueStepEstimation(date);
- }
- /** Get current parameter value at specific date with step estimation.
- * @param date date for which the value wants to be known. Only if
- * parameter driver has 1 value estimated over the all orbit determination
- * period (not validity period intervals for estimation), the date value can
- * be <em>{@code null}</em> and then the only estimated value will be
- * returned, in this case the date can also be whatever the value returned would
- * be the same. Moreover in this particular case one can also call the {@link #getValue()}.
- * @return current parameter value at date date, or for the all period if
- * no validity period (= 1 value estimated over the all orbit determination
- * period)
- */
- public double getValueStepEstimation(final AbsoluteDate date) {
- return getNbOfValues() == 1 ? valueSpanMap.getFirstSpan().getData() : valueSpanMap.get(date);
- }
- /** Get current parameter value at specific date with continuous estimation.
- * @param date date for which the value wants to be known. Only if
- * parameter driver has 1 value estimated over the all orbit determination
- * period (not validity period intervals for estimation), the date value can
- * be <em>{@code null}</em> and then the only estimated value will be
- * returned, in this case the date can also be whatever the value returned would
- * be the same. Moreover in this particular case one can also call the {@link #getValue()}.
- * @return current parameter value at date date, or for the all period if
- * no validity period (= 1 value estimated over the all orbit determination
- * period)
- * @since 12.0
- */
- public double getValueContinuousEstimation(final AbsoluteDate date) {
- //TODO
- throw new UnsupportedOperationException();
- }
- /** Get the value as a gradient at special date.
- * @param freeParameters total number of free parameters in the gradient
- * @param indices indices of the differentiation parameters in derivatives computations
- * @return value with derivatives, will throw exception if called on a PDriver having
- * several values driven
- * @since 10.2
- */
- public Gradient getValue(final int freeParameters, final Map<String, Integer> indices) {
- Integer index = null;
- for (Span<String> span = nameSpanMap.getFirstSpan(); span != null; span = span.next()) {
- index = indices.get(span.getData());
- if (index != null) {
- break;
- }
- }
- return (index == null) ? Gradient.constant(freeParameters, getValue()) : Gradient.variable(freeParameters, index, getValue());
- }
- /** Get the value as a gradient at special date.
- * @param freeParameters total number of free parameters in the gradient
- * @param indices indices of the differentiation parameters in derivatives computations,
- * must be span name and not driver name
- * @param date date for which the value wants to be known. Only if
- * parameter driver has 1 value estimated over the all orbit determination
- * period (not validity period intervals for estimation), the date value can
- * be <em>{@code null}</em> and then the only estimated value will be
- * returned
- * @return value with derivatives
- * @since 10.2
- */
- public Gradient getValue(final int freeParameters, final Map<String, Integer> indices, final AbsoluteDate date) {
- Integer index = null;
- for (Span<String> span = nameSpanMap.getFirstSpan(); span != null; span = span.next()) {
- index = indices.get(span.getData());
- if (index != null) {
- break;
- }
- }
- return (index == null) ? Gradient.constant(freeParameters, getValue(date)) : Gradient.variable(freeParameters, index, getValue(date));
- }
- /** Set parameter value at specific date.
- * <p>
- * If {@code newValue} is below {@link #getMinValue()}, it will
- * be silently set to {@link #getMinValue()}. If {@code newValue} is
- * above {@link #getMaxValue()}, it will be silently set to {@link
- * #getMaxValue()}.
- * </p>
- * @param date date for which the value wants to be set. Only if
- * parameter driver has 1 value estimated over the all orbit determination
- * period (not validity period intervals for estimation), the date value can
- * be <em>{@code null}</em>
- * @param newValue new value to set
- */
- public void setValue(final double newValue, final AbsoluteDate date) {
- double previousValue = Double.NaN;
- AbsoluteDate referenceDateSpan = AbsoluteDate.ARBITRARY_EPOCH;
- // if valid for infinity (only 1 value estimation for the orbit determination )
- if (getNbOfValues() == 1) {
- previousValue = this.getValue(referenceDateSpan);
- this.valueSpanMap = new TimeSpanMap<>(FastMath.max(minValue, FastMath.min(maxValue, newValue)));
- // if needs to be estimated per time range / validity period
- // if several value intervals
- } else {
- final Span<Double> valueSpan = valueSpanMap.getSpan(date);
- previousValue = valueSpan.getData();
- referenceDateSpan = valueSpan.getStart();
- // if the Span considered is from past infinity to valueSpanEndDate it is
- // impossible to addValidAfter past infinity because it is creating a new span that
- // is why the below trick was set up
- if (referenceDateSpan.equals(AbsoluteDate.PAST_INFINITY)) {
- referenceDateSpan = valueSpan.getEnd();
- this.valueSpanMap.addValidBefore(FastMath.max(minValue, FastMath.min(maxValue, newValue)),
- referenceDateSpan, false);
- } else {
- this.valueSpanMap.addValidAfter(FastMath.max(minValue, FastMath.min(maxValue, newValue)),
- referenceDateSpan, false);
- }
- }
- for (final ParameterObserver observer : observers) {
- observer.valueChanged(previousValue, this, date);
- }
- }
- /** Set parameter value. Only usable on ParameterDriver
- * which have only 1 span on their TimeSpanMap value (that is
- * to say for which the setPeriod method wasn't called)
- * <p>
- * If {@code newValue} is below {@link #getMinValue()}, it will
- * be silently set to {@link #getMinValue()}. If {@code newValue} is
- * above {@link #getMaxValue()}, it will be silently set to {@link
- * #getMaxValue()}.
- * </p>
- * @param newValue new value to set
- */
- public void setValue(final double newValue) {
- if (getNbOfValues() == 1) {
- final AbsoluteDate referenceDateSpan = AbsoluteDate.ARBITRARY_EPOCH;
- final double previousValue = this.getValue(referenceDateSpan);
- this.valueSpanMap = new TimeSpanMap<>(FastMath.max(minValue, FastMath.min(maxValue, newValue)));
- for (final ParameterObserver observer : observers) {
- observer.valueChanged(previousValue, this, referenceDateSpan);
- }
- } else {
- throw new OrekitIllegalStateException(OrekitMessages.PARAMETER_WITH_SEVERAL_ESTIMATED_VALUES, name, "setValue(date)");
- }
- }
- /** Configure a parameter selection status.
- * <p>
- * Selection is used for estimated parameters in orbit determination,
- * or to compute the Jacobian matrix in partial derivatives computation.
- * </p>
- * @param selected if true the parameter is selected,
- * otherwise it will be fixed
- */
- public void setSelected(final boolean selected) {
- final boolean previousSelection = isSelected();
- this.selected = selected;
- for (final ParameterObserver observer : observers) {
- observer.selectionChanged(previousSelection, this);
- }
- }
- /** Check if parameter is selected.
- * <p>
- * Selection is used for estimated parameters in orbit determination,
- * or to compute the Jacobian matrix in partial derivatives computation.
- * </p>
- * @return true if parameter is selected, false if it is not
- */
- public boolean isSelected() {
- return selected;
- }
- /** Set parameter estimation to continuous, by default step estimation.
- * <p> Continuous estimation : when a value wants to be known at date
- * t, the value returned will be an interpolation between start value
- * of the span corresponding to date t and end value (which corresponds
- * to the start of the next span).
- * </p>
- * <p> Step estimation : when a value wants to be
- * known at date t, the value returned will be the value of the beginning
- * of span corresponding to date t, step estimation.
- * </p>
- * @param continuous if true the parameter will be estimated
- * with continuous estimation, if false with step estimation.
- */
- public void setContinuousEstimation(final boolean continuous) {
- final boolean previousEstimation = isContinuousEstimation();
- this.isEstimationContinuous = continuous;
- for (final ParameterObserver observer : observers) {
- observer.estimationTypeChanged(previousEstimation, this);
- }
- }
- /** Check if parameter estimation is continuous, that is to say when
- * a value wants to be known at date t, the value returned
- * will be an interpolation between start value on span corresponding
- * for date t and end value (which corresponds to the start of the next
- * span), continuous estimation. Or not continuous, that is to say when a value wants to be
- * known at date t, the value returned will be the value of the start
- * of span corresponding to date t, step estimation.
- * @return true if continuous estimation/definition, false if step estimation/definition
- * @since 12.0
- */
- public boolean isContinuousEstimation() {
- return isEstimationContinuous;
- }
- /** Get a text representation of the parameter.
- * @return text representation of the parameter, in the form name = value.
- */
- public String toString() {
- return name + " = " + valueSpanMap.get(AbsoluteDate.ARBITRARY_EPOCH);
- }
- }