MultiplexedMeasurement.java

  1. /* Copyright 2002-2020 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.     /** Multiplexed measurements. */
  38.     private final List<ObservedMeasurement<?>> observedMeasurements;

  39.     /** Multiplexed measurements. */
  40.     private final List<EstimatedMeasurement<?>> estimatedMeasurements;

  41.     /** Multiplexed parameters drivers. */
  42.     private ParameterDriversList parametersDrivers;

  43.     /** Total dimension. */
  44.     private final int dimension;

  45.     /** Total number of satellites involved. */
  46.     private final int nbSat;

  47.     /** States mapping. */
  48.     private final int[][] mapping;

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

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

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

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

  92.     }

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

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

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

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

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

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

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

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

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

  133.         }

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

  139.         // copy multiplexed value
  140.         multiplexed.setEstimatedValue(value);

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

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

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

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

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

  170.             index += dimI;

  171.         }

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

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

  181.         return multiplexed;

  182.     }

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

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

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

  205.         return multiplexed;

  206.     }

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

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

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

  227.         return satellites;

  228.     }

  229. }