Region of Interest Observation in LEO Using Custom Sensor

Dear all,

I would like to use the Orekit Python Wrapper for an observation study of the aurora borealis from a LEO with a sensor of lets say 40° x 40° rectangular field of view. I started this study in pure Python but due to the lack of a proper geometry library I would like to change my working horse.

Since I have never worked with Orekit yet, I only have a rough road map of how to carry it out and therefore wanted to ask for a first general guidance to identify the important tools to use.

So far I could identify the following ingredients to my study:

  1. Defining a region of interest (wherein the aurora would occur) by e.g. using a spherical circle of some radius with center at the magnetic North Pole projected onto the Earth’s surface (assuming its a sphere).

  2. Defining the geometry of the sensor’s field of view: as it has a rectangular field of view I imagine it to look like a pyramid from space towards Earth.

  3. Simulation of a LEO polar orbit using a certain set of keplerian elements.

  4. For each time step of propagation check if the field of view intersects with the region of interest and calculate the intersection e.g. as a fraction of the region of interest itself.

  5. Being able to access the results to visualise in Python.

I would probably start with Nadir pointing but ultimately change to a rotation across the ground track to increase the accessible region of interest.

Could you tell me if these plans are in the scope of Orekit and if so would you kindly point me into the right directions for starting point?

Thanks a lot!

Hi!

Welcome to the Orekit forum! :slight_smile:
We are very sorry for this late answer.

Unfortunately, I’m not a Python expert… but I can try to give you some help.

Knowing the geodetic points defining the region, you can easily build an object that can be used to detect entry/exit of the region during an orbit propagation.

The first step is to build the list of GeodeticPoint that define the region. The more points you have, the more your region can be closed to a spherical region. Please note that initializing a GeodeticPoint object is very easy. It just requires the latitude, the longitude, and the altitude of the point on Earth. With Orekit, we usually forget that the latitude and longitude must be defined in radians.

Once the list of GeodeticPoint built (lets call it pointList), you can construct the zone using EllipsoidTessellator.buildSimpleZone(tolerance, pointList). The value of tolerance is typically equal to 1.0e-10. The buildSimpleZone method will return a SphericalPolygonsSet that can be used in Orekit to initialize the FootprintOverlapDetector used to detect entry/exit of the zone. This class is an event detector that can be added to a propagator to detect entry/exit during an orbit propagation.

All the available geometries to define sensor’s field of view in Orekit are available in the org.orekit.geometry.fov package. As you want a rectangular field of view, I recommend you to use the DoubleDihedraFieldOfView. You can find some example on how initializing it in the test class of this class.

Let fov be the DoubleDihedraFieldOfView and zone be the SphericalPolygonsSet built from the list of GeodeticPoint and the buildSimpleZone method as presented previously. The FootprintOverlapDetector can be initialized like that:

ecef = FramesFactory.getITRF(IERSConventions.IERS_2010, true)
earth = OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, Constants.WGS84_EARTH_FLATTENING,  ecef)
targetZoneDetector = FootprintOverlapDetector(fov,  earth, zone, 10000.0)

Just note that using this detector, the propagation will stop when the region leaves the field of view. This behavior is due to the default handler of the detector which is StopOnIncreasing. You can easily override this configuration by calling the .withHandler() method of the event detector. Overrinding the default handler can be very useflul for your need. You can create you own handler (i.e., class) by implementing the PythonEventHandler interface of the Orekit Python Wrapper. It can help you to identify when the region enters or leaves the field of view. For instance by printing the epochs of saving some data to do plots at the end of the propagation.

targetZoneDetector = targetZoneDetector.withHandler(myWonderfulHandler)

To define the initial orbit in Keplerian elements (lets call it initialOrbit), you have to use the KeplerianOrbit class. After defining the initial orbit, you can propagate it using an analytical (e.g., Eckstein-Hechler) or a numerical (i.e., NumericalPropagator) orbit propagator.

For instance, you can initialize the Eckstein-Hechler model like that:

provider   = GravityFieldFactory.getUnnormalizedProvider(6, 6)
propagator =  EcksteinHechlerPropagator(initialOrbit, Propagator.DEFAULT_MASS, provider)

And, you can initialize a Numerical propagator like that:

integrationStep = 60
integrator      = ClassicalRungeKuttaIntegrator(integrationStep)
propagator      = NumericalPropagator(integrator)
initialState    = SpacecraftState(initialOrbit)
propagator.setInitialState(initialState)
# Add a force model
gravityField = HolmesFeatherstoneAttractionModel(ecef, GravityFieldFactory.getNormalizedProvider(6, 6))
propagator.addForceModel(gravityField)
# Add an attitude provider
attitude = NadirPointing(initialOrbit.getFrame(), earth)
propagator.addAttitudeProvider(attitude)
# Add the event detector for region entry/exit
propagator.addEventDetector(targetZoneDetector)

For the example with the numerical orbit propagator, I defined a nadir pointing law for the attitude mode. It is a classical attitude mode for Earth observation satellites. The attitude provider can also be added to the analytical orbit propagator using the same method.
Moreover, you can find also the force models that can be added to a numerical orbit propagator in the org.orekit.forces package.

After initializing the orbit propagator, the orbit propagation is performed by calling the propagate(target) method. Where target is the target epoch of the propagation.

When implementing you own handler for the FootprintOverlapDetector. The compiler will ask you to implement the eventOccurred(state, detector, increasing) method. This method is called each time the event is detected. For the FootprintOverlapDetector the increasing flag is equal to false when the region enters the Field Of View and true when the region leaves the Field Of View. The state parameter is the spacecraft state at the event detection epoch and the detector is the event detector related to the handler (i.e., FootprintOverlapDetector in this case). At detection epoch you can have the footprint of the field of view on ground by calling the getFootprint method of the fov. You can access the fov thanks to the detector parameter of the eventOccurred method. Indeed, FootprintOverlapDetector has a method getFOV().

That is the limit of my Python skills :sweat_smile:

Finally, the following posts can also help you: Post1, Post 2, and Post 3
Please note that all the examples above were writtent directly in the forum, i.e., without any IDE or compiler. So they may contain typo.

Best regards,
Bryan

2 Likes

Dear Bryan,

thanks a lot for this very detailed response!
I will work through it and might come back for follow up discussion if my lack of knowledge on orekit strikes again :slight_smile:

Cheers!