Skip to content
Snippets Groups Projects
Commit 9de44861 authored by Petrus Hyvönen's avatar Petrus Hyvönen
Browse files

Updated notebook for recent pandas updates

parent faf1eea7
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id: tags:
# Event Detectors in Orekit
%% Cell type:markdown id: tags:
## Authors
Lots of parts are directly from the orekit documentation on [propagation](https://www.orekit.org/site-orekit-10.1/architecture/propagation.html), with some updates, simplifications and Pythonification by Petrus Hyvönen, SSC
## Learning Goals
* *What are Event Detectors*: Why are these useful
* *How do I use Event Detectors*: How is it implemented in Orekit and Python
## Keywords
orekit, propagation, event detectors
%% Cell type:code id: tags:
``` python
%matplotlib inline
```
%% Cell type:markdown id: tags:
Initialize orkit and bring up the python-java interface
%% Cell type:code id: tags:
``` python
import orekit
vm = orekit.initVM()
```
%% Cell type:markdown id: tags:
Now set up the pointer to the orekit-data.zip file, using one of the helper files. The file should be in current directory if not specified otherwise.
%% Cell type:code id: tags:
``` python
from orekit.pyhelpers import setup_orekit_curdir, absolutedate_to_datetime
setup_orekit_curdir()
```
%% Cell type:markdown id: tags:
Now we are set up to import and use objects from the orekit library. Packages can be imported as they were native Python packages
%% Cell type:markdown id: tags:
# Event Detectors
_Before starting this introduction, please make sure you have refreshed the tutorials on Orbit Definition and Propagation._
%% Cell type:markdown id: tags:
The propagators in Orekit is part of an architecture that supports detecting certain discrete conditions that occur during the propagation. This can be that a spacecraft enters eclipse, becomes visible from a ground station, crosses the perigee or a number of other interesting things that may occur during the orbit.
This feature is activated by registering EventDetectors to the propagator. All proppagators in Orekit supports the EventDetector mechanism.
%% Cell type:markdown id: tags:
Users can define their own EventDetectors but there are also several predefined EventDetectors
already available, amongst which :
- a simple DateDetector, which is simply triggered at a predefined date, and can be reset to add new dates on the run (which is useful to set up delays starting when a previous event is been detected)
- an ElevationDetector, which is triggered at raising or setting time of a satellite with respect to a ground point, taking atmospheric refraction into account and either constant elevation or ground mask when threshold elevation is azimuth-dependent
- an ElevationExtremumDetector, which is triggered at maximum (or minimum) satellite elevation with respect to a ground point
- an AltitudeDetector which is triggered when satellite crosses a predefined altitude limit and can be used to compute easily operational forecasts
- a FieldOfViewDetector which is triggered when some target enters or exits a satellite sensor Field Of View (any shape),
- a CircularFieldOfViewDetector which is triggered when some target enters or exits a satellite sensor Field Of View (circular shape),
- a FootprintOverlapDetector which is triggered when a sensor Field Of View (any shape, even split in non-connected parts or containing holes) overlaps a geographic zone, which can be non-convex, split in different sub-zones, have holes, contain the pole,
- a GeographicZoneDetector, which is triggered when the spacecraft enters or leave a zone, which can be non-convex, split in different sub-zones, have holes, contain the pole,
- a GroundFieldOfViewDetector, which is triggered when the spacecraft enters or leave a ground based Field Of View, which can be non-convex, split in different sub-zones, have holes,
- an EclipseDetector, which is triggered when some body enters or exits the umbra or the penumbra of another occulting body,
- an ApsideDetector, which is triggered at apogee and perigee,
- a NodeDetector, which is triggered at ascending and descending nodes,
- a PositionAngleDetector, which is triggered when satellite angle on orbit crosses some value (works with either anomaly, latitude argument or longitude argument and with either true, eccentric or mean angles),
- LatitudeCrossingDetector, LatitudeExtremumDetector, LongitudeCrossingDetector, LongitudeExtremumDetector, which are triggered when satellite position with respect to central body reaches some predefined values,
- an AlignmentDetector, which is triggered when satellite and some body projected in the orbital plane have a specified angular separation (the term AlignmentDetector is clearly a misnomer as the angular separation may be non-zero),
- an AngularSeparationDetector, which is triggered when angular separation between satellite and some beacon as seen by an observer goes below a threshold. The beacon is typically the Sun, the observer is typically a ground station
- An EventShifter is also provided in order to slightly shift the events occurrences times. A typical use case is for handling operational delays before or after some physical event really occurs.
An EventSlopeFilter is provided when user is only interested in one kind of events that occurs in pairs like raising in the raising/setting pair for elevation detector, or eclipse entry in the entry/exit pair for eclipse detector. The filter does not simply ignore events after they have been detected, it filters them before they are located and hence save some computation time by not doing an accurate search for events that will ultimately be ignored.
An EventEnablingPredicateFilter is provided when user wants to filter out some events based on an external condition set up by a user-provided enabling predicate function. This allow for example to dynamically turn some events on and off during propagation or to set up some elaborate logic like triggering on elevation first time derivative (i.e. one elevation maximum) but only when elevation itself is above some threshold.
A BooleanDetector is provided to combine several other detectors with boolean operators and, or and not. This allows for example to detect when a satellite is both visible from a ground station and out of eclipse.
%% Cell type:code id: tags:
``` python
from org.orekit.orbits import KeplerianOrbit, PositionAngle
from org.orekit.propagation.analytical import KeplerianPropagator
from org.orekit.time import AbsoluteDate, TimeScalesFactory
from org.orekit.utils import Constants, IERSConventions
from org.orekit.frames import FramesFactory
from org.orekit.bodies import OneAxisEllipsoid, CelestialBodyFactory
```
%% Cell type:code id: tags:
``` python
from math import radians, degrees
import pandas as pd
```
%% Cell type:code id: tags:
``` python
utc = TimeScalesFactory.getUTC()
```
%% Cell type:markdown id: tags:
Let us do a small example, based on the orbit we used in the Propagation tutorial.
%% Cell type:code id: tags:
``` python
ra = 500 * 1000 # Apogee
rp = 400 * 1000 # Perigee
i = radians(87.0) # inclination
omega = radians(20.0) # perigee argument
raan = radians(10.0) # right ascension of ascending node
lv = radians(0.0) # True anomaly
epochDate = AbsoluteDate(2020, 1, 1, 0, 0, 00.000, utc)
initial_date = epochDate
a = (rp + ra + 2 * Constants.WGS84_EARTH_EQUATORIAL_RADIUS) / 2.0
e = 1.0 - (rp + Constants.WGS84_EARTH_EQUATORIAL_RADIUS) / a
## Inertial frame where the satellite is defined
inertialFrame = FramesFactory.getEME2000()
## Orbit construction as Keplerian
initialOrbit = KeplerianOrbit(a, e, i, omega, raan, lv,
PositionAngle.TRUE,
inertialFrame, epochDate, Constants.WGS84_EARTH_MU)
initialOrbit
```
%% Output
<KeplerianOrbit: Keplerian parameters: {a: 6828137.0; e: 0.007322641593160761; i: 86.99999999999999; pa: 20.0; raan: 10.0; v: 0.0;}>
%% Cell type:code id: tags:
``` python
propagator = KeplerianPropagator(initialOrbit)
```
%% Cell type:markdown id: tags:
## Adding Event Detectors
%% Cell type:markdown id: tags:
In the first example we create an EventDetector for eclipse, when the satellite is not illuminated by the Sun, and is in the full shadow of the Earth.
%% Cell type:code id: tags:
``` python
ITRF = FramesFactory.getITRF(IERSConventions.IERS_2010, True)
earth = OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
Constants.WGS84_EARTH_FLATTENING,
ITRF)
```
%% Cell type:code id: tags:
``` python
sun = CelestialBodyFactory.getSun()
sunRadius = 696000000.0
```
%% Cell type:code id: tags:
``` python
from org.orekit.propagation.events import EclipseDetector, EventsLogger
from org.orekit.propagation.events.handlers import ContinueOnEvent
```
%% Cell type:markdown id: tags:
The EclipseDetector class is documented at the [Orekit API](https://www.orekit.org/site-orekit-latest/apidocs/org/orekit/propagation/events/EclipseDetector.html) and will detect entering and leaving the full shadow (Umbra) or when some part of the Sun is covered by Earth (Penumbra).
In the detector, we can also set which EventHandler that we want to use, we can also write our own. In this case we use an EventHandler that will just let the propagator continue after an event has been detected.
%% Cell type:code id: tags:
``` python
eclipse_detector = EclipseDetector(sun, sunRadius, earth).withUmbra().withHandler(ContinueOnEvent())
```
%% Cell type:markdown id: tags:
There are several ways to collect these events when they happen, one of the ways is to use an Orekit EventsLogger that will store the events during the propagation.
%% Cell type:code id: tags:
``` python
logger = EventsLogger()
logged_detector = logger.monitorDetector(eclipse_detector)
```
%% Cell type:markdown id: tags:
We add the eclipse detector, together with the eventslogger to our propagator.
%% Cell type:code id: tags:
``` python
propagator.addEventDetector(logged_detector)
```
%% Cell type:markdown id: tags:
The propagation is executed in same way as in previous examples.
%% Cell type:code id: tags:
``` python
state = propagator.propagate(initial_date, initial_date.shiftedBy(3600.0 * 24))
state.getDate()
```
%% Output
<AbsoluteDate: 2020-01-02T00:00:00.000>
<AbsoluteDate: 2020-01-02T00:00:00.000Z>
%% Cell type:markdown id: tags:
Now we can fetch the events that the logger found.
%% Cell type:code id: tags:
``` python
events = logger.getLoggedEvents()
events.size()
```
%% Output
32
%% Cell type:markdown id: tags:
This is a code snippet that goes through the events and store them in a Pandas DataFrame that is very useful for handling tables in Python. In this, the dates are converted also to Python DateTime objects. Please note that if any further use of the data in Orekit is to be done, it is advisable also to save the Orekit AbsoluteDate.
%% Cell type:code id: tags:
``` python
start_time = None
result = pd.DataFrame()
result = []
for event in logger.getLoggedEvents():
if not event.isIncreasing():
start_time = event.getState().getDate()
elif start_time:
stop_time = event.getState().getDate()
result = result.append({"Start":absolutedate_to_datetime(start_time),
"Stop":absolutedate_to_datetime(stop_time),
"EclipseDuration": stop_time.durationFrom(start_time)/60},
ignore_index=True)
result.append({ "Start":absolutedate_to_datetime(start_time),
"Stop":absolutedate_to_datetime(stop_time),
"EclipseDuration": stop_time.durationFrom(start_time)/60})
start_time = None
result
result_df = pd.DataFrame.from_dict(result)
result_df
```
%% Output
EclipseDuration Start Stop
0 18.077653 2020-01-01 00:08:45.102790 2020-01-01 00:26:49.761988
1 18.068964 2020-01-01 01:42:22.923764 2020-01-01 02:00:27.061606
2 18.060506 2020-01-01 03:16:00.738934 2020-01-01 03:34:04.369298
3 18.052280 2020-01-01 04:49:38.548244 2020-01-01 05:07:41.685056
4 18.044287 2020-01-01 06:23:16.351637 2020-01-01 06:41:19.008874
5 18.036528 2020-01-01 07:56:54.149057 2020-01-01 08:14:56.340741
6 18.029003 2020-01-01 09:30:31.940450 2020-01-01 09:48:33.680649
7 18.021714 2020-01-01 11:04:09.725763 2020-01-01 11:22:11.028587
8 18.014660 2020-01-01 12:37:47.504944 2020-01-01 12:55:48.384546
9 18.007843 2020-01-01 14:11:25.277944 2020-01-01 14:29:25.748515
10 18.001263 2020-01-01 15:45:03.044716 2020-01-01 16:03:03.120486
11 17.994921 2020-01-01 17:18:40.805211 2020-01-01 17:36:40.500451
12 17.988817 2020-01-01 18:52:18.559383 2020-01-01 19:10:17.888399
13 17.982952 2020-01-01 20:25:56.307186 2020-01-01 20:43:55.284322
14 17.977327 2020-01-01 21:59:34.048572 2020-01-01 22:17:32.688210
15 17.971943 2020-01-01 23:33:11.783493 2020-01-01 23:51:10.100051
Start Stop EclipseDuration
0 2020-01-01 00:08:45.102790 2020-01-01 00:26:49.761988 18.077653
1 2020-01-01 01:42:22.923764 2020-01-01 02:00:27.061606 18.068964
2 2020-01-01 03:16:00.738934 2020-01-01 03:34:04.369298 18.060506
3 2020-01-01 04:49:38.548244 2020-01-01 05:07:41.685056 18.052280
4 2020-01-01 06:23:16.351637 2020-01-01 06:41:19.008874 18.044287
5 2020-01-01 07:56:54.149057 2020-01-01 08:14:56.340741 18.036528
6 2020-01-01 09:30:31.940450 2020-01-01 09:48:33.680649 18.029003
7 2020-01-01 11:04:09.725763 2020-01-01 11:22:11.028587 18.021714
8 2020-01-01 12:37:47.504944 2020-01-01 12:55:48.384546 18.014660
9 2020-01-01 14:11:25.277944 2020-01-01 14:29:25.748515 18.007843
10 2020-01-01 15:45:03.044716 2020-01-01 16:03:03.120486 18.001263
11 2020-01-01 17:18:40.805211 2020-01-01 17:36:40.500451 17.994921
12 2020-01-01 18:52:18.559383 2020-01-01 19:10:17.888399 17.988817
13 2020-01-01 20:25:56.307186 2020-01-01 20:43:55.284322 17.982952
14 2020-01-01 21:59:34.048572 2020-01-01 22:17:32.688210 17.977327
15 2020-01-01 23:33:11.783493 2020-01-01 23:51:10.100051 17.971943
%% Cell type:markdown id: tags:
# Exercise 1
%% Cell type:markdown id: tags:
In this case you are to calculate the ground station visibilities for the above orbit, with a minimum elevation of 5 degrees above the horizon. The detector to use is the [ElevationDetector](https://www.orekit.org/site-orekit-latest/apidocs/org/orekit/propagation/events/ElevationDetector.html). Create a similar pandas table as above of the start / stop time of the visibilities.
%% Cell type:code id: tags:
``` python
```
%% Cell type:markdown id: tags:
# Exercise 2
%% Cell type:markdown id: tags:
The satellite you are simulating does not have any batteries onboard, so it needs to be fully in sunlight to operate. Perform a calculation of when your ground station has visibility to the spacecraft, and that the spacecraft is in full sunlight.
Hint: Check the BooleanDetector, but there are other ways to do this too!
%% Cell type:code id: tags:
``` python
```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment