use of org.hipparchus.geometry.euclidean.threed.Vector3D in project Orekit by CS-SI.
the class TurnAroundRangeMeasurementCreator method handleStep.
/**
* Function handling the steps of the propagator
* A turn-around measurement needs 2 stations, a master and a slave
* The measurement is a signal:
* - Emitted from the master ground station
* - Reflected on the spacecraft
* - Reflected on the slave ground station
* - Reflected on the spacecraft again
* - Received on the master ground station
* Its value is the elapsed time between emission and reception
* divided by 2c were c is the speed of light.
*
* The path of the signal is divided into 2 legs:
* - The 1st leg goes from emission by the master station to reception by the slave station
* - The 2nd leg goes from emission by the slave station to reception by the master station
*
* The spacecraft state date should, after a few iterations of the estimation process, be
* set to the date of arrival/departure of the signal to/from the slave station.
* It is guaranteed by implementation of the estimated measurement.
* This is done to avoid big shifts in time to compute the transit states.
* See TurnAroundRange.java for more
* Thus the spacecraft date is the date when the 1st leg of the path ends and the 2nd leg begins
*/
public void handleStep(final SpacecraftState currentState, final boolean isLast) throws OrekitException {
try {
for (Map.Entry<GroundStation, GroundStation> entry : context.TARstations.entrySet()) {
final GroundStation masterStation = entry.getKey();
final GroundStation slaveStation = entry.getValue();
final AbsoluteDate date = currentState.getDate();
final Frame inertial = currentState.getFrame();
final Vector3D position = currentState.toTransform().getInverse().transformPosition(antennaPhaseCenter);
// Create a TAR measurement only if elevation for both stations is higher than elevationMin°
if ((masterStation.getBaseFrame().getElevation(position, inertial, date) > FastMath.toRadians(30.0)) && (slaveStation.getBaseFrame().getElevation(position, inertial, date) > FastMath.toRadians(30.0))) {
// The solver used
final UnivariateSolver solver = new BracketingNthOrderBrentSolver(1.0e-12, 5);
// Spacecraft date t = date of arrival/departure of the signal to/from from the slave station
// Slave station position in inertial frame at t
final Vector3D slaveStationPosition = slaveStation.getOffsetToInertial(inertial, date).transformPosition(Vector3D.ZERO);
// Downlink time of flight to slave station
// The date of arrival/departure of the signal to/from the slave station is known and
// equal to spacecraft date t.
// Therefore we can use the function "downlinkTimeOfFlight" from GroundStation class
// final double slaveTauD = slaveStation.downlinkTimeOfFlight(currentState, date);
final double slaveTauD = solver.solve(1000, new UnivariateFunction() {
public double value(final double x) throws OrekitExceptionWrapper {
final SpacecraftState transitState = currentState.shiftedBy(-x);
final double d = Vector3D.distance(transitState.toTransform().getInverse().transformPosition(antennaPhaseCenter), slaveStationPosition);
return d - x * Constants.SPEED_OF_LIGHT;
}
}, -1.0, 1.0);
// Uplink time of flight from slave station
// A solver is used to know where the satellite is when it receives the signal
// back from the slave station
final double slaveTauU = solver.solve(1000, new UnivariateFunction() {
public double value(final double x) throws OrekitExceptionWrapper {
final SpacecraftState transitState = currentState.shiftedBy(+x);
final double d = Vector3D.distance(transitState.toTransform().getInverse().transformPosition(antennaPhaseCenter), slaveStationPosition);
return d - x * Constants.SPEED_OF_LIGHT;
}
}, -1.0, 1.0);
// Find the position of the master station at signal departure and arrival
// ----
// Transit state position & date for the 1st leg of the signal path
final SpacecraftState S1 = currentState.shiftedBy(-slaveTauD);
final Vector3D P1 = S1.toTransform().getInverse().transformPosition(antennaPhaseCenter);
final AbsoluteDate T1 = date.shiftedBy(-slaveTauD);
// Transit state position & date for the 2nd leg of the signal path
final Vector3D P2 = currentState.shiftedBy(+slaveTauU).toTransform().getInverse().transformPosition(antennaPhaseCenter);
final AbsoluteDate T2 = date.shiftedBy(+slaveTauU);
// Master station downlink delay - from P2 to master station
// We use a solver to know where the master station is when it receives
// the signal back from the satellite on the 2nd leg of the path
final double masterTauD = solver.solve(1000, new UnivariateFunction() {
public double value(final double x) throws OrekitExceptionWrapper {
try {
final Transform t = masterStation.getOffsetToInertial(inertial, T2.shiftedBy(+x));
final double d = Vector3D.distance(P2, t.transformPosition(Vector3D.ZERO));
return d - x * Constants.SPEED_OF_LIGHT;
} catch (OrekitException oe) {
throw new OrekitExceptionWrapper(oe);
}
}
}, -1.0, 1.0);
final AbsoluteDate masterReceptionDate = T2.shiftedBy(+masterTauD);
final TimeStampedPVCoordinates masterStationAtReception = masterStation.getOffsetToInertial(inertial, masterReceptionDate).transformPVCoordinates(new TimeStampedPVCoordinates(masterReceptionDate, PVCoordinates.ZERO));
// Master station uplink delay - from master station to P1
// Here the state date is known. Thus we can use the function "signalTimeOfFlight"
// of the AbstractMeasurement class
final double masterTauU = AbstractMeasurement.signalTimeOfFlight(masterStationAtReception, P1, T1);
final AbsoluteDate masterEmissionDate = T1.shiftedBy(-masterTauU);
final Vector3D masterStationAtEmission = masterStation.getOffsetToInertial(inertial, masterEmissionDate).transformPosition(Vector3D.ZERO);
// Uplink/downlink distance from/to slave station
final double slaveDownLinkDistance = Vector3D.distance(P1, slaveStationPosition);
final double slaveUpLinkDistance = Vector3D.distance(P2, slaveStationPosition);
// Uplink/downlink distance from/to master station
final double masterUpLinkDistance = Vector3D.distance(P1, masterStationAtEmission);
final double masterDownLinkDistance = Vector3D.distance(P2, masterStationAtReception.getPosition());
addMeasurement(new TurnAroundRange(masterStation, slaveStation, masterReceptionDate, 0.5 * (masterUpLinkDistance + slaveDownLinkDistance + slaveUpLinkDistance + masterDownLinkDistance), 1.0, 10));
}
}
} catch (OrekitExceptionWrapper oew) {
throw new OrekitException(oew.getException());
} catch (OrekitException oe) {
throw new OrekitException(oe);
}
}
use of org.hipparchus.geometry.euclidean.threed.Vector3D in project Orekit by CS-SI.
the class OnBoardAntennaInterSatellitesRangeModifierTest method testPreliminary.
@Test
public void testPreliminary() throws OrekitException {
// this test does not check OnBoardAntennaInterSatellitesRangeModifier at all,
// it just checks InterSatellitesRangeMeasurementCreator behaves as necessary for the other test
// the *real* test is testEffect below
Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
final NumericalPropagatorBuilder propagatorBuilder = context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true, 1.0e-6, 60.0, 0.001);
propagatorBuilder.setAttitudeProvider(new LofOffset(propagatorBuilder.getFrame(), LOFType.LVLH));
// create perfect inter-satellites range measurements without antenna offset
final TimeStampedPVCoordinates original = context.initialOrbit.getPVCoordinates();
final Orbit closeOrbit = new CartesianOrbit(new TimeStampedPVCoordinates(context.initialOrbit.getDate(), original.getPosition().add(new Vector3D(1000, 2000, 3000)), original.getVelocity().add(new Vector3D(-0.03, 0.01, 0.02))), context.initialOrbit.getFrame(), context.initialOrbit.getMu());
final Propagator closePropagator = EstimationTestUtils.createPropagator(closeOrbit, propagatorBuilder);
closePropagator.setEphemerisMode();
closePropagator.propagate(context.initialOrbit.getDate().shiftedBy(3.5 * closeOrbit.getKeplerianPeriod()));
final BoundedPropagator ephemeris = closePropagator.getGeneratedEphemeris();
final Propagator p1 = EstimationTestUtils.createPropagator(context.initialOrbit, propagatorBuilder);
final List<ObservedMeasurement<?>> spacecraftCenteredMeasurements = EstimationTestUtils.createMeasurements(p1, new InterSatellitesRangeMeasurementCreator(ephemeris, Vector3D.ZERO, Vector3D.ZERO), 1.0, 3.0, 300.0);
// create perfect inter-satellites range measurements with antenna offset
final double xOffset1 = -2.5;
final double yOffset2 = 0.8;
final Propagator p2 = EstimationTestUtils.createPropagator(context.initialOrbit, propagatorBuilder);
final List<ObservedMeasurement<?>> antennaCenteredMeasurements = EstimationTestUtils.createMeasurements(p2, new InterSatellitesRangeMeasurementCreator(ephemeris, new Vector3D(xOffset1, 0, 0), new Vector3D(0, yOffset2, 0)), 1.0, 3.0, 300.0);
for (int i = 0; i < spacecraftCenteredMeasurements.size(); ++i) {
InterSatellitesRange sr = (InterSatellitesRange) spacecraftCenteredMeasurements.get(i);
InterSatellitesRange ar = (InterSatellitesRange) antennaCenteredMeasurements.get(i);
Assert.assertEquals(0.0, sr.getDate().durationFrom(ar.getDate()), 2.0e-8);
Assert.assertTrue(ar.getObservedValue()[0] - sr.getObservedValue()[0] >= -1.0);
Assert.assertTrue(ar.getObservedValue()[0] - sr.getObservedValue()[0] <= -0.36);
}
}
use of org.hipparchus.geometry.euclidean.threed.Vector3D in project Orekit by CS-SI.
the class OnBoardAntennaTurnAroundRangeModifierTest method testPreliminary.
@Test
public void testPreliminary() throws OrekitException {
// this test does not check OnBoardAntennaTurnAroundRangeModifier at all,
// it just checks TurnAroundRangeMeasurementCreator behaves as necessary for the other test
// the *real* test is testEffect below
Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
final NumericalPropagatorBuilder propagatorBuilder = context.createBuilder(OrbitType.KEPLERIAN, PositionAngle.TRUE, true, 1.0e-6, 60.0, 0.001);
propagatorBuilder.setAttitudeProvider(new LofOffset(propagatorBuilder.getFrame(), LOFType.LVLH));
// create perfect turn-around range measurements without antenna offset
final Propagator p1 = EstimationTestUtils.createPropagator(context.initialOrbit, propagatorBuilder);
final List<ObservedMeasurement<?>> spacecraftCenteredMeasurements = EstimationTestUtils.createMeasurements(p1, new TurnAroundRangeMeasurementCreator(context, Vector3D.ZERO), 1.0, 3.0, 300.0);
// create perfect turn-around range measurements with antenna offset
final double xOffset = -2.5;
final Propagator p2 = EstimationTestUtils.createPropagator(context.initialOrbit, propagatorBuilder);
final List<ObservedMeasurement<?>> antennaCenteredMeasurements = EstimationTestUtils.createMeasurements(p2, new TurnAroundRangeMeasurementCreator(context, new Vector3D(xOffset, 0, 0)), 1.0, 3.0, 300.0);
for (int i = 0; i < spacecraftCenteredMeasurements.size(); ++i) {
TurnAroundRange sr = (TurnAroundRange) spacecraftCenteredMeasurements.get(i);
TurnAroundRange ar = (TurnAroundRange) antennaCenteredMeasurements.get(i);
Assert.assertEquals(0.0, sr.getDate().durationFrom(ar.getDate()), 2.0e-8);
Assert.assertTrue(ar.getObservedValue()[0] - sr.getObservedValue()[0] >= 2.0 * xOffset);
Assert.assertTrue(ar.getObservedValue()[0] - sr.getObservedValue()[0] <= 1.8 * xOffset);
}
}
use of org.hipparchus.geometry.euclidean.threed.Vector3D in project Orekit by CS-SI.
the class NRLMSISE00Test method testDensity.
@Test
public void testDensity() throws OrekitException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
// Build the input params provider
final InputParams ip = new InputParams();
// Get Sun
final PVCoordinatesProvider sun = CelestialBodyFactory.getSun();
// Get Earth body shape
final Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
final OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, Constants.WGS84_EARTH_FLATTENING, itrf);
// Build the model
final NRLMSISE00 atm = new NRLMSISE00(ip, sun, earth).withSwitch(9, -1);
// Build the date
final AbsoluteDate date = new AbsoluteDate(new DateComponents(2003, 172), new TimeComponents(29000.), TimeScalesFactory.getUT1(IERSConventions.IERS_2010, true));
// Build the position
final double alt = 400.;
final double lat = 60.;
final double lon = -70.;
final GeodeticPoint point = new GeodeticPoint(FastMath.toRadians(lat), FastMath.toRadians(lon), alt * 1000.);
final Vector3D pos = earth.transform(point);
// Run
final double rho = atm.getDensity(date, pos, itrf);
final double lst = 29000. / 3600. - 70. / 15.;
final double[] ap = { 4., 100., 100., 100., 100., 100., 100. };
Class<?> outputClass = getOutputClass();
Constructor<?> cons = outputClass.getDeclaredConstructor(NRLMSISE00.class, Integer.TYPE, Double.TYPE, Double.TYPE, Double.TYPE, Double.TYPE, Double.TYPE, Double.TYPE, double[].class);
cons.setAccessible(true);
Method gtd7d = outputClass.getDeclaredMethod("gtd7d", Double.TYPE);
gtd7d.setAccessible(true);
Method getDensity = outputClass.getDeclaredMethod("getDensity", Integer.TYPE);
getDensity.setAccessible(true);
final Object out = createOutput(atm, 172, 29000., 60., -70, lst, 150., 150., ap);
gtd7d.invoke(out, 400.0);
Assert.assertEquals(rho, ((Double) getDensity.invoke(out, 5)).doubleValue(), rho * 1.e-3);
}
use of org.hipparchus.geometry.euclidean.threed.Vector3D in project Orekit by CS-SI.
the class HolmesFeatherstoneAttractionModelTest method testRelativeNumericPrecision.
@Test
public void testRelativeNumericPrecision() throws OrekitException {
// this test is similar in spirit to section 4.2 of Holmes and Featherstone paper,
// but reduced to lower degree since our reference implementation is MUCH slower
// than the one used in the paper (Clenshaw method)
int max = 50;
NormalizedSphericalHarmonicsProvider provider = new GleasonProvider(max, max);
HolmesFeatherstoneAttractionModel model = new HolmesFeatherstoneAttractionModel(itrf, provider);
Assert.assertTrue(model.dependsOnPositionOnly());
// Note that despite it uses adjustable high accuracy, the reference model
// uses unstable formulas and hence loses lots of digits near poles.
// This implies that if we still want about 16 digits near the poles, we
// need to ask for at least 30 digits in computation. Setting for example
// the following to 28 digits makes the test fail as the relative errors
// raise to about 10^-12 near North pole and near 10^-11 near South pole.
// The reason for this is that the reference becomes less accurate than
// the model we are testing!
int digits = 30;
ReferenceFieldModel refModel = new ReferenceFieldModel(provider, digits);
double r = 1.25;
for (double theta = 0.01; theta < 3.14; theta += 0.1) {
Vector3D position = new Vector3D(r * FastMath.sin(theta), 0.0, r * FastMath.cos(theta));
Dfp refValue = refModel.nonCentralPart(null, position);
double value = model.nonCentralPart(null, position, model.getMu());
double relativeError = error(refValue, value).divide(refValue).toDouble();
Assert.assertEquals(0, relativeError, 7.0e-15);
}
}
Aggregations