Event Finding¶
To use the events system, first load the relevent modules:
import godot.core.events as events
# optionally avoid verbose logging messages
import godot.core.util as util
util.suppressLogger()
Now we want to construct a frames system. We do this by creating a universe with the necessary frames pre-built. The universe is generated with a yaml file. Loading this text into the system is easy. We import the cosmos module, and the yaml module and then construct our universe.
import godot.cosmos as cosmos
import ruamel.yaml as yaml
uniConfig = cosmos.util.load_yaml('universe.yml')
uni = cosmos.Universe(uniConfig)
we want to find the visibility periods of the Sun and Moon from New Norcia, so we creat a Python function for the elevation from each:
import godot.core.astro as astro
def moonElev( epo ):
x = uni.frames.vector3('New_Norcia', 'Moon', 'New_Norcia', epo)
return astro.sphericalFromCart(x)[2]
def sunElev( epo ):
x = uni.frames.vector3('New_Norcia', 'Sun', 'New_Norcia', epo)
return astro.sphericalFromCart(x)[2]
This is only approximate, because it does not consider the visibility mask from New Norcia or the finite angular shape of the bodies, but it is good enough for this test. Users should feel free to adapt the functions to make the computation more accurate. Now we can compute the event interval sets. There are a few numerical values to be selected for this process.
First choose the span of the search:
import godot.core.tempo as tempo
epoch1 = tempo.parseEpoch("2018-06-05T14:00:00.000 UTC")
epoch2 = tempo.parseEpoch("2018-06-14T14:00:00.000 UTC")
rng = tempo.EpochRange( epoch1, epoch2 )
We set the tolerance for the event search in the independent variable (time) in seconds.
xtol = 1e-9
We set the step size for the search. This should be so that there is at most one maximum or minimum of the function in every step. For visibility it is okay to set this anywhere up to 0.5 days
step = 43200.0
Now we generate a grid of epochs
grid = rng.createGrid(step)
Finally, we set an epsilon for computing function derivatives by numerical differences to help with the search
eps = 1e-6
Now we can compute the event intervals when the bodies are visible from New Norcia
moon_visible = events.generateEventIntervalSet( moonElev, eps, grid, xtol )
print(moon_visible)
sun_visible = events.generateEventIntervalSet( sunElev, eps, grid, xtol )
print(sun_visible)
Suppose we were astronomers and wanted to view Mars from a telescope. To plan our observations we want to find the times when our target (say, Mars) is visible but the Sun and Moon are below the horizon. This is easy.
First compute the visibility periods for Mars:
def marsElev( epo ):
x = uni.frames.vector3('New_Norcia', 'MarsBarycenter', 'New_Norcia', epo)
return astro.sphericalFromCart(x)[2]
mars_visible = events.generateEventIntervalSet( marsElev, eps, grid, xtol )
print(mars_visible)
We can combine event interval sets to find the times when at least one of the confitions are true:
sun_or_moon_visible = events.merge( [ sun_visible , moon_visible ])
print(sun_or_moon_visible)
Or when all the conditions are true:
sun_and_moon_visible = events.overlap( [ sun_visible , moon_visible ])
print(sun_and_moon_visible)
We can also take the complement. Now we want to find the times when the Sun and Moon are not visible
no_sun_or_moon_visible = sun_or_moon_visible.complement()
print(sun_or_moon_visible)
and find the overlap of that with the Mars visibility times.
mars_visible_without_sun_and_moon = events.overlap( [ no_sun_or_moon_visible , mars_visible ])
print("Mars Visible without Sun and Moon:")
print(mars_visible_without_sun_and_moon)
Of course the whole computation could be made more complex quite easily. Suppose you had a Mars orbiter and wanted to ensure it was visible from New Norcia, or you wanted to compute times when you though Mars was goind to be hit by an Asteroid, or you wanted to observe Phobos or Deimos. All of these computations could be done in the same way and combined with each other to find the interval you wanted.