1   /* Copyright 2002-2026 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.propagation.relative.clohessywiltshire;
19  
20  import org.hipparchus.geometry.euclidean.threed.Vector3D;
21  import org.hipparchus.linear.MatrixUtils;
22  import org.hipparchus.linear.RealMatrix;
23  import org.orekit.utils.PVCoordinates;
24  import org.orekit.utils.TimeStampedPVCoordinates;
25  
26  /**
27   * This class stores the 4 sub-matrices of the 6x6 state transition matrix of the Clohessy-Wiltshire equations.
28   *
29   * @author Jérôme Tabeaud
30   * @author Romain Cuvillon
31   * @since 14.0
32   */
33  public class ClohessyWiltshireMatrices {
34  
35      /**
36       * Time since epoch used in computing the matrices, in seconds.
37       */
38      private final double timeSinceEpoch;
39  
40      /**
41       * Matrix that multiplies the position to compute the position.
42       */
43      private final RealMatrix phiRR;
44  
45      /**
46       * Matrix that multiplies the velocity to compute the position.
47       */
48      private final RealMatrix phiRV;
49  
50      /**
51       * Matrix that multiplies the position to compute the velocity.
52       */
53      private final RealMatrix phiVR;
54  
55      /**
56       * Matrix that multiplies the velocity to compute the velocity.
57       */
58      private final RealMatrix phiVV;
59  
60      /**
61       * Constructor of the 4 sub-matrices of the 6x6 state transition matrix of the Clohessy-Wiltshire equations.
62       * <blockquote>
63       * &delta;<b>r</b>(t) = &phi;<sub>rr</sub>(t) &delta;<b>r</b><sub>0</sub> + &phi;<sub>rv</sub>(t)
64       * &delta;<b>v</b><sub>0</sub>
65       * <br><br>
66       * &delta;<b>v</b>(t) = &phi;<sub>vr</sub>(t) &delta;<b>r</b><sub>0</sub> + &phi;<sub>vv</sub>(t)
67       * &delta;<b>v</b><sub>0</sub>
68       * </blockquote>
69       *
70       * @param timeSinceEpoch duration in seconds since epoch
71       * @param phiRR          position to position transition sub-matrix
72       * @param phiRV          velocity to position transition sub-matrix
73       * @param phiVR          position to velocity transition sub-matrix
74       * @param phiVV          velocity to velocity transition sub-matrix
75       */
76      public ClohessyWiltshireMatrices(final double timeSinceEpoch, final RealMatrix phiRR, final RealMatrix phiRV,
77                                       final RealMatrix phiVR, final RealMatrix phiVV) {
78          this.timeSinceEpoch = timeSinceEpoch;
79          this.phiRR          = phiRR;
80          this.phiRV          = phiRV;
81          this.phiVR          = phiVR;
82          this.phiVV          = phiVV;
83      }
84  
85      /**
86       * Get the sub-matrix of the transition matrix &phi;<sub>rr</sub>(t).
87       *
88       * @return &phi;<sub>rr</sub>(t) sub-matrix
89       */
90      public RealMatrix getPhiRR() {
91          return phiRR;
92      }
93  
94      /**
95       * Get the sub-matrix of the transition matrix &phi;<sub>rv</sub>(t).
96       *
97       * @return &phi;<sub>rv</sub>(t) sub-matrix
98       */
99      public RealMatrix getPhiRV() {
100         return phiRV;
101     }
102 
103     /**
104      * Get the sub-matrix of the transition matrix &phi;<sub>vr</sub>(t).
105      *
106      * @return &phi;<sub>vr</sub>(t) sub-matrix
107      */
108     public RealMatrix getPhiVR() {
109         return phiVR;
110     }
111 
112     /**
113      * Get the sub-matrix of the transition matrix &phi;<sub>vv</sub>(t).
114      *
115      * @return &phi;<sub>vv</sub>(t) sub-matrix
116      */
117     public RealMatrix getPhiVV() {
118         return phiVV;
119     }
120 
121     /**
122      * Transforms the input initial PVT expressed in the target's QSW LOF to the PVT at the time encoded in the
123      * Clohessy-Wiltshire matrices contained in the object.
124      * <p>pos(t) = Φrr * pos(0) + Φrv * vel(0)</p>
125      * <p>vel(t) = Φvr * pos(0) + Φvv * vel(0)</p>
126      *
127      * @param pvt input initial PVT expressed in the target's QSW LOF.
128      * @return PVT at the time encoded in the Clohessy-Wiltshire matrices, expressed in the target's QSW LOF.
129      */
130     public TimeStampedPVCoordinates transform(final TimeStampedPVCoordinates pvt) {
131         return new TimeStampedPVCoordinates(pvt.getDate().shiftedBy(timeSinceEpoch),
132                                             transform(new PVCoordinates(pvt.getPosition(), pvt.getVelocity())));
133     }
134 
135     /**
136      * Transforms the input initial PV expressed in the target's QSW LOF to the PV at the time encoded in the
137      * Clohessy-Wiltshire matrices contained in the object.
138      * <p>pos(t) = Φrr * pos(0) + Φrv * vel(0)</p>
139      * <p>vel(t) = Φvr * pos(0) + Φvv * vel(0)</p>
140      *
141      * @param pv input initial PV expressed in the target's QSW LOF.
142      * @return PV at the time encoded in the Clohessy-Wiltshire matrices, expressed in the target's QSW LOF.
143      */
144     public PVCoordinates transform(final PVCoordinates pv) {
145 
146         // Convert Vector3D to RealMatrix
147         final RealMatrix pos0 = MatrixUtils.createColumnRealMatrix(pv.getPosition().toArray());
148         final RealMatrix vel0 = MatrixUtils.createColumnRealMatrix(pv.getVelocity().toArray());
149 
150         // Transform the input PV using the current matrices
151         final Vector3D pos1 = new Vector3D(phiRR.multiply(pos0).add(phiRV.multiply(vel0)).getColumn(0));
152         final Vector3D vel1 = new Vector3D(phiVR.multiply(pos0).add(phiVV.multiply(vel0)).getColumn(0));
153 
154         // Return transformed PV
155         return new PVCoordinates(pos1, vel1);
156     }
157 }