YawSteering.java

  1. /* Copyright 2002-2016 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.apache.commons.math3.geometry.euclidean.threed.Vector3D;
  19. import org.orekit.errors.OrekitException;
  20. import org.orekit.frames.Frame;
  21. import org.orekit.time.AbsoluteDate;
  22. import org.orekit.utils.PVCoordinates;
  23. import org.orekit.utils.PVCoordinatesProvider;
  24. import org.orekit.utils.TimeStampedAngularCoordinates;
  25. import org.orekit.utils.TimeStampedPVCoordinates;


  26. /**
  27.  * This class handles yaw steering law.

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

  61.     /** Serializable UID. */
  62.     private static final long serialVersionUID = 20150529L;

  63.     /** Pointing axis. */
  64.     private static final PVCoordinates PLUS_Z =
  65.             new PVCoordinates(Vector3D.PLUS_K, Vector3D.ZERO, Vector3D.ZERO);

  66.     /** Underlying ground pointing attitude provider.  */
  67.     private final GroundPointing groundPointingLaw;

  68.     /** Sun motion model. */
  69.     private final PVCoordinatesProvider sun;

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

  72.     /** Creates a new instance.
  73.      * @param groundPointingLaw ground pointing attitude provider without yaw compensation
  74.      * @param sun sun motion model
  75.      * @param phasingAxis satellite axis that must be roughly in Sun direction
  76.      * (if solar arrays rotation axis is Y, then this axis should be either +X or -X)
  77.      * @deprecated as of 7.1, replaced with {@link #YawSteering(Frame, GroundPointing, PVCoordinatesProvider, Vector3D)}
  78.      */
  79.     @Deprecated
  80.     public YawSteering(final GroundPointing groundPointingLaw,
  81.                        final PVCoordinatesProvider sun,
  82.                        final Vector3D phasingAxis) {
  83.         super(groundPointingLaw.getBodyFrame());
  84.         this.groundPointingLaw = groundPointingLaw;
  85.         this.sun = sun;
  86.         this.phasingNormal = new PVCoordinates(Vector3D.crossProduct(Vector3D.PLUS_K, phasingAxis).normalize(),
  87.                                                Vector3D.ZERO,
  88.                                                Vector3D.ZERO);
  89.     }

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

  111.     /** Get the underlying (ground pointing) attitude provider.
  112.      * @return underlying attitude provider, which in this case is a {@link GroundPointing} instance
  113.      */
  114.     public AttitudeProvider getUnderlyingAttitudeProvider() {
  115.         return groundPointingLaw;
  116.     }

  117.     /** {@inheritDoc} */
  118.     protected TimeStampedPVCoordinates getTargetPV(final PVCoordinatesProvider pvProv,
  119.                                                    final AbsoluteDate date, final Frame frame)
  120.         throws OrekitException {
  121.         return groundPointingLaw.getTargetPV(pvProv, date, frame);
  122.     }

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

  135.     /** {@inheritDoc} */
  136.     @Override
  137.     public Attitude getAttitude(final PVCoordinatesProvider pvProv,
  138.                                 final AbsoluteDate date, final Frame frame)
  139.         throws OrekitException {

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

  142.         // Compensation rotation definition :
  143.         //  . Z satellite axis is unchanged
  144.         //  . phasing axis shall be aligned to sun direction
  145.         final PVCoordinates sunDirection = new PVCoordinates(pvProv.getPVCoordinates(date, frame),
  146.                                                              sun.getPVCoordinates(date, frame));
  147.         final PVCoordinates sunNormal =
  148.                 PVCoordinates.crossProduct(PLUS_Z, base.getOrientation().applyTo(sunDirection));
  149.         final TimeStampedAngularCoordinates compensation =
  150.                 new TimeStampedAngularCoordinates(date,
  151.                                                   PLUS_Z, sunNormal.normalize(),
  152.                                                   PLUS_Z, phasingNormal,
  153.                                                   1.0e-9);

  154.         // add compensation
  155.         return new Attitude(frame, compensation.addOffset(base.getOrientation()));

  156.     }

  157. }