1   /* Copyright 2002-2025 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  
18  package org.orekit.files.ccsds.ndm.odm;
19  
20  import java.util.function.Supplier;
21  
22  import org.hipparchus.linear.MatrixUtils;
23  import org.hipparchus.linear.RealMatrix;
24  import org.orekit.errors.OrekitException;
25  import org.orekit.errors.OrekitMessages;
26  import org.orekit.files.ccsds.definitions.FrameFacade;
27  import org.orekit.files.ccsds.section.CommentsContainer;
28  import org.orekit.files.ccsds.section.Data;
29  import org.orekit.time.AbsoluteDate;
30  
31  /** Container for OPM/OMM/OCM Cartesian covariance matrix.
32   * <p>
33   * Beware that the Orekit getters and setters all rely on SI units. The parsers
34   * and writers take care of converting these SI units into CCSDS mandatory units.
35   * The {@link org.orekit.utils.units.Unit Unit} class provides useful
36   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
37   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} methods in case the callers
38   * already use CCSDS units instead of the API SI units. The general-purpose
39   * {@link org.orekit.utils.units.Unit Unit} class (without an 's') and the
40   * CCSDS-specific {@link org.orekit.files.ccsds.definitions.Units Units} class
41   * (with an 's') also provide some predefined units. These predefined units and the
42   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
43   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} conversion methods are indeed
44   * what the parsers and writers use for the conversions.
45   * </p>
46   * @author sports
47   * @since 6.1
48   */
49  public class CartesianCovariance extends CommentsContainer implements Data {
50  
51      /** Labels for matrix row/columns. */
52      private static final String[] LABELS = {
53          "X", "Y", "Z", "X_DOT", "Y_DOT", "Z_DOT"
54      };
55  
56      /** Supplier for default reference frame. */
57      private final Supplier<FrameFacade> defaultFrameSupplier;
58  
59      /** Matrix epoch. */
60      private AbsoluteDate epoch;
61  
62      /** Reference frame in which data are given. */
63      private FrameFacade referenceFrame;
64  
65      /** Position/Velocity covariance matrix. */
66      private final RealMatrix covarianceMatrix;
67  
68      /** Create an empty data set.
69       * @param defaultFrameSupplier supplier for default reference frame
70       * if no frame is specified in the CCSDS message
71       */
72      public CartesianCovariance(final Supplier<FrameFacade> defaultFrameSupplier) {
73          this.defaultFrameSupplier = defaultFrameSupplier;
74          covarianceMatrix = MatrixUtils.createRealMatrix(6, 6);
75          for (int i = 0; i < covarianceMatrix.getRowDimension(); ++i) {
76              for (int j = 0; j <= i; ++j) {
77                  covarianceMatrix.setEntry(i, j, Double.NaN);
78              }
79          }
80      }
81  
82      /** {@inheritDoc} */
83      @Override
84      public void validate(final double version) {
85          super.validate(version);
86          checkNotNull(epoch, CartesianCovarianceKey.EPOCH.name());
87          for (int i = 0; i < covarianceMatrix.getRowDimension(); ++i) {
88              for (int j = 0; j <= i; ++j) {
89                  if (Double.isNaN(covarianceMatrix.getEntry(i, j))) {
90                      throw new OrekitException(OrekitMessages.CCSDS_MISSING_KEYWORD,
91                                                "C" + LABELS[i] + "_" + LABELS[j]);
92                  }
93              }
94          }
95      }
96  
97      /** Get matrix epoch.
98       * @return matrix epoch
99       */
100     public AbsoluteDate getEpoch() {
101         return epoch;
102     }
103 
104     /** Set matrix epoch.
105      * @param epoch matrix epoch
106      */
107     public void setEpoch(final AbsoluteDate epoch) {
108         refuseFurtherComments();
109         this.epoch = epoch;
110     }
111 
112     /**
113      * Get the reference frame.
114      *
115      * @return The reference frame specified by the {@code COV_REF_FRAME} keyword
116      * or inherited from metadata
117      */
118     public FrameFacade getReferenceFrame() {
119         return referenceFrame == null ? defaultFrameSupplier.get() : referenceFrame;
120     }
121 
122     /** Set the reference frame in which data are given.
123      * @param referenceFrame the reference frame to be set
124      */
125     public void setReferenceFrame(final FrameFacade referenceFrame) {
126         refuseFurtherComments();
127         this.referenceFrame = referenceFrame;
128     }
129 
130     /** Get the Position/Velocity covariance matrix.
131      * @return the Position/Velocity covariance matrix
132      */
133     public RealMatrix getCovarianceMatrix() {
134         return covarianceMatrix;
135     }
136 
137     /** Set an entry in the Position/Velocity covariance matrix.
138      * <p>
139      * Both m(j, k) and m(k, j) are set.
140      * </p>
141      * @param j row index (must be between 0 and 5 (inclusive)
142      * @param k column index (must be between 0 and 5 (inclusive)
143      * @param entry value of the matrix entry
144      */
145     public void setCovarianceMatrixEntry(final int j, final int k, final double entry) {
146         refuseFurtherComments();
147         covarianceMatrix.setEntry(j, k, entry);
148         covarianceMatrix.setEntry(k, j, entry);
149     }
150 
151 }