diff --git a/src/tutorials/java/AffinagePleiades/AffinageRugged.java b/src/tutorials/java/AffinagePleiades/AffinageRugged.java new file mode 100644 index 0000000000000000000000000000000000000000..c1ba241675dee2f023c4e8af3ca8c8afdd485e43 --- /dev/null +++ b/src/tutorials/java/AffinagePleiades/AffinageRugged.java @@ -0,0 +1,223 @@ +/* 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 AffinagePleiades; + +import org.hipparchus.geometry.euclidean.threed.Vector3D; +import org.hipparchus.util.FastMath; +import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresOptimizer.Optimum; + +import java.io.File; +import java.util.Locale; +import java.util.Collections; + + + +import org.orekit.bodies.BodyShape; +import org.orekit.bodies.GeodeticPoint; +import org.orekit.data.DataProvidersManager; +import org.orekit.data.DirectoryCrawler; +import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitExceptionWrapper; +import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider; + +import org.orekit.orbits.Orbit; +import org.orekit.rugged.api.AlgorithmId; +import org.orekit.rugged.api.BodyRotatingFrameId; +import org.orekit.rugged.api.EllipsoidId; +import org.orekit.rugged.api.InertialFrameId; +import org.orekit.rugged.api.Rugged; +import org.orekit.rugged.api.RuggedBuilder; +import org.orekit.rugged.errors.RuggedException; +import org.orekit.rugged.linesensor.LineSensor; + +import org.orekit.time.AbsoluteDate; +import org.orekit.utils.AngularDerivativesFilter; +import org.orekit.utils.CartesianDerivativesFilter; +import org.orekit.utils.PVCoordinates; + +/** + * Parameter estimation context + * @author Jonathan Guinet + * + */ +public class AffinageRugged { + + public static void main(String[] args) { + + try { + + // Initialize Orekit, assuming an orekit-data folder is in user home directory + File home = new File(System.getProperty("user.home")); + File orekitData = new File(home, "workspace/data/orekit-data"); + DataProvidersManager.getInstance().addProvider(new DirectoryCrawler(orekitData)); + + + //CreateOrbit + OrbitModel orbitmodel = new OrbitModel(); + BodyShape earth = orbitmodel.createEarth(); + NormalizedSphericalHarmonicsProvider gravityField = orbitmodel.createGravityField(); + + //create Pleiades Viewing Model + PleiadesViewingModel pleiadesViewingModel = new PleiadesViewingModel(); + AbsoluteDate minDate = pleiadesViewingModel.getMinDate(); + AbsoluteDate maxDate = pleiadesViewingModel.getMaxDate(); + AbsoluteDate refDate = pleiadesViewingModel.getDatationReference(); + + Orbit orbit = orbitmodel.createOrbit(gravityField.getMu(), refDate); + + PVCoordinates PV = orbit.getPVCoordinates(earth.getBodyFrame()); + GeodeticPoint gp = earth.transform(PV.getPosition(), earth.getBodyFrame(), orbit.getDate()); + + + + System.out.format(" **** Orbit Definition **** %n"); + + System.out.format(Locale.US, "Geodetic Point at date %s : φ = %8.10f °, λ = %8.10f %n",orbit.getDate().toString(), + FastMath.toDegrees(gp.getLatitude()), + FastMath.toDegrees(gp.getLongitude())); + + + System.out.format(" **** Build Viewing Model **** %n"); + + + // Build Rugged ... + RuggedBuilder ruggedBuilder = new RuggedBuilder(); + + LineSensor lineSensor = pleiadesViewingModel.getLineSensor(); + ruggedBuilder.addLineSensor(lineSensor); + + + ruggedBuilder.setAlgorithm(AlgorithmId.IGNORE_DEM_USE_ELLIPSOID); + ruggedBuilder.setEllipsoid(EllipsoidId.WGS84, BodyRotatingFrameId.ITRF); + ruggedBuilder.setTimeSpan(minDate,maxDate, 0.001, 5.0). + setTrajectory(InertialFrameId.EME2000, + orbitmodel.orbitToPV(orbit, earth, minDate.shiftedBy(-0.0), maxDate.shiftedBy(+0.0), 0.25), + 8, CartesianDerivativesFilter.USE_PV, + orbitmodel.orbitToQ(orbit, earth, minDate.shiftedBy(-0.0), maxDate.shiftedBy(+0.0), 0.25), + 2, AngularDerivativesFilter.USE_R); + Rugged rugged = ruggedBuilder.build(); + + + + + Vector3D position = lineSensor.getPosition(); // This returns a zero vector since we set the relative position of the sensor w.r.T the satellite to 0. + AbsoluteDate firstLineDate = lineSensor.getDate(pleiadesViewingModel.dimension/2); + System.out.format("date %s %n",firstLineDate.toString()); + Vector3D los = lineSensor.getLOS(firstLineDate,0); + GeodeticPoint upLeftPoint = rugged.directLocation(firstLineDate, position, los); + System.out.format(Locale.US, "upper left point: φ = %8.10f °, λ = %8.10f °, h = %8.3f m%n", + FastMath.toDegrees(upLeftPoint.getLatitude()), + FastMath.toDegrees(upLeftPoint.getLongitude()), + upLeftPoint.getAltitude()); + los = lineSensor.getLOS(firstLineDate,pleiadesViewingModel.dimension-1); + GeodeticPoint upRightPoint = rugged.directLocation(firstLineDate, position, los); + System.out.format(Locale.US, "upper right point: φ = %8.10f °, λ = %8.10f °, h = %8.3f m%n", + FastMath.toDegrees(upRightPoint.getLatitude()), + FastMath.toDegrees(upRightPoint.getLongitude()),upRightPoint.getAltitude()); + los = lineSensor.getLOS(firstLineDate,pleiadesViewingModel.dimension/2); + GeodeticPoint centerPoint = rugged.directLocation(firstLineDate, position, los); + System.out.format(Locale.US, "center point: φ = %8.10f °, λ = %8.10f °, h = %8.3f m%n", + FastMath.toDegrees(centerPoint.getLatitude()), + FastMath.toDegrees(centerPoint.getLongitude()),centerPoint.getAltitude()); + + + System.out.format(" **** Add roll and pitch values **** %n"); + + + double rollValue = FastMath.toRadians( 0.1); + double pitchValue = FastMath.toRadians(-0.3); + + System.out.format("roll : %3.5f pitch : %3.5f \n",rollValue,pitchValue); + + + rugged. + getLineSensor("line"). + getParametersDrivers(). + filter(driver -> driver.getName().equals("roll")). + findFirst().get().setValue(rollValue); + + rugged. + getLineSensor("line"). + getParametersDrivers(). + filter(driver -> driver.getName().equals("pitch")). + findFirst().get().setValue(pitchValue); + + + System.out.format(" **** Generate Measures **** %n"); + + MeasureGenerator measure = new MeasureGenerator(pleiadesViewingModel,rugged); + measure.CreateMeasure(1000, 1000); + + System.out.format(" **** Reset Roll/Pitch **** %n"); + rugged. + getLineSensor(pleiadesViewingModel.getSensorName()). + getParametersDrivers(). + filter(driver -> driver.getName().equals("roll") || driver.getName().equals("pitch")). + forEach(driver -> { + try { + driver.setSelected(true); + driver.setValue(0.0); + } catch (OrekitException e) { + throw new OrekitExceptionWrapper(e); + } + }); + + + + System.out.format(" **** Start optimization **** %n"); + // perform parameters estimation + int maxIterations = 15; + double convergenceThreshold = 1.0e-9; + + System.out.format("iterations max %d convergence threshold %3.6e \n",maxIterations, convergenceThreshold); + + + Optimum optimum = rugged.estimateFreeParameters(Collections.singletonList(measure.getMapping()), maxIterations,convergenceThreshold); + + + System.out.format(" Optimization performed in %d interation \n",optimum.getEvaluations()); + + // check estimated values + double estimatedRoll = rugged.getLineSensor(pleiadesViewingModel.getSensorName()). + getParametersDrivers(). + filter(driver -> driver.getName().equals("roll")). + findFirst().get().getValue(); + double rollError = (estimatedRoll - rollValue); + System.out.format("Estimated roll %3.5f roll error %3.6e %n", estimatedRoll, rollError); + + double estimatedPitch = rugged.getLineSensor(pleiadesViewingModel.getSensorName()). + getParametersDrivers(). + filter(driver -> driver.getName().equals("pitch")). + findFirst().get().getValue(); + double pitchError = (estimatedPitch - pitchValue); + System.out.format("Estimated pitch %3.5f pitch error %3.6e %n ", estimatedPitch, pitchError); + + + + } catch (OrekitException oe) { + System.err.println(oe.getLocalizedMessage()); + System.exit(1); + } catch (RuggedException re) { + System.err.println(re.getLocalizedMessage()); + System.exit(1); + } + + } + + + +} diff --git a/src/tutorials/java/AffinagePleiades/MeasureGenerator.java b/src/tutorials/java/AffinagePleiades/MeasureGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..30ced6c94e7cd2b856a24b39cdb0742b94459b9e --- /dev/null +++ b/src/tutorials/java/AffinagePleiades/MeasureGenerator.java @@ -0,0 +1,84 @@ +/* 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 AffinagePleiades; + + +import org.orekit.rugged.api.SensorToGroundMapping; +import org.orekit.rugged.api.Rugged; +import org.orekit.rugged.linesensor.LineSensor; +import org.orekit.rugged.linesensor.SensorPixel; +import org.orekit.rugged.errors.RuggedException; +import org.orekit.time.AbsoluteDate; +import org.orekit.bodies.GeodeticPoint; + +/** class for measure generation + * @author Jonathan Guinet + */ +public class MeasureGenerator { + + + /** mapping */ + private SensorToGroundMapping mapping; + + private Rugged rugged; + + private LineSensor sensor; + + private PleiadesViewingModel viewingModel; + + + + /** Simple constructor. + * <p> + * + * </p> + */ + public MeasureGenerator(PleiadesViewingModel viewingModel, Rugged rugged) throws RuggedException + { + + // generate reference mapping + String sensorName = viewingModel.getSensorName(); + mapping = new SensorToGroundMapping(sensorName); + this.rugged = rugged; + this.viewingModel = viewingModel; + sensor = rugged.getLineSensor(mapping.getSensorName()); + + } + + public SensorToGroundMapping getMapping() { + return mapping; + } + + + public void CreateMeasure(final int lineSampling,final int pixelSampling) throws RuggedException + { + + for (double line = 0; line < viewingModel.dimension; line += lineSampling) { + + AbsoluteDate date = sensor.getDate(line); + for (int pixel = 0; pixel < sensor.getNbPixels(); pixel += pixelSampling) { + GeodeticPoint gp2 = rugged.directLocation(date, sensor.getPosition(), + sensor.getLOS(date, pixel)); + mapping.addMapping(new SensorPixel(line, pixel), gp2); + } + } + } + + + +} + diff --git a/src/tutorials/java/AffinagePleiades/OrbitModel.java b/src/tutorials/java/AffinagePleiades/OrbitModel.java new file mode 100644 index 0000000000000000000000000000000000000000..4379aefa0dbcb97c5b9c6d438c2fc8305b77e937 --- /dev/null +++ b/src/tutorials/java/AffinagePleiades/OrbitModel.java @@ -0,0 +1,203 @@ +/* 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 AffinagePleiades; + + +import org.hipparchus.geometry.euclidean.threed.Rotation; +import org.hipparchus.geometry.euclidean.threed.Vector3D; +import org.hipparchus.ode.nonstiff.DormandPrince853Integrator; +import org.hipparchus.util.FastMath; +import java.util.ArrayList; +import java.util.List; + +import org.orekit.attitudes.AttitudeProvider; +import org.orekit.attitudes.NadirPointing; +import org.orekit.attitudes.YawCompensation; +import org.orekit.bodies.BodyShape; +import org.orekit.bodies.CelestialBodyFactory; +import org.orekit.bodies.OneAxisEllipsoid; +import org.orekit.errors.OrekitException; +import org.orekit.forces.gravity.HolmesFeatherstoneAttractionModel; +import org.orekit.forces.gravity.ThirdBodyAttraction; +import org.orekit.forces.gravity.potential.GravityFieldFactory; +import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider; +import org.orekit.frames.Frame; +import org.orekit.frames.FramesFactory; +import org.orekit.frames.Transform; +import org.orekit.orbits.CircularOrbit; +import org.orekit.orbits.Orbit; +import org.orekit.orbits.OrbitType; +import org.orekit.orbits.PositionAngle; +import org.orekit.propagation.Propagator; +import org.orekit.propagation.SpacecraftState; +import org.orekit.propagation.analytical.KeplerianPropagator; +import org.orekit.propagation.numerical.NumericalPropagator; +import org.orekit.propagation.sampling.OrekitFixedStepHandler; +import org.orekit.time.AbsoluteDate; +import org.orekit.time.TimeScale; +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; + + +/** + * Orbit Model class to generate PV and Q + * @author jguinet + * + */ + +public class OrbitModel { + + public static void addSatellitePV(TimeScale gps, Frame eme2000, Frame itrf, + ArrayList<TimeStampedPVCoordinates> satellitePVList, + String absDate, + double px, double py, double pz, double vx, double vy, double vz) + throws OrekitException { + AbsoluteDate ephemerisDate = new AbsoluteDate(absDate, gps); + Vector3D position = new Vector3D(px, py, pz); + Vector3D velocity = new Vector3D(vx, vy, vz); + PVCoordinates pvITRF = new PVCoordinates(position, velocity); + Transform transform = itrf.getTransformTo(eme2000, ephemerisDate); + Vector3D pEME2000 = transform.transformPosition(pvITRF.getPosition()); + Vector3D vEME2000 = transform.transformVector(pvITRF.getVelocity()); + satellitePVList.add(new TimeStampedPVCoordinates(ephemerisDate, pEME2000, vEME2000, Vector3D.ZERO)); + } + + public void addSatelliteQ(TimeScale gps, ArrayList<TimeStampedAngularCoordinates> satelliteQList, + String absDate, double q0, double q1, double q2, double q3) { + AbsoluteDate attitudeDate = new AbsoluteDate(absDate, gps); + Rotation rotation = new Rotation(q0, q1, q2, q3, true); + TimeStampedAngularCoordinates pair = + new TimeStampedAngularCoordinates(attitudeDate, rotation, Vector3D.ZERO, Vector3D.ZERO); + satelliteQList.add(pair); + } + + public BodyShape createEarth() + throws OrekitException { + return new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, + Constants.WGS84_EARTH_FLATTENING, + FramesFactory.getITRF(IERSConventions.IERS_2010, true)); + } + + public NormalizedSphericalHarmonicsProvider createGravityField() + throws OrekitException { + return GravityFieldFactory.getNormalizedProvider(12, 12); + } + + public Orbit createOrbit(double mu,AbsoluteDate date) + throws OrekitException { + // the following orbital parameters have been computed using + // Orekit tutorial about phasing, using the following configuration: + // + // orbit.date = 2012-01-01T00:00:00.000 + // phasing.orbits.number = 143 + // phasing.days.number = 10 + // sun.synchronous.reference.latitude = 0 + // sun.synchronous.reference.ascending = false + // sun.synchronous.mean.solar.time = 10:30:00 + // gravity.field.degree = 12 + // gravity.field.order = 12 + + Frame eme2000 = FramesFactory.getEME2000(); + //return new CircularOrbit(7173352.811913891, + return new CircularOrbit(694000.0 + Constants.WGS84_EARTH_EQUATORIAL_RADIUS,//ajouter Rayon + -4.029194321683225E-4, 0.0013530362644647786, + FastMath.toRadians(98.2), //pleiades inclinaison 98.2 + FastMath.toRadians(-86.47), + FastMath.toRadians(135.9), PositionAngle.TRUE, + eme2000, date, mu); + } + + public Propagator createPropagator(BodyShape earth, + NormalizedSphericalHarmonicsProvider gravityField, + Orbit orbit) + throws OrekitException { + + AttitudeProvider yawCompensation = new YawCompensation(orbit.getFrame(), new NadirPointing(orbit.getFrame(), earth)); + SpacecraftState state = new SpacecraftState(orbit, + yawCompensation.getAttitude(orbit, + orbit.getDate(), + orbit.getFrame()), + 1180.0); + + // numerical model for improving orbit + OrbitType type = OrbitType.CIRCULAR; + double[][] tolerances = NumericalPropagator.tolerances(0.1, orbit, type); + DormandPrince853Integrator integrator = + new DormandPrince853Integrator(1.0e-4 * orbit.getKeplerianPeriod(), + 1.0e-1 * orbit.getKeplerianPeriod(), + tolerances[0], tolerances[1]); + integrator.setInitialStepSize(1.0e-2 * orbit.getKeplerianPeriod()); + NumericalPropagator numericalPropagator = new NumericalPropagator(integrator); + numericalPropagator.addForceModel(new HolmesFeatherstoneAttractionModel(earth.getBodyFrame(), gravityField)); + numericalPropagator.addForceModel(new ThirdBodyAttraction(CelestialBodyFactory.getSun())); + numericalPropagator.addForceModel(new ThirdBodyAttraction(CelestialBodyFactory.getMoon())); + numericalPropagator.setOrbitType(type); + numericalPropagator.setInitialState(state); + numericalPropagator.setAttitudeProvider(yawCompensation); + return numericalPropagator; + + } + + + public List<TimeStampedPVCoordinates> orbitToPV(Orbit orbit, BodyShape earth, + AbsoluteDate minDate, AbsoluteDate maxDate, + double step) + throws OrekitException { + Propagator propagator = new KeplerianPropagator(orbit); + propagator.setAttitudeProvider(new YawCompensation(orbit.getFrame(), new NadirPointing(orbit.getFrame(), earth))); + propagator.propagate(minDate); + final List<TimeStampedPVCoordinates> list = new ArrayList<TimeStampedPVCoordinates>(); + propagator.setMasterMode(step, new OrekitFixedStepHandler() { + public void init(SpacecraftState s0, AbsoluteDate t) { + } + public void handleStep(SpacecraftState currentState, boolean isLast) { + list.add(new TimeStampedPVCoordinates(currentState.getDate(), + currentState.getPVCoordinates().getPosition(), + currentState.getPVCoordinates().getVelocity(), + Vector3D.ZERO)); + } + }); + propagator.propagate(maxDate); + return list; + } + + public List<TimeStampedAngularCoordinates> orbitToQ(Orbit orbit, BodyShape earth, + AbsoluteDate minDate, AbsoluteDate maxDate, + double step) + throws OrekitException { + Propagator propagator = new KeplerianPropagator(orbit); + propagator.setAttitudeProvider(new YawCompensation(orbit.getFrame(), new NadirPointing(orbit.getFrame(), earth))); + propagator.propagate(minDate); + final List<TimeStampedAngularCoordinates> list = new ArrayList<TimeStampedAngularCoordinates>(); + propagator.setMasterMode(step, new OrekitFixedStepHandler() { + public void init(SpacecraftState s0, AbsoluteDate t) { + } + public void handleStep(SpacecraftState currentState, boolean isLast) { + list.add(new TimeStampedAngularCoordinates(currentState.getDate(), + currentState.getAttitude().getRotation(), + Vector3D.ZERO, Vector3D.ZERO)); + } + }); + propagator.propagate(maxDate); + return list; + } + +} + diff --git a/src/tutorials/java/AffinagePleiades/PleiadesViewingModel.java b/src/tutorials/java/AffinagePleiades/PleiadesViewingModel.java new file mode 100644 index 0000000000000000000000000000000000000000..60b46b21bbe89465f013c2e6be4b85a49dccbc9b --- /dev/null +++ b/src/tutorials/java/AffinagePleiades/PleiadesViewingModel.java @@ -0,0 +1,165 @@ +/* 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 AffinagePleiades; + + + +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.FastMath; +import java.util.ArrayList; +import java.util.List; + + +import org.orekit.rugged.los.FixedRotation; +import org.orekit.rugged.los.LOSBuilder; +import org.orekit.rugged.los.TimeDependentLOS; +import org.orekit.time.AbsoluteDate; +import org.orekit.time.TimeScale; +import org.orekit.time.TimeScalesFactory; +import org.orekit.rugged.linesensor.LinearLineDatation; +import org.orekit.rugged.linesensor.LineDatation; +import org.orekit.rugged.linesensor.LineSensor; + +import org.orekit.rugged.errors.RuggedException; +import org.orekit.errors.OrekitException; + + +public class PleiadesViewingModel { + + public double fov = 1.6; // 20km - alt 694km + public double angle = 0.0; + public double incidence = 15.0; + public LineSensor lineSensor; + public int dimension = 40000; + public String date = "2016-01-01T00:00:00.0"; + + private String sensorName; + + /** Simple constructor. + * <p> + * + * </p> + */ + public PleiadesViewingModel() throws RuggedException, OrekitException { + sensorName = "line"; + this.createLineSensor(); + } + + public LOSBuilder rawLOS(Vector3D center, Vector3D normal, double halfAperture, int n) + { + + List<Vector3D> list = new ArrayList<Vector3D>(n); + for (int i = 0; i < n; ++i) { + double alpha = (halfAperture * (2 * i + 1 - n)) / (n - 1); + list.add(new Rotation(normal, alpha, RotationConvention.VECTOR_OPERATOR).applyTo(center)); + } + return new LOSBuilder(list); + } + + + public TimeDependentLOS buildLOS() + { + + + + // one line sensor + // position: 1.5m in front (+X) and 20 cm above (-Z) of the S/C center of mass + // los: swath in the (YZ) plane, looking at 50° roll, 2.6" per pixel + LOSBuilder losBuilder = rawLOS(new Rotation(Vector3D.PLUS_I, + FastMath.toRadians(angle), + RotationConvention.VECTOR_OPERATOR).applyTo(Vector3D.PLUS_K), Vector3D.PLUS_I, FastMath.toRadians(fov/2), dimension); + + + losBuilder.addTransform(new FixedRotation("roll", Vector3D.MINUS_I, 0.0)); + losBuilder.addTransform(new FixedRotation("pitch", Vector3D.MINUS_J, 0.0)); + + return losBuilder.build(); + } + + + public AbsoluteDate getDatationReference() throws OrekitException + { + // We use Orekit for handling time and dates, and Rugged for defining the datation model: + TimeScale utc = TimeScalesFactory.getUTC(); + return new AbsoluteDate(date, utc); + } + + + + + + public AbsoluteDate getMinDate() throws RuggedException + { + return lineSensor.getDate(0); + } + + public AbsoluteDate getMaxDate() throws RuggedException + { + return lineSensor.getDate(dimension); + } + + public LineSensor getLineSensor() { + return lineSensor; + } + + public String getSensorName() { + return sensorName; + } + + + private void createLineSensor() + throws RuggedException, OrekitException { + + //System.out.println("add line sensor"); + + + + // TBN: refining data are read only for level L1B or L1C + //System.out.println("refining info"); + + // Offset of the MSI from center of mass of satellite + //System.out.println("MSI offset from center of mass of satellite"); + // one line sensor + // position: 1.5m in front (+X) and 20 cm above (-Z) of the S/C center of mass + // los: swath in the (YZ) plane, looking at 50° roll, 2.6" per pixel + //Vector3D msiOffset = new Vector3D(1.5, 0, -0.2); + Vector3D msiOffset = new Vector3D(0, 0, 0); + + + + // to do build complex los + TimeDependentLOS lineOfSight = buildLOS(); + + + double linePeriod = 1.0 / 1.5e-3; + // linear datation model: at reference time we get the middle line, and the rate is one line every 1.5ms + + + + LineDatation lineDatation = new LinearLineDatation(getDatationReference(), dimension / 2, linePeriod); + //LineDatation lineDatation = new LinearLineDatation(absDate, 1d, 20); + lineSensor = new LineSensor(sensorName, lineDatation, msiOffset, lineOfSight); + + + } + + +} +