NadirPointing.java

  1. /* Copyright 2002-2024 CS GROUP
  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 java.util.ArrayList;
  19. import java.util.List;

  20. import org.hipparchus.CalculusFieldElement;
  21. import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
  22. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  23. import org.orekit.bodies.BodyShape;
  24. import org.orekit.bodies.FieldGeodeticPoint;
  25. import org.orekit.bodies.GeodeticPoint;
  26. import org.orekit.frames.FieldStaticTransform;
  27. import org.orekit.frames.FieldTransform;
  28. import org.orekit.frames.Frame;
  29. import org.orekit.frames.StaticTransform;
  30. import org.orekit.frames.Transform;
  31. import org.orekit.time.AbsoluteDate;
  32. import org.orekit.time.FieldAbsoluteDate;
  33. import org.orekit.time.FieldTimeInterpolator;
  34. import org.orekit.time.TimeInterpolator;
  35. import org.orekit.utils.CartesianDerivativesFilter;
  36. import org.orekit.utils.FieldPVCoordinatesProvider;
  37. import org.orekit.utils.PVCoordinatesProvider;
  38. import org.orekit.utils.TimeStampedFieldPVCoordinates;
  39. import org.orekit.utils.TimeStampedFieldPVCoordinatesHermiteInterpolator;
  40. import org.orekit.utils.TimeStampedPVCoordinates;
  41. import org.orekit.utils.TimeStampedPVCoordinatesHermiteInterpolator;

  42. /**
  43.  * This class handles nadir pointing attitude provider.

  44.  * <p>
  45.  * This class represents the attitude provider where the satellite z axis is
  46.  * pointing to the vertical of the ground point under satellite.</p>
  47.  * <p>
  48.  * The object <code>NadirPointing</code> is guaranteed to be immutable.
  49.  * </p>
  50.  * @see     GroundPointing
  51.  * @author V&eacute;ronique Pommier-Maurussane
  52.  */
  53. public class NadirPointing extends GroundPointing {

  54.     /** Body shape.  */
  55.     private final BodyShape shape;

  56.     /** Creates new instance.
  57.      * @param inertialFrame frame in which orbital velocities are computed
  58.      * @param shape Body shape
  59.      * @since 7.1
  60.      */
  61.     public NadirPointing(final Frame inertialFrame, final BodyShape shape) {
  62.         // Call constructor of superclass
  63.         super(inertialFrame, shape.getBodyFrame());
  64.         this.shape = shape;
  65.     }

  66.     /** {@inheritDoc} */
  67.     public TimeStampedPVCoordinates getTargetPV(final PVCoordinatesProvider pvProv,
  68.                                                 final AbsoluteDate date, final Frame frame) {

  69.         // transform from specified reference frame to body frame
  70.         final Transform refToBody = frame.getTransformTo(shape.getBodyFrame(), date);

  71.         // sample intersection points in current date neighborhood
  72.         final double h  = 0.01;
  73.         final List<TimeStampedPVCoordinates> sample = new ArrayList<>();
  74.         sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(-2 * h), frame), refToBody.staticShiftedBy(-2 * h)));
  75.         sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(-h),     frame), refToBody.staticShiftedBy(-h)));
  76.         sample.add(nadirRef(pvProv.getPVCoordinates(date,                   frame), refToBody));
  77.         sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(+h),     frame), refToBody.staticShiftedBy(+h)));
  78.         sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(+2 * h), frame), refToBody.staticShiftedBy(+2 * h)));

  79.         // create interpolator
  80.         final TimeInterpolator<TimeStampedPVCoordinates> interpolator =
  81.                 new TimeStampedPVCoordinatesHermiteInterpolator(sample.size(), CartesianDerivativesFilter.USE_P);

  82.         // use interpolation to compute properly the time-derivatives
  83.         return interpolator.interpolate(date, sample);

  84.     }

  85.     /** {@inheritDoc} */
  86.     public <T extends CalculusFieldElement<T>> TimeStampedFieldPVCoordinates<T> getTargetPV(final FieldPVCoordinatesProvider<T> pvProv,
  87.                                                                                             final FieldAbsoluteDate<T> date,
  88.                                                                                             final Frame frame) {

  89.         // zero
  90.         final T zero = date.getField().getZero();

  91.         // transform from specified reference frame to body frame
  92.         final FieldTransform<T> refToBody = frame.getTransformTo(shape.getBodyFrame(), date);

  93.         // sample intersection points in current date neighborhood
  94.         final double h  = 0.01;
  95.         final List<TimeStampedFieldPVCoordinates<T>> sample = new ArrayList<>();
  96.         sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(-2 * h), frame), refToBody.staticShiftedBy(zero.add(-2 * h))));
  97.         sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(-h),     frame), refToBody.staticShiftedBy(zero.add(-h))));
  98.         sample.add(nadirRef(pvProv.getPVCoordinates(date,                   frame), refToBody));
  99.         sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(+h),     frame), refToBody.staticShiftedBy(zero.add(+h))));
  100.         sample.add(nadirRef(pvProv.getPVCoordinates(date.shiftedBy(+2 * h), frame), refToBody.staticShiftedBy(zero.add(+2 * h))));

  101.         // create interpolator
  102.         final FieldTimeInterpolator<TimeStampedFieldPVCoordinates<T>, T> interpolator =
  103.                 new TimeStampedFieldPVCoordinatesHermiteInterpolator<>(sample.size(), CartesianDerivativesFilter.USE_P);

  104.         // use interpolation to compute properly the time-derivatives
  105.         return interpolator.interpolate(date, sample);

  106.     }

  107.     /** Compute ground point in nadir direction, in reference frame.
  108.      * @param scRef spacecraft coordinates in reference frame
  109.      * @param refToBody transform from reference frame to body frame
  110.      * @return intersection point in body frame (only the position is set!)
  111.      */
  112.     private TimeStampedPVCoordinates nadirRef(final TimeStampedPVCoordinates scRef,
  113.                                               final StaticTransform refToBody) {

  114.         final Vector3D satInBodyFrame = refToBody.transformPosition(scRef.getPosition());

  115.         // satellite position in geodetic coordinates
  116.         final GeodeticPoint gpSat = shape.transform(satInBodyFrame, getBodyFrame(), scRef.getDate());

  117.         // nadir position in geodetic coordinates
  118.         final GeodeticPoint gpNadir = new GeodeticPoint(gpSat.getLatitude(), gpSat.getLongitude(), 0.0);

  119.         // nadir point position in body frame
  120.         final Vector3D pNadirBody = shape.transform(gpNadir);

  121.         // nadir point position in reference frame
  122.         final Vector3D pNadirRef = refToBody.getInverse().transformPosition(pNadirBody);

  123.         return new TimeStampedPVCoordinates(scRef.getDate(), pNadirRef, Vector3D.ZERO, Vector3D.ZERO);

  124.     }

  125.     /** Compute ground point in nadir direction, in reference frame.
  126.      * @param scRef spacecraft coordinates in reference frame
  127.      * @param refToBody transform from reference frame to body frame
  128.      * @param <T> type of the field elements
  129.      * @return intersection point in body frame (only the position is set!)
  130.      * @since 9.0
  131.      */
  132.     private <T extends CalculusFieldElement<T>> TimeStampedFieldPVCoordinates<T> nadirRef(final TimeStampedFieldPVCoordinates<T> scRef,
  133.                                                                                           final FieldStaticTransform<T> refToBody) {

  134.         final FieldVector3D<T> satInBodyFrame = refToBody.transformPosition(scRef.getPosition());

  135.         // satellite position in geodetic coordinates
  136.         final FieldGeodeticPoint<T> gpSat = shape.transform(satInBodyFrame, getBodyFrame(), scRef.getDate());

  137.         // nadir position in geodetic coordinates
  138.         final FieldGeodeticPoint<T> gpNadir = new FieldGeodeticPoint<>(gpSat.getLatitude(), gpSat.getLongitude(),
  139.                                                                        gpSat.getAltitude().getField().getZero());

  140.         // nadir point position in body frame
  141.         final FieldVector3D<T> pNadirBody = shape.transform(gpNadir);

  142.         // nadir point position in reference frame
  143.         final FieldVector3D<T> pNadirRef = refToBody.getInverse().transformPosition(pNadirBody);

  144.         final FieldVector3D<T> zero = FieldVector3D.getZero(gpSat.getAltitude().getField());
  145.         return new TimeStampedFieldPVCoordinates<>(scRef.getDate(), pNadirRef, zero, zero);

  146.     }

  147. }