MultiplexedMeasurement.java

  1. /* Copyright 2002-2022 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.estimation.measurements;

  18. import java.util.ArrayList;
  19. import java.util.Arrays;
  20. import java.util.IdentityHashMap;
  21. import java.util.List;
  22. import java.util.Map;
  23. import java.util.function.Function;

  24. import org.orekit.propagation.SpacecraftState;
  25. import org.orekit.utils.ParameterDriver;
  26. import org.orekit.utils.ParameterDriversList;
  27. import org.orekit.utils.TimeStampedPVCoordinates;

  28. /** Class multiplexing several measurements as one.
  29.  * <p>
  30.  * Date comes from the first measurement, observed and estimated
  31.  * values result from gathering all underlying measurements values.
  32.  *
  33.  * @author Luc Maisonobe
  34.  * @since 10.1
  35.  */
  36. public class MultiplexedMeasurement extends AbstractMeasurement<MultiplexedMeasurement> {

  37.     /** Type of the measurement. */
  38.     public static final String MEASUREMENT_TYPE = "MultiplexedMeasurement";

  39.     /** Multiplexed measurements. */
  40.     private final List<ObservedMeasurement<?>> observedMeasurements;

  41.     /** Multiplexed measurements. */
  42.     private final List<EstimatedMeasurement<?>> estimatedMeasurements;

  43.     /** Multiplexed parameters drivers. */
  44.     private ParameterDriversList parametersDrivers;

  45.     /** Total dimension. */
  46.     private final int dimension;

  47.     /** Total number of satellites involved. */
  48.     private final int nbSat;

  49.     /** States mapping. */
  50.     private final int[][] mapping;

  51.     /** Simple constructor.
  52.      * @param measurements measurements to multiplex
  53.      * @since 10.1
  54.      */
  55.     public MultiplexedMeasurement(final List<ObservedMeasurement<?>> measurements) {
  56.         super(measurements.get(0).getDate(),
  57.               multiplex(measurements, m -> m.getObservedValue()),
  58.               multiplex(measurements, m -> m.getTheoreticalStandardDeviation()),
  59.               multiplex(measurements, m -> m.getBaseWeight()),
  60.               multiplex(measurements));

  61.         this.observedMeasurements  = measurements;
  62.         this.estimatedMeasurements = new ArrayList<>();
  63.         this.parametersDrivers     = new ParameterDriversList();

  64.         // gather parameters drivers
  65.         int dim = 0;
  66.         for (final ObservedMeasurement<?> m : measurements) {
  67.             for (final ParameterDriver driver : m.getParametersDrivers()) {
  68.                 parametersDrivers.add(driver);
  69.             }
  70.             dim += m.getDimension();
  71.         }
  72.         parametersDrivers.sort();
  73.         for (final ParameterDriver driver : parametersDrivers.getDrivers()) {
  74.             addParameterDriver(driver);
  75.         }
  76.         this.dimension = dim;

  77.         // set up states mappings for observed satellites
  78.         final List<ObservableSatellite> deduplicated = getSatellites();
  79.         this.nbSat   = deduplicated.size();
  80.         this.mapping = new int[measurements.size()][];
  81.         for (int i = 0; i < mapping.length; ++i) {
  82.             final List<ObservableSatellite> satellites = measurements.get(i).getSatellites();
  83.             mapping[i] = new int[satellites.size()];
  84.             for (int j = 0; j < mapping[i].length; ++j) {
  85.                 final int index = satellites.get(j).getPropagatorIndex();
  86.                 for (int k = 0; k < nbSat; ++k) {
  87.                     if (deduplicated.get(k).getPropagatorIndex() == index) {
  88.                         mapping[i][j] = k;
  89.                         break;
  90.                     }
  91.                 }
  92.             }
  93.         }

  94.     }

  95.     /** Get the underlying measurements.
  96.      * @return underlying measurements
  97.      */
  98.     public List<ObservedMeasurement<?>> getMeasurements() {
  99.         return observedMeasurements;
  100.     }

  101.     /** Get the underlying estimated measurements.
  102.      * @return underlying estimated measurements
  103.      */
  104.     public List<EstimatedMeasurement<?>> getEstimatedMeasurements() {
  105.         return estimatedMeasurements;
  106.     }

  107.     /** {@inheritDoc} */
  108.     @Override
  109.     protected EstimatedMeasurement<MultiplexedMeasurement> theoreticalEvaluation(final int iteration, final int evaluation,
  110.                                                                                  final SpacecraftState[] states) {

  111.         final SpacecraftState[]              evaluationStates = new SpacecraftState[nbSat];
  112.         final List<TimeStampedPVCoordinates> participants     = new ArrayList<>();
  113.         final double[]                       value            = new double[dimension];

  114.         // loop over all multiplexed measurements
  115.         estimatedMeasurements.clear();
  116.         int index = 0;
  117.         for (int i = 0; i < observedMeasurements.size(); ++i) {

  118.             // filter states involved in the current measurement
  119.             final SpacecraftState[] filteredStates = new SpacecraftState[mapping[i].length];
  120.             for (int j = 0; j < mapping[i].length; ++j) {
  121.                 filteredStates[j] = states[mapping[i][j]];
  122.             }

  123.             // perform evaluation
  124.             final EstimatedMeasurement<?> eI = observedMeasurements.get(i).estimate(iteration, evaluation, filteredStates);
  125.             estimatedMeasurements.add(eI);

  126.             // extract results
  127.             final double[] valueI = eI.getEstimatedValue();
  128.             System.arraycopy(valueI, 0, value, index, valueI.length);
  129.             index += valueI.length;

  130.             // extract states
  131.             final SpacecraftState[] statesI = eI.getStates();
  132.             for (int j = 0; j < mapping[i].length; ++j) {
  133.                 evaluationStates[mapping[i][j]] = statesI[j];
  134.             }

  135.         }

  136.         // create multiplexed estimation
  137.         final EstimatedMeasurement<MultiplexedMeasurement> multiplexed =
  138.                         new EstimatedMeasurement<>(this, iteration, evaluation,
  139.                                                    evaluationStates,
  140.                                                    participants.toArray(new TimeStampedPVCoordinates[0]));

  141.         // copy multiplexed value
  142.         multiplexed.setEstimatedValue(value);

  143.         // combine derivatives
  144.         final int                            stateSize             = estimatedMeasurements.get(0).getStateSize();
  145.         final double[]                       zeroDerivative        = new double[stateSize];
  146.         final double[][][]                   stateDerivatives      = new double[nbSat][dimension][];
  147.         for (final double[][] m : stateDerivatives) {
  148.             Arrays.fill(m, zeroDerivative);
  149.         }

  150.         final Map<ParameterDriver, double[]> parametersDerivatives = new IdentityHashMap<>();
  151.         index = 0;
  152.         for (int i = 0; i < observedMeasurements.size(); ++i) {

  153.             final EstimatedMeasurement<?> eI   = estimatedMeasurements.get(i);
  154.             final int                     idx  = index;
  155.             final int                     dimI = eI.getObservedMeasurement().getDimension();

  156.             // state derivatives
  157.             for (int j = 0; j < mapping[i].length; ++j) {
  158.                 System.arraycopy(eI.getStateDerivatives(j), 0,
  159.                                  stateDerivatives[mapping[i][j]], index,
  160.                                  dimI);
  161.             }

  162.             // parameters derivatives
  163.             eI.getDerivativesDrivers().forEach(driver -> {
  164.                 final ParameterDriversList.DelegatingDriver delegating = parametersDrivers.findByName(driver.getName());
  165.                 double[] derivatives = parametersDerivatives.get(delegating);
  166.                 if (derivatives == null) {
  167.                     derivatives = new double[dimension];
  168.                     parametersDerivatives.put(delegating, derivatives);
  169.                 }
  170.                 System.arraycopy(eI.getParameterDerivatives(driver), 0, derivatives, idx, dimI);
  171.             });

  172.             index += dimI;

  173.         }

  174.         // set states derivatives
  175.         for (int i = 0; i < nbSat; ++i) {
  176.             multiplexed.setStateDerivatives(i, stateDerivatives[i]);
  177.         }

  178.         // set parameters derivatives
  179.         parametersDerivatives.
  180.             entrySet().
  181.             stream().
  182.             forEach(e -> multiplexed.setParameterDerivatives(e.getKey(), e.getValue()));

  183.         return multiplexed;

  184.     }

  185.     /** Multiplex measurements data.
  186.      * @param measurements measurements to multiplex
  187.      * @param extractor data extraction function
  188.      * @return multiplexed data
  189.      */
  190.     private static double[] multiplex(final List<ObservedMeasurement<?>> measurements,
  191.                                       final Function<ObservedMeasurement<?>, double[]> extractor) {

  192.         // gather individual parts
  193.         final List<double[]> parts = new ArrayList<> (measurements.size());
  194.         int n = 0;
  195.         for (final ObservedMeasurement<?> measurement : measurements) {
  196.             final double[] p = extractor.apply(measurement);
  197.             parts.add(p);
  198.             n += p.length;
  199.         }

  200.         // create multiplexed data
  201.         final double[] multiplexed = new double[n];
  202.         int index = 0;
  203.         for (final double[] p : parts) {
  204.             System.arraycopy(p, 0, multiplexed, index, p.length);
  205.             index += p.length;
  206.         }

  207.         return multiplexed;

  208.     }

  209.     /** Multiplex satellites data.
  210.      * @param measurements measurements to multiplex
  211.      * @return multiplexed satellites data
  212.      */
  213.     private static List<ObservableSatellite> multiplex(final List<ObservedMeasurement<?>> measurements) {

  214.         final List<ObservableSatellite> satellites = new ArrayList<>();

  215.         // gather all satellites, removing duplicates
  216.         for (final ObservedMeasurement<?> measurement : measurements) {
  217.             for (final ObservableSatellite satellite : measurement.getSatellites()) {
  218.                 boolean searching = true;
  219.                 for (int i = 0; i < satellites.size() && searching; ++i) {
  220.                     // check if we already know this satellite
  221.                     searching = satellite.getPropagatorIndex() != satellites.get(i).getPropagatorIndex();
  222.                 }
  223.                 if (searching) {
  224.                     // this is a new satellite, add it to the global list
  225.                     satellites.add(satellite);
  226.                 }
  227.             }
  228.         }

  229.         return satellites;

  230.     }

  231. }