astronoby 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/CHANGELOG.md +235 -0
- data/README.md +19 -1
- data/UPGRADING.md +270 -0
- data/docs/README.md +105 -16
- data/docs/altitude_crossings.md +92 -0
- data/docs/angles.md +1 -0
- data/docs/configuration.md +28 -17
- data/docs/coordinates.md +72 -12
- data/docs/deep_sky_bodies.md +46 -1
- data/docs/ephem.md +5 -2
- data/docs/equinoxes_solstices_times.md +4 -3
- data/docs/glossary.md +99 -1
- data/docs/iers.md +40 -0
- data/docs/instant.md +33 -21
- data/docs/lunar_eclipses.md +208 -0
- data/docs/lunar_observation.md +87 -0
- data/docs/moon_phases.md +4 -1
- data/docs/observer.md +20 -6
- data/docs/planetary_phenomena.md +78 -0
- data/docs/reference_frames.md +192 -34
- data/docs/rise_transit_set_times.md +6 -4
- data/docs/solar_system_bodies.md +26 -4
- data/docs/twilight_times.md +43 -24
- data/lib/astronoby/angle.rb +63 -2
- data/lib/astronoby/angles/dms.rb +18 -1
- data/lib/astronoby/angles/hms.rb +14 -1
- data/lib/astronoby/angular_velocity.rb +21 -0
- data/lib/astronoby/bodies/deep_sky_object.rb +6 -1
- data/lib/astronoby/bodies/deep_sky_object_position.rb +35 -38
- data/lib/astronoby/bodies/earth.rb +7 -44
- data/lib/astronoby/bodies/jupiter.rb +10 -0
- data/lib/astronoby/bodies/mars.rb +10 -0
- data/lib/astronoby/bodies/mercury.rb +10 -0
- data/lib/astronoby/bodies/moon.rb +158 -32
- data/lib/astronoby/bodies/neptune.rb +10 -0
- data/lib/astronoby/bodies/saturn.rb +10 -0
- data/lib/astronoby/bodies/solar_system_body.rb +240 -61
- data/lib/astronoby/bodies/sun.rb +79 -4
- data/lib/astronoby/bodies/uranus.rb +10 -0
- data/lib/astronoby/bodies/venus.rb +10 -0
- data/lib/astronoby/body.rb +6 -0
- data/lib/astronoby/cache.rb +13 -0
- data/lib/astronoby/center.rb +84 -0
- data/lib/astronoby/constants.rb +1 -2
- data/lib/astronoby/constellation.rb +9 -1
- data/lib/astronoby/constellations/data.rb +1 -1
- data/lib/astronoby/coordinates/ecliptic.rb +10 -1
- data/lib/astronoby/coordinates/equatorial.rb +79 -13
- data/lib/astronoby/coordinates/geodetic.rb +102 -0
- data/lib/astronoby/coordinates/horizontal.rb +13 -1
- data/lib/astronoby/delta_t.rb +44 -0
- data/lib/astronoby/distance.rb +35 -0
- data/lib/astronoby/duration.rb +116 -0
- data/lib/astronoby/earth_rotation.rb +70 -0
- data/lib/astronoby/equinox_solstice.rb +31 -8
- data/lib/astronoby/errors.rb +11 -0
- data/lib/astronoby/events/altitude_crossing.rb +29 -0
- data/lib/astronoby/events/altitude_crossing_calculator.rb +511 -0
- data/lib/astronoby/events/altitude_extreme.rb +31 -0
- data/lib/astronoby/events/conjunction.rb +51 -0
- data/lib/astronoby/events/conjunction_opposition_calculator.rb +84 -0
- data/lib/astronoby/events/extremum_calculator.rb +23 -176
- data/lib/astronoby/events/greatest_elongation.rb +58 -0
- data/lib/astronoby/events/greatest_elongation_calculator.rb +56 -0
- data/lib/astronoby/events/lunar_eclipse.rb +111 -0
- data/lib/astronoby/events/lunar_eclipse_calculator.rb +397 -0
- data/lib/astronoby/events/lunar_eclipse_geometry.rb +115 -0
- data/lib/astronoby/events/lunar_eclipse_phase.rb +45 -0
- data/lib/astronoby/events/lunar_eclipse_visibility.rb +296 -0
- data/lib/astronoby/events/opposition.rb +19 -0
- data/lib/astronoby/events/rise_transit_set_calculator.rb +9 -13
- data/lib/astronoby/events/rise_transit_set_event.rb +12 -1
- data/lib/astronoby/events/rise_transit_set_events.rb +12 -1
- data/lib/astronoby/events/twilight_calculator.rb +37 -147
- data/lib/astronoby/events/twilight_event.rb +24 -6
- data/lib/astronoby/events/twilight_events.rb +26 -6
- data/lib/astronoby/extremum_finder.rb +148 -0
- data/lib/astronoby/horizon.rb +40 -0
- data/lib/astronoby/horizontal_transformation.rb +112 -0
- data/lib/astronoby/instant.rb +56 -16
- data/lib/astronoby/libration.rb +25 -0
- data/lib/astronoby/mean_obliquity.rb +8 -0
- data/lib/astronoby/moon_orientation_ephemeris.rb +69 -0
- data/lib/astronoby/moon_physical_ephemeris.rb +263 -0
- data/lib/astronoby/nutation.rb +10 -20
- data/lib/astronoby/observer.rb +67 -49
- data/lib/astronoby/orientation.rb +107 -0
- data/lib/astronoby/position.rb +16 -0
- data/lib/astronoby/precession.rb +62 -61
- data/lib/astronoby/reference_frame.rb +80 -9
- data/lib/astronoby/reference_frames/apparent.rb +43 -12
- data/lib/astronoby/reference_frames/astrometric.rb +14 -1
- data/lib/astronoby/reference_frames/geometric.rb +7 -1
- data/lib/astronoby/reference_frames/mean_of_date.rb +19 -1
- data/lib/astronoby/reference_frames/teme.rb +159 -0
- data/lib/astronoby/reference_frames/topocentric.rb +36 -4
- data/lib/astronoby/refraction.rb +26 -5
- data/lib/astronoby/root_finder.rb +90 -0
- data/lib/astronoby/rotation.rb +49 -0
- data/lib/astronoby/time/greenwich_apparent_sidereal_time.rb +19 -8
- data/lib/astronoby/time/greenwich_mean_sidereal_time.rb +44 -5
- data/lib/astronoby/time/greenwich_sidereal_time.rb +21 -0
- data/lib/astronoby/time/local_apparent_sidereal_time.rb +21 -0
- data/lib/astronoby/time/local_mean_sidereal_time.rb +21 -0
- data/lib/astronoby/time/local_sidereal_time.rb +24 -0
- data/lib/astronoby/time/sidereal_time.rb +23 -1
- data/lib/astronoby/true_obliquity.rb +4 -0
- data/lib/astronoby/util/maths.rb +8 -0
- data/lib/astronoby/util/time.rb +0 -497
- data/lib/astronoby/vector.rb +10 -0
- data/lib/astronoby/velocity.rb +39 -0
- data/lib/astronoby/version.rb +1 -1
- data/lib/astronoby.rb +30 -0
- metadata +80 -5
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Lunar Observation
|
|
2
|
+
|
|
3
|
+
Beyond phases and apsides, Astronoby exposes the quantities lunar observers rely on to describe the Moon's appearance and orientation in the sky: its libration, the position angle of its rotation axis, the position angle of its bright limb, and the parallactic angle. By default they follow Jean Meeus, *Astronomical Algorithms*, 2nd edition, and are derived from the Moon's and the Sun's apparent positions, which Astronoby already computes from the ephemeris. The libration and the position angle of the axis can additionally use the integrated lunar orientation from a JPL DE kernel to reach arcsecond accuracy, as described below.
|
|
4
|
+
|
|
5
|
+
All of these are available directly on a `Astronoby::Moon` instance.
|
|
6
|
+
|
|
7
|
+
```rb
|
|
8
|
+
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
9
|
+
instant = Astronoby::Instant.from_time(Time.utc(2025, 3, 1))
|
|
10
|
+
moon = Astronoby::Moon.new(instant: instant, ephem: ephem)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Libration
|
|
14
|
+
|
|
15
|
+
Libration is the apparent oscillation that lets an observer on Earth see slightly more than half of the lunar surface over time. `Astronoby::Moon#libration` returns a `Astronoby::Libration` value object holding the total (optical plus physical) libration in longitude and latitude, both as `Astronoby::Angle` objects. A positive longitude exposes more of the Moon's eastern limb (Mare Crisium side); a positive latitude exposes more of its northern limb.
|
|
16
|
+
|
|
17
|
+
```rb
|
|
18
|
+
libration = moon.libration
|
|
19
|
+
|
|
20
|
+
libration.longitude.str(:dms) # => "-2° 5′ 4.4219″"
|
|
21
|
+
libration.latitude.str(:dms) # => "+0° 28′ 45.9616″"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
By default this is the analytic optical plus physical libration from Meeus's series. Compared with the lunar orientation integrated in the JPL DE solution (as reported by JPL Horizons), the libration in longitude and the position angle of the axis agree to within a few arcseconds, while the libration in latitude agrees to about 0.02 degrees. That residual is the well known difference between the mean lunar equator used by the classical Meeus method and the DE mean-Earth frame. It is eliminated by loading an orientation kernel.
|
|
25
|
+
|
|
26
|
+
## Arcsecond accuracy with an orientation kernel
|
|
27
|
+
|
|
28
|
+
For the libration and the position angle of the axis, you can reach the accuracy of JPL Horizons, Skyfield and IMCCE by also loading a binary PCK lunar orientation kernel, such as `moon_pa_de440_200625.bpc`, which carries the integrated DE440 orientation of the Moon. Load it once with `Astronoby::Orientation` and pass it to the Moon alongside the ephemeris.
|
|
29
|
+
|
|
30
|
+
```rb
|
|
31
|
+
ephem = Astronoby::Ephem.load("de440.bsp")
|
|
32
|
+
orientation = Astronoby::Orientation.load("moon_pa_de440_200625.bpc")
|
|
33
|
+
|
|
34
|
+
moon = Astronoby::Moon.new(instant: instant, ephem: ephem, orientation: orientation)
|
|
35
|
+
|
|
36
|
+
moon.libration.latitude.str(:dms) # => "+0° 27′ 27.7258″"
|
|
37
|
+
moon.position_angle_of_axis.str(:dms) # => "-21° 48′ 32.9625″"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The libration is then computed as the selenographic longitude and latitude of the sub-Earth point in the Moon's mean-Earth body-fixed frame, and matches JPL Horizons to better than an arcsecond. Without an orientation kernel the Moon keeps using the analytic method, so this is an opt-in refinement, not a requirement. The `bright_limb_position_angle` and `parallactic_angle` are unaffected and do not need a kernel.
|
|
41
|
+
|
|
42
|
+
If you do not already have the kernel, Astronoby can download it for you.
|
|
43
|
+
|
|
44
|
+
```rb
|
|
45
|
+
Astronoby::Orientation.download(
|
|
46
|
+
name: "moon_pa_de440_200625.bpc",
|
|
47
|
+
target: "moon_pa_de440_200625.bpc"
|
|
48
|
+
)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Position angle of the axis
|
|
52
|
+
|
|
53
|
+
`Astronoby::Moon#position_angle_of_axis` returns the position angle of the Moon's axis of rotation, the angle of the projection of the lunar north pole, measured eastward from the north point of the disk. It is returned as an `Astronoby::Angle`.
|
|
54
|
+
|
|
55
|
+
```rb
|
|
56
|
+
moon.position_angle_of_axis.str(:dms) # => "-21° 48′ 46.657″"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Position angle of the bright limb
|
|
60
|
+
|
|
61
|
+
`Astronoby::Moon#bright_limb_position_angle` returns the position angle of the midpoint of the illuminated limb, measured eastward from the north point of the disk, between 0 and 360 degrees. It is a geocentric quantity computed from the apparent equatorial coordinates of the Moon and the Sun, and it points towards the Sun, since the bright limb is the limb facing the Sun.
|
|
62
|
+
|
|
63
|
+
```rb
|
|
64
|
+
moon.bright_limb_position_angle.str(:dms) # => "+248° 1′ 57.9467″"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Parallactic angle
|
|
68
|
+
|
|
69
|
+
The parallactic angle is the angle at the Moon between the direction of the north celestial pole and the direction of the observer's zenith. Unlike the previous quantities it depends on the observer, so it is computed from the topocentric place, where lunar parallax is significant. `Astronoby::Moon#parallactic_angle` takes an observer and returns an `Astronoby::Angle`.
|
|
70
|
+
|
|
71
|
+
```rb
|
|
72
|
+
observer = Astronoby::Observer.new(
|
|
73
|
+
latitude: Astronoby::Angle.from_degrees(48.8566),
|
|
74
|
+
longitude: Astronoby::Angle.from_degrees(2.3522)
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
moon.parallactic_angle(observer: observer).str(:dms) # => "+11° 42′ 47.1246″"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## See also
|
|
81
|
+
|
|
82
|
+
- [Solar System Bodies](solar_system_bodies.md) - for the Moon's other properties
|
|
83
|
+
- [Moon Phases](moon_phases.md) - for lunar phase events
|
|
84
|
+
- [Lunar Eclipses](lunar_eclipses.md) - for eclipses of the Moon
|
|
85
|
+
- [Observer](observer.md) - for setting up observation locations
|
|
86
|
+
- [Reference Frames](reference_frames.md) - for coordinate systems
|
|
87
|
+
- [Angles](angles.md) - for working with angular measurements
|
data/docs/moon_phases.md
CHANGED
|
@@ -69,11 +69,14 @@ phases.each { puts "#{_1.phase}: #{_1.time}" }
|
|
|
69
69
|
# new_moon: 2024-05-08 03:21:56 UTC
|
|
70
70
|
# first_quarter: 2024-05-15 11:48:02 UTC
|
|
71
71
|
# full_moon: 2024-05-23 13:53:12 UTC
|
|
72
|
-
# last_quarter: 2024-05-30 17:12:
|
|
72
|
+
# last_quarter: 2024-05-30 17:12:42 UTC
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
## See also
|
|
76
|
+
|
|
76
77
|
- [Twilight Times](twilight_times.md) - for sun-related events
|
|
77
78
|
- [Rise, Transit and Set Times](rise_transit_set_times.md) - for moon events
|
|
79
|
+
- [Lunar Observation](lunar_observation.md) - for libration, axis and limb angles
|
|
80
|
+
- [Lunar Eclipses](lunar_eclipses.md) - for eclipses of the Moon
|
|
78
81
|
- [Solar System Bodies](solar_system_bodies.md) - for moon object details
|
|
79
82
|
- [Ephemerides](ephem.md) - for data sources
|
data/docs/observer.md
CHANGED
|
@@ -6,19 +6,31 @@ events computed by Astronoby are location and date based.
|
|
|
6
6
|
## Initialization
|
|
7
7
|
|
|
8
8
|
The two required key arguments to instantiate an observer are:
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
- `latitude` (`Astronoby::Angle`): the angle from the equator to the observer,
|
|
10
11
|
from 90° to -90°, with positive angles for the Northern Hemisphere.
|
|
11
|
-
|
|
12
|
+
- `longitude` (`Astronoby::Angle`): the angle from the Greenwich meridian to the
|
|
12
13
|
observer, from 180° to -180°, with positive angles eastward of the Greenwich
|
|
13
14
|
meridian.
|
|
14
15
|
|
|
15
|
-
Latitude and longitude are defined according to the [World Geodetic System]
|
|
16
|
-
In other words, they are the same as those used for the [GPS].
|
|
16
|
+
Latitude and longitude are defined according to the [World Geodetic System]
|
|
17
|
+
(WGS-84). In other words, they are the same as those used for the [GPS].
|
|
18
|
+
|
|
19
|
+
Internally, the observer's geodetic coordinates are converted to geocentric
|
|
20
|
+
Cartesian coordinates in the **International Terrestrial Reference System
|
|
21
|
+
(ITRS)**, also known as Earth-Centered Earth-Fixed (ECEF). These are then
|
|
22
|
+
rotated into the celestial frame using Earth rotation (GAST) via
|
|
23
|
+
`Astronoby::EarthRotation` and IERS polar motion corrections. See
|
|
24
|
+
[Reference Frames](reference_frames.md) for details.
|
|
25
|
+
|
|
26
|
+
The reverse conversion (ECEF → geodetic) is available via
|
|
27
|
+
[`Astronoby::Coordinates::Geodetic.from_ecef`][Coordinates page].
|
|
17
28
|
|
|
18
29
|
It is also possible to give the following optional key arguments:
|
|
19
|
-
|
|
30
|
+
|
|
31
|
+
- `elevation` (`Astronoby::Distance`): the distance above or below the average
|
|
20
32
|
sea level
|
|
21
|
-
|
|
33
|
+
- `utc_offset`: local time difference with UTC. Check the [timezone specifiers]
|
|
22
34
|
for the format.
|
|
23
35
|
|
|
24
36
|
```rb
|
|
@@ -57,8 +69,10 @@ observer1 == observer2
|
|
|
57
69
|
[GPS]: https://en.wikipedia.org/wiki/GPS
|
|
58
70
|
[timezone specifiers]: https://ruby-doc.org/3.4.1/Time.html#class-Time-label-Timezone+Specifiers
|
|
59
71
|
[Angles page]: angles.md
|
|
72
|
+
[Coordinates page]: coordinates.md#geodetic
|
|
60
73
|
|
|
61
74
|
## See also
|
|
75
|
+
|
|
62
76
|
- [Angles](angles.md) - for working with latitude and longitude
|
|
63
77
|
- [Coordinates](coordinates.md) - for understanding position systems
|
|
64
78
|
- [Reference Frames](reference_frames.md) - for topocentric calculations
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Planetary Phenomena
|
|
2
|
+
|
|
3
|
+
Astronoby computes the classic planetary phenomena relative to the Sun: conjunctions, oppositions, and greatest elongations. They are all defined in the apparent geocentric ecliptic frame of date.
|
|
4
|
+
|
|
5
|
+
The available phenomena depend on the planet. Inferior planets (Mercury and Venus) have conjunctions and greatest elongations. Superior planets (Mars to Neptune) have conjunctions and oppositions. Requesting a phenomenon that cannot occur for a given body raises an `Astronoby::UnsupportedEventError`.
|
|
6
|
+
|
|
7
|
+
Each method takes an ephemeris and a time range, and returns the events found within that range.
|
|
8
|
+
|
|
9
|
+
## Oppositions
|
|
10
|
+
|
|
11
|
+
An opposition is the instant when a superior planet and the Sun have opposite apparent ecliptic longitudes (a difference of 180 degrees), so the planet is opposite the Sun in the sky.
|
|
12
|
+
|
|
13
|
+
```rb
|
|
14
|
+
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
15
|
+
|
|
16
|
+
opposition = Astronoby::Mars.opposition_events(
|
|
17
|
+
ephem: ephem,
|
|
18
|
+
start_time: Time.utc(2025, 1, 1),
|
|
19
|
+
end_time: Time.utc(2026, 1, 1)
|
|
20
|
+
).first
|
|
21
|
+
|
|
22
|
+
opposition.instant.to_time # => 2025-01-16 02:38:35 UTC
|
|
23
|
+
opposition.body # => Astronoby::Mars
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Conjunctions
|
|
27
|
+
|
|
28
|
+
A conjunction is the instant when a planet and the Sun share the same apparent ecliptic longitude. Each conjunction is classified as inferior (the planet passes between the Earth and the Sun) or superior (the planet passes behind the Sun), determined from the apparent distances. Superior planets only ever have superior conjunctions.
|
|
29
|
+
|
|
30
|
+
```rb
|
|
31
|
+
conjunction = Astronoby::Venus.conjunction_events(
|
|
32
|
+
ephem: ephem,
|
|
33
|
+
start_time: Time.utc(2025, 1, 1),
|
|
34
|
+
end_time: Time.utc(2026, 1, 1)
|
|
35
|
+
).first
|
|
36
|
+
|
|
37
|
+
conjunction.instant.to_time # => 2025-03-23 01:07:30 UTC
|
|
38
|
+
conjunction.inferior? # => true
|
|
39
|
+
conjunction.superior? # => false
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Greatest elongations
|
|
43
|
+
|
|
44
|
+
A greatest elongation is the instant when an inferior planet reaches its maximum apparent angular separation from the Sun. It is eastern when the planet is east of the Sun (visible in the evening sky) and western when it is west of the Sun (visible in the morning sky).
|
|
45
|
+
|
|
46
|
+
```rb
|
|
47
|
+
elongation = Astronoby::Mercury.greatest_elongation_events(
|
|
48
|
+
ephem: ephem,
|
|
49
|
+
start_time: Time.utc(2025, 1, 1),
|
|
50
|
+
end_time: Time.utc(2026, 1, 1)
|
|
51
|
+
).first
|
|
52
|
+
|
|
53
|
+
elongation.instant.to_time # => 2025-03-08 06:09:18 UTC
|
|
54
|
+
elongation.angle.degrees # => 18.25
|
|
55
|
+
elongation.eastern? # => true
|
|
56
|
+
elongation.western? # => false
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Elongation of a body
|
|
60
|
+
|
|
61
|
+
The elongation of any Solar System body, the apparent Sun-Earth-body angle, is also available directly on a body instance, along with the side of the Sun it lies on.
|
|
62
|
+
|
|
63
|
+
```rb
|
|
64
|
+
instant = Astronoby::Instant.from_time(Time.utc(2025, 7, 14))
|
|
65
|
+
venus = Astronoby::Venus.new(instant: instant, ephem: ephem)
|
|
66
|
+
|
|
67
|
+
venus.elongation.degrees # => 41.47
|
|
68
|
+
venus.eastern? # => false
|
|
69
|
+
venus.western? # => true
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## See also
|
|
73
|
+
|
|
74
|
+
- [Solar System Bodies](solar_system_bodies.md) - for planets and their properties
|
|
75
|
+
- [Equinoxes and Solstices Times](equinoxes_solstices_times.md) - for solar events
|
|
76
|
+
- [Moon Phases](moon_phases.md) - for lunar events
|
|
77
|
+
- [Reference Frames](reference_frames.md) - for coordinate systems
|
|
78
|
+
- [Ephemerides](ephem.md) - for data sources
|
data/docs/reference_frames.md
CHANGED
|
@@ -3,28 +3,42 @@
|
|
|
3
3
|
A given body at a given time can be perceived at different positions, depending
|
|
4
4
|
on the reference frame and the corrections applied.
|
|
5
5
|
|
|
6
|
-
Astronoby provides five reference frames for
|
|
6
|
+
Astronoby provides five reference frames for celestial bodies, forming a
|
|
7
|
+
transformation chain:
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
```
|
|
10
|
+
Geometric (BCRS)
|
|
11
|
+
→ Astrometric (GCRS)
|
|
12
|
+
→ Mean of date
|
|
13
|
+
→ Apparent
|
|
14
|
+
→ Topocentric
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Each step applies physical corrections to move closer to what an observer
|
|
18
|
+
actually sees. The standard reference systems used follow the IAU/IERS
|
|
19
|
+
conventions (see [Standard reference systems](#standard-reference-systems)
|
|
20
|
+
below).
|
|
21
|
+
|
|
22
|
+
A separate **TEME** (True Equator, Mean Equinox) frame is also available for
|
|
23
|
+
satellite tracking. See [TEME](#teme) below.
|
|
13
24
|
|
|
14
25
|
All reference frames provide this common interface:
|
|
15
26
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
- `#position`: Vector of position as x,y,z `Astronoby::Distance` objects
|
|
28
|
+
- `#velocity`: Vector of velocity as x,y,z `Astronoby::Velocity` objects
|
|
29
|
+
- `#distance`: Distance from the centre (`Astronoby::Distance`)
|
|
30
|
+
- `#center`: The centre the frame is relative to (`Astronoby::Center`)
|
|
31
|
+
- `#equatorial`: Equatorial coordinates (`Astronoby::Coordinates::Equatorial`)
|
|
32
|
+
- `#ecliptic`: Ecliptic coordinates (`Astronoby::Coordinates::Ecliptic`)
|
|
33
|
+
- `#separation_from(other)`: Angular separation to another frame
|
|
34
|
+
(`Astronoby::Angle`)
|
|
21
35
|
|
|
22
36
|
## Geometric
|
|
23
37
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
38
|
+
The geometric frame corresponds to the **Barycentric Celestial Reference System
|
|
39
|
+
(BCRS)**, centered on the Solar System barycentre, with axes aligned to the
|
|
40
|
+
**International Celestial Reference System (ICRS)**. It is the raw position
|
|
41
|
+
read from the ephemeris file, with no corrections applied.
|
|
28
42
|
|
|
29
43
|
```rb
|
|
30
44
|
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
@@ -36,7 +50,7 @@ geometric = moon.geometric
|
|
|
36
50
|
# => #<Astronoby::Geometric:0x000000011e7ffd40
|
|
37
51
|
|
|
38
52
|
geometric.distance.au
|
|
39
|
-
# => 1.
|
|
53
|
+
# => 1.0095091267969827
|
|
40
54
|
|
|
41
55
|
geometric.equatorial.right_ascension.str(:hms, precision: 0)
|
|
42
56
|
# => "20h 13m 52s"
|
|
@@ -44,11 +58,11 @@ geometric.equatorial.right_ascension.str(:hms, precision: 0)
|
|
|
44
58
|
|
|
45
59
|
## Astrometric
|
|
46
60
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
61
|
+
The astrometric frame corresponds to the **Geocentric Celestial Reference System
|
|
62
|
+
(GCRS)**, centered on the Earth's centre, with axes still aligned to the ICRS.
|
|
63
|
+
It is obtained by subtracting the Earth's barycentric position from the target's
|
|
64
|
+
light-time-corrected barycentric position. All subsequent frames are also
|
|
65
|
+
Earth-centered.
|
|
52
66
|
|
|
53
67
|
```rb
|
|
54
68
|
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
@@ -67,10 +81,13 @@ astrometric.equatorial.right_ascension.str(:hms, precision: 0)
|
|
|
67
81
|
|
|
68
82
|
## Mean of date
|
|
69
83
|
|
|
70
|
-
This
|
|
71
|
-
|
|
72
|
-
|
|
84
|
+
This frame is referred to the **mean equator and mean equinox of the date**. It
|
|
85
|
+
is obtained by applying the precession-bias matrix to the geocentric ICRS
|
|
86
|
+
position, rotating it from the ICRS axes to the mean pole and equinox at the
|
|
87
|
+
given instant.
|
|
73
88
|
|
|
89
|
+
Astronoby uses the **IAU 2006 precession** model in its Fukushima-Williams
|
|
90
|
+
four-angle parameterization, which includes the ICRS-to-J2000 frame bias.
|
|
74
91
|
|
|
75
92
|
```rb
|
|
76
93
|
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
@@ -86,11 +103,17 @@ mean_of_date.equatorial.right_ascension.str(:hms, precision: 0)
|
|
|
86
103
|
|
|
87
104
|
## Apparent
|
|
88
105
|
|
|
89
|
-
This
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
106
|
+
This frame is referred to the **true equator and true equinox of the date**. It
|
|
107
|
+
represents the position of a celestial object as seen from the centre of the
|
|
108
|
+
Earth. The following corrections are applied to the astrometric position:
|
|
109
|
+
|
|
110
|
+
- **Aberration**: relativistic stellar aberration due to Earth's velocity
|
|
111
|
+
(Explanatory Supplement, Ch. 7.2.3)
|
|
112
|
+
- **Precession**: IAU 2006 Fukushima-Williams precession-bias matrix
|
|
113
|
+
- **Nutation**: IAU 2000B 77-term nutation model
|
|
114
|
+
|
|
115
|
+
The combined N \* PB matrix rotates the aberration-corrected GCRS position into
|
|
116
|
+
the true equator and equinox frame of the date.
|
|
94
117
|
|
|
95
118
|
```rb
|
|
96
119
|
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
@@ -106,10 +129,16 @@ apparent.equatorial.right_ascension.str(:hms, precision: 0)
|
|
|
106
129
|
|
|
107
130
|
## Topocentric
|
|
108
131
|
|
|
109
|
-
This
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
132
|
+
This is the final frame in the chain, providing the position of a celestial body
|
|
133
|
+
as seen from a specific location on Earth's surface. It can only be produced
|
|
134
|
+
given an observer (`Astronoby::Observer`). It provides an additional set of
|
|
135
|
+
coordinates: horizontal (`Astronoby::Coordinates::Horizontal`).
|
|
136
|
+
|
|
137
|
+
To go from the apparent frame (true equator and equinox) to the topocentric
|
|
138
|
+
frame, the observer's position must be transformed from the **International
|
|
139
|
+
Terrestrial Reference System (ITRS)** into the same true-equinox frame. This is
|
|
140
|
+
done by applying the **IERS polar motion matrix** (W) followed by the Earth
|
|
141
|
+
rotation via **Greenwich Apparent Sidereal Time (GAST)**.
|
|
113
142
|
|
|
114
143
|
```rb
|
|
115
144
|
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
@@ -124,12 +153,141 @@ moon = Astronoby::Moon.new(ephem: ephem, instant: instant)
|
|
|
124
153
|
topocentric = moon.observed_by(observer)
|
|
125
154
|
|
|
126
155
|
topocentric.horizontal.azimuth.str(:dms, precision: 0)
|
|
127
|
-
# => "+90° 14′
|
|
156
|
+
# => "+90° 14′ 24″"
|
|
128
157
|
```
|
|
129
158
|
|
|
130
159
|
You can learn more about observers on the [Observer page].
|
|
131
160
|
|
|
161
|
+
## Angular separation
|
|
162
|
+
|
|
163
|
+
Any two frames can be compared with `#separation_from`, which returns the
|
|
164
|
+
angular separation (an `Astronoby::Angle`, between 0° and 180°) between the two
|
|
165
|
+
targets' directions as seen from their shared centre.
|
|
166
|
+
|
|
167
|
+
The two frames may belong to different kinds of objects (a Solar System body
|
|
168
|
+
and a deep-sky object, for example) as long as they are in the same reference
|
|
169
|
+
frame and at the same instant. Otherwise the separation is not physically
|
|
170
|
+
meaningful and an `Astronoby::IncompatibleArgumentsError` is raised.
|
|
171
|
+
|
|
172
|
+
```rb
|
|
173
|
+
ephem = Astronoby::Ephem.load("inpop19a.bsp")
|
|
174
|
+
instant = Astronoby::Instant.from_time(Time.utc(2020, 12, 21, 18))
|
|
175
|
+
|
|
176
|
+
jupiter = Astronoby::Jupiter.new(ephem: ephem, instant: instant)
|
|
177
|
+
saturn = Astronoby::Saturn.new(ephem: ephem, instant: instant)
|
|
178
|
+
|
|
179
|
+
# The 2020 "Great Conjunction", the closest since 1623
|
|
180
|
+
separation = jupiter.apparent.separation_from(saturn.apparent)
|
|
181
|
+
|
|
182
|
+
separation.str(:dms, precision: 0)
|
|
183
|
+
# => "+0° 6′ 6″"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## TEME
|
|
187
|
+
|
|
188
|
+
The **TEME (True Equator, Mean Equinox)** frame is the output frame of the
|
|
189
|
+
SGP4/SDP4 satellite orbit propagators. Unlike the five frames above, TEME is
|
|
190
|
+
not part of the celestial body chain — it is constructed directly from SGP4
|
|
191
|
+
output and provides its own conversion methods.
|
|
192
|
+
|
|
193
|
+
TEME shares the true equator with the apparent frame but uses the mean equinox
|
|
194
|
+
(tracked by GMST) instead of the true equinox (tracked by GAST). The
|
|
195
|
+
difference between the two is the equation of the equinoxes.
|
|
196
|
+
|
|
197
|
+
### Conversions
|
|
198
|
+
|
|
199
|
+
`Astronoby::Teme` provides three conversion methods:
|
|
200
|
+
|
|
201
|
+
- `#to_ecef` - ECEF position and velocity, using R₃(GMST) and the ω×r
|
|
202
|
+
velocity correction. The returned `EcefCoordinates` object also provides
|
|
203
|
+
a `#geodetic` method to convert to WGS-84 geodetic coordinates
|
|
204
|
+
(`Astronoby::Coordinates::Geodetic`)
|
|
205
|
+
- `#to_gcrs` - GCRS position and velocity (returns an `Astronoby::Astrometric`
|
|
206
|
+
frame), using the transposed precession and nutation matrices
|
|
207
|
+
- `#observed_by(observer)` - topocentric position as seen from a specific
|
|
208
|
+
observer (returns an `Astronoby::Topocentric` frame)
|
|
209
|
+
|
|
210
|
+
```rb
|
|
211
|
+
instant = Astronoby::Instant.from_time(Time.utc(2025, 6, 15, 12))
|
|
212
|
+
|
|
213
|
+
# Construct from SGP4 output
|
|
214
|
+
teme = Astronoby::Teme.new(
|
|
215
|
+
position: Astronoby::Distance.vector_from_meters(
|
|
216
|
+
[4_154_639.35, 768_141.62, -5_327_440.29]
|
|
217
|
+
),
|
|
218
|
+
velocity: Astronoby::Velocity.vector_from_mps(
|
|
219
|
+
[-1152.15, 7561.14, 192.76]
|
|
220
|
+
),
|
|
221
|
+
instant: instant
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
# Convert to ECEF
|
|
225
|
+
ecef = teme.to_ecef
|
|
226
|
+
ecef.position[0].km
|
|
227
|
+
# => 1196.49...
|
|
228
|
+
|
|
229
|
+
# Convert ECEF to geodetic (WGS-84)
|
|
230
|
+
geodetic = ecef.geodetic
|
|
231
|
+
geodetic.latitude.str(:dms)
|
|
232
|
+
# => "+10° 29′ 51.7526″"
|
|
233
|
+
|
|
234
|
+
# Convert to GCRS
|
|
235
|
+
gcrs = teme.to_gcrs
|
|
236
|
+
gcrs.equatorial.right_ascension.str(:hms, precision: 0)
|
|
237
|
+
# => "0h 40m 42s"
|
|
238
|
+
|
|
239
|
+
# Observe from a location
|
|
240
|
+
observer = Astronoby::Observer.new(
|
|
241
|
+
latitude: Astronoby::Angle.from_degrees(48.8566),
|
|
242
|
+
longitude: Astronoby::Angle.from_degrees(2.3522)
|
|
243
|
+
)
|
|
244
|
+
topocentric = teme.observed_by(observer)
|
|
245
|
+
topocentric.horizontal.azimuth.str(:dms, precision: 0)
|
|
246
|
+
# => "+223° 53′ 41″"
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Earth rotation
|
|
250
|
+
|
|
251
|
+
`Astronoby::EarthRotation` provides standalone Earth rotation matrices:
|
|
252
|
+
|
|
253
|
+
- `EarthRotation.matrix_for(instant)` — R₃(GAST), the apparent rotation
|
|
254
|
+
matrix (used for observer placement in the true-equinox frame)
|
|
255
|
+
- `EarthRotation.mean_matrix_for(instant)` — R₃(GMST), the mean rotation
|
|
256
|
+
matrix (used for TEME ↔ ECEF conversions)
|
|
257
|
+
|
|
258
|
+
Both return 3×3 orthogonal rotation matrices that transform ECEF coordinates
|
|
259
|
+
into the corresponding celestial frame.
|
|
260
|
+
|
|
261
|
+
## Standard reference systems
|
|
262
|
+
|
|
263
|
+
The table below maps Astronoby's reference frames to standard IAU/IERS
|
|
264
|
+
reference systems and lists the corrections applied at each step.
|
|
265
|
+
|
|
266
|
+
| Astronoby frame | Standard system | Origin | Axes | Corrections applied |
|
|
267
|
+
| --------------- | --------------- | ----------------------- | ----------------------------------- | ----------------------------------------------------------------------- |
|
|
268
|
+
| Geometric | BCRS | Solar System barycentre | ICRS | None (raw ephemeris) |
|
|
269
|
+
| Astrometric | GCRS | Earth centre | ICRS | Light-time, origin shift |
|
|
270
|
+
| Mean of date | — | Earth centre | Mean equator & equinox of date | IAU 2006 precession (Fukushima-Williams, incl. frame bias) |
|
|
271
|
+
| Apparent | — | Earth centre | True equator & equinox of date | Aberration, precession, IAU 2000B nutation |
|
|
272
|
+
| Topocentric | — | Observer | True equator & equinox of date | GAST earth rotation, IERS polar motion, observer position (WGS-84/ITRS) |
|
|
273
|
+
| TEME | — | Earth centre | True equator & mean equinox of date | SGP4/SDP4 output frame; converts to ECEF, GCRS, or topocentric |
|
|
274
|
+
|
|
275
|
+
### Models and references
|
|
276
|
+
|
|
277
|
+
- **Precession**: IAU 2006 P03, Fukushima-Williams parameterization including
|
|
278
|
+
ICRS frame bias (IERS Conventions 2010, Section 5.6.4; ERFA `eraPfw06` /
|
|
279
|
+
`eraFw2m`)
|
|
280
|
+
- **Nutation**: IAU 2000B, 77-term truncation of the IAU 2000A model (IERS
|
|
281
|
+
Conventions 2010, Section 5.5.2)
|
|
282
|
+
- **Aberration**: Relativistic stellar aberration (Explanatory Supplement to the
|
|
283
|
+
Astronomical Almanac, Ch. 7.2.3)
|
|
284
|
+
- **Earth rotation**: Greenwich Apparent Sidereal Time (GAST) computed as GMST +
|
|
285
|
+
equation of equinoxes (IERS Conventions 2010, Section 5.5.7)
|
|
286
|
+
- **Polar motion**: IERS Earth Orientation Parameters via the `iers` gem
|
|
287
|
+
- **Observer coordinates**: WGS-84 geodetic to geocentric (ITRS/ECEF) conversion
|
|
288
|
+
|
|
132
289
|
## See also
|
|
290
|
+
|
|
133
291
|
- [Coordinates](coordinates.md) - for understanding coordinate systems
|
|
134
292
|
- [Observer](observer.md) - for location setup
|
|
135
293
|
- [Solar System Bodies](solar_system_bodies.md) - for object positions
|
|
@@ -10,10 +10,11 @@ Once instantiated, the calculator doesn't do anything yet, it waits for your
|
|
|
10
10
|
instruction.
|
|
11
11
|
|
|
12
12
|
It takes as key arguments:
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
- `body` (`Astronoby::SolarSystemBody` or `Astronoby::DeepSkyObject`): any
|
|
14
15
|
supported celestial body, e.g. `Astronoby::Sun`
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
- `observer` (`Astronoby::Observer`): location on Earth of the observer
|
|
17
|
+
- `ephem`: ephemeris to provide the initial raw data
|
|
17
18
|
|
|
18
19
|
You can learn more about [Solar System bodies] and [ephemerides].
|
|
19
20
|
|
|
@@ -56,7 +57,7 @@ events.transit_times
|
|
|
56
57
|
# => [2025-05-01 07:21:34 UTC, 2025-05-02 07:18:01 UTC]
|
|
57
58
|
|
|
58
59
|
events.setting_times
|
|
59
|
-
# => [2025-05-01 13:14:24 UTC, 2025-05-02 13:10:
|
|
60
|
+
# => [2025-05-01 13:14:24 UTC, 2025-05-02 13:10:58 UTC]
|
|
60
61
|
```
|
|
61
62
|
|
|
62
63
|
## `#events_on`
|
|
@@ -113,6 +114,7 @@ event.setting_time.localtime(utc_offset)
|
|
|
113
114
|
[ephemerides]: ephem.md
|
|
114
115
|
|
|
115
116
|
## See also
|
|
117
|
+
|
|
116
118
|
- [Twilight Times](twilight_times.md) - for sun-related events
|
|
117
119
|
- [Solar System Bodies](solar_system_bodies.md) - for object information
|
|
118
120
|
- [Observer](observer.md) - for location setup
|
data/docs/solar_system_bodies.md
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Currently, Astronoby only supports the following major bodies of the Solar
|
|
4
4
|
System:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
|
|
6
|
+
- the Sun (`Astronoby::Sun`)
|
|
7
|
+
- planets from Mercury to Neptune, including the Earth (`Astronoby::Earth`, ...)
|
|
8
|
+
- the Moon (`Astronoby::Moon`)
|
|
8
9
|
|
|
9
10
|
Given an ephemeris (`Astronoby::Ephem`) and an instant object
|
|
10
11
|
(`Astronoby::Instant`), these classes enable you to get instances which provide
|
|
@@ -21,7 +22,7 @@ venus = Astronoby::Venus.new(ephem: ephem, instant: instant)
|
|
|
21
22
|
apparent_position = venus.apparent.position
|
|
22
23
|
|
|
23
24
|
apparent_position.x.km.round
|
|
24
|
-
# => -
|
|
25
|
+
# => -148794597
|
|
25
26
|
```
|
|
26
27
|
|
|
27
28
|
Each of these bodies also provides its own equatorial radius
|
|
@@ -60,6 +61,26 @@ venus.constellation.abbreviation
|
|
|
60
61
|
# => "Cnc"
|
|
61
62
|
```
|
|
62
63
|
|
|
64
|
+
### `#elongation`
|
|
65
|
+
|
|
66
|
+
Apparent angular distance between the body and the Sun, as seen from Earth
|
|
67
|
+
("Sun-Earth-object" angle). Returns a `Astronoby::Angle` object.
|
|
68
|
+
|
|
69
|
+
```rb
|
|
70
|
+
venus.elongation.degrees.round
|
|
71
|
+
# => 41
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### `#eastern?` and `#western?`
|
|
75
|
+
|
|
76
|
+
Whether the body lies east of the Sun (visible in the evening) or west of it
|
|
77
|
+
(visible in the morning). Both return a `Boolean`.
|
|
78
|
+
|
|
79
|
+
```rb
|
|
80
|
+
venus.eastern? # => false
|
|
81
|
+
venus.western? # => true
|
|
82
|
+
```
|
|
83
|
+
|
|
63
84
|
### `#phase_angle`
|
|
64
85
|
|
|
65
86
|
"Sun-object-Earth" angle. Returns a `Astronoby::Angle` object.
|
|
@@ -101,6 +122,7 @@ Astronoby::Venus.absolute_magnitude
|
|
|
101
122
|
[reference frames]: reference_frames.md
|
|
102
123
|
|
|
103
124
|
## See also
|
|
125
|
+
|
|
104
126
|
- [Ephemerides](ephem.md) - for understanding data sources
|
|
105
127
|
- [Reference Frames](reference_frames.md) - for coordinate systems
|
|
106
128
|
- [Observer](observer.md) - for setting up observation locations
|