astronoby 0.9.0 → 0.10.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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/CHANGELOG.md +101 -0
  4. data/README.md +6 -1
  5. data/UPGRADING.md +84 -0
  6. data/docs/README.md +80 -15
  7. data/docs/angles.md +1 -0
  8. data/docs/configuration.md +20 -17
  9. data/docs/coordinates.md +72 -12
  10. data/docs/deep_sky_bodies.md +1 -1
  11. data/docs/ephem.md +5 -2
  12. data/docs/equinoxes_solstices_times.md +4 -3
  13. data/docs/glossary.md +97 -1
  14. data/docs/iers.md +40 -0
  15. data/docs/instant.md +20 -15
  16. data/docs/lunar_eclipses.md +93 -0
  17. data/docs/lunar_observation.md +87 -0
  18. data/docs/moon_phases.md +4 -1
  19. data/docs/observer.md +20 -6
  20. data/docs/planetary_phenomena.md +78 -0
  21. data/docs/reference_frames.md +192 -34
  22. data/docs/rise_transit_set_times.md +6 -4
  23. data/docs/solar_system_bodies.md +26 -4
  24. data/docs/twilight_times.md +25 -21
  25. data/lib/astronoby/angle.rb +63 -2
  26. data/lib/astronoby/angles/dms.rb +18 -1
  27. data/lib/astronoby/angles/hms.rb +14 -1
  28. data/lib/astronoby/angular_velocity.rb +21 -0
  29. data/lib/astronoby/bodies/deep_sky_object.rb +6 -1
  30. data/lib/astronoby/bodies/deep_sky_object_position.rb +32 -17
  31. data/lib/astronoby/bodies/earth.rb +7 -44
  32. data/lib/astronoby/bodies/jupiter.rb +10 -0
  33. data/lib/astronoby/bodies/mars.rb +10 -0
  34. data/lib/astronoby/bodies/mercury.rb +10 -0
  35. data/lib/astronoby/bodies/moon.rb +158 -32
  36. data/lib/astronoby/bodies/neptune.rb +10 -0
  37. data/lib/astronoby/bodies/saturn.rb +10 -0
  38. data/lib/astronoby/bodies/solar_system_body.rb +240 -61
  39. data/lib/astronoby/bodies/sun.rb +79 -4
  40. data/lib/astronoby/bodies/uranus.rb +10 -0
  41. data/lib/astronoby/bodies/venus.rb +10 -0
  42. data/lib/astronoby/body.rb +6 -0
  43. data/lib/astronoby/center.rb +84 -0
  44. data/lib/astronoby/constellation.rb +9 -1
  45. data/lib/astronoby/coordinates/ecliptic.rb +10 -1
  46. data/lib/astronoby/coordinates/equatorial.rb +64 -8
  47. data/lib/astronoby/coordinates/geodetic.rb +102 -0
  48. data/lib/astronoby/coordinates/horizontal.rb +13 -1
  49. data/lib/astronoby/distance.rb +35 -0
  50. data/lib/astronoby/duration.rb +116 -0
  51. data/lib/astronoby/earth_rotation.rb +70 -0
  52. data/lib/astronoby/equinox_solstice.rb +31 -8
  53. data/lib/astronoby/errors.rb +11 -0
  54. data/lib/astronoby/events/conjunction.rb +51 -0
  55. data/lib/astronoby/events/conjunction_opposition_calculator.rb +84 -0
  56. data/lib/astronoby/events/eclipse_phase.rb +27 -0
  57. data/lib/astronoby/events/extremum_calculator.rb +23 -176
  58. data/lib/astronoby/events/greatest_elongation.rb +58 -0
  59. data/lib/astronoby/events/greatest_elongation_calculator.rb +56 -0
  60. data/lib/astronoby/events/lunar_eclipse.rb +99 -0
  61. data/lib/astronoby/events/lunar_eclipse_calculator.rb +285 -0
  62. data/lib/astronoby/events/opposition.rb +19 -0
  63. data/lib/astronoby/events/rise_transit_set_event.rb +12 -1
  64. data/lib/astronoby/events/rise_transit_set_events.rb +12 -1
  65. data/lib/astronoby/events/twilight_event.rb +24 -6
  66. data/lib/astronoby/events/twilight_events.rb +26 -6
  67. data/lib/astronoby/extremum_finder.rb +148 -0
  68. data/lib/astronoby/instant.rb +10 -7
  69. data/lib/astronoby/libration.rb +25 -0
  70. data/lib/astronoby/mean_obliquity.rb +8 -0
  71. data/lib/astronoby/moon_orientation_ephemeris.rb +69 -0
  72. data/lib/astronoby/moon_physical_ephemeris.rb +263 -0
  73. data/lib/astronoby/nutation.rb +10 -20
  74. data/lib/astronoby/observer.rb +67 -49
  75. data/lib/astronoby/orientation.rb +107 -0
  76. data/lib/astronoby/position.rb +16 -0
  77. data/lib/astronoby/precession.rb +61 -60
  78. data/lib/astronoby/reference_frame.rb +73 -7
  79. data/lib/astronoby/reference_frames/apparent.rb +26 -7
  80. data/lib/astronoby/reference_frames/astrometric.rb +14 -1
  81. data/lib/astronoby/reference_frames/geometric.rb +7 -1
  82. data/lib/astronoby/reference_frames/mean_of_date.rb +13 -1
  83. data/lib/astronoby/reference_frames/teme.rb +153 -0
  84. data/lib/astronoby/reference_frames/topocentric.rb +30 -4
  85. data/lib/astronoby/refraction.rb +26 -5
  86. data/lib/astronoby/root_finder.rb +83 -0
  87. data/lib/astronoby/rotation.rb +49 -0
  88. data/lib/astronoby/time/greenwich_apparent_sidereal_time.rb +9 -0
  89. data/lib/astronoby/time/greenwich_mean_sidereal_time.rb +42 -5
  90. data/lib/astronoby/time/greenwich_sidereal_time.rb +21 -0
  91. data/lib/astronoby/time/local_apparent_sidereal_time.rb +21 -0
  92. data/lib/astronoby/time/local_mean_sidereal_time.rb +21 -0
  93. data/lib/astronoby/time/local_sidereal_time.rb +24 -0
  94. data/lib/astronoby/time/sidereal_time.rb +23 -1
  95. data/lib/astronoby/true_obliquity.rb +4 -0
  96. data/lib/astronoby/util/maths.rb +8 -0
  97. data/lib/astronoby/util/time.rb +10 -485
  98. data/lib/astronoby/vector.rb +10 -0
  99. data/lib/astronoby/velocity.rb +39 -0
  100. data/lib/astronoby/version.rb +1 -1
  101. data/lib/astronoby.rb +22 -0
  102. metadata +45 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: becadc2ba01e7620f12b20a5192e8537ed9f717336bb43471734fd5be9561675
