Search in sources :

Example 11 with Line

use of org.hipparchus.geometry.euclidean.threed.Line in project Orekit by CS-SI.

the class OneAxisEllipsoidTest method testLineIntersection.

@Test
public void testLineIntersection() throws OrekitException {
    AbsoluteDate date = AbsoluteDate.J2000_EPOCH;
    Frame frame = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
    OneAxisEllipsoid model = new OneAxisEllipsoid(100.0, 0.9, frame);
    Vector3D point = new Vector3D(0.0, 93.7139699, 3.5930796);
    Vector3D direction = new Vector3D(0.0, 1.0, 1.0);
    Line line = new Line(point, point.add(direction), 1.0e-10);
    GeodeticPoint gp = model.getIntersectionPoint(line, point, frame, date);
    Assert.assertEquals(gp.getAltitude(), 0.0, 1.0e-12);
    Assert.assertTrue(line.contains(model.transform(gp)));
    model = new OneAxisEllipsoid(100.0, 0.9, frame);
    point = new Vector3D(0.0, -93.7139699, -3.5930796);
    direction = new Vector3D(0.0, -1.0, -1.0);
    line = new Line(point, point.add(direction), 1.0e-10).revert();
    gp = model.getIntersectionPoint(line, point, frame, date);
    Assert.assertTrue(line.contains(model.transform(gp)));
    model = new OneAxisEllipsoid(100.0, 0.9, frame);
    point = new Vector3D(0.0, -93.7139699, 3.5930796);
    direction = new Vector3D(0.0, -1.0, 1.0);
    line = new Line(point, point.add(direction), 1.0e-10);
    gp = model.getIntersectionPoint(line, point, frame, date);
    Assert.assertTrue(line.contains(model.transform(gp)));
    model = new OneAxisEllipsoid(100.0, 0.9, frame);
    point = new Vector3D(-93.7139699, 0.0, 3.5930796);
    direction = new Vector3D(-1.0, 0.0, 1.0);
    line = new Line(point, point.add(direction), 1.0e-10);
    gp = model.getIntersectionPoint(line, point, frame, date);
    Assert.assertTrue(line.contains(model.transform(gp)));
    Assert.assertFalse(line.contains(new Vector3D(0, 0, 7000000)));
    point = new Vector3D(0.0, 0.0, 110);
    direction = new Vector3D(0.0, 0.0, 1.0);
    line = new Line(point, point.add(direction), 1.0e-10);
    gp = model.getIntersectionPoint(line, point, frame, date);
    Assert.assertEquals(gp.getLatitude(), FastMath.PI / 2, 1.0e-12);
    point = new Vector3D(0.0, 110, 0);
    direction = new Vector3D(0.0, 1.0, 0.0);
    line = new Line(point, point.add(direction), 1.0e-10);
    gp = model.getIntersectionPoint(line, point, frame, date);
    Assert.assertEquals(gp.getLatitude(), 0, 1.0e-12);
}
Also used : Line(org.hipparchus.geometry.euclidean.threed.Line) Frame(org.orekit.frames.Frame) FieldVector3D(org.hipparchus.geometry.euclidean.threed.FieldVector3D) Vector3D(org.hipparchus.geometry.euclidean.threed.Vector3D) FieldAbsoluteDate(org.orekit.time.FieldAbsoluteDate) AbsoluteDate(org.orekit.time.AbsoluteDate) Test(org.junit.Test)

Example 12 with Line

use of org.hipparchus.geometry.euclidean.threed.Line in project Orekit by CS-SI.

the class YawCompensationTest method testAlignment.

/**
 * Test that pointed target motion is along -X sat axis
 */
@Test
public void testAlignment() throws OrekitException {
    GroundPointing notCompensated = new NadirPointing(circOrbit.getFrame(), earthShape);
    YawCompensation compensated = new YawCompensation(circOrbit.getFrame(), notCompensated);
    Attitude att0 = compensated.getAttitude(circOrbit, circOrbit.getDate(), circOrbit.getFrame());
    // ground point in satellite Z direction
    Vector3D satInert = circOrbit.getPVCoordinates().getPosition();
    Vector3D zInert = att0.getRotation().applyInverseTo(Vector3D.PLUS_K);
    GeodeticPoint gp = earthShape.getIntersectionPoint(new Line(satInert, satInert.add(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, zInert), 1.0e-10), satInert, circOrbit.getFrame(), circOrbit.getDate());
    PVCoordinates pEarth = new PVCoordinates(earthShape.transform(gp), Vector3D.ZERO, Vector3D.ZERO);
    double minYWithoutCompensation = Double.POSITIVE_INFINITY;
    double maxYWithoutCompensation = Double.NEGATIVE_INFINITY;
    double minYDotWithoutCompensation = Double.POSITIVE_INFINITY;
    double maxYDotWithoutCompensation = Double.NEGATIVE_INFINITY;
    double minYWithCompensation = Double.POSITIVE_INFINITY;
    double maxYWithCompensation = Double.NEGATIVE_INFINITY;
    double minYDotWithCompensation = Double.POSITIVE_INFINITY;
    double maxYDotWithCompensation = Double.NEGATIVE_INFINITY;
    for (double dt = -0.2; dt < 0.2; dt += 0.002) {
        PVCoordinates withoutCompensation = toSpacecraft(pEarth, circOrbit.shiftedBy(dt), notCompensated);
        if (FastMath.abs(withoutCompensation.getPosition().getX()) <= 1000.0) {
            minYWithoutCompensation = FastMath.min(minYWithoutCompensation, withoutCompensation.getPosition().getY());
            maxYWithoutCompensation = FastMath.max(maxYWithoutCompensation, withoutCompensation.getPosition().getY());
            minYDotWithoutCompensation = FastMath.min(minYDotWithoutCompensation, withoutCompensation.getVelocity().getY());
            maxYDotWithoutCompensation = FastMath.max(maxYDotWithoutCompensation, withoutCompensation.getVelocity().getY());
        }
        PVCoordinates withCompensation = toSpacecraft(pEarth, circOrbit.shiftedBy(dt), compensated);
        if (FastMath.abs(withCompensation.getPosition().getX()) <= 1000.0) {
            minYWithCompensation = FastMath.min(minYWithCompensation, withCompensation.getPosition().getY());
            maxYWithCompensation = FastMath.max(maxYWithCompensation, withCompensation.getPosition().getY());
            minYDotWithCompensation = FastMath.min(minYDotWithCompensation, withCompensation.getVelocity().getY());
            maxYDotWithCompensation = FastMath.max(maxYDotWithCompensation, withCompensation.getVelocity().getY());
        }
    }
    // when the ground point is close to cross the push-broom line (i.e. when Δx decreases from +1000m to -1000m)
    // it will drift along the Y axis if we don't apply compensation
    // but will remain nearly at Δy=0 if we do apply compensation
    // in fact, as the yaw compensation mode removes the linear drift,
    // what remains is a parabola Δy = a uΔx²
    Assert.assertEquals(-55.7056, minYWithoutCompensation, 0.0001);
    Assert.assertEquals(+55.7056, maxYWithoutCompensation, 0.0001);
    Assert.assertEquals(352.5667, minYDotWithoutCompensation, 0.0001);
    Assert.assertEquals(352.5677, maxYDotWithoutCompensation, 0.0001);
    Assert.assertEquals(0.0000, minYWithCompensation, 0.0001);
    Assert.assertEquals(0.0008, maxYWithCompensation, 0.0001);
    Assert.assertEquals(-0.0101, minYDotWithCompensation, 0.0001);
    Assert.assertEquals(0.0102, maxYDotWithCompensation, 0.0001);
}
Also used : Line(org.hipparchus.geometry.euclidean.threed.Line) Vector3D(org.hipparchus.geometry.euclidean.threed.Vector3D) TimeStampedPVCoordinates(org.orekit.utils.TimeStampedPVCoordinates) PVCoordinates(org.orekit.utils.PVCoordinates) TimeStampedFieldPVCoordinates(org.orekit.utils.TimeStampedFieldPVCoordinates) GeodeticPoint(org.orekit.bodies.GeodeticPoint) Test(org.junit.Test)

Example 13 with Line

use of org.hipparchus.geometry.euclidean.threed.Line in project Orekit by CS-SI.

the class LofOffsetPointing method losIntersectionWithBody.

/**
 * Compute line of sight intersection with body.
 * @param scToBody transform from spacecraft frame to body frame
 * @return intersection point in body frame (only the position is set!)
 * @exception OrekitException if line of sight does not intersect body
 */
private TimeStampedPVCoordinates losIntersectionWithBody(final Transform scToBody) throws OrekitException {
    // compute satellite pointing axis and position/velocity in body frame
    final Vector3D pointingBodyFrame = scToBody.transformVector(satPointingVector);
    final Vector3D pBodyFrame = scToBody.transformPosition(Vector3D.ZERO);
    // Line from satellite following pointing direction
    // we use arbitrarily the Earth radius as a scaling factor, it could be anything else
    final Line pointingLine = new Line(pBodyFrame, pBodyFrame.add(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, pointingBodyFrame), 1.0e-10);
    // Intersection with body shape
    final GeodeticPoint gpIntersection = shape.getIntersectionPoint(pointingLine, pBodyFrame, shape.getBodyFrame(), scToBody.getDate());
    final Vector3D pIntersection = (gpIntersection == null) ? null : shape.transform(gpIntersection);
    // Check there is an intersection and it is not in the reverse pointing direction
    if ((pIntersection == null) || (Vector3D.dotProduct(pIntersection.subtract(pBodyFrame), pointingBodyFrame) < 0)) {
        throw new OrekitException(OrekitMessages.ATTITUDE_POINTING_LAW_DOES_NOT_POINT_TO_GROUND);
    }
    return new TimeStampedPVCoordinates(scToBody.getDate(), pIntersection, Vector3D.ZERO, Vector3D.ZERO);
}
Also used : Line(org.hipparchus.geometry.euclidean.threed.Line) FieldLine(org.hipparchus.geometry.euclidean.threed.FieldLine) Vector3D(org.hipparchus.geometry.euclidean.threed.Vector3D) FieldVector3D(org.hipparchus.geometry.euclidean.threed.FieldVector3D) OrekitException(org.orekit.errors.OrekitException) GeodeticPoint(org.orekit.bodies.GeodeticPoint) FieldGeodeticPoint(org.orekit.bodies.FieldGeodeticPoint) TimeStampedPVCoordinates(org.orekit.utils.TimeStampedPVCoordinates)

Example 14 with Line

use of org.hipparchus.geometry.euclidean.threed.Line in project Orekit by CS-SI.

the class FieldOfView method getFootprint.

/**
 * Get the footprint of the field Of View on ground.
 * <p>
 * This method assumes the Field Of View is centered on some carrier,
 * which will typically be a spacecraft or a ground station antenna.
 * The points in the footprint boundary loops are all at altitude zero
 * with respect to the ellipsoid, they correspond either to projection
 * on ground of the edges of the Field Of View, or to points on the body
 * limb if the Field Of View goes past horizon. The points on the limb
 * see the carrier origin at zero elevation. If the Field Of View is so
 * large it contains entirely the body, all points will correspond to
 * points at limb. If the Field Of View looks away from body, the
 * boundary loops will be an empty list. The points within footprint
 * the loops are sorted in trigonometric order as seen from the carrier.
 * This implies that someone traveling on ground from one point to the
 * next one will have the points visible from the carrier on his left
 * hand side, and the points not visible from the carrier on his right
 * hand side.
 * </p>
 * <p>
 * The truncation of Field Of View at limb can induce strange results
 * for complex Fields Of View. If for example a Field Of View is a
 * ring with a hole and part of the ring goes past horizon, then instead
 * of having a single loop with a C-shaped boundary, the method will
 * still return two loops truncated at the limb, one clockwise and one
 * counterclockwise, hence "closing" the C-shape twice. This behavior
 * is considered acceptable.
 * </p>
 * <p>
 * If the carrier is a spacecraft, then the {@code fovToBody} transform
 * can be computed from a {@link org.orekit.propagation.SpacecraftState}
 * as follows:
 * </p>
 * <pre>
 * Transform inertToBody = state.getFrame().getTransformTo(body.getBodyFrame(), state.getDate());
 * Transform fovToBody   = new Transform(state.getDate(),
 *                                       state.toTransform().getInverse(),
 *                                       inertToBody);
 * </pre>
 * <p>
 * If the carrier is a ground station, located using a topocentric frame
 * and managing its pointing direction using a transform between the
 * dish frame and the topocentric frame, then the {@code fovToBody} transform
 * can be computed as follows:
 * </p>
 * <pre>
 * Transform topoToBody = topocentricFrame.getTransformTo(body.getBodyFrame(), date);
 * Transform topoToDish = ...
 * Transform fovToBody  = new Transform(date,
 *                                      topoToDish.getInverse(),
 *                                      topoToBody);
 * </pre>
 * <p>
 * Only the raw zone is used, the angular margin is ignored here.
 * </p>
 * @param fovToBody transform between the frame in which the Field Of View
 * is defined and body frame.
 * @param body body surface the Field Of View will be projected on
 * @param angularStep step used for boundary loops sampling (radians)
 * @return list footprint boundary loops (there may be several independent
 * loops if the Field Of View shape is complex)
 * @throws OrekitException if some frame conversion fails or if carrier is
 * below body surface
 */
List<List<GeodeticPoint>> getFootprint(final Transform fovToBody, final OneAxisEllipsoid body, final double angularStep) throws OrekitException {
    final Frame bodyFrame = body.getBodyFrame();
    final Vector3D position = fovToBody.transformPosition(Vector3D.ZERO);
    final double r = position.getNorm();
    if (body.isInside(position)) {
        throw new OrekitException(OrekitMessages.POINT_INSIDE_ELLIPSOID);
    }
    final List<List<GeodeticPoint>> footprint = new ArrayList<List<GeodeticPoint>>();
    final List<Vertex> boundary = zone.getBoundaryLoops();
    for (final Vertex loopStart : boundary) {
        int count = 0;
        final List<GeodeticPoint> loop = new ArrayList<GeodeticPoint>();
        boolean intersectionsFound = false;
        for (Edge edge = loopStart.getOutgoing(); count == 0 || edge.getStart() != loopStart; edge = edge.getEnd().getOutgoing()) {
            ++count;
            final int n = (int) FastMath.ceil(edge.getLength() / angularStep);
            final double delta = edge.getLength() / n;
            for (int i = 0; i < n; ++i) {
                final Vector3D awaySC = new Vector3D(r, edge.getPointAt(i * delta));
                final Vector3D awayBody = fovToBody.transformPosition(awaySC);
                final Line lineOfSight = new Line(position, awayBody, 1.0e-3);
                GeodeticPoint gp = body.getIntersectionPoint(lineOfSight, position, bodyFrame, null);
                if (gp != null && Vector3D.dotProduct(awayBody.subtract(position), body.transform(gp).subtract(position)) < 0) {
                    // the intersection is in fact on the half-line pointing
                    // towards the back side, it is a spurious intersection
                    gp = null;
                }
                if (gp != null) {
                    // the line of sight does intersect the body
                    intersectionsFound = true;
                } else {
                    // the line of sight does not intersect body
                    // we use a point on the limb
                    gp = body.transform(body.pointOnLimb(position, awayBody), bodyFrame, null);
                }
                // add the point in front of the list
                // (to ensure the loop will be in trigonometric orientation)
                loop.add(0, gp);
            }
        }
        if (intersectionsFound) {
            // at least some of the points did intersect the body,
            // this loop contributes to the footprint
            footprint.add(loop);
        }
    }
    if (footprint.isEmpty()) {
        // none of the Field Of View loops cross the body
        // either the body is outside of Field Of View, or it is fully contained
        // we check the center
        final Vector3D bodyCenter = fovToBody.getInverse().transformPosition(Vector3D.ZERO);
        if (zone.checkPoint(new S2Point(bodyCenter)) != Region.Location.OUTSIDE) {
            // the body is fully contained in the Field Of View
            // we use the full limb as the footprint
            final Vector3D x = bodyCenter.orthogonal();
            final Vector3D y = Vector3D.crossProduct(bodyCenter, x).normalize();
            final double sinEta = body.getEquatorialRadius() / r;
            final double sinEta2 = sinEta * sinEta;
            final double cosAlpha = (FastMath.cos(angularStep) + sinEta2 - 1) / sinEta2;
            final int n = (int) FastMath.ceil(MathUtils.TWO_PI / FastMath.acos(cosAlpha));
            final double delta = MathUtils.TWO_PI / n;
            final List<GeodeticPoint> loop = new ArrayList<GeodeticPoint>(n);
            for (int i = 0; i < n; ++i) {
                final Vector3D outside = new Vector3D(r * FastMath.cos(i * delta), x, r * FastMath.sin(i * delta), y);
                loop.add(body.transform(body.pointOnLimb(position, outside), bodyFrame, null));
            }
            footprint.add(loop);
        }
    }
    return footprint;
}
Also used : Vertex(org.hipparchus.geometry.spherical.twod.Vertex) Frame(org.orekit.frames.Frame) S2Point(org.hipparchus.geometry.spherical.twod.S2Point) ArrayList(java.util.ArrayList) S2Point(org.hipparchus.geometry.spherical.twod.S2Point) GeodeticPoint(org.orekit.bodies.GeodeticPoint) Line(org.hipparchus.geometry.euclidean.threed.Line) Vector3D(org.hipparchus.geometry.euclidean.threed.Vector3D) OrekitException(org.orekit.errors.OrekitException) ArrayList(java.util.ArrayList) List(java.util.List) GeodeticPoint(org.orekit.bodies.GeodeticPoint) Edge(org.hipparchus.geometry.spherical.twod.Edge)

Example 15 with Line

use of org.hipparchus.geometry.euclidean.threed.Line in project Orekit by CS-SI.

the class TargetPointingTest method testTargetInPointingDirection.

/**
 * Test if defined target belongs to the direction pointed by the satellite
 */
