1   /* Copyright 2022-2025 Luc Maisonobe
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.generation;
18  
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.List;
22  import java.util.Map;
23  
24  import org.orekit.estimation.measurements.EstimatedMeasurementBase;
25  import org.orekit.estimation.measurements.EstimationModifier;
26  import org.orekit.estimation.measurements.MultiplexedMeasurement;
27  import org.orekit.estimation.measurements.ObservableSatellite;
28  import org.orekit.estimation.measurements.ObservedMeasurement;
29  import org.orekit.propagation.SpacecraftState;
30  import org.orekit.propagation.sampling.OrekitStepInterpolator;
31  import org.orekit.time.AbsoluteDate;
32  
33  
34  /** Builder for {@link MultiplexedMeasurement} measurements.
35   * @author Luc Maisonobe
36   * @since 12.0
37   */
38  public class MultiplexedMeasurementBuilder implements MeasurementBuilder<MultiplexedMeasurement> {
39  
40      /** Builders for individual measurements. */
41      private final List<MeasurementBuilder<?>> builders;
42  
43      /** Satellites related to this builder. */
44      private final ObservableSatellite[] satellites;
45  
46      /** Modifiers that apply to the measurement.*/
47      private final List<EstimationModifier<MultiplexedMeasurement>> modifiers;
48  
49      /** Simple constructor.
50       * @param builders builders for multiplexed measurements
51       */
52      public MultiplexedMeasurementBuilder(final List<MeasurementBuilder<?>> builders) {
53          this.builders  = builders;
54          this.modifiers = new ArrayList<>();
55  
56          final List<ObservableSatellite> list = new ArrayList<>();
57          for (final MeasurementBuilder<?> builder : builders) {
58              for (final ObservableSatellite satellite : builder.getSatellites()) {
59                  if (!list.contains(satellite)) {
60                      list.add(satellite);
61                  }
62              }
63          }
64          this.satellites = list.toArray(new ObservableSatellite[0]);
65  
66      }
67  
68      /** {@inheritDoc}
69       * <p>
70       * This implementation stores the time span of the measurements generation.
71       * </p>
72       */
73      @Override
74      public void init(final AbsoluteDate start, final AbsoluteDate end) {
75          for (final MeasurementBuilder<?> builder : builders) {
76              builder.init(start, end);
77          }
78      }
79  
80      /** {@inheritDoc} */
81      @Override
82      public void addModifier(final EstimationModifier<MultiplexedMeasurement> modifier) {
83          modifiers.add(modifier);
84      }
85  
86      /** {@inheritDoc} */
87      @Override
88      public List<EstimationModifier<MultiplexedMeasurement>> getModifiers() {
89          return Collections.unmodifiableList(modifiers);
90      }
91  
92      /** {@inheritDoc} */
93      @Override
94      public EstimatedMeasurementBase<MultiplexedMeasurement> build(final AbsoluteDate date,
95                                                                    final Map<ObservableSatellite, OrekitStepInterpolator> interpolators) {
96  
97          // estimate underlying measurements
98          final List<EstimatedMeasurementBase<?>> underlyingEstimated = new ArrayList<>(builders.size());
99          final List<ObservedMeasurement<?>>      underlyingObserved  = new ArrayList<>(builders.size());
100         for (final MeasurementBuilder<?> builder : builders) {
101             final EstimatedMeasurementBase<?> built = builder.build(date, interpolators);
102             underlyingEstimated.add(built);
103             underlyingObserved.add(built.getObservedMeasurement());
104         }
105 
106         // generate observed multiplexed measurement
107         final MultiplexedMeasurement measurement = new MultiplexedMeasurement(underlyingObserved);
108         for (final EstimationModifier<MultiplexedMeasurement> modifier : getModifiers()) {
109             measurement.addModifier(modifier);
110         }
111 
112         // generate estimated multiplexed measurement
113         final SpacecraftState[] states = new SpacecraftState[satellites.length];
114         for (int i = 0; i < underlyingEstimated.size(); ++i) {
115             final EstimatedMeasurementBase<?> mI = underlyingEstimated.get(i);
116             final SpacecraftState[] statesI = mI.getStates();
117             for (int j = 0; j < statesI.length; ++j) {
118                 states[measurement.getMultiplexedStateIndex(i, j)] = statesI[j];
119             }
120         }
121         return measurement.estimateWithoutDerivatives(states);
122 
123     }
124 
125     /** {@inheritDoc} */
126     @Override
127     public ObservableSatellite[] getSatellites() {
128         return satellites.clone();
129     }
130 
131 }