SlewingPanel.java

  1. /* Copyright 2022-2025 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.forces;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  20. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  21. import org.hipparchus.util.FastMath;
  22. import org.hipparchus.util.FieldSinCos;
  23. import org.hipparchus.util.SinCos;
  24. import org.orekit.propagation.FieldSpacecraftState;
  25. import org.orekit.propagation.SpacecraftState;
  26. import org.orekit.time.AbsoluteDate;

  27. /** Class representing one panel of a satellite, slewing about an axis at constant rate.
  28.  * <p>
  29.  * It is mainly used to represent a solar array with fixed rate rotation.
  30.  * </p>
  31.  * <p>
  32.  * The panel rotation evolves linearly according to a start position and an
  33.  * angular rate (which can be set to 0 for non-rotating panels, which may
  34.  * occur in special modes or during contingencies).
  35.  * </p>
  36.  * <p>
  37.  * These panels are considered to be always {@link #isDoubleSided() double-sided}.
  38.  * </p>
  39.  *
  40.  * @author Luc Maisonobe
  41.  * @since 3.0
  42.  */
  43. public class SlewingPanel extends Panel {

  44.     /** Rotation rate of the panel (rad/s). */
  45.     private final double rotationRate;

  46.     /** Reference date for the panel rotation. */
  47.     private final AbsoluteDate referenceDate;

  48.     /** Panel reference axis in spacecraft frame (may be null). */
  49.     private final Vector3D rX;

  50.     /** Panel third axis in spacecraft frame (may be null). */
  51.     private final Vector3D rY;

  52.     /** Simple constructor.
  53.      * <p>
  54.      * As the sum of absorption coefficient, specular reflection coefficient and
  55.      * diffuse reflection coefficient is exactly 1, only the first two coefficients
  56.      * are needed here, the third one is deduced from the other ones.
  57.      * </p>
  58.      * <p>
  59.      * The panel is considered to rotate about one axis in order to make its normal
  60.      * point as close as possible to the target. It means the target will always be
  61.      * in the plane defined by the rotation axis and the panel normal.
  62.      * </p>
  63.      * @param rotationAxis rotation axis of the panel
  64.      * @param rotationRate rotation rate of the panel (rad/s)
  65.      * @param referenceDate reference date for the panel rotation
  66.      * @param referenceNormal direction of the panel normal at reference date in spacecraft frame
  67.      * @param area panel area in m²
  68.      * @param drag drag coefficient
  69.      * @param liftRatio drag lift ratio (proportion between 0 and 1 of atmosphere modecules
  70.      * that will experience specular reflection when hitting spacecraft instead
  71.      * of experiencing diffuse reflection, hence producing lift)
  72.      * @param absorption radiation pressure absorption coefficient (between 0 and 1)
  73.      * @param reflection radiation pressure specular reflection coefficient (between 0 and 1)
  74.      */
  75.     public SlewingPanel(final Vector3D rotationAxis, final double rotationRate,
  76.                         final AbsoluteDate referenceDate, final Vector3D referenceNormal,
  77.                         final double area,
  78.                         final double drag, final double liftRatio,
  79.                         final double absorption, final double reflection) {
  80.         super(area, true, drag, liftRatio, absorption, reflection);

  81.         this.rotationRate    = rotationRate;
  82.         this.referenceDate   = referenceDate;
  83.         this.rY              = Vector3D.crossProduct(rotationAxis, referenceNormal).normalize();
  84.         this.rX              = Vector3D.crossProduct(rY, rotationAxis).normalize();

  85.     }

  86.     /** {@inheritDoc} */
  87.     @Override
  88.     public Vector3D getNormal(final SpacecraftState state) {
  89.         // use a simple rotation at fixed rate
  90.         final SinCos sc = FastMath.sinCos(state.getDate().durationFrom(referenceDate) * rotationRate);
  91.         return new Vector3D(sc.cos(), rX, sc.sin(), rY);
  92.     }

  93.     /** {@inheritDoc} */
  94.     @Override
  95.     public <T extends CalculusFieldElement<T>> FieldVector3D<T> getNormal(final FieldSpacecraftState<T> state) {
  96.         // use a simple rotation at fixed rate
  97.         final FieldSinCos<T> sc = FastMath.sinCos(state.getDate().durationFrom(referenceDate).multiply(rotationRate));
  98.         return new FieldVector3D<>(sc.cos(), rX, sc.sin(), rY);
  99.     }

  100. }