1   /* Copyright 2013-2019 CS Systèmes d'Information
2    * Licensed to CS Systèmes d'Information (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.rugged.los;
18  
19  import java.util.stream.Stream;
20  
21  import org.hipparchus.analysis.differentiation.DerivativeStructure;
22  import org.hipparchus.geometry.euclidean.threed.FieldRotation;
23  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24  import org.hipparchus.geometry.euclidean.threed.Rotation;
25  import org.hipparchus.geometry.euclidean.threed.RotationConvention;
26  import org.hipparchus.geometry.euclidean.threed.Vector3D;
27  import org.hipparchus.util.FastMath;
28  import org.orekit.rugged.utils.DSGenerator;
29  import org.orekit.utils.ParameterDriver;
30  import org.orekit.utils.ParameterObserver;
31  
32  /** {@link TimeIndependentLOSTransform LOS transform} based on a fixed rotation.
33   * @author Luc Maisonobe
34   * @see LOSBuilder
35   */
36  public class FixedRotation implements TimeIndependentLOSTransform {
37  
38      /** Parameters scaling factor.
39       * <p>
40       * We use a power of 2 to avoid numeric noise introduction
41       * in the multiplications/divisions sequences.
42       * </p>
43       */
44      private final double SCALE = FastMath.scalb(1.0, -20);
45  
46      /** Rotation axis. */
47      private final Vector3D axis;
48  
49      /** Underlying rotation. */
50      private Rotation rotation;
51  
52      /** Underlying rotation with derivatives. */
53      private FieldRotation<DerivativeStructure> rDS;
54  
55      /** Driver for rotation angle. */
56      private final ParameterDriver angleDriver;
57  
58      /** Simple constructor.
59       * <p>
60       * The single parameter is the rotation angle.
61       * </p>
62       * @param name name of the rotation (used for estimated parameters identification)
63       * @param axis rotation axis
64       * @param angle rotation angle
65       */
66      public FixedRotation(final String name, final Vector3D axis, final double angle) {
67  
68          this.axis     = axis;
69          this.rotation = null;
70          this.rDS      = null;
71          this.angleDriver = new ParameterDriver(name, angle, SCALE, -2 * FastMath.PI, 2 * FastMath.PI);
72          angleDriver.addObserver(new ParameterObserver() {
73              @Override
74              public void valueChanged(final double previousValue, final ParameterDriver driver) {
75                  // reset rotations to null, they will be evaluated lazily if needed
76                  rotation = null;
77                  rDS      = null;
78              }
79          });
80      }
81  
82      /** {@inheritDoc} */
83      @Override
84      public Stream<ParameterDriver> getParametersDrivers() {
85          return Stream.of(angleDriver);
86      }
87  
88      /** {@inheritDoc} */
89      @Override
90      public Vector3D transformLOS(final int i, final Vector3D los) {
91          if (rotation == null) {
92              // lazy evaluation of the rotation
93              rotation = new Rotation(axis, angleDriver.getValue(), RotationConvention.VECTOR_OPERATOR);
94          }
95          return rotation.applyTo(los);
96      }
97  
98      /** {@inheritDoc} */
99      @Override
100     public FieldVector3D<DerivativeStructure> transformLOS(final int i, final FieldVector3D<DerivativeStructure> los,
101                                                            final DSGenerator generator) {
102         if (rDS == null) {
103             // lazy evaluation of the rotation
104             final FieldVector3D<DerivativeStructure> axisDS =
105                             new FieldVector3D<DerivativeStructure>(generator.constant(axis.getX()),
106                                                                    generator.constant(axis.getY()),
107                                                                    generator.constant(axis.getZ()));
108             final DerivativeStructure angleDS = generator.variable(angleDriver);
109             rDS = new FieldRotation<DerivativeStructure>(axisDS, angleDS, RotationConvention.VECTOR_OPERATOR);
110         }
111         return rDS.applyTo(los);
112     }
113 
114 }