YawSteering.java

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

  18. import org.hipparchus.Field;
  19. import org.hipparchus.RealFieldElement;
  20. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  21. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  22. import org.orekit.errors.OrekitException;
  23. import org.orekit.frames.Frame;
  24. import org.orekit.time.AbsoluteDate;
  25. import org.orekit.time.FieldAbsoluteDate;
  26. import org.orekit.utils.FieldPVCoordinates;
  27. import org.orekit.utils.FieldPVCoordinatesProvider;
  28. import org.orekit.utils.PVCoordinates;
  29. import org.orekit.utils.PVCoordinatesProvider;
  30. import org.orekit.utils.TimeStampedAngularCoordinates;
  31. import org.orekit.utils.TimeStampedFieldAngularCoordinates;
  32. import org.orekit.utils.TimeStampedFieldPVCoordinates;
  33. import org.orekit.utils.TimeStampedPVCoordinates;


  34. /**
  35.  * This class handles yaw steering law.

  36.  * <p>
  37.  * Yaw steering is mainly used for low Earth orbiting satellites with no
  38.  * missions-related constraints on yaw angle. It sets the yaw angle in
  39.  * such a way the solar arrays have maximal lighting without changing the
  40.  * roll and pitch.
  41.  * </p>
  42.  * <p>
  43.  * The motion in yaw is smooth when the Sun is far from the orbital plane,
  44.  * but gets more and more <i>square like</i> as the Sun gets closer to the
  45.  * orbital plane. The degenerate extreme case with the Sun in the orbital
  46.  * plane leads to a yaw angle switching between two steady states, with
  47.  * instantaneaous π radians rotations at each switch, two times per orbit.
  48.  * This degenerate case is clearly not operationally sound so another pointing
  49.  * mode is chosen when Sun comes closer than some predefined threshold to the
  50.  * orbital plane.
  51.  * </p>
  52.  * <p>
  53.  * This class can handle (for now) only a theoretically perfect yaw steering
  54.  * (i.e. the yaw angle is exactly the optimal angle). Smoothed yaw steering with a
  55.  * few sine waves approaching the optimal angle will be added in the future if
  56.  * needed.
  57.  * </p>
  58.  * <p>
  59.  * This attitude is implemented as a wrapper on top of an underlying ground
  60.  * pointing law that defines the roll and pitch angles.
  61.  * </p>
  62.  * <p>
  63.  * Instances of this class are guaranteed to be immutable.
  64.  * </p>
  65.  * @see    GroundPointing
  66.  * @author Luc Maisonobe
  67.  */
  68. public class YawSteering extends GroundPointing implements AttitudeProviderModifier {

  69.     /** Serializable UID. */
  70.     private static final long serialVersionUID = 20150529L;

  71.     /** Pointing axis. */
  72.     private static final PVCoordinates PLUS_Z =
  73.             new PVCoordinates(Vector3D.PLUS_K, Vector3D.ZERO, Vector3D.ZERO);

  74.     /** Underlying ground pointing attitude provider.  */
  75.     private final GroundPointing groundPointingLaw;

  76.     /** Sun motion model. */
  77.     private final PVCoordinatesProvider sun;

  78.     /** Normal to the plane where the Sun must remain. */
  79.     private final PVCoordinates phasingNormal;

  80.     /** Creates a new instance.
  81.      * @param inertialFrame frame in which orbital velocities are computed
  82.      * @param groundPointingLaw ground pointing attitude provider without yaw compensation
  83.      * @param sun sun motion model
  84.      * @param phasingAxis satellite axis that must be roughly in Sun direction
  85.      * (if solar arrays rotation axis is Y, then this axis should be either +X or -X)
  86.      * @exception OrekitException if the frame specified is not a pseudo-inertial frame
  87.      * @since 7.1
  88.      */
  89.     public YawSteering(final Frame inertialFrame,
  90.                        final GroundPointing groundPointingLaw,
  91.                        final PVCoordinatesProvider sun,
  92.                        final Vector3D phasingAxis)
  93.         throws OrekitException {
  94.         super(inertialFrame, groundPointingLaw.getBodyFrame());
  95.         this.groundPointingLaw = groundPointingLaw;
  96.         this.sun = sun;
  97.         this.phasingNormal = new PVCoordinates(Vector3D.crossProduct(Vector3D.PLUS_K, phasingAxis).normalize(),
  98.                                                Vector3D.ZERO,
  99.                                                Vector3D.ZERO);
  100.     }

  101.     /** Get the underlying (ground pointing) attitude provider.
  102.      * @return underlying attitude provider, which in this case is a {@link GroundPointing} instance
  103.      */
  104.     public AttitudeProvider getUnderlyingAttitudeProvider() {
  105.         return groundPointingLaw;
  106.     }

  107.     /** {@inheritDoc} */
  108.     public TimeStampedPVCoordinates getTargetPV(final PVCoordinatesProvider pvProv,
  109.                                                 final AbsoluteDate date, final Frame frame)
  110.         throws OrekitException {
  111.         return groundPointingLaw.getTargetPV(pvProv, date, frame);
  112.     }

  113.     /** {@inheritDoc} */
  114.     public <T extends RealFieldElement<T>> TimeStampedFieldPVCoordinates<T> getTargetPV(final FieldPVCoordinatesProvider<T> pvProv,
  115.                                                                                         final FieldAbsoluteDate<T> date,
  116.                                                                                         final Frame frame)
  117.         throws OrekitException {
  118.         return groundPointingLaw.getTargetPV(pvProv, date, frame);
  119.     }

  120.     /** Compute the base system state at given date, without compensation.
  121.      * @param pvProv provider for PV coordinates
  122.      * @param date date at which state is requested
  123.      * @param frame reference frame from which attitude is computed
  124.      * @return satellite base attitude state, i.e without compensation.
  125.      * @throws OrekitException if some specific error occurs
  126.      */
  127.     public Attitude getBaseState(final PVCoordinatesProvider pvProv,
  128.                                  final AbsoluteDate date, final Frame frame)
  129.         throws OrekitException {
  130.         return groundPointingLaw.getAttitude(pvProv, date, frame);
  131.     }

  132.     /** Compute the base system state at given date, without compensation.
  133.      * @param pvProv provider for PV coordinates
  134.      * @param date date at which state is requested
  135.      * @param frame reference frame from which attitude is computed
  136.      * @param <T> type of the field elements
  137.      * @return satellite base attitude state, i.e without compensation.
  138.      * @throws OrekitException if some specific error occurs
  139.      * @since 9.0
  140.      */
  141.     public <T extends RealFieldElement<T>> FieldAttitude<T> getBaseState(final FieldPVCoordinatesProvider<T> pvProv,
  142.                                                                          final FieldAbsoluteDate<T> date, final Frame frame)
  143.         throws OrekitException {
  144.         return groundPointingLaw.getAttitude(pvProv, date, frame);
  145.     }

  146.     /** {@inheritDoc} */
  147.     @Override
  148.     public Attitude getAttitude(final PVCoordinatesProvider pvProv,
  149.                                 final AbsoluteDate date, final Frame frame)
  150.         throws OrekitException {

  151.         // attitude from base attitude provider
  152.         final Attitude base = getBaseState(pvProv, date, frame);

  153.         // Compensation rotation definition :
  154.         //  . Z satellite axis is unchanged
  155.         //  . phasing axis shall be aligned to sun direction
  156.         final PVCoordinates sunDirection = new PVCoordinates(pvProv.getPVCoordinates(date, frame),
  157.                                                              sun.getPVCoordinates(date, frame));
  158.         final PVCoordinates sunNormal =
  159.                 PVCoordinates.crossProduct(PLUS_Z, base.getOrientation().applyTo(sunDirection));
  160.         final TimeStampedAngularCoordinates compensation =
  161.                 new TimeStampedAngularCoordinates(date,
  162.                                                   PLUS_Z, sunNormal.normalize(),
  163.                                                   PLUS_Z, phasingNormal,
  164.                                                   1.0e-9);

  165.         // add compensation
  166.         return new Attitude(frame, compensation.addOffset(base.getOrientation()));

  167.     }

  168.     /** {@inheritDoc} */
  169.     @Override
  170.     public <T extends RealFieldElement<T>> FieldAttitude<T> getAttitude(final FieldPVCoordinatesProvider<T> pvProv,
  171.                                                                         final FieldAbsoluteDate<T> date, final Frame frame)
  172.         throws OrekitException {

  173.         final Field<T>              field = date.getField();
  174.         final FieldVector3D<T>      zero  = FieldVector3D.getZero(field);
  175.         final FieldPVCoordinates<T> plusZ = new FieldPVCoordinates<>(FieldVector3D.getPlusK(field), zero, zero);

  176.         // attitude from base attitude provider
  177.         final FieldAttitude<T> base = getBaseState(pvProv, date, frame);

  178.         // Compensation rotation definition :
  179.         //  . Z satellite axis is unchanged
  180.         //  . phasing axis shall be aligned to sun direction
  181.         final FieldPVCoordinates<T> sunDirection =
  182.                         new FieldPVCoordinates<>(pvProv.getPVCoordinates(date, frame),
  183.                                                  new FieldPVCoordinates<>(field,
  184.                                                                           sun.getPVCoordinates(date.toAbsoluteDate(), frame)));
  185.         final FieldPVCoordinates<T> sunNormal =
  186.                 plusZ.crossProduct(base.getOrientation().applyTo(sunDirection));
  187.         final TimeStampedFieldAngularCoordinates<T> compensation =
  188.                 new TimeStampedFieldAngularCoordinates<>(date,
  189.                                                          plusZ, sunNormal.normalize(),
  190.                                                          plusZ, new FieldPVCoordinates<>(field, phasingNormal),
  191.                                                          1.0e-9);

  192.         // add compensation
  193.         return new FieldAttitude<>(frame, compensation.addOffset(base.getOrientation()));

  194.     }

  195. }