Skip to content
Snippets Groups Projects
Commit a2b0e151 authored by Mikael Fillastre's avatar Mikael Fillastre
Browse files

Add tests and comments

parent 902243b1
No related branches found
No related tags found
No related merge requests found
......@@ -32,9 +32,16 @@ import org.orekit.utils.FieldPVCoordinatesProvider;
import org.orekit.utils.PVCoordinatesProvider;
/**
* This class is used to both manage the attitude of the satellite and the
* direction of thrust. TODO more comments how it is used, where, present
* alternatives
* This class is used in to both manage the attitude of the satellite and the
* direction of thrust.
*
* It is used in ConfigurableLowThrustManeuver to set the spacecraft attitude
* according to the expected thrust direction.
*
* The direction can be variable or fixed, defined in the spaceraft frame, a
* Local Orbital Frame or a user frame.
*
* It is also possible to use an external attitude provider.
*
* @author Mikael Fillastre
* @author Andrea Fiorentino
......@@ -49,7 +56,7 @@ public class ThrustDirectionAndAttitudeProvider implements AttitudeProvider {
private static final String FIELD_NAME_LOF_TYPE = "thrustDirectionLofType";
/** Types, see builders for details. */
private enum ThrustDirectionProviderType {
private enum ThrustDirectionAndAttitudeProviderType {
/** SATELLITE_ATTITUDE. */
SATELLITE_ATTITUDE,
/** CUSTOM_ATTITUDE. */
......@@ -61,7 +68,7 @@ public class ThrustDirectionAndAttitudeProvider implements AttitudeProvider {
}
/** Type. */
private final ThrustDirectionProviderType type;
private final ThrustDirectionAndAttitudeProviderType type;
/**
* External attitude provider, for CUSTOM_ATTITUDE type. Set to null otherwise.
*/
......@@ -83,7 +90,7 @@ public class ThrustDirectionAndAttitudeProvider implements AttitudeProvider {
*/
private final LOFType thrustDirectionLofType;
private ThrustDirectionAndAttitudeProvider(final ThrustDirectionProviderType type,
private ThrustDirectionAndAttitudeProvider(final ThrustDirectionAndAttitudeProviderType type,
final AttitudeProvider attitudeProvider, final VariableThrustDirectionVector variableDirectionInFrame,
final Vector3D thrusterAxisInSatelliteFrame, final Frame frame, final LOFType thrustDirectionLofType) {
this.type = type;
......@@ -95,30 +102,30 @@ public class ThrustDirectionAndAttitudeProvider implements AttitudeProvider {
}
private static void checkParameterNotNull(final Object parameter, final String name,
final ThrustDirectionProviderType type) {
final ThrustDirectionAndAttitudeProviderType type) {
if (parameter == null) {
throw new OrekitException(OrekitMessages.PARAMETER_NOT_SET, name,
"ThrustDirectionProvider-" + type.toString());
"ThrustDirectionAndAttitudeProvider-" + type.toString());
}
}
/**
* Build a ThrustDirectionProvider from a fixed direction in the satellite
* frame. The satellite attitude won't be managed by this object
* Build a ThrustDirectionAndAttitudeProvider from a fixed direction in the
* satellite frame. The satellite attitude won't be managed by this object
*
* @param direction constant direction in the satellite frame
* @return a new instance
*/
public static ThrustDirectionAndAttitudeProvider buildFromFixedDirectionInSatelliteFrame(final Vector3D direction) {
final ThrustDirectionAndAttitudeProvider obj = new ThrustDirectionAndAttitudeProvider(
ThrustDirectionProviderType.SATELLITE_ATTITUDE, null, null, direction, null, null);
ThrustDirectionAndAttitudeProviderType.SATELLITE_ATTITUDE, null, null, direction, null, null);
checkParameterNotNull(direction, "thrusterAxisInSatelliteFrame", obj.type);
return obj;
}
/**
* Build a ThrustDirectionProvider where the attitude is provided by an
* external. Object the direction of thrust will be constant
* Build a ThrustDirectionAndAttitudeProvider where the attitude is provided by
* an external. Object the direction of thrust will be constant
*
* @param attitudeProvider the object that provide the satellite attitude
* @param direction thruster axis in satellite frame
......@@ -127,14 +134,15 @@ public class ThrustDirectionAndAttitudeProvider implements AttitudeProvider {
public static ThrustDirectionAndAttitudeProvider buildFromCustomAttitude(final AttitudeProvider attitudeProvider,
final Vector3D direction) {
final ThrustDirectionAndAttitudeProvider obj = new ThrustDirectionAndAttitudeProvider(
ThrustDirectionProviderType.CUSTOM_ATTITUDE, attitudeProvider, null, direction, null, null);
ThrustDirectionAndAttitudeProviderType.CUSTOM_ATTITUDE, attitudeProvider, null, direction, null, null);
checkParameterNotNull(attitudeProvider, "attitudeProvider", obj.type);
checkParameterNotNull(direction, "direction", obj.type);
return obj;
}
/**
* Build a ThrustDirectionProvider by a variable direction in a custom frame.
* Build a ThrustDirectionAndAttitudeProvider by a variable direction in a
* custom frame.
*
* @param thrustDirectionFrame reference frame for thrust direction
* @param variableDirectionInFrame the object providing the thrust direction
......@@ -144,7 +152,7 @@ public class ThrustDirectionAndAttitudeProvider implements AttitudeProvider {
public static ThrustDirectionAndAttitudeProvider buildFromDirectionInFrame(final Frame thrustDirectionFrame,
final VariableThrustDirectionVector variableDirectionInFrame, final Vector3D thrusterAxisInSatelliteFrame) {
final ThrustDirectionAndAttitudeProvider obj = new ThrustDirectionAndAttitudeProvider(
ThrustDirectionProviderType.DIRECTION_IN_FRAME, null, variableDirectionInFrame,
ThrustDirectionAndAttitudeProviderType.DIRECTION_IN_FRAME, null, variableDirectionInFrame,
thrusterAxisInSatelliteFrame, thrustDirectionFrame, null);
checkParameterNotNull(variableDirectionInFrame, FIELD_NAME_VARIABLE_DIRECTION, obj.type);
checkParameterNotNull(thrustDirectionFrame, FIELD_NAME_DIRECTION_FRAME, obj.type);
......@@ -152,8 +160,8 @@ public class ThrustDirectionAndAttitudeProvider implements AttitudeProvider {
}
/**
* Build a ThrustDirectionProvider by a variable direction in a Local Orbital
* Frame.
* Build a ThrustDirectionAndAttitudeProvider by a variable direction in a Local
* Orbital Frame.
*
* @param thrustDirectionLofType Local Orbital Frame type
* @param variableDirectionInFrame the object providing the thrust direction
......@@ -163,7 +171,7 @@ public class ThrustDirectionAndAttitudeProvider implements AttitudeProvider {
public static ThrustDirectionAndAttitudeProvider buildFromDirectionInLOF(final LOFType thrustDirectionLofType,
final VariableThrustDirectionVector variableDirectionInFrame, final Vector3D thrusterAxisInSatelliteFrame) {
final ThrustDirectionAndAttitudeProvider obj = new ThrustDirectionAndAttitudeProvider(
ThrustDirectionProviderType.DIRECTION_IN_LOF, null, variableDirectionInFrame,
ThrustDirectionAndAttitudeProviderType.DIRECTION_IN_LOF, null, variableDirectionInFrame,
thrusterAxisInSatelliteFrame, null, thrustDirectionLofType);
checkParameterNotNull(variableDirectionInFrame, FIELD_NAME_VARIABLE_DIRECTION, obj.type);
checkParameterNotNull(thrustDirectionLofType, FIELD_NAME_LOF_TYPE, obj.type);
......@@ -184,7 +192,7 @@ public class ThrustDirectionAndAttitudeProvider implements AttitudeProvider {
return getAttitudeFromFrame(pvProv, date, frame);
default:
throw new OrekitException(OrekitMessages.INVALID_TYPE_FOR_FUNCTION,
"ThrustDirectionProvider.getAttitude", "type", type.toString());
"ThrustDirectionAndAttitudeProvider.getAttitude", "type", type.toString());
}
}
......@@ -192,14 +200,14 @@ public class ThrustDirectionAndAttitudeProvider implements AttitudeProvider {
public <T extends RealFieldElement<T>> FieldAttitude<T> getAttitude(final FieldPVCoordinatesProvider<T> pvProv,
final FieldAbsoluteDate<T> date, final Frame frame) {
throw new OrekitException(OrekitMessages.FUNCTION_NOT_IMPLEMENTED,
"ThrustDirectionProvider with RealFieldElement");
"ThrustDirectionAndAttitudeProvider with RealFieldElement");
}
public Attitude getAttitudeFromFrame(final PVCoordinatesProvider pvProv, final AbsoluteDate date,
final Frame frame) {
final Rotation inertial2ThrusterFrame;
if (type.equals(ThrustDirectionProviderType.DIRECTION_IN_FRAME)) {
if (type.equals(ThrustDirectionAndAttitudeProviderType.DIRECTION_IN_FRAME)) {
inertial2ThrusterFrame = frame.getTransformTo(thrustDirectionFrame, date).getRotation();
} else { // LOF
inertial2ThrusterFrame = thrustDirectionLofType.rotationFromInertial(pvProv.getPVCoordinates(date, frame));
......@@ -216,7 +224,7 @@ public class ThrustDirectionAndAttitudeProvider implements AttitudeProvider {
public AttitudeProvider getManeuverAttitudeProvider() {
AttitudeProvider attitudeProviderToReturn = null;
if (type != ThrustDirectionProviderType.SATELLITE_ATTITUDE) {
if (type != ThrustDirectionAndAttitudeProviderType.SATELLITE_ATTITUDE) {
attitudeProviderToReturn = this;
} // else default behavior
return attitudeProviderToReturn;
......
/* Copyright 2020 Exotrail
* 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.
* Exotrail 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.forces.maneuvers.propulsion;
import org.hipparchus.geometry.euclidean.threed.Rotation;
import org.hipparchus.geometry.euclidean.threed.RotationConvention;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.Decimal64;
import org.hipparchus.util.FastMath;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.Utils;
import org.orekit.attitudes.Attitude;
import org.orekit.attitudes.AttitudeProvider;
import org.orekit.attitudes.LofOffset;
import org.orekit.errors.OrekitException;
import org.orekit.frames.FactoryManagedFrame;
import org.orekit.frames.FramesFactory;
import org.orekit.frames.LOFType;
import org.orekit.orbits.KeplerianOrbit;
import org.orekit.orbits.PositionAngle;
import org.orekit.propagation.analytical.KeplerianPropagator;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.FieldAbsoluteDate;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;
import org.orekit.utils.PVCoordinatesProvider;
public class ThrustDirectionAndAttitudeProviderTest {
/** */
private static final double EPSILON_ROTATION = 1E-15;
/** */
private FactoryManagedFrame frame;
/** */
private AbsoluteDate date;
/** */
private PVCoordinatesProvider pvProv;
/** */
private final Vector3D thrusterAxisInSatelliteFrame = Vector3D.PLUS_J;
@Before
public void setUp() {
Utils.setDataRoot("regular-data");
frame = FramesFactory.getCIRF(IERSConventions.IERS_2010, true);
date = new AbsoluteDate(2020, 01, 01, TimeScalesFactory.getUTC());
final double sma = Constants.EGM96_EARTH_EQUATORIAL_RADIUS + 700e3;
final double ecc = 0.01;
final double inc = FastMath.toRadians(60);
final double pa = FastMath.toRadians(0);
final double raan = 0.;
final double anomaly = FastMath.toRadians(0);
final KeplerianOrbit initialOrbit = new KeplerianOrbit(sma, ecc, inc, pa, raan, anomaly, PositionAngle.TRUE,
FramesFactory.getCIRF(IERSConventions.IERS_2010, true), date, Constants.EGM96_EARTH_MU);
pvProv = new KeplerianPropagator(initialOrbit);
}
private AttitudeProvider buildVelocityAttitudeProvider() {
return new LofOffset(frame, LOFType.TNW);
}
@Test(expected = OrekitException.class)
public void fixedDirectionCanNotProvideTheAttitude() {
final ThrustDirectionAndAttitudeProvider provider = ThrustDirectionAndAttitudeProvider
.buildFromFixedDirectionInSatelliteFrame(Vector3D.PLUS_I);
Assert.assertNull(provider.getManeuverAttitudeProvider());
provider.getAttitude(pvProv, date, frame); // raise an error
}
@Test(expected = OrekitException.class)
public void missingParameterTest() {
ThrustDirectionAndAttitudeProvider.buildFromDirectionInFrame(frame, null, thrusterAxisInSatelliteFrame);
}
@Test
public void attitudeFromDirectionInFrame() {
final Vector3D fixedThrustDirection = new Vector3D(1, 2, 3).normalize();
final ConstantThrustDirectionVector thrustDirectionInertial = new ConstantThrustDirectionVector(
fixedThrustDirection);
final ThrustDirectionAndAttitudeProvider provider = ThrustDirectionAndAttitudeProvider
.buildFromDirectionInFrame(frame, thrustDirectionInertial, thrusterAxisInSatelliteFrame);
Assert.assertNotNull(provider.getManeuverAttitudeProvider());
// attitude from Frame: inertial => sat
final Attitude inertialToSat = provider.getAttitude(pvProv, date, frame);
final Vector3D thrustDirectionRecomputed = inertialToSat.getRotation().revert()
.applyTo(thrusterAxisInSatelliteFrame);
Assert.assertEquals(0, fixedThrustDirection.subtract(thrustDirectionRecomputed).getNorm(), EPSILON_ROTATION);
}
@Test
public void attitudeFromDirectionInLOF() {
final Vector3D fixedThrustDirection = Vector3D.PLUS_I;
final ConstantThrustDirectionVector thrustDirectionTNW = new ConstantThrustDirectionVector(Vector3D.PLUS_I);
final ThrustDirectionAndAttitudeProvider provider = ThrustDirectionAndAttitudeProvider
.buildFromDirectionInLOF(LOFType.TNW, thrustDirectionTNW, thrusterAxisInSatelliteFrame);
Assert.assertNotNull(provider.getManeuverAttitudeProvider());
// attitude from Frame: inertial => sat
final Attitude inertialToSat = provider.getAttitude(pvProv, date, frame);
// recompute rotation from satellite frame to TNW
final Rotation inertialToLof = LOFType.TNW.transformFromInertial(date, pvProv.getPVCoordinates(date, frame))
.getRotation();
final Rotation satToLof = inertialToLof.compose(inertialToSat.getRotation().revert(),
RotationConvention.VECTOR_OPERATOR);
final Vector3D thrustDirectionRecomputed = satToLof.applyTo(thrusterAxisInSatelliteFrame);
Assert.assertEquals(0., fixedThrustDirection.subtract(thrustDirectionRecomputed).getNorm(), EPSILON_ROTATION);
}
@Test
public void attitudeFromCustomProvider() {
final ThrustDirectionAndAttitudeProvider provider = ThrustDirectionAndAttitudeProvider
.buildFromCustomAttitude(buildVelocityAttitudeProvider(), thrusterAxisInSatelliteFrame);
Assert.assertNotNull(provider.getManeuverAttitudeProvider());
Assert.assertEquals(
buildVelocityAttitudeProvider().getAttitude(pvProv, date, frame).getRotation()
.applyTo(thrusterAxisInSatelliteFrame),
provider.getAttitude(pvProv, date, frame).getRotation().applyTo(thrusterAxisInSatelliteFrame));
}
@Test(expected = OrekitException.class)
public void getAttitudeFieldError() {
final ThrustDirectionAndAttitudeProvider provider = ThrustDirectionAndAttitudeProvider
.buildFromCustomAttitude(buildVelocityAttitudeProvider(), Vector3D.PLUS_I);
Assert.assertNotNull(provider.getManeuverAttitudeProvider());
provider.getAttitude(null, new FieldAbsoluteDate<>(date, new Decimal64(0)), frame); // raise an error
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment