diff --git a/src/main/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossing.java b/src/main/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossing.java index 7715ca6d23b1e0a40164d3bd1c86e4a1a910afae..29ebaf320ec590128183b77a421bf5edae261217 100644 --- a/src/main/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossing.java +++ b/src/main/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossing.java @@ -526,7 +526,7 @@ public class SensorMeanPlaneCrossing { * @exception RuggedException if geometry cannot be computed for some line or * if the maximum number of evaluations is exceeded */ - public CrossingResult slowFind(final PVCoordinates targetPV, final double initialGuess) + private CrossingResult slowFind(final PVCoordinates targetPV, final double initialGuess) throws RuggedException { try { diff --git a/src/main/java/org/orekit/rugged/los/FixedRotation.java b/src/main/java/org/orekit/rugged/los/FixedRotation.java index 3638aee9e2042fb887c9c2ecd2909b5854d21f34..00983195cf1db6f5624225d36bf09b7c4b78c38a 100644 --- a/src/main/java/org/orekit/rugged/los/FixedRotation.java +++ b/src/main/java/org/orekit/rugged/los/FixedRotation.java @@ -74,7 +74,7 @@ public class FixedRotation implements TimeIndependentLOSTransform { angleDriver.addObserver(new ParameterObserver() { @Override public void valueChanged(final double previousValue, final ParameterDriver driver) { - // reset rotations to null, they will evaluated lazily if needed + // reset rotations to null, they will be evaluated lazily if needed rotation = null; rDS = null; } diff --git a/src/main/java/org/orekit/rugged/los/PolynomialRotation.java b/src/main/java/org/orekit/rugged/los/PolynomialRotation.java index 158c6dce5f2d876563bbc612a4209664828962c3..e3224400e285c8bc4d66681a311b3f8a636896ab 100644 --- a/src/main/java/org/orekit/rugged/los/PolynomialRotation.java +++ b/src/main/java/org/orekit/rugged/los/PolynomialRotation.java @@ -88,7 +88,7 @@ public class PolynomialRotation implements LOSTransform { final ParameterObserver resettingObserver = new ParameterObserver() { @Override public void valueChanged(final double previousValue, final ParameterDriver driver) { - // reset rotations to null, they will evaluated lazily if needed + // reset rotations to null, they will be evaluated lazily if needed angle = null; axisDS = null; angleDS = null; @@ -97,7 +97,7 @@ public class PolynomialRotation implements LOSTransform { try { for (int i = 0; i < angleCoeffs.length; ++i) { coefficientsDrivers[i] = new ParameterDriver(name + "[" + i + "]", angleCoeffs[i], SCALE, - Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); + Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); coefficientsDrivers[i].addObserver(resettingObserver); } } catch (OrekitException oe) { diff --git a/src/test/java/org/orekit/rugged/linesensor/FixedRotationtest.java b/src/test/java/org/orekit/rugged/linesensor/FixedRotationtest.java new file mode 100644 index 0000000000000000000000000000000000000000..cf2ee7bb91b9f5551d194d3d889aa93d158b6706 --- /dev/null +++ b/src/test/java/org/orekit/rugged/linesensor/FixedRotationtest.java @@ -0,0 +1,247 @@ +/* Copyright 2013-2016 CS Systèmes d'Information + * Licensed to CS Systèmes d'Information (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.rugged.linesensor; + +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.hipparchus.analysis.UnivariateMatrixFunction; +import org.hipparchus.analysis.differentiation.DerivativeStructure; +import org.hipparchus.analysis.differentiation.FiniteDifferencesDifferentiator; +import org.hipparchus.analysis.differentiation.UnivariateDifferentiableMatrixFunction; +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.hipparchus.random.UncorrelatedRandomVectorGenerator; +import org.hipparchus.random.UniformRandomGenerator; +import org.hipparchus.random.Well19937a; +import org.hipparchus.util.FastMath; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitExceptionWrapper; +import org.orekit.rugged.errors.RuggedException; +import org.orekit.rugged.los.FixedRotation; +import org.orekit.rugged.los.LOSBuilder; +import org.orekit.rugged.los.TimeDependentLOS; +import org.orekit.rugged.utils.DSGenerator; +import org.orekit.time.AbsoluteDate; +import org.orekit.utils.ParameterDriver; + +public class FixedRotationtest { + + private List<Vector3D> raw; + + @Test + public void testIdentity() throws RuggedException, OrekitException { + UniformRandomGenerator rng = new UniformRandomGenerator(new Well19937a(0xaba71348a77d77cbl)); + UncorrelatedRandomVectorGenerator rvg = new UncorrelatedRandomVectorGenerator(3, rng); + for (int k = 0; k < 20; ++k) { + LOSBuilder builder = new LOSBuilder(raw); + builder.addTransform(new FixedRotation("identity", + new Vector3D(rvg.nextVector()), + 0.0)); + TimeDependentLOS tdl = builder.build(); + for (int i = 0; i < raw.size(); ++i) { + Assert.assertEquals(0.0, + Vector3D.distance(raw.get(i), tdl.getLOS(i, AbsoluteDate.J2000_EPOCH)), + 2.0e-15); + } + + Assert.assertEquals(1, tdl.getParametersDrivers().count()); + Assert.assertEquals("identity", tdl.getParametersDrivers().findFirst().get().getName()); + + } + } + + @Test + public void testCombination() throws RuggedException, OrekitException { + UniformRandomGenerator rng = new UniformRandomGenerator(new Well19937a(0xefac03d9be4d24b9l)); + UncorrelatedRandomVectorGenerator rvg = new UncorrelatedRandomVectorGenerator(3, rng); + for (int k = 0; k < 20; ++k) { + + LOSBuilder builder = new LOSBuilder(raw); + + Vector3D axis1 = new Vector3D(rvg.nextVector()); + double angle1 = 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3); + builder.addTransform(new FixedRotation("r1", axis1, angle1)); + Rotation r1 = new Rotation(axis1, angle1, RotationConvention.VECTOR_OPERATOR); + + Vector3D axis2 = new Vector3D(rvg.nextVector()); + double angle2 = 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3); + builder.addTransform(new FixedRotation("r2", axis2, angle2)); + Rotation r2 = new Rotation(axis2, angle2, RotationConvention.VECTOR_OPERATOR); + + Vector3D axis3 = new Vector3D(rvg.nextVector()); + double angle3 = 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3); + builder.addTransform(new FixedRotation("r3", axis3, angle3)); + Rotation r3 = new Rotation(axis3, angle3, RotationConvention.VECTOR_OPERATOR); + + TimeDependentLOS tdl = builder.build(); + Rotation combined = r3.applyTo(r2.applyTo(r1)); + + for (int i = 0; i < raw.size(); ++i) { + Assert.assertEquals(0.0, + Vector3D.distance(combined.applyTo(raw.get(i)), + tdl.getLOS(i, AbsoluteDate.J2000_EPOCH)), + 2.0e-15); + } + + List<ParameterDriver> drivers = tdl.getParametersDrivers().collect(Collectors.toList()); + Assert.assertEquals(3, drivers.size()); + ParameterDriver driver1 = drivers.get(0); + ParameterDriver driver2 = drivers.get(1); + ParameterDriver driver3 = drivers.get(2); + Assert.assertEquals("r1", driver1.getName()); + Assert.assertEquals(-2 * FastMath.PI, driver1.getMinValue(), 2.0e-15); + Assert.assertEquals(+2 * FastMath.PI, driver1.getMaxValue(), 2.0e-15); + Assert.assertEquals(angle1, driver1.getValue(), 2.0e-15); + Assert.assertEquals("r2", driver2.getName()); + Assert.assertEquals(-2 * FastMath.PI, driver2.getMinValue(), 2.0e-15); + Assert.assertEquals(+2 * FastMath.PI, driver2.getMaxValue(), 2.0e-15); + Assert.assertEquals(angle2, driver2.getValue(), 2.0e-15); + Assert.assertEquals("r3", driver3.getName()); + Assert.assertEquals(-2 * FastMath.PI, driver3.getMinValue(), 2.0e-15); + Assert.assertEquals(+2 * FastMath.PI, driver3.getMaxValue(), 2.0e-15); + Assert.assertEquals(angle3, driver3.getValue(), 2.0e-15); + + driver1.setValue(0.0); + driver2.setValue(0.0); + driver3.setValue(0.0); + + for (int i = 0; i < raw.size(); ++i) { + Assert.assertEquals(0.0, + Vector3D.distance(raw.get(i), + tdl.getLOS(i, AbsoluteDate.J2000_EPOCH)), + 2.0e-15); + } + + } + } + + @Test + public void testDerivatives() throws RuggedException, OrekitException { + UniformRandomGenerator rng = new UniformRandomGenerator(new Well19937a(0xddae2b46b2207e08l)); + UncorrelatedRandomVectorGenerator rvg = new UncorrelatedRandomVectorGenerator(3, rng); + for (int k = 0; k < 20; ++k) { + + LOSBuilder builder = new LOSBuilder(raw); + + builder.addTransform(new FixedRotation("r1", + new Vector3D(rvg.nextVector()), + 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3))); + builder.addTransform(new FixedRotation("r2", + new Vector3D(rvg.nextVector()), + 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3))); + builder.addTransform(new FixedRotation("r3", + new Vector3D(rvg.nextVector()), + 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3))); + TimeDependentLOS tdl = builder.build(); + final List<ParameterDriver> selected = tdl.getParametersDrivers().collect(Collectors.toList()); + for (final ParameterDriver driver : selected) { + driver.setSelected(true); + } + DSGenerator generator = new DSGenerator() { + + /** {@inheritDoc} */ + @Override + public List<ParameterDriver> getSelected() { + return selected; + } + + /** {@inheritDoc} */ + @Override + public DerivativeStructure constant(final double value) { + return new DerivativeStructure(selected.size(), 1, value); + } + + /** {@inheritDoc} */ + @Override + public DerivativeStructure variable(final ParameterDriver driver) { + int index = 0; + for (ParameterDriver d : getSelected()) { + if (d == driver) { + return new DerivativeStructure(getSelected().size(), 1, index, driver.getValue()); + } + ++index; + } + return constant(driver.getValue()); + } + + }; + Assert.assertEquals(3, generator.getSelected().size()); + + FiniteDifferencesDifferentiator differentiator = + new FiniteDifferencesDifferentiator(4, 0.001); + int index = 0; + for (final ParameterDriver driver : selected) { + int[] orders = new int[selected.size()]; + orders[index] = 1; + UnivariateDifferentiableMatrixFunction f = + differentiator.differentiate((UnivariateMatrixFunction) x -> { + try { + double oldX = driver.getValue(); + double[][] matrix = new double[raw.size()][]; + driver.setValue(x); + for (int i = 0 ; i < raw.size(); ++i) { + matrix[i] = tdl.getLOS(i, AbsoluteDate.J2000_EPOCH).toArray(); + } + driver.setValue(oldX); + return matrix; + } catch (OrekitException oe) { + throw new OrekitExceptionWrapper(oe); + } + }); + DerivativeStructure[][] mDS = f.value(new DerivativeStructure(1, 1, 0, driver.getValue())); + for (int i = 0; i < raw.size(); ++i) { + Vector3D los = tdl.getLOS(i, AbsoluteDate.J2000_EPOCH); + FieldVector3D<DerivativeStructure> losDS = + tdl.getLOSDerivatives(i, AbsoluteDate.J2000_EPOCH, generator); + Assert.assertEquals(los.getX(), losDS.getX().getValue(), 2.0e-15); + Assert.assertEquals(los.getY(), losDS.getY().getValue(), 2.0e-15); + Assert.assertEquals(los.getZ(), losDS.getZ().getValue(), 2.0e-15); + Assert.assertEquals(mDS[i][0].getPartialDerivative(1), losDS.getX().getPartialDerivative(orders), 2.0e-12); + Assert.assertEquals(mDS[i][1].getPartialDerivative(1), losDS.getY().getPartialDerivative(orders), 2.0e-12); + Assert.assertEquals(mDS[i][2].getPartialDerivative(1), losDS.getZ().getPartialDerivative(orders), 2.0e-12); + } + ++index; + } + } + + } + + @Before + public void setUp() throws OrekitException, URISyntaxException { + + final Vector3D normal = Vector3D.PLUS_I; + final Vector3D fovCenter = Vector3D.PLUS_K; + final Vector3D cross = Vector3D.crossProduct(normal, fovCenter); + + // build lists of pixels regularly spread on a perfect plane + raw = new ArrayList<Vector3D>(); + for (int i = -100; i <= 100; ++i) { + final double alpha = i * 0.17 / 1000; + raw.add(new Vector3D(FastMath.cos(alpha), fovCenter, FastMath.sin(alpha), cross)); + } + + } + +} diff --git a/src/test/java/org/orekit/rugged/linesensor/PolynomialRotationtest.java b/src/test/java/org/orekit/rugged/linesensor/PolynomialRotationtest.java new file mode 100644 index 0000000000000000000000000000000000000000..e878bacef1699fc2955d0cb6c926238141b763c5 --- /dev/null +++ b/src/test/java/org/orekit/rugged/linesensor/PolynomialRotationtest.java @@ -0,0 +1,263 @@ +/* Copyright 2013-2016 CS Systèmes d'Information + * Licensed to CS Systèmes d'Information (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.rugged.linesensor; + +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.hipparchus.analysis.UnivariateMatrixFunction; +import org.hipparchus.analysis.differentiation.DerivativeStructure; +import org.hipparchus.analysis.differentiation.FiniteDifferencesDifferentiator; +import org.hipparchus.analysis.differentiation.UnivariateDifferentiableMatrixFunction; +import org.hipparchus.analysis.polynomials.PolynomialFunction; +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.hipparchus.random.UncorrelatedRandomVectorGenerator; +import org.hipparchus.random.UniformRandomGenerator; +import org.hipparchus.random.Well19937a; +import org.hipparchus.util.FastMath; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitExceptionWrapper; +import org.orekit.rugged.errors.RuggedException; +import org.orekit.rugged.los.PolynomialRotation; +import org.orekit.rugged.los.LOSBuilder; +import org.orekit.rugged.los.TimeDependentLOS; +import org.orekit.rugged.utils.DSGenerator; +import org.orekit.time.AbsoluteDate; +import org.orekit.utils.ParameterDriver; + +public class PolynomialRotationtest { + + private List<Vector3D> raw; + + @Test + public void testIdentity() throws RuggedException, OrekitException { + UniformRandomGenerator rng = new UniformRandomGenerator(new Well19937a(0xbe0d9b530fe7f53cl)); + UncorrelatedRandomVectorGenerator rvg = new UncorrelatedRandomVectorGenerator(3, rng); + for (int k = 0; k < 20; ++k) { + LOSBuilder builder = new LOSBuilder(raw); + builder.addTransform(new PolynomialRotation("identity", + new Vector3D(rvg.nextVector()), + AbsoluteDate.J2000_EPOCH, 0.0)); + TimeDependentLOS tdl = builder.build(); + for (int i = 0; i < raw.size(); ++i) { + Assert.assertEquals(0.0, + Vector3D.distance(raw.get(i), tdl.getLOS(i, AbsoluteDate.J2000_EPOCH)), + 2.0e-15); + } + + Assert.assertEquals(1, tdl.getParametersDrivers().count()); + Assert.assertEquals("identity[0]", tdl.getParametersDrivers().findFirst().get().getName()); + + } + } + + @Test + public void testFixedCombination() throws RuggedException, OrekitException { + UniformRandomGenerator rng = new UniformRandomGenerator(new Well19937a(0xdc4cfdea38edd2bbl)); + UncorrelatedRandomVectorGenerator rvg = new UncorrelatedRandomVectorGenerator(3, rng); + for (int k = 0; k < 20; ++k) { + + LOSBuilder builder = new LOSBuilder(raw); + + Vector3D axis1 = new Vector3D(rvg.nextVector()); + double angle1 = 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3); + builder.addTransform(new PolynomialRotation("r1", axis1, AbsoluteDate.J2000_EPOCH, angle1)); + Rotation r1 = new Rotation(axis1, angle1, RotationConvention.VECTOR_OPERATOR); + + Vector3D axis2 = new Vector3D(rvg.nextVector()); + double angle2 = 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3); + builder.addTransform(new PolynomialRotation("r2", axis2, AbsoluteDate.J2000_EPOCH, angle2)); + Rotation r2 = new Rotation(axis2, angle2, RotationConvention.VECTOR_OPERATOR); + + Vector3D axis3 = new Vector3D(rvg.nextVector()); + double angle3 = 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3); + builder.addTransform(new PolynomialRotation("r3", axis3, AbsoluteDate.J2000_EPOCH, angle3)); + Rotation r3 = new Rotation(axis3, angle3, RotationConvention.VECTOR_OPERATOR); + + TimeDependentLOS tdl = builder.build(); + Rotation combined = r3.applyTo(r2.applyTo(r1)); + + for (int i = 0; i < raw.size(); ++i) { + Assert.assertEquals(0.0, + Vector3D.distance(combined.applyTo(raw.get(i)), + tdl.getLOS(i, AbsoluteDate.J2000_EPOCH)), + 2.0e-15); + } + + List<ParameterDriver> drivers = tdl.getParametersDrivers().collect(Collectors.toList()); + Assert.assertEquals(3, drivers.size()); + ParameterDriver driver1 = drivers.get(0); + ParameterDriver driver2 = drivers.get(1); + ParameterDriver driver3 = drivers.get(2); + Assert.assertEquals("r1[0]", driver1.getName()); + Assert.assertTrue(Double.isInfinite(driver1.getMinValue())); + Assert.assertTrue(driver1.getMinValue() < 0); + Assert.assertTrue(Double.isInfinite(driver1.getMaxValue())); + Assert.assertTrue(driver1.getMaxValue() > 0); + Assert.assertEquals(angle1, driver1.getValue(), 2.0e-15); + Assert.assertEquals("r2[0]", driver2.getName()); + Assert.assertTrue(Double.isInfinite(driver2.getMinValue())); + Assert.assertTrue(driver2.getMinValue() < 0); + Assert.assertTrue(Double.isInfinite(driver2.getMaxValue())); + Assert.assertTrue(driver2.getMaxValue() > 0); + Assert.assertEquals(angle2, driver2.getValue(), 2.0e-15); + Assert.assertEquals("r3[0]", driver3.getName()); + Assert.assertTrue(Double.isInfinite(driver3.getMinValue())); + Assert.assertTrue(driver3.getMinValue() < 0); + Assert.assertTrue(Double.isInfinite(driver3.getMaxValue())); + Assert.assertTrue(driver3.getMaxValue() > 0); + Assert.assertEquals(angle3, driver3.getValue(), 2.0e-15); + + driver1.setValue(0.0); + driver2.setValue(0.0); + driver3.setValue(0.0); + + for (int i = 0; i < raw.size(); ++i) { + Assert.assertEquals(0.0, + Vector3D.distance(raw.get(i), + tdl.getLOS(i, AbsoluteDate.J2000_EPOCH)), + 2.0e-15); + } + + } + } + + @Test + public void testDerivatives() throws RuggedException, OrekitException { + UniformRandomGenerator rng = new UniformRandomGenerator(new Well19937a(0xc60acfc04eb27935l)); + UncorrelatedRandomVectorGenerator rvg = new UncorrelatedRandomVectorGenerator(3, rng); + for (int k = 0; k < 20; ++k) { + + LOSBuilder builder = new LOSBuilder(raw); + + builder.addTransform(new PolynomialRotation("r1", + new Vector3D(rvg.nextVector()), + AbsoluteDate.J2000_EPOCH, + 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3), + 1.0e-4 * 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3))); + builder.addTransform(new PolynomialRotation("r2", + new Vector3D(rvg.nextVector()), + AbsoluteDate.J2000_EPOCH, + new PolynomialFunction(new double[] { + 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3), + 1.0e-4 * 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3), + 1.0e-8 * 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3) + }))); + builder.addTransform(new PolynomialRotation("r3", + new Vector3D(rvg.nextVector()), + AbsoluteDate.J2000_EPOCH, + 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3), + 1.0e-4 * 2 * FastMath.PI * rng.nextNormalizedDouble() / FastMath.sqrt(3))); + TimeDependentLOS tdl = builder.build(); + final List<ParameterDriver> selected = tdl.getParametersDrivers().collect(Collectors.toList()); + for (final ParameterDriver driver : selected) { + driver.setSelected(true); + } + DSGenerator generator = new DSGenerator() { + + /** {@inheritDoc} */ + @Override + public List<ParameterDriver> getSelected() { + return selected; + } + + /** {@inheritDoc} */ + @Override + public DerivativeStructure constant(final double value) { + return new DerivativeStructure(selected.size(), 1, value); + } + + /** {@inheritDoc} */ + @Override + public DerivativeStructure variable(final ParameterDriver driver) { + int index = 0; + for (ParameterDriver d : getSelected()) { + if (d == driver) { + return new DerivativeStructure(getSelected().size(), 1, index, driver.getValue()); + } + ++index; + } + return constant(driver.getValue()); + } + + }; + Assert.assertEquals(7, generator.getSelected().size()); + + FiniteDifferencesDifferentiator differentiator = + new FiniteDifferencesDifferentiator(4, 0.0001); + int index = 0; + final AbsoluteDate date = AbsoluteDate.J2000_EPOCH.shiftedBy(7.0); + for (final ParameterDriver driver : selected) { + int[] orders = new int[selected.size()]; + orders[index] = 1; + UnivariateDifferentiableMatrixFunction f = + differentiator.differentiate((UnivariateMatrixFunction) x -> { + try { + double oldX = driver.getValue(); + double[][] matrix = new double[raw.size()][]; + driver.setValue(x); + for (int i = 0 ; i < raw.size(); ++i) { + matrix[i] = tdl.getLOS(i, date).toArray(); + } + driver.setValue(oldX); + return matrix; + } catch (OrekitException oe) { + throw new OrekitExceptionWrapper(oe); + } + }); + DerivativeStructure[][] mDS = f.value(new DerivativeStructure(1, 1, 0, driver.getValue())); + for (int i = 0; i < raw.size(); ++i) { + Vector3D los = tdl.getLOS(i, date); + FieldVector3D<DerivativeStructure> losDS = tdl.getLOSDerivatives(i, date, generator); + Assert.assertEquals(los.getX(), losDS.getX().getValue(), 2.0e-15); + Assert.assertEquals(los.getY(), losDS.getY().getValue(), 2.0e-15); + Assert.assertEquals(los.getZ(), losDS.getZ().getValue(), 2.0e-15); + Assert.assertEquals(mDS[i][0].getPartialDerivative(1), losDS.getX().getPartialDerivative(orders), 2.0e-10); + Assert.assertEquals(mDS[i][1].getPartialDerivative(1), losDS.getY().getPartialDerivative(orders), 2.0e-10); + Assert.assertEquals(mDS[i][2].getPartialDerivative(1), losDS.getZ().getPartialDerivative(orders), 2.0e-10); + } + ++index; + } + } + + } + + @Before + public void setUp() throws OrekitException, URISyntaxException { + + final Vector3D normal = Vector3D.PLUS_I; + final Vector3D fovCenter = Vector3D.PLUS_K; + final Vector3D cross = Vector3D.crossProduct(normal, fovCenter); + + // build lists of pixels regularly spread on a perfect plane + raw = new ArrayList<Vector3D>(); + for (int i = -100; i <= 100; ++i) { + final double alpha = i * 0.17 / 1000; + raw.add(new Vector3D(FastMath.cos(alpha), fovCenter, FastMath.sin(alpha), cross)); + } + + } + +} diff --git a/src/test/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossingTest.java b/src/test/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossingTest.java index 3f5125b088e8dcd22149a4a8f0d947d110b26ced..18043694437be6c7b7b5a023a1d369b18c141d5c 100644 --- a/src/test/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossingTest.java +++ b/src/test/java/org/orekit/rugged/linesensor/SensorMeanPlaneCrossingTest.java @@ -22,6 +22,8 @@ import org.hipparchus.random.RandomGenerator; import org.hipparchus.random.Well19937a; import org.hipparchus.util.FastMath; import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; @@ -47,6 +49,7 @@ import org.orekit.propagation.SpacecraftState; import org.orekit.propagation.analytical.KeplerianPropagator; import org.orekit.propagation.sampling.OrekitFixedStepHandler; import org.orekit.rugged.errors.RuggedException; +import org.orekit.rugged.linesensor.SensorMeanPlaneCrossing.CrossingResult; import org.orekit.rugged.los.LOSBuilder; import org.orekit.rugged.utils.SpacecraftToObservedBody; import org.orekit.time.AbsoluteDate; @@ -54,6 +57,7 @@ import org.orekit.utils.AngularDerivativesFilter; import org.orekit.utils.CartesianDerivativesFilter; import org.orekit.utils.Constants; import org.orekit.utils.IERSConventions; +import org.orekit.utils.PVCoordinates; import org.orekit.utils.TimeStampedAngularCoordinates; import org.orekit.utils.TimeStampedPVCoordinates; @@ -216,6 +220,72 @@ public class SensorMeanPlaneCrossingTest { } + @Test + public void testSlowFind() + throws RuggedException, OrekitException, NoSuchMethodException, + SecurityException, IllegalAccessException, IllegalArgumentException, + InvocationTargetException { + + final Vector3D position = new Vector3D(1.5, Vector3D.PLUS_I); + final Vector3D normal = Vector3D.PLUS_I; + final Vector3D fovCenter = Vector3D.PLUS_K; + final Vector3D cross = Vector3D.crossProduct(normal, fovCenter); + + // build lists of pixels regularly spread on a perfect plane + final List<Vector3D> los = new ArrayList<Vector3D>(); + for (int i = -1000; i <= 1000; ++i) { + final double alpha = i * 0.17 / 1000; + los.add(new Vector3D(FastMath.cos(alpha), fovCenter, FastMath.sin(alpha), cross)); + } + + final LineSensor sensor = new LineSensor("perfect line", + new LinearLineDatation(AbsoluteDate.J2000_EPOCH, 0.0, 1.0 / 1.5e-3), + position, new LOSBuilder(los).build()); + + Assert.assertEquals("perfect line", sensor.getName()); + Assert.assertEquals(AbsoluteDate.J2000_EPOCH, sensor.getDate(0.0)); + Assert.assertEquals(0.0, Vector3D.distance(position, sensor.getPosition()), 1.0e-15); + + SensorMeanPlaneCrossing mean = new SensorMeanPlaneCrossing(sensor, createInterpolator(sensor), + 0, 2000, true, true, 50, 1.0e-6); + + double refLine = 1200.0; + AbsoluteDate refDate = sensor.getDate(refLine); + int refPixel= 1800; + Transform b2i = mean.getScToBody().getBodyToInertial(refDate); + Transform sc2i = mean.getScToBody().getScToInertial(refDate); + Transform sc2b = new Transform(refDate, sc2i, b2i.getInverse()); + Vector3D p1 = sc2b.transformPosition(position); + Vector3D p2 = sc2b.transformPosition(new Vector3D(1, position, + 1.0e6, los.get(refPixel))); + Line line = new Line(p1, p2, 0.001); + BodyShape earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, + Constants.WGS84_EARTH_FLATTENING, + mean.getScToBody().getBodyFrame()); + GeodeticPoint groundPoint = earth.getIntersectionPoint(line, p1, mean.getScToBody().getBodyFrame(), refDate); + Vector3D gpCartesian = earth.transform(groundPoint); + SensorMeanPlaneCrossing.CrossingResult result = mean.find(gpCartesian); + + Method slowFind = SensorMeanPlaneCrossing.class.getDeclaredMethod("slowFind", + PVCoordinates.class, + Double.TYPE); + slowFind.setAccessible(true); + SensorMeanPlaneCrossing.CrossingResult slowResult = + (CrossingResult) slowFind.invoke(mean, + new PVCoordinates(gpCartesian, Vector3D.ZERO), + 400.0); + + Assert.assertEquals(result.getLine(), slowResult.getLine(), 2.0e-8); + Assert.assertEquals(0.0, + Vector3D.distance(result.getTargetDirection(), + slowResult.getTargetDirection()), + 2.0e-13); + Assert.assertEquals(0.0, + Vector3D.distance(result.getTargetDirectionDerivative(), + slowResult.getTargetDirectionDerivative()), + 1.0e-15); + } + private SpacecraftToObservedBody createInterpolator(LineSensor sensor) throws RuggedException, OrekitException { Orbit orbit = new CircularOrbit(7173352.811913891,