AlignedAndConstrained.java

  1. /* Copyright 2002-2024 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.attitudes;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.Field;
  20. import org.hipparchus.analysis.differentiation.FieldUnivariateDerivative2;
  21. import org.hipparchus.analysis.differentiation.UnivariateDerivative2;
  22. import org.hipparchus.analysis.differentiation.UnivariateDerivative2Field;
  23. import org.hipparchus.geometry.euclidean.threed.FieldRotation;
  24. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  25. import org.hipparchus.geometry.euclidean.threed.Rotation;
  26. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  27. import org.orekit.bodies.OneAxisEllipsoid;
  28. import org.orekit.frames.Frame;
  29. import org.orekit.time.AbsoluteDate;
  30. import org.orekit.time.FieldAbsoluteDate;
  31. import org.orekit.utils.AngularCoordinates;
  32. import org.orekit.utils.ExtendedPositionProvider;
  33. import org.orekit.utils.FieldAngularCoordinates;
  34. import org.orekit.utils.FieldPVCoordinatesProvider;
  35. import org.orekit.utils.PVCoordinatesProvider;
  36. import org.orekit.utils.TimeStampedFieldPVCoordinates;
  37. import org.orekit.utils.TimeStampedPVCoordinates;

  38. import java.util.HashMap;
  39. import java.util.Map;

  40. /**
  41.  * Attitude provider with one satellite vector aligned and another one constrained to two targets.
  42.  * @author Luc Maisonobe
  43.  * @since 12.2
  44.  */
  45. public class AlignedAndConstrained implements AttitudeProvider
  46. {

  47.     /** Satellite vector for primary target. */
  48.     private final FieldVector3D<UnivariateDerivative2> primarySat;

  49.     /** Primary target. */
  50.     private final TargetProvider primaryTarget;

  51.     /** Satellite vector for secondary target. */
  52.     private final FieldVector3D<UnivariateDerivative2> secondarySat;

  53.     /** Secondary target. */
  54.     private final TargetProvider secondaryTarget;

  55.     /** Sun model. */
  56.     private final ExtendedPositionProvider sun;

  57.     /** Earth model. */
  58.     private final OneAxisEllipsoid earth;

  59.     /** Cached field-based satellite vectors. */
  60.     private final transient Map<Field<? extends CalculusFieldElement<?>>, Cache<? extends CalculusFieldElement<?>>>
  61.         cachedSatelliteVectors;

  62.     /**
  63.      * Simple constructor.
  64.      * @param primarySat      satellite vector for primary target
  65.      * @param primaryTarget   primary target
  66.      * @param secondarySat    satellite vector for secondary target
  67.      * @param secondaryTarget secondary target
  68.      * @param sun             Sun model
  69.      * @param earth           Earth model
  70.      */
  71.     public AlignedAndConstrained(final Vector3D primarySat, final TargetProvider primaryTarget,
  72.                                  final Vector3D secondarySat, final TargetProvider secondaryTarget,
  73.                                  final ExtendedPositionProvider sun,
  74.                                  final OneAxisEllipsoid earth)
  75.     {
  76.         this.primarySat             = new FieldVector3D<>(UnivariateDerivative2Field.getInstance(), primarySat);
  77.         this.primaryTarget          = primaryTarget;
  78.         this.secondarySat           = new FieldVector3D<>(UnivariateDerivative2Field.getInstance(), secondarySat);
  79.         this.secondaryTarget        = secondaryTarget;
  80.         this.sun                    = sun;
  81.         this.earth                  = earth;
  82.         this.cachedSatelliteVectors = new HashMap<>();
  83.     }

  84.     /** {@inheritDoc} */
  85.     @Override
  86.     public Rotation getAttitudeRotation(final PVCoordinatesProvider pvProv, final AbsoluteDate date, final Frame frame) {
  87.         final TimeStampedPVCoordinates satPV = pvProv.getPVCoordinates(date, frame);

  88.         // compute targets references at the specified date
  89.         final Vector3D primaryDirection   = primaryTarget.getTargetDirection(sun, earth, satPV, frame);
  90.         final Vector3D secondaryDirection = secondaryTarget.getTargetDirection(sun, earth, satPV, frame);

  91.         // compute transform from inertial frame to satellite frame
  92.         return new Rotation(primaryDirection, secondaryDirection, primarySat.toVector3D(), secondarySat.toVector3D());
  93.     }

  94.     /** {@inheritDoc} */
  95.     @Override
  96.     public Attitude getAttitude(final PVCoordinatesProvider pvProv,
  97.                                 final AbsoluteDate date,
  98.                                 final Frame frame)
  99.     {
  100.         final TimeStampedPVCoordinates satPV = pvProv.getPVCoordinates(date, frame);

  101.         // compute targets references at the specified date
  102.         final FieldVector3D<UnivariateDerivative2> primaryDirection   = primaryTarget.getDerivative2TargetDirection(sun, earth, satPV, frame);
  103.         final FieldVector3D<UnivariateDerivative2> secondaryDirection = secondaryTarget.getDerivative2TargetDirection(sun, earth, satPV, frame);

  104.         // compute transform from inertial frame to satellite frame
  105.         final FieldRotation<UnivariateDerivative2> inertToSatRotation =
  106.             new FieldRotation<>(primaryDirection, secondaryDirection, primarySat, secondarySat);

  107.         // build the attitude
  108.         return new Attitude(date, frame, new AngularCoordinates(inertToSatRotation));

  109.     }

  110.     /** {@inheritDoc} */
  111.     @Override
  112.     public <T extends CalculusFieldElement<T>> FieldRotation<T> getAttitudeRotation(final FieldPVCoordinatesProvider<T> pvProv,
  113.                                                                                     final FieldAbsoluteDate<T> date,
  114.                                                                                     final Frame frame) {
  115.         final TimeStampedFieldPVCoordinates<T> satPV = pvProv.getPVCoordinates(date, frame);

  116.         // compute targets references at the specified date
  117.         final FieldVector3D<T> primaryDirection   = primaryTarget.getTargetDirection(sun, earth, satPV, frame);
  118.         final FieldVector3D<T> secondaryDirection = secondaryTarget.getTargetDirection(sun, earth, satPV, frame);

  119.         // compute transform from inertial frame to satellite frame
  120.         final Field<T> field = date.getField();
  121.         return new FieldRotation<>(primaryDirection, secondaryDirection,
  122.                 new FieldVector3D<>(field, primarySat.toVector3D()), new FieldVector3D<>(field, secondarySat.toVector3D()));
  123.     }

  124.     /** {@inheritDoc} */
  125.     @Override
  126.     public <T extends CalculusFieldElement<T>> FieldAttitude<T> getAttitude(final FieldPVCoordinatesProvider<T> pvProv,
  127.                                                                             final FieldAbsoluteDate<T> date,
  128.                                                                             final Frame frame)
  129.     {
  130.         // get the satellite vectors for specified field
  131.         @SuppressWarnings("unchecked")
  132.         final Cache<T> satVectors =
  133.             (Cache<T>) cachedSatelliteVectors.computeIfAbsent(date.getField(),
  134.                                                               f -> new Cache<>(date.getField(), primarySat, secondarySat));

  135.         final TimeStampedFieldPVCoordinates<T> satPV = pvProv.getPVCoordinates(date, frame);

  136.         // compute targets references at the specified date
  137.         final FieldVector3D<FieldUnivariateDerivative2<T>> primaryDirection   = primaryTarget.getDerivative2TargetDirection(sun, earth, satPV, frame);
  138.         final FieldVector3D<FieldUnivariateDerivative2<T>> secondaryDirection = secondaryTarget.getDerivative2TargetDirection(sun, earth, satPV, frame);

  139.         // compute transform from inertial frame to satellite frame
  140.         final FieldRotation<FieldUnivariateDerivative2<T>> inertToSatRotation =
  141.             new FieldRotation<>(primaryDirection, secondaryDirection, satVectors.primarySat, satVectors.secondarySat);

  142.         // build the attitude
  143.         return new FieldAttitude<>(date, frame, new FieldAngularCoordinates<>(inertToSatRotation));

  144.     }

  145.     /** Container for cached satellite vectors. */
  146.     private static class Cache<T extends CalculusFieldElement<T>> {

  147.         /** Satellite vector for primary target. */
  148.         private final FieldVector3D<FieldUnivariateDerivative2<T>> primarySat;

  149.         /** Satellite vector for primary target. */
  150.         private final FieldVector3D<FieldUnivariateDerivative2<T>> secondarySat;

  151.         /** Simple constructor.
  152.          * @param field field to which the elements belong
  153.          * @param primarySat satellite vector for primary target
  154.          * @param secondarySat satellite vector for primary target
  155.          */
  156.         Cache(final Field<T> field,
  157.               final FieldVector3D<UnivariateDerivative2> primarySat,
  158.               final FieldVector3D<UnivariateDerivative2> secondarySat) {
  159.             final FieldUnivariateDerivative2<T> zero =
  160.                 new FieldUnivariateDerivative2<>(field.getZero(), field.getZero(), field.getZero());
  161.             this.primarySat   = new FieldVector3D<>(zero.newInstance(primarySat.getX().getValue()),
  162.                                                     zero.newInstance(primarySat.getY().getValue()),
  163.                                                     zero.newInstance(primarySat.getZ().getValue()));
  164.             this.secondarySat = new FieldVector3D<>(zero.newInstance(secondarySat.getX().getValue()),
  165.                                                     zero.newInstance(secondarySat.getY().getValue()),
  166.                                                     zero.newInstance(secondarySat.getZ().getValue()));
  167.         }

  168.     }

  169. }