4
- data.tar.gz: 47c5743867f09c58f49093645da7534def3836135883f44929d4da15f73a441a
3
+ metadata.gz: 3e781560f80c12781becc942c58f026386dbc252bff0830ab154e1217dba319f
4
+ data.tar.gz: '0939683834940fe9bef423fe6e59b5a8ce5a1c53921015ee612c0f258c0fd224'
5
5
  SHA512:
6
- metadata.gz: 2b04c971a79ac8201e21398dc0cc02b920cdadde538a0eb7d5d59dbc260661cbda51f3a72a434695b596634848f361a96b9533074f399d23d1e3d21fac89d772
7
- data.tar.gz: f71973fd392c15a243a28ac09e521e813adf4900eefacfbc55712bd4f942c46b3351cfe44e183c1e809b0285b0ffb22ab320afd26b84c3d329be7fe79897378d
6
+ metadata.gz: 731fe3a326ddeca238f9479647e61e0554bbef2e10a35e468079240a58e8482a3e21b316fc61d5bcfb6962de353002e882c1e104f3e5c1626f6a02177a55a9a1
7
+ data.tar.gz: 035fb37802b80e6be88c216d0b117e3804bcd55c75871c4de4d6554e55fe8634f39e7dfe73e794bef4d00d35e59ccdbab65851bf34525a05f3ef290c4a5d2373
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.4.4
1
+ 4.0.5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,106 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.10.0 - 2026-06-26
4
+
5
+ _If you are upgrading: please see [UPGRADING.md]._
6
+
7
+ ### Bug fixes
8
+
9
+ * Fix constant name typo ([#245])
10
+ * Fix matrix multiplication order in Apparent frame ([#250])
11
+ * Remove spurious N·P from observer ECEF-to-TOD transformation ([#251])
12
+ * Apply aberration in GCRS before precession/nutation rotation ([#253])
13
+ * Fix Moon magnitude ([#254])
14
+ * Fix astrometric position for Deep Sky Objects ([#272])
15
+
16
+ ### Features
17
+
18
+ * Defer Solar System body computations lazily ([#244])
19
+ * Integrate `iers` gem for Delta T and GMST ([#249])
20
+ * Add IERS polar motion correction to observer ECEF-to-TOD transformation ([#252])
21
+ * Fall back to polynomial GMST for dates outside IERS EOP range ([#255])
22
+ * Add ICRS frame bias to precession matrix ([#257])
23
+ * Extract `EarthRotation` class from `Observer` ([#260])
24
+ * Add TEME reference frame for satellite tracking ([#261])
25
+ * Add ECEF to geodetic conversion (WGS-84) ([#262])
26
+ * Memoize per-instant conversions on `Instant` ([#268])
27
+ * Add `ReferenceFrame#separation_from` for angular separation ([#269])
28
+ * Introduce `Center`, `Body` and `Position` domain objects ([#270])
29
+ * Add planetary phenomena ([#271])
30
+ * Add lunar libration, position angle of axis and bright limb ([#273])
31
+ * Add `Astronoby::Orientation` for arcsecond lunar libration ([#279])
32
+ * Add Lunar eclipses ([#280])
33
+ * Add `Astronoby::Duration` ([#281])
34
+
35
+ ### Improvements
36
+
37
+ * Optimize nutation loop by eliminating array allocations ([#246])
38
+ * Reuse single Nutation instance in observer matrix computation ([#247])
39
+ * Memoize Observer geodetic computation methods ([#248])
40
+ * Update documentation with recent values ([#256])
41
+ * Update referential frames documentation ([#258])
42
+ * YARD documentation update ([#259])
43
+ * Update zlib, JSON and ERB for security reasons
44
+ * Add references to README
45
+ * Bump actions/checkout from 5 to 7 by @dependabot ([#239], [#276])
46
+ * Bump rubyzip from 3.2.1 to 3.4.0 by @dependabot ([#237], [#267], [#275])
47
+ * Bump irb from 1.15.2 to 1.17.0 by @dependabot ([#242])
48
+ * Bump standard from 1.51.1 to 1.55.0 by @dependabot ([#243], [#274])
49
+ * Bump rake from 13.3.1 to 13.4.2 by @dependabot ([#264])
50
+ * Bump ephem from 0.4.1 to 0.5.0 by @dependabot ([#278])
51
+ * Upgrade default Ruby to 4.0.5 ([#277])
52
+
53
+ ### Backward-incompatible changes
54
+
55
+ * Minimum Ruby version bumped to 3.2.0 ([#249])
56
+ * Delta T and GMST now use IERS data ([#249])
57
+ * Defer Solar System body computations lazily ([#244])
58
+ * `SolarSystemBody#ephem` is now publicly accessible ([#244])
59
+ * `ReferenceFrame#center_identifier` replaced by `#center` ([#270])
60
+ * `Sun#equation_of_time` now returns a `Duration` ([#281])
61
+
62
+ **Full Changelog**: https://github.com/rhannequin/astronoby/compare/v0.9.0...v0.10.0
63
+
64
+ [#237]: https://github.com/rhannequin/astronoby/pull/237
65
+ [#239]: https://github.com/rhannequin/astronoby/pull/239
66
+ [#242]: https://github.com/rhannequin/astronoby/pull/242
67
+ [#243]: https://github.com/rhannequin/astronoby/pull/243
68
+ [#244]: https://github.com/rhannequin/astronoby/pull/244
69
+ [#245]: https://github.com/rhannequin/astronoby/pull/245
70
+ [#246]: https://github.com/rhannequin/astronoby/pull/246
71
+ [#247]: https://github.com/rhannequin/astronoby/pull/247
72
+ [#248]: https://github.com/rhannequin/astronoby/pull/248
73
+ [#249]: https://github.com/rhannequin/astronoby/pull/249
74
+ [#250]: https://github.com/rhannequin/astronoby/pull/250
75
+ [#251]: https://github.com/rhannequin/astronoby/pull/251
76
+ [#252]: https://github.com/rhannequin/astronoby/pull/252
77
+ [#253]: https://github.com/rhannequin/astronoby/pull/253
78
+ [#254]: https://github.com/rhannequin/astronoby/pull/254
79
+ [#255]: https://github.com/rhannequin/astronoby/pull/255
80
+ [#256]: https://github.com/rhannequin/astronoby/pull/256
81
+ [#257]: https://github.com/rhannequin/astronoby/pull/257
82
+ [#258]: https://github.com/rhannequin/astronoby/pull/258
83
+ [#259]: https://github.com/rhannequin/astronoby/pull/259
84
+ [#260]: https://github.com/rhannequin/astronoby/pull/260
85
+ [#261]: https://github.com/rhannequin/astronoby/pull/261
86
+ [#262]: https://github.com/rhannequin/astronoby/pull/262
87
+ [#264]: https://github.com/rhannequin/astronoby/pull/264
88
+ [#267]: https://github.com/rhannequin/astronoby/pull/267
89
+ [#268]: https://github.com/rhannequin/astronoby/pull/268
90
+ [#269]: https://github.com/rhannequin/astronoby/pull/269
91
+ [#270]: https://github.com/rhannequin/astronoby/pull/270
92
+ [#271]: https://github.com/rhannequin/astronoby/pull/271
93
+ [#272]: https://github.com/rhannequin/astronoby/pull/272
94
+ [#273]: https://github.com/rhannequin/astronoby/pull/273
95
+ [#274]: https://github.com/rhannequin/astronoby/pull/274
96
+ [#275]: https://github.com/rhannequin/astronoby/pull/275
97
+ [#276]: https://github.com/rhannequin/astronoby/pull/276
98
+ [#277]: https://github.com/rhannequin/astronoby/pull/277
99
+ [#278]: https://github.com/rhannequin/astronoby/pull/278
100
+ [#279]: https://github.com/rhannequin/astronoby/pull/279
101
+ [#280]: https://github.com/rhannequin/astronoby/pull/280
102
+ [#281]: https://github.com/rhannequin/astronoby/pull/281
103
+
3
104
  ## 0.9.0 - 2025-10-31
4
105
 
5
106
  _If you are upgrading: please see [UPGRADING.md]._
data/README.md CHANGED
@@ -11,7 +11,9 @@ Some algorithms are based on the following astrometry books:
11
11
  Duffet-Smith and Jonathan Zwart
12
12
 
13
13
  Solar System bodies' positions are computed based on ephemerides from the
14
- [IMCCE] or [NASA/JPL].
14
+ [IMCCE] or [NASA/JPL]. The library also supports Earth-orbiting satellite
15
+ tracking through the [TEME] reference frame, suitable for use with SGP4/SDP4
16
+ orbit propagators.
15
17
 
16
18
  ## Content
17
19
  - [Installation](#installation)
@@ -45,6 +47,8 @@ previous versions, you can access the documentation in the README for each
45
47
  and objects
46
48
  - [Reference Frames](docs/reference_frames.md) - for coordinate systems
47
49
  - [Observer Setup](docs/observer.md) - for location configuration
50
+ - [IERS Data](docs/iers.md) - for Delta T and Greenwich Mean Sidereal Time
51
+ (GMST) data management
48
52
  - [Glossary](docs/glossary.md) - for astronomical and technical terms
49
53
 
50
54
  ### Expected breaking changes notice
@@ -122,6 +126,7 @@ Everyone interacting in the Astronoby project's codebases, issue trackers, chat
122
126
  rooms and mailing lists is expected to follow the [code of conduct].
123
127
 
124
128
  [NASA/JPL]: https://ssd.jpl.nasa.gov/planets/eph_export.html
129
+ [TEME]: https://github.com/rhannequin/astronoby/blob/main/docs/reference_frames.md#teme
125
130
  [Bundler]: https://bundler.io
126
131
  [`docs/`]: https://github.com/rhannequin/astronoby/blob/main/docs
127
132
  [release]: https://github.com/rhannequin/astronoby/releases
data/UPGRADING.md CHANGED
@@ -7,6 +7,90 @@ changes to it as long as a major version has not been released.
7
7
  If you are already using Astronoby and wish to follow the changes to its
8
8
  public API, please read the upgrading notes for each release.
9
9
 
10
+ ## Upgrading from 0.9.0 to 0.10.0
11
+
12
+ ### Minimum Ruby version bumped to 3.2.0
13
+
14
+ The minimum required Ruby version is now 3.2.0 (previously 3.0.0), due to the
15
+ new `iers` gem dependency.
16
+
17
+ ### Delta T and GMST now use IERS data
18
+
19
+ Delta T (TT - UT1) is now computed from IERS data via the
20
+ [`iers`](https://github.com/rhannequin/iers) gem instead of hardcoded lookup
21
+ tables. Greenwich Mean Sidereal Time (GMST) is now computed using the IERS
22
+ Conventions 2010 ERA-based expression instead of the Duffett-Smith polynomial.
23
+
24
+ Both changes improve accuracy significantly (Delta T error reduced from ~0.5s
25
+ to ~0.001s, GMST error reduced by 600-2200x vs Skyfield). As a result,
26
+ computed values for sidereal times, horizontal coordinates, and
27
+ rise/transit/set times may differ slightly from previous versions.
28
+
29
+ The `iers` gem ships with bundled data files that work out of the box. See
30
+ [IERS Data](docs/iers.md) for details on data coverage and updates.
31
+
32
+ ### `SolarSystemBody` initialization is now lazy
33
+
34
+ `SolarSystemBody#initialize` no longer eagerly computes geometric positions,
35
+ light-time corrections, or Sun data. All computations are now deferred until
36
+ the corresponding method is first called. This means ephemeris-related errors
37
+ will surface on first property access rather than during instantiation.
38
+
39
+ ### `SolarSystemBody#geometric` is now a lazy method
40
+
41
+ `geometric` was previously exposed via `attr_reader` and eagerly computed in
42
+ `initialize`. It is now a lazy memoized method. The public interface is
43
+ unchanged — `body.geometric` still returns a `Geometric` object.
44
+
45
+ ### `SolarSystemBody#ephem` is now publicly accessible
46
+
47
+ The `ephem` object passed to `initialize` is now exposed via `attr_reader`.
48
+
49
+ ### `ReferenceFrame#center_identifier` replaced by `#center`
50
+
51
+ Every reference frame previously exposed `#center_identifier`, an `Integer`
52
+ (e.g. `Astronoby::SolarSystemBody::EARTH`) for barycentric/geocentric frames or
53
+ a `[longitude, latitude]` array for topocentric frames. It is replaced by
54
+ `#center`, which returns an `Astronoby::Center` value object.
55
+
56
+ ```rb
57
+ # Before
58
+ frame.center_identifier # => 399 or [longitude, latitude]
59
+
60
+ # After
61
+ frame.center # => #<Astronoby::Center ...>
62
+ frame.center.geocentric? # => true
63
+ frame.center == Astronoby::Center.geocentric # => true
64
+ frame.center.observer # => the Observer, for topocentric frames
65
+ ```
66
+
67
+ Two topocentric centers are equal when their observers share the same
68
+ latitude, longitude and elevation (atmospheric parameters are ignored).
69
+
70
+ ### `Sun#equation_of_time` now returns a `Duration`
71
+
72
+ Lengths of time are now wrapped in a new `Astronoby::Duration` value object,
73
+ consistent with `Angle`, `Distance` and `Velocity`. As a result,
74
+ `Sun#equation_of_time` returns an `Astronoby::Duration` instead of an
75
+ `Integer` of seconds. Call `#seconds` to get the previous value.
76
+
77
+ ```rb
78
+ # Before
79
+ sun.equation_of_time # => -185
80
+
81
+ # After
82
+ sun.equation_of_time # => #<Astronoby::Duration ...>
83
+ sun.equation_of_time.seconds # => -185
84
+ sun.equation_of_time.minutes # => -3.08...
85
+ ```
86
+
87
+ A `Duration` can be built with `from_seconds`, `from_minutes`, `from_hours`
88
+ and `from_days`, and read back in any of those units. It is immutable,
89
+ comparable, and supports `+` and `-`.
90
+
91
+ Note that `EclipsePhase#duration`, also introduced in this release, returns
92
+ an `Astronoby::Duration` as well.
93
+
10
94
  ## Upgrading from 0.8.0 to 0.9.0
11
95
 
12
96
  ### Constant `MINUTES_PER_DEGREE` renamed
data/docs/README.md CHANGED
@@ -62,10 +62,10 @@ You can learn more about reference frames and positions on the
62
62
 
63
63
  ```rb
64
64
  topocentric.horizontal.azimuth.str(:dms)
65
- # => "+175° 34′ 28.2724″"
65
+ # => "+175° 34′ 33.2353″"
66
66
 
67
67
  topocentric.horizontal.altitude.str(:dms)
68
- # => "+64° 22′ 58.1084″"
68
+ # => "+64° 22′ 58.229″"
69
69
  ```
70
70
 
71
71
  You can learn more about coordinates on the [Coordinates page].
@@ -108,22 +108,22 @@ calculator = Astronoby::TwilightCalculator.new(
108
108
  event = calculator.event_on(Date.new(2025, 5, 1))
109
109
 
110
110
  event.morning_astronomical_twilight_time
111
- # => 2025-05-01 02:17:28 UTC
111
+ # => 2025-05-01 02:17:07 UTC
112
112
 
113
113
  event.morning_nautical_twilight_time
114
- # => 2025-05-01 03:10:17 UTC
114
+ # => 2025-05-01 03:09:44 UTC
115
115
 
116
116
  event.morning_civil_twilight_time
117
- # => 2025-05-01 03:55:17 UTC
117
+ # => 2025-05-01 03:54:38 UTC
118
118
 
119
119
  event.evening_civil_twilight_time
120
- # => 2025-05-01 19:40:12 UTC
120
+ # => 2025-05-01 19:41:51 UTC
121
121
 
122
122
  event.evening_nautical_twilight_time
123
- # => 2025-05-01 20:25:12 UTC
123
+ # => 2025-05-01 20:26:56 UTC
124
124
 
125
125
  event.evening_astronomical_twilight_time
126
- # => 2025-05-01 21:18:01 UTC
126
+ # => 2025-05-01 21:19:57 UTC
127
127
  ```
128
128
 
129
129
  You can learn more about this calculator on the [Twilight times page].
@@ -141,7 +141,7 @@ may_2024_phases.each { puts "#{_1.phase}: #{_1.time}" }
141
141
  # new_moon: 2024-05-08 03:21:56 UTC
142
142
  # first_quarter: 2024-05-15 11:48:02 UTC
143
143
  # full_moon: 2024-05-23 13:53:12 UTC
144
- # last_quarter: 2024-05-30 17:12:43 UTC
144
+ # last_quarter: 2024-05-30 17:12:42 UTC
145
145
  ```
146
146
 
147
147
  ```rb
@@ -150,14 +150,53 @@ instant = Astronoby::Instant.from_time(time)
150
150
  moon = Astronoby::Moon.new(ephem: ephem, instant: instant)
151
151
 
152
152
  moon.illuminated_fraction.round(2)
153
- # => 0.15
153
+ # => 0.95
154
154
 
155
155
  moon.current_phase_fraction.round(2)
156
- # => 0.11
156
+ # => 0.59
157
157
  ```
158
158
 
159
159
  You can learn more about phases on the [Moon phases page].
160
160
 
161
+ ## Lunar observation
162
+
163
+ ```rb
164
+ time = Time.utc(2025, 3, 1)
165
+ instant = Astronoby::Instant.from_time(time)
166
+ moon = Astronoby::Moon.new(ephem: ephem, instant: instant)
167
+
168
+ moon.libration.longitude.str(:dms)
169
+ # => "-2° 5′ 4.4219″"
170
+
171
+ moon.libration.latitude.str(:dms)
172
+ # => "+0° 28′ 45.9616″"
173
+
174
+ moon.position_angle_of_axis.str(:dms)
175
+ # => "-21° 48′ 46.657″"
176
+
177
+ moon.bright_limb_position_angle.str(:dms)
178
+ # => "+248° 1′ 57.9467″"
179
+ ```
180
+
181
+ You can learn more about libration, axis and limb angles on the
182
+ [Lunar observation page].
183
+
184
+ ## Lunar eclipses
185
+
186
+ ```rb
187
+ eclipses = Astronoby::Moon.eclipse_events(
188
+ ephem: ephem,
189
+ start_time: Time.utc(2025, 1, 1),
190
+ end_time: Time.utc(2026, 1, 1)
191
+ )
192
+
193
+ eclipses.map { |eclipse| [eclipse.instant.to_time, eclipse.kind] }
194
+ # => [[2025-03-14 06:58:47 UTC, :total], [2025-09-07 18:11:49 UTC, :total]]
195
+ ```
196
+
197
+ You can learn more about umbral and penumbral magnitudes, phases and contact
198
+ times on the [Lunar eclipses page].
199
+
161
200
  ## Equinox and solstice times
162
201
 
163
202
  ```rb
@@ -166,18 +205,39 @@ Astronoby::EquinoxSolstice.march_equinox(2025, ephem)
166
205
  # => 2025-03-20 09:01:29 UTC
167
206
 
168
207
  Astronoby::EquinoxSolstice.june_solstice(2025, ephem)
169
- # => 2025-06-21 02:42:19 UTC
208
+ # => 2025-06-21 02:42:16 UTC
170
209
 
171
210
  Astronoby::EquinoxSolstice.september_equinox(2025, ephem)
172
- # => 2025-09-22 18:19:22 UTC
211
+ # => 2025-09-22 18:19:21 UTC
173
212
 
174
213
  Astronoby::EquinoxSolstice.december_solstice(2025, ephem)
175
- # => 2025-12-21 15:03:03 UTC
214
+ # => 2025-12-21 15:03:05 UTC
176
215
  ```
177
216
 
178
217
  You can learn more about equinoxes and solstices on the
179
218
  [Equinoxes and solstices times page].
180
219
 
220
+ ## Planetary phenomena
221
+
222
+ ```rb
223
+ Astronoby::Mars.opposition_events(
224
+ ephem: ephem,
225
+ start_time: Time.utc(2025, 1, 1),
226
+ end_time: Time.utc(2026, 1, 1)
227
+ ).first.instant.to_time
228
+ # => 2025-01-16 02:38:35 UTC
229
+
230
+ Astronoby::Venus.greatest_elongation_events(
231
+ ephem: ephem,
232
+ start_time: Time.utc(2025, 1, 1),
233
+ end_time: Time.utc(2026, 1, 1)
234
+ ).first.angle.degrees.round(1)
235
+ # => 47.2
236
+ ```
237
+
238
+ You can learn more about conjunctions, oppositions and greatest elongations on
239
+ the [Planetary phenomena page].
240
+
181
241
  ## Deep-sky objects
182
242
 
183
243
  It is possible to manipulate any deep-sky possible, given equatorial coordinates
@@ -200,13 +260,15 @@ vega = Astronoby::DeepSkyObject.new(equatorial_coordinates: vega_j2000)
200
260
  vega_position = vega.at(instant)
201
261
 
202
262
  vega_position.apparent.equatorial.right_ascension.str(:hms)
203
- # => "18h 36m 56.3363s"
263
+ # => "18h 37m 48.2804s"
204
264
  ```
205
265
 
206
266
  You can learn more about deep-sky objects on the [Deep-sky Bodies page].
207
267
 
208
268
  ## See also
269
+
209
270
  - [Glossary](glossary.md) - for astronomical and technical terms
271
+ - [IERS Data](iers.md) - for Delta T and GMST data management
210
272
  - [Configuration](configuration.md) - for performance tuning
211
273
  - [Performance Benchmarks](../benchmarks/README.md) - for testing improvements
212
274
 
@@ -220,5 +282,8 @@ You can learn more about deep-sky objects on the [Deep-sky Bodies page].
220
282
  [Rise, transit and setting times page]: rise_transit_set_times.md
221
283
  [Twilight times page]: twilight_times.md
222
284
  [Moon phases page]: moon_phases.md
285
+ [Lunar observation page]: lunar_observation.md
286
+ [Lunar eclipses page]: lunar_eclipses.md
223
287
  [Equinoxes and solstices times page]: equinoxes_solstices_times.md
288
+ [Planetary phenomena page]: planetary_phenomena.md
224
289
  [Deep-sky Bodies page]: deep_sky_bodies.md
data/docs/angles.md CHANGED
@@ -131,6 +131,7 @@ angle1.negative? # => false
131
131
  ```
132
132
 
133
133
  ## See also
134
+
134
135
  - [Coordinates](coordinates.md) - for using angles in coordinate systems
135
136
  - [Observer](observer.md) - for latitude and longitude
136
137
  - [Reference Frames](reference_frames.md) - for position calculations
@@ -20,11 +20,12 @@ Astronoby.configuration.cache_enabled = true
20
20
 
21
21
  Once caching is enabled, it will be used for the following parts of the library
22
22
  with default precision values:
23
- * [Geometric positions]
24
- * [Topocentric positions] when computing rising/transit/setting times
25
- * [Moon phases]
26
- * Nutation
27
- * Precession
23
+
24
+ - [Geometric positions]
25
+ - [Topocentric positions] when computing rising/transit/setting times
26
+ - [Moon phases]
27
+ - Nutation
28
+ - Precession
28
29
 
29
30
  ## Cache precision
30
31
 
@@ -35,10 +36,11 @@ However, users may want to improve performance even more at the cost of some
35
36
  precision.
36
37
 
37
38
  It is possible to change the precision value for the following:
38
- * Geometric position, default: `9`
39
- * Topocentric position, default: `5`
40
- * Nutation, default: `2`
41
- * Precession, default: `2`
39
+
40
+ - Geometric position, default: `9`
41
+ - Topocentric position, default: `5`
42
+ - Nutation, default: `2`
43
+ - Precession, default: `2`
42
44
 
43
45
  ### Precision value
44
46
 
@@ -49,14 +51,14 @@ Let's take the example of `1`. Rounding a Julian Day with only one digit means
49
51
  that all times within 8640 seconds will be rounded to the same instant, which
50
52
  means a maximum rounding of 2.4 hours.
51
53
 
52
- * `1`: 2.4 hours
53
- * `2`: 14.4 minutes
54
- * `3`: 86.4 seconds
55
- * `4`: 8.6 seconds
56
- * `5`: 0.86 seconds
57
- * `6`: 0.086 seconds
58
- * `7`: 0.0086 seconds
59
- * ...
54
+ - `1`: 2.4 hours
55
+ - `2`: 14.4 minutes
56
+ - `3`: 86.4 seconds
57
+ - `4`: 8.6 seconds
58
+ - `5`: 0.86 seconds
59
+ - `6`: 0.086 seconds
60
+ - `7`: 0.0086 seconds
61
+ - ...
60
62
 
61
63
  ### Setting custom precision
62
64
 
@@ -92,6 +94,7 @@ Astronoby.cache.max_size
92
94
  [Julian Day]: https://en.wikipedia.org/wiki/Julian_day
93
95
 
94
96
  ## See also
97
+
95
98
  - [Reference Frames](reference_frames.md) - for understanding position calculations
96
99
  - [Ephemerides](ephem.md) - for data sources
97
100
  - [Performance Benchmarks](benchmarks/README.md) - for testing improvements
data/docs/coordinates.md CHANGED
@@ -1,13 +1,15 @@
1
1
  # Coordinates
2
2
 
3
- Astronoby provides three different types of coordinates:
3
+ Astronoby provides four types of coordinates:
4
4
 
5
- * Equatorial
6
- * Ecliptic
7
- * Horizontal
5
+ - Equatorial
6
+ - Ecliptic
7
+ - Horizontal
8
+ - Geodetic
8
9
 
9
10
  Equatorial and ecliptic coordinates are available for each [reference frame],
10
- while horizontal coordinates are only available for a topocentric position.
11
+ horizontal coordinates are only available for a topocentric position, and
12
+ geodetic coordinates are used for Earth-surface positions (ECEF ↔ WGS-84).
11
13
 
12
14
  ## Equatorial
13
15
 
@@ -36,7 +38,7 @@ saturn = Astronoby::Saturn.new(ephem: ephem, instant: instant)
36
38
  equatorial = saturn.apparent.equatorial
37
39
 
38
40
  equatorial.right_ascension.str(:hms)
39
- # => "20h 45m 2.6702s"
41
+ # => "20h 45m 2.6681s"
40
42
  ```
41
43
 
42
44
  You can learn more about angles on the [Angle page].
@@ -49,7 +51,7 @@ is at -90°.
49
51
 
50
52
  ```rb
51
53
  equatorial.declination.str(:dms)
52
- # => "-18° 46′ 16.1226″"
54
+ # => "-18° 46′ 16.0931″"
53
55
  ```
54
56
 
55
57
  ### Hour angle
@@ -63,7 +65,7 @@ time. By convention, the hour angle is usually displayed in hours.
63
65
  longitude = Astronoby::Angle.from_degrees(2)
64
66
 
65
67
  equatorial.compute_hour_angle(longitude: longitude, time: time).str(:hms)
66
- # => "23h 27m 54.9585s"
68
+ # => "23h 27m 54.1924s"
67
69
  ```
68
70
 
69
71
  ## Ecliptic
@@ -101,7 +103,7 @@ saturn = Astronoby::Saturn.new(ephem: ephem, instant: instant)
101
103
  ecliptic = saturn.apparent.ecliptic
102
104
 
103
105
  ecliptic.latitude.str(:dms)
104
- # => "-0° 41′ 27.5439″"
106
+ # => "-0° 41′ 27.5077″"
105
107
  ```
106
108
 
107
109
  ### Longitude
@@ -111,7 +113,7 @@ ecliptic towards the north (positive) or south (negative) ecliptic pole.
111
113
 
112
114
  ```rb
113
115
  ecliptic.longitude.str(:dms)
114
- # => "+308° 38′ 33.1744″"
116
+ # => "+308° 38′ 33.1535″"
115
117
  ```
116
118
 
117
119
  ## Horizontal
@@ -142,7 +144,7 @@ saturn = Astronoby::Saturn.new(ephem: ephem, instant: instant)
142
144
  horizontal = saturn.observed_by(observer).horizontal
143
145
 
144
146
  horizontal.altitude.str(:dms)
145
- # => "+28° 46′ 39.5994″"
147
+ # => "+28° 46′ 38.3398″"
146
148
  ```
147
149
 
148
150
  ### Azimuth
@@ -152,15 +154,73 @@ eastward.
152
154
 
153
155
  ```rb
154
156
  horizontal.azimuth.str(:dms)
155
- # => "+171° 19′ 50.5798″"
157
+ # => "+171° 19′ 38.2567″"
156
158
  ```
157
159
 
160
+ ## Geodetic
161
+
162
+ Geodetic coordinates describe a position on or above the Earth's surface using
163
+ the [WGS-84] reference ellipsoid, the same system used by GPS. They have three
164
+ attributes:
165
+
166
+ ### Latitude
167
+
168
+ The angle from the equator to the point on the ellipsoid surface, from +90°
169
+ (North Pole) to -90° (South Pole).
170
+
171
+ ### Longitude
172
+
173
+ The angle from the Greenwich meridian, from +180° to -180°, with positive
174
+ angles eastward.
175
+
176
+ ### Elevation
177
+
178
+ The distance above (or below) the WGS-84 ellipsoid surface.
179
+
180
+ ### From ECEF
181
+
182
+ Geodetic coordinates can be derived from Earth-Centered Earth-Fixed (ECEF)
183
+ Cartesian coordinates using `Astronoby::Coordinates::Geodetic.from_ecef`. This
184
+ is particularly useful for satellite tracking, where a propagator produces ECEF
185
+ positions via `Astronoby::Teme#to_ecef`:
186
+
187
+ ```rb
188
+ teme = Astronoby::Teme.new(
189
+ position: Astronoby::Distance.vector_from_meters(
190
+ [5_094_180.16, 6_127_644.66, 6_380_344.53]
191
+ ),
192
+ velocity: Astronoby::Velocity.vector_from_mps(
193
+ [-4746.13, 785.82, 5531.93]
194
+ ),
195
+ instant: instant
196
+ )
197
+
198
+ geodetic = teme.to_ecef.geodetic
199
+
200
+ geodetic.latitude.str(:dms)
201
+ # => "+38° 48′ 3.3038″"
202
+
203
+ geodetic.longitude.str(:dms)
204
+ # => "+97° 27′ 6.7374″"
205
+
206
+ geodetic.elevation.km.round
207
+ # => 3838
208
+ ```
209
+
210
+ The conversion uses Bowring's iterative method, which converges in 2-3
211
+ iterations for typical satellite altitudes.
212
+
213
+ The forward direction (geodetic → ECEF) is handled by
214
+ [`Astronoby::Observer#geocentric_position`][Observer page].
215
+
216
+ [WGS-84]: https://en.wikipedia.org/wiki/World_Geodetic_System
158
217
  [reference frame]: reference_frames.md
159
218
  [Wikipedia]: https://en.wikipedia.org/wiki/Equatorial_coordinate_system
160
219
  [Angle page]: angles.md
161
220
  [topocentric position]: reference_frames.md#topocentric
162
221
 
163
222
  ## See also
223
+
164
224
  - [Reference Frames](reference_frames.md) - for coordinate system details
165
225
  - [Angles](angles.md) - for working with angular measurements
166
226
  - [Observer](observer.md) - for location setup
@@ -63,7 +63,7 @@ vega_with_proper_motion
63
63
  .equatorial
64
64
  .right_ascension
65
65
  .str(:hms)
66
- # => "18h 37m 48.7215s"
66
+ # => "18h 37m 48.706s"
67
67
  ```
68
68
 
69
69
  You can learn more about [ephemerides] and [reference frames].
data/docs/ephem.md CHANGED
@@ -17,8 +17,9 @@ providing the filename.
17
17
  ### Manually
18
18
 
19
19
  Ephemerides are available for download from:
20
- * the JPL public FTP interface: https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/
21
- * the INPOP releases page of the IMCCE: https://www.imcce.fr/inpop
20
+
21
+ - the JPL public FTP interface: https://ssd.jpl.nasa.gov/ftp/eph/planets/bsp/
22
+ - the INPOP releases page of the IMCCE: https://www.imcce.fr/inpop
22
23
 
23
24
  You can download any `.bsp` file. For the moment, Astronoby only supports the
24
25
  planets of the Solar System, and the Sun and the Moon, so you need to
@@ -48,6 +49,7 @@ ephem = Astronoby::Ephem.load("tmp/de421.bsp")
48
49
 
49
50
  JPL produces many different kernels over the years, with different accuracy and
50
51
  ranges of supported years. Here are some that we recommend to begin with:
52
+
51
53
  - `de421.bsp`: from 1900 to 2050, 17 MB
52
54
  - `de440s.bsp`: from 1849 to 2150, 32 MB
53
55
  - `inpop19a.bsp`: from 1900 to 2100, 22 MB
@@ -79,6 +81,7 @@ the target `399`.
79
81
  [IMCCE]: https://www.imcce.fr
80
82
 
81
83
  ## See also
84
+
82
85
  - [Solar System Bodies](solar_system_bodies.md) - for using ephemeris data
83
86
  - [Reference Frames](reference_frames.md) - for coordinate calculations
84
87
  - [Observer](observer.md) - for location-based calculations