All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.orekit.utils.ParameterDriver Maven / Gradle / Ivy

Go to download

OREKIT (ORbits Extrapolation KIT) is a low level space dynamics library. It provides basic elements (orbits, dates, attitude, frames ...) and various algorithms to handle them (conversions, analytical and numerical propagation, pointing ...).

There is a newer version: 12.2
Show newest version
/* Copyright 2002-2021 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.OrekitMessages;
import org.orekit.time.AbsoluteDate;


/** Class allowing to drive the value of a parameter.
 * 

* 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)} method to update the * parameter value. Each time the value is set, the physical model * will be notified as it will register a {@link ParameterObserver * ParameterObserver} for this purpose. *

*

* 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 * must retrieve a parameter driver. *

* @see ParameterObserver * @author Luc Maisonobe * @since 8.0 */ public class ParameterDriver { /** Name of the parameter. */ private String name; /** 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; /** Current value. */ private double value; /** Selection status. *

* Selection is used for estimated parameters in orbit determination, * or to compute the Jacobian matrix in partial derivatives computation. *

*/ private boolean selected; /** Observers observing this driver. */ private final List observers; /** Simple constructor. *

* At construction, the parameter is configured as not selected, * the reference date is set to {@code null} and the value is set to the * {@code referenceValue}. *

* @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 * @param maxValue maximum value */ 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.referenceValue = referenceValue; this.scale = scale; this.minValue = minValue; this.maxValue = maxValue; this.referenceDate = null; this.value = referenceValue; this.selected = false; this.observers = new ArrayList<>(); } /** Add an observer for this driver. *

* The observer {@link ParameterObserver#valueChanged(double, ParameterDriver) * valueChanged} method is called once automatically when the * observer is added, and then called at each value change. *

* @param observer observer to add * while being updated */ public void addObserver(final ParameterObserver observer) { observers.add(observer); observer.valueChanged(getValue(), this); } /** Remove an observer. * @param observer observer to remove * @since 9.1 */ public void removeObserver(final ParameterObserver observer) { for (final Iterator 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 getObservers() { return Collections.unmodifiableList(observers); } /** Change the 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); } } /** Get name. * @return name */ public String getName() { return name; } /** 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 current value is not out of min/max range setValue(value); } /** 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 current value is not out of min/max range setValue(value); } /** 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. *

* 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}. *

* @return normalized value */ public double getNormalizedValue() { return (value - referenceValue) / scale; } /** Set normalized value. *

* 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}. *

* @param normalized value */ public void setNormalizedValue(final double normalized) { setValue(referenceValue + 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. * @return current parameter value */ public double getValue() { return value; } /** Get the value as a gradient. * @param freeParameters total number of free parameters in the gradient * @param indices indices of the differentiation parameters in derivatives computations * @return value with derivatives * @since 10.2 */ public Gradient getValue(final int freeParameters, final Map indices) { final Integer index = indices.get(name); return (index == null) ? Gradient.constant(freeParameters, value) : Gradient.variable(freeParameters, index, value); } /** Set parameter value. *

* 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()}. *

* @param newValue new value */ public void setValue(final double newValue) { final double previousValue = getValue(); value = FastMath.max(minValue, FastMath.min(maxValue, newValue)); for (final ParameterObserver observer : observers) { observer.valueChanged(previousValue, this); } } /** Configure a parameter selection status. *

* Selection is used for estimated parameters in orbit determination, * or to compute the Jacobian matrix in partial derivatives computation. *

* @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. *

* Selection is used for estimated parameters in orbit determination, * or to compute the Jacobian matrix in partial derivatives computation. *

* @return true if parameter is selected, false if it is not */ public boolean isSelected() { return selected; } /** Get a text representation of the parameter. * @return text representation of the parameter, in the form name = value. */ public String toString() { return name + " = " + value; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy