All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.orekit.attitudes.YawCompensation Maven / Gradle / Ivy

Go to download

OREKIT (ORbits Extrapolation KIT) is a low level space dynamics library. It provides basic elements (orbits, dates, attitude, frames ...) and various algorithms to handle them (conversions, analytical and numerical propagation, pointing ...).

There is a newer version: 12.2
Show newest version
/* Copyright 2002-2024 CS GROUP
 * Licensed to CS GROUP (CS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * CS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.orekit.attitudes;

import org.hipparchus.Field;
import org.hipparchus.CalculusFieldElement;
import org.hipparchus.geometry.euclidean.threed.FieldRotation;
import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
import org.hipparchus.geometry.euclidean.threed.Rotation;
import org.hipparchus.geometry.euclidean.threed.RotationConvention;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.orekit.frames.FieldTransform;
import org.orekit.frames.Frame;
import org.orekit.frames.Transform;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.FieldAbsoluteDate;
import org.orekit.utils.FieldPVCoordinates;
import org.orekit.utils.FieldPVCoordinatesProvider;
import org.orekit.utils.PVCoordinates;
import org.orekit.utils.PVCoordinatesProvider;
import org.orekit.utils.TimeStampedAngularCoordinates;
import org.orekit.utils.TimeStampedFieldAngularCoordinates;


/**
 * This class handles yaw compensation attitude provider.

 * 

* Yaw compensation is mainly used for Earth observation satellites. As a * satellites moves along its track, the image of ground points move on * the focal point of the optical sensor. This motion is a combination of * the satellite motion, but also on the Earth rotation and on the current * attitude (in particular if the pointing includes Roll or Pitch offset). * In order to reduce geometrical distortion, the yaw angle is changed a * little from the simple ground pointing attitude such that the apparent * motion of ground points is along a prescribed axis (orthogonal to the * optical sensors rows), taking into account all effects. *

*

* This attitude is implemented as a wrapper on top of an underlying ground * pointing law that defines the roll and pitch angles. *

*

* Instances of this class are guaranteed to be immutable. *

* @see GroundPointing * @author Véronique Pommier-Maurussane */ public class YawCompensation extends GroundPointingAttitudeModifier implements AttitudeProviderModifier { /** J axis. */ private static final PVCoordinates PLUS_J = new PVCoordinates(Vector3D.PLUS_J, Vector3D.ZERO, Vector3D.ZERO); /** K axis. */ private static final PVCoordinates PLUS_K = new PVCoordinates(Vector3D.PLUS_K, Vector3D.ZERO, Vector3D.ZERO); /** Creates a new instance. * @param inertialFrame frame in which orbital velocities are computed * @param groundPointingLaw ground pointing attitude provider without yaw compensation * @since 7.1 */ public YawCompensation(final Frame inertialFrame, final GroundPointing groundPointingLaw) { super(inertialFrame, groundPointingLaw.getBodyFrame(), groundPointingLaw); } /** {@inheritDoc} */ @Override public Attitude getAttitude(final PVCoordinatesProvider pvProv, final AbsoluteDate date, final Frame frame) { final Transform bodyToRef = getBodyFrame().getTransformTo(frame, date); // compute sliding target ground point final PVCoordinates slidingRef = getTargetPV(pvProv, date, frame); final PVCoordinates slidingBody = bodyToRef.getInverse().transformPVCoordinates(slidingRef); // compute relative position of sliding ground point with respect to satellite final PVCoordinates relativePosition = new PVCoordinates(pvProv.getPVCoordinates(date, frame), slidingRef); // compute relative velocity of fixed ground point with respect to sliding ground point // the velocity part of the transformPVCoordinates for the sliding point ps // from body frame to reference frame is: // d(ps_ref)/dt = r(d(ps_body)/dt + dq/dt) - Ω ⨯ ps_ref // where r is the rotation part of the transform, Ω is the corresponding // angular rate, and dq/dt is the derivative of the translation part of the // transform (the translation itself, without derivative, is hidden in the // ps_ref part in the cross product). // The sliding point ps is co-located to a fixed ground point pf (i.e. they have the // same position at time of computation), but this fixed point as zero velocity // with respect to the ground. So the velocity part of the transformPVCoordinates // for this fixed point can be computed using the same formula as above: // from body frame to reference frame is: // d(pf_ref)/dt = r(0 + dq/dt) - Ω ⨯ pf_ref // so remembering that the two points are at the same location at computation time, // i.e. that at t=0 pf_ref=ps_ref, the relative velocity between the fixed point // and the sliding point is given by the simple expression: // d(ps_ref)/dt - d(pf_ref)/dt = r(d(ps_body)/dt) // the acceleration is computed by differentiating the expression, which gives: // d²(ps_ref)/dt² - d²(pf_ref)/dt² = r(d²(ps_body)/dt²) - Ω ⨯ [d(ps_ref)/dt - d(pf_ref)/dt] final Vector3D v = bodyToRef.getRotation().applyTo(slidingBody.getVelocity()); final Vector3D a = new Vector3D(+1, bodyToRef.getRotation().applyTo(slidingBody.getAcceleration()), -1, Vector3D.crossProduct(bodyToRef.getRotationRate(), v)); final PVCoordinates relativeVelocity = new PVCoordinates(v, a, Vector3D.ZERO); final PVCoordinates relativeNormal = PVCoordinates.crossProduct(relativePosition, relativeVelocity).normalize(); // attitude definition : // . Z satellite axis points to sliding target // . target relative velocity is in (Z, X) plane, in the -X half plane part return new Attitude(frame, new TimeStampedAngularCoordinates(date, relativePosition.normalize(), relativeNormal.normalize(), PLUS_K, PLUS_J, 1.0e-9)); } /** {@inheritDoc} */ @Override public > FieldAttitude getAttitude(final FieldPVCoordinatesProvider pvProv, final FieldAbsoluteDate date, final Frame frame) { final Field field = date.getField(); final FieldVector3D zero = FieldVector3D.getZero(field); final FieldPVCoordinates plusJ = new FieldPVCoordinates<>(FieldVector3D.getPlusJ(field), zero, zero); final FieldPVCoordinates plusK = new FieldPVCoordinates<>(FieldVector3D.getPlusK(field), zero, zero); final FieldTransform bodyToRef = getBodyFrame().getTransformTo(frame, date); // compute sliding target ground point final FieldPVCoordinates slidingRef = getTargetPV(pvProv, date, frame); final FieldPVCoordinates slidingBody = bodyToRef.getInverse().transformPVCoordinates(slidingRef); // compute relative position of sliding ground point with respect to satellite final FieldPVCoordinates relativePosition = new FieldPVCoordinates<>(pvProv.getPVCoordinates(date, frame), slidingRef); // compute relative velocity of fixed ground point with respect to sliding ground point // the velocity part of the transformPVCoordinates for the sliding point ps // from body frame to reference frame is: // d(ps_ref)/dt = r(d(ps_body)/dt + dq/dt) - Ω ⨯ ps_ref // where r is the rotation part of the transform, Ω is the corresponding // angular rate, and dq/dt is the derivative of the translation part of the // transform (the translation itself, without derivative, is hidden in the // ps_ref part in the cross product). // The sliding point ps is co-located to a fixed ground point pf (i.e. they have the // same position at time of computation), but this fixed point as zero velocity // with respect to the ground. So the velocity part of the transformPVCoordinates // for this fixed point can be computed using the same formula as above: // from body frame to reference frame is: // d(pf_ref)/dt = r(0 + dq/dt) - Ω ⨯ pf_ref // so remembering that the two points are at the same location at computation time, // i.e. that at t=0 pf_ref=ps_ref, the relative velocity between the fixed point // and the sliding point is given by the simple expression: // d(ps_ref)/dt - d(pf_ref)/dt = r(d(ps_body)/dt) // the acceleration is computed by differentiating the expression, which gives: // d²(ps_ref)/dt² - d²(pf_ref)/dt² = r(d²(ps_body)/dt²) - Ω ⨯ [d(ps_ref)/dt - d(pf_ref)/dt] final FieldVector3D v = bodyToRef.getRotation().applyTo(slidingBody.getVelocity()); final FieldVector3D a = new FieldVector3D<>(+1, bodyToRef.getRotation().applyTo(slidingBody.getAcceleration()), -1, FieldVector3D.crossProduct(bodyToRef.getRotationRate(), v)); final FieldPVCoordinates relativeVelocity = new FieldPVCoordinates<>(v, a, FieldVector3D.getZero(date.getField())); final FieldPVCoordinates relativeNormal = relativePosition.crossProduct(relativeVelocity).normalize(); // attitude definition : // . Z satellite axis points to sliding target // . target relative velocity is in (Z, X) plane, in the -X half plane part return new FieldAttitude<>(frame, new TimeStampedFieldAngularCoordinates<>(date, relativePosition.normalize(), relativeNormal.normalize(), plusK, plusJ, 1.0e-9)); } /** Compute the yaw compensation angle at date. * @param pvProv provider for PV coordinates * @param date date at which compensation is requested * @param frame reference frame from which attitude is computed * @return yaw compensation angle for orbit. */ public double getYawAngle(final PVCoordinatesProvider pvProv, final AbsoluteDate date, final Frame frame) { final Rotation rBase = getBaseState(pvProv, date, frame).getRotation(); final Rotation rCompensated = getAttitude(pvProv, date, frame).getRotation(); final Rotation compensation = rCompensated.compose(rBase.revert(), RotationConvention.VECTOR_OPERATOR); return -compensation.applyTo(Vector3D.PLUS_I).getAlpha(); } /** Compute the yaw compensation angle at date. * @param pvProv provider for PV coordinates * @param date date at which compensation is requested * @param frame reference frame from which attitude is computed * @param type of the field elements * @return yaw compensation angle for orbit. * @since 9.0 */ public > T getYawAngle(final FieldPVCoordinatesProvider pvProv, final FieldAbsoluteDate date, final Frame frame) { final FieldRotation rBase = getBaseState(pvProv, date, frame).getRotation(); final FieldRotation rCompensated = getAttitude(pvProv, date, frame).getRotation(); final FieldRotation compensation = rCompensated.compose(rBase.revert(), RotationConvention.VECTOR_OPERATOR); return compensation.applyTo(Vector3D.PLUS_I).getAlpha().negate(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy