Ground Sensor Field of View with Inertial Orientation

Dear Orekit experts,

We are trying to create a field of view detector for a ground station, i.e. check if a satellite is in the field of view of the ground-based sensor. The sensor has a limited FoV and is pointing in an inertial direction, i.e. fixed right ascension and declination. (In the future, we’d also like to track a satellite, i.e. have the pointing direction follow a trajectory.)

We were thinking of using the GroundFieldOfViewDetector with a Frame aligned with the FoV pointing direction. That is, a frame with its origin at the ground station’s location, the X-axis aligned with the pointing direction and the Y- and Z- axis aligned with the orientation of the FoV. So, a frame which a moving origin, but the orientation inertially aligned.

So far, we have not been able to create such a frame. We have tried to create a new Frame based on a parent Frame by providing a translation and rotation (like in TopocentricFrame). Unfortunately, this didn’t work out since the position/origin is defined in an ECEF frame (or time-dependent in ECI frame) and the rotation is defined in an ECI frame, so we need different parent frames for the translation and rotation. We have tried with a subclass of the Frame class, called PointingFrame:

public PointingFrame(BodyShape parentShape, final GeodeticPoint point,  
                     PointingDirection pointingDirection, final String name) {

    super(parentShape.getBodyFrame(), 
          new Transform(AbsoluteDate.ARBITRARY_EPOCH, 
                        parentShape.getBodyFrame().getTransformTo(FramesFactory.getEME2000(), AbsoluteDate.ARBITRARY_EPOCH), 
                        new Transform(AbsoluteDate.ARBITRARY_EPOCH,  
                                      new Transform(AbsoluteDate.ARBITRARY_EPOCH,
                                                    new Rotation(Vector3D.PLUS_I, Vector3D.PLUS_J, 
                                                                  new Vector3D(FastMath.cos(FastMath.toRadians(pointingDirection.getDeclination()))* FastMath.cos(FastMath.toRadians(pointingDirection.getRightAscension())),FastMath.cos(FastMath.toRadians(pointingDirection.getDeclination()))*FastMath.sin(FastMath.toRadians(pointingDirection.getRightAscension())),FastMath.sin(FastMath.toRadians(pointingDirection.getDeclination()))),
                                                                  Vector3D.PLUS_K.crossProduct(new Vector3D(FastMath.cos(FastMath.toRadians(pointingDirection.getDeclination()))* FastMath.cos(FastMath.toRadians(pointingDirection.getRightAscension())), FastMath.cos(FastMath.toRadians(pointingDirection.getDeclination()))*FastMath.sin(FastMath.toRadians(pointingDirection.getRightAscension())),FastMath.sin(FastMath.toRadians(pointingDirection.getDeclination()))))), Vector3D.ZERO),
                                      new Transform(AbsoluteDate.ARBITRARY_EPOCH, parentShape.getBodyFrame().getTransformTo(FramesFactory.getEME2000(), AbsoluteDate.ARBITRARY_EPOCH).freeze().transformVector(parentShape.transform(point))))),

           name, false);

        this.parentShape = parentShape;
        this.point = point;

    }

The tutorials and this forum suggest to use a TransformProvider like in JPLCelestialBody.InertiallyOriented or maybe an UpdatableFrame. But we are not sure which is the best way to proceed.
Could you give us a hint regarding creating the desired frame? Or is a better solution to create a new GroundFieldOfViewDetector with dedicated line of sight calculation inside?

Thanks in advance for your help!

Best wishes,

Hi @alvaro.mch

The simplest way to achieve what you need seems to set up a TransformProvider as you can build
the transform for any date as you want.
You can start by implementing the method that takes an AbsoluteDate parameter and just have the other method (the one that takes a FieldAbsoluteDate parameter) return null. This will work as long as you don’t use derivatives, i.e. as long as you don’t use this in an orbit determination process. Once the simple method has been validated, you can implement the second method, which is mainly a copy of the first one with double primitive variables changed to fields, this should not be too complex to do as your provider will only build a few objects (rotations and vectors) and pack them in a transform. We can help for this “fieldification”.