@Test
public void testTargetInPointingDirection() throws OrekitException {
    // Create computation date
    AbsoluteDate date = new AbsoluteDate(new DateComponents(2008, 04, 07), TimeComponents.H00, TimeScalesFactory.getUTC());
    // Reference frame = ITRF
    Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
    // Elliptic earth shape
    OneAxisEllipsoid earthShape = new OneAxisEllipsoid(6378136.460, 1 / 298.257222101, itrf);
    // Create target pointing attitude provider
    GeodeticPoint geoTarget = new GeodeticPoint(FastMath.toRadians(43.36), FastMath.toRadians(1.26), 600.);
    TargetPointing targetAttitudeLaw = new TargetPointing(FramesFactory.getEME2000(), geoTarget, earthShape);
    // Satellite position
    // ********************
    // Create satellite position as circular parameters
    CircularOrbit circ = new CircularOrbit(7178000.0, 0.5e-4, -0.5e-4, FastMath.toRadians(50.), FastMath.toRadians(270.), FastMath.toRadians(5.300), PositionAngle.MEAN, FramesFactory.getEME2000(), date, mu);
    // Transform satellite position to position/velocity parameters in EME2000 frame
    PVCoordinates pvSatEME2000 = circ.getPVCoordinates();
    // Pointing direction
    // ********************
    // Get satellite attitude rotation, i.e rotation from EME2000 frame to satellite frame
    Rotation rotSatEME2000 = targetAttitudeLaw.getAttitude(circ, date, circ.getFrame()).getRotation();
    // Transform Z axis from satellite frame to EME2000
    Vector3D zSatEME2000 = rotSatEME2000.applyInverseTo(Vector3D.PLUS_K);
    // Line containing satellite point and following pointing direction
    Vector3D p = eme2000ToItrf.transformPosition(pvSatEME2000.getPosition());
    Line pointingLine = new Line(p, p.add(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, eme2000ToItrf.transformVector(zSatEME2000)), 1.0e-10);
    // Check that the line contains earth center
    double distance = pointingLine.distance(earthShape.transform(geoTarget));
    Assert.assertEquals(0, distance, 1.e-7);
}
Also used : Line(org.hipparchus.geometry.euclidean.threed.Line) Frame(org.orekit.frames.Frame) OneAxisEllipsoid(org.orekit.bodies.OneAxisEllipsoid) CircularOrbit(org.orekit.orbits.CircularOrbit) Vector3D(org.hipparchus.geometry.euclidean.threed.Vector3D) TimeStampedPVCoordinates(org.orekit.utils.TimeStampedPVCoordinates) PVCoordinates(org.orekit.utils.PVCoordinates) TimeStampedFieldPVCoordinates(org.orekit.utils.TimeStampedFieldPVCoordinates) DateComponents(org.orekit.time.DateComponents) GeodeticPoint(org.orekit.bodies.GeodeticPoint) Rotation(org.hipparchus.geometry.euclidean.threed.Rotation) FieldAbsoluteDate(org.orekit.time.FieldAbsoluteDate) AbsoluteDate(org.orekit.time.AbsoluteDate) Test(org.junit.Test)

Aggregations

Line (org.hipparchus.geometry.euclidean.threed.Line)20 Vector3D (org.hipparchus.geometry.euclidean.threed.Vector3D)19 FieldVector3D (org.hipparchus.geometry.euclidean.threed.FieldVector3D)12 Test (org.junit.Test)11 GeodeticPoint (org.orekit.bodies.GeodeticPoint)10 Frame (org.orekit.frames.Frame)9 Transform (org.orekit.frames.Transform)6 FieldAbsoluteDate (org.orekit.time.FieldAbsoluteDate)6 TimeStampedPVCoordinates (org.orekit.utils.TimeStampedPVCoordinates)6 FieldLine (org.hipparchus.geometry.euclidean.threed.FieldLine)5 AbsoluteDate (org.orekit.time.AbsoluteDate)5 OrekitException (org.orekit.errors.OrekitException)4 PVCoordinates (org.orekit.utils.PVCoordinates)4 Rotation (org.hipparchus.geometry.euclidean.threed.Rotation)3 RandomGenerator (org.hipparchus.random.RandomGenerator)3 Well19937a (org.hipparchus.random.Well19937a)3 FieldGeodeticPoint (org.orekit.bodies.FieldGeodeticPoint)3 FieldTransform (org.orekit.frames.FieldTransform)3 DateComponents (org.orekit.time.DateComponents)3 TimeStampedFieldPVCoordinates (org.orekit.utils.TimeStampedFieldPVCoordinates)3