astronoby 0.6.0 → 0.7.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 -0
- data/.standard.yml +1 -0
- data/CHANGELOG.md +116 -0
- data/Gemfile.lock +45 -23
- data/README.md +42 -285
- data/UPGRADING.md +238 -0
- data/lib/astronoby/aberration.rb +56 -31
- data/lib/astronoby/angle.rb +20 -16
- data/lib/astronoby/angles/dms.rb +2 -2
- data/lib/astronoby/angles/hms.rb +2 -2
- data/lib/astronoby/bodies/earth.rb +56 -0
- data/lib/astronoby/bodies/jupiter.rb +11 -0
- data/lib/astronoby/bodies/mars.rb +11 -0
- data/lib/astronoby/bodies/mercury.rb +11 -0
- data/lib/astronoby/bodies/moon.rb +50 -290
- data/lib/astronoby/bodies/neptune.rb +11 -0
- data/lib/astronoby/bodies/saturn.rb +11 -0
- data/lib/astronoby/bodies/solar_system_body.rb +122 -0
- data/lib/astronoby/bodies/sun.rb +16 -220
- data/lib/astronoby/bodies/uranus.rb +11 -0
- data/lib/astronoby/bodies/venus.rb +11 -0
- data/lib/astronoby/constants.rb +13 -1
- data/lib/astronoby/coordinates/ecliptic.rb +2 -37
- data/lib/astronoby/coordinates/equatorial.rb +25 -7
- data/lib/astronoby/coordinates/horizontal.rb +0 -46
- data/lib/astronoby/corrections/light_time_delay.rb +90 -0
- data/lib/astronoby/deflection.rb +187 -0
- data/lib/astronoby/distance.rb +9 -0
- data/lib/astronoby/ephem.rb +39 -0
- data/lib/astronoby/equinox_solstice.rb +21 -18
- data/lib/astronoby/errors.rb +4 -0
- data/lib/astronoby/events/moon_phases.rb +2 -1
- data/lib/astronoby/events/rise_transit_set_calculator.rb +352 -0
- data/lib/astronoby/events/rise_transit_set_event.rb +13 -0
- data/lib/astronoby/events/rise_transit_set_events.rb +13 -0
- data/lib/astronoby/events/twilight_calculator.rb +166 -0
- data/lib/astronoby/events/twilight_event.rb +28 -0
- data/lib/astronoby/instant.rb +171 -0
- data/lib/astronoby/mean_obliquity.rb +23 -10
- data/lib/astronoby/nutation.rb +227 -42
- data/lib/astronoby/observer.rb +55 -0
- data/lib/astronoby/precession.rb +91 -17
- data/lib/astronoby/reference_frame.rb +49 -0
- data/lib/astronoby/reference_frames/apparent.rb +60 -0
- data/lib/astronoby/reference_frames/astrometric.rb +21 -0
- data/lib/astronoby/reference_frames/geometric.rb +20 -0
- data/lib/astronoby/reference_frames/mean_of_date.rb +38 -0
- data/lib/astronoby/reference_frames/topocentric.rb +82 -0
- data/lib/astronoby/true_obliquity.rb +2 -1
- data/lib/astronoby/util/maths.rb +70 -73
- data/lib/astronoby/util/time.rb +454 -31
- data/lib/astronoby/vector.rb +36 -0
- data/lib/astronoby/velocity.rb +116 -0
- data/lib/astronoby/version.rb +1 -1
- data/lib/astronoby.rb +26 -5
- metadata +61 -16
- data/.tool-versions +0 -1
- data/lib/astronoby/astronomical_models/ephemeride_lunaire_parisienne.rb +0 -143
- data/lib/astronoby/events/observation_events.rb +0 -285
- data/lib/astronoby/events/rise_transit_set_iteration.rb +0 -218
- data/lib/astronoby/events/twilight_events.rb +0 -121
- data/lib/astronoby/util/astrodynamics.rb +0 -60
data/lib/astronoby/bodies/sun.rb
CHANGED
@@ -1,29 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Astronoby
|
4
|
-
class Sun
|
5
|
-
|
6
|
-
ANGULAR_DIAMETER = Angle.from_degrees(0.533128)
|
7
|
-
INTERPOLATION_FACTOR = 24.07
|
4
|
+
class Sun < SolarSystemBody
|
5
|
+
EQUATORIAL_RADIUS = Distance.from_meters(695_700_000)
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
ASTRONOMICAL = :astronomical
|
13
|
-
].freeze
|
14
|
-
|
15
|
-
TWILIGHT_ANGLES = {
|
16
|
-
CIVIL => Angle.from_degrees(96),
|
17
|
-
NAUTICAL => Angle.from_degrees(102),
|
18
|
-
ASTRONOMICAL => Angle.from_degrees(108)
|
19
|
-
}.freeze
|
20
|
-
|
21
|
-
PERIODS_OF_THE_DAY = [
|
22
|
-
MORNING = :morning,
|
23
|
-
EVENING = :evening
|
24
|
-
].freeze
|
25
|
-
|
26
|
-
attr_reader :time
|
7
|
+
def self.ephemeris_segments(_ephem_source)
|
8
|
+
[[SOLAR_SYSTEM_BARYCENTER, SUN]]
|
9
|
+
end
|
27
10
|
|
28
11
|
# Source:
|
29
12
|
# Title: Astronomical Algorithms
|
@@ -31,215 +14,28 @@ module Astronoby
|
|
31
14
|
# Edition: 2nd edition
|
32
15
|
# Chapter: 28 - Equation of Time
|
33
16
|
|
34
|
-
# @param date_or_time [Date, Time] Requested date
|
35
17
|
# @return [Integer] Equation of time in seconds
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
epoch = Epoch.from_time(time)
|
40
|
-
sun = new(time: time)
|
41
|
-
right_ascension = sun
|
42
|
-
.apparent_ecliptic_coordinates
|
43
|
-
.to_apparent_equatorial(epoch: epoch)
|
44
|
-
.right_ascension
|
45
|
-
t = (epoch - Epoch::J2000) / Constants::DAYS_PER_JULIAN_MILLENIA
|
18
|
+
def equation_of_time
|
19
|
+
right_ascension = apparent.equatorial.right_ascension
|
20
|
+
t = (@instant.julian_date - Epoch::J2000) / Constants::DAYS_PER_JULIAN_MILLENIA
|
46
21
|
l0 = (280.4664567 +
|
47
22
|
360_007.6982779 * t +
|
48
23
|
0.03032028 * t**2 +
|
49
24
|
t**3 / 49_931 -
|
50
25
|
t**4 / 15_300 -
|
51
26
|
t**5 / 2_000_000) % Constants::DEGREES_PER_CIRCLE
|
52
|
-
nutation = Nutation.
|
53
|
-
obliquity = TrueObliquity.for_epoch(
|
27
|
+
nutation = Nutation.new(instant: instant).nutation_in_longitude
|
28
|
+
obliquity = TrueObliquity.for_epoch(@instant.julian_date)
|
54
29
|
|
55
30
|
(
|
56
31
|
Angle
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
32
|
+
.from_degrees(
|
33
|
+
l0 -
|
34
|
+
Constants::EQUATION_OF_TIME_CONSTANT -
|
35
|
+
right_ascension.degrees +
|
36
|
+
nutation.degrees * obliquity.cos
|
37
|
+
).hours * Constants::SECONDS_PER_HOUR
|
63
38
|
).round
|
64
39
|
end
|
65
|
-
|
66
|
-
# Source:
|
67
|
-
# Title: Celestial Calculations
|
68
|
-
# Author: J. L. Lawrence
|
69
|
-
# Edition: MIT Press
|
70
|
-
# Chapter: 6 - The Sun
|
71
|
-
|
72
|
-
# @param time [Time] Considered time
|
73
|
-
def initialize(time:)
|
74
|
-
@time = time
|
75
|
-
end
|
76
|
-
|
77
|
-
def epoch
|
78
|
-
@epoch ||= Epoch.from_time(@time)
|
79
|
-
end
|
80
|
-
|
81
|
-
def true_ecliptic_coordinates
|
82
|
-
Coordinates::Ecliptic.new(
|
83
|
-
latitude: Angle.zero,
|
84
|
-
longitude: true_longitude
|
85
|
-
)
|
86
|
-
end
|
87
|
-
|
88
|
-
def apparent_ecliptic_coordinates
|
89
|
-
nutation = Nutation.for_ecliptic_longitude(epoch: epoch)
|
90
|
-
longitude_with_aberration = Aberration.for_ecliptic_coordinates(
|
91
|
-
coordinates: true_ecliptic_coordinates,
|
92
|
-
epoch: epoch
|
93
|
-
).longitude
|
94
|
-
apparent_longitude = nutation + longitude_with_aberration
|
95
|
-
|
96
|
-
Coordinates::Ecliptic.new(
|
97
|
-
latitude: Angle.zero,
|
98
|
-
longitude: apparent_longitude
|
99
|
-
)
|
100
|
-
end
|
101
|
-
|
102
|
-
# Computes the Sun's horizontal coordinates
|
103
|
-
#
|
104
|
-
# @param observer [Astronoby::Observer] Observer of the event
|
105
|
-
# @return [Astronoby::Coordinates::Horizontal] Sun's horizontal coordinates
|
106
|
-
def horizontal_coordinates(observer:)
|
107
|
-
apparent_ecliptic_coordinates
|
108
|
-
.to_apparent_equatorial(epoch: epoch)
|
109
|
-
.to_horizontal(time: @time, observer: observer)
|
110
|
-
end
|
111
|
-
|
112
|
-
# @param observer [Astronoby::Observer] Observer of the event
|
113
|
-
# @return [Astronoby::Events::ObservationEvents] Sun's observation events
|
114
|
-
def observation_events(observer:)
|
115
|
-
today = @time.to_date
|
116
|
-
leap_seconds = Util::Time.terrestrial_universal_time_delta(today)
|
117
|
-
yesterday = today.prev_day
|
118
|
-
yesterday_midnight_terrestrial_time =
|
119
|
-
Time.utc(yesterday.year, yesterday.month, yesterday.day) - leap_seconds
|
120
|
-
yesterday_epoch = Epoch.from_time(yesterday_midnight_terrestrial_time)
|
121
|
-
today_midnight_terrestrial_time =
|
122
|
-
Time.utc(today.year, today.month, today.day) - leap_seconds
|
123
|
-
today_epoch = Epoch.from_time(today_midnight_terrestrial_time)
|
124
|
-
tomorrow = today.next_day
|
125
|
-
tomorrow_midnight_terrestrial_time =
|
126
|
-
Time.utc(tomorrow.year, tomorrow.month, tomorrow.day) - leap_seconds
|
127
|
-
tomorrow_epoch = Epoch.from_time(tomorrow_midnight_terrestrial_time)
|
128
|
-
|
129
|
-
coordinates_of_the_previous_day = self.class
|
130
|
-
.new(time: yesterday_midnight_terrestrial_time)
|
131
|
-
.apparent_ecliptic_coordinates
|
132
|
-
.to_apparent_equatorial(epoch: yesterday_epoch)
|
133
|
-
coordinates_of_the_day = self.class
|
134
|
-
.new(time: today_midnight_terrestrial_time)
|
135
|
-
.apparent_ecliptic_coordinates
|
136
|
-
.to_apparent_equatorial(epoch: today_epoch)
|
137
|
-
coordinates_of_the_next_day = self.class
|
138
|
-
.new(time: tomorrow_midnight_terrestrial_time)
|
139
|
-
.apparent_ecliptic_coordinates
|
140
|
-
.to_apparent_equatorial(epoch: tomorrow_epoch)
|
141
|
-
|
142
|
-
Events::ObservationEvents.new(
|
143
|
-
observer: observer,
|
144
|
-
date: today,
|
145
|
-
coordinates_of_the_previous_day: coordinates_of_the_previous_day,
|
146
|
-
coordinates_of_the_day: coordinates_of_the_day,
|
147
|
-
coordinates_of_the_next_day: coordinates_of_the_next_day,
|
148
|
-
additional_altitude: Angle.from_degrees(angular_size.degrees / 2)
|
149
|
-
)
|
150
|
-
end
|
151
|
-
|
152
|
-
# @param observer [Astronoby::Observer] Observer of the events
|
153
|
-
# @return [Astronoby::Events::TwilightEvents] Sun's twilight events
|
154
|
-
def twilight_events(observer:)
|
155
|
-
Events::TwilightEvents.new(sun: self, observer: observer)
|
156
|
-
end
|
157
|
-
|
158
|
-
# @return [Astronoby::Distance] Earth-Sun distance
|
159
|
-
def earth_distance
|
160
|
-
Distance.from_meters(
|
161
|
-
SEMI_MAJOR_AXIS_IN_METERS / distance_angular_size_factor
|
162
|
-
)
|
163
|
-
end
|
164
|
-
|
165
|
-
# @return [Astronoby::Angle] Apparent Sun's angular size
|
166
|
-
def angular_size
|
167
|
-
Angle.from_degrees(
|
168
|
-
ANGULAR_DIAMETER.degrees * distance_angular_size_factor
|
169
|
-
)
|
170
|
-
end
|
171
|
-
|
172
|
-
# @return [Astronoby::Angle] Sun's true anomaly
|
173
|
-
def true_anomaly
|
174
|
-
eccentric_anomaly = Util::Astrodynamics.eccentric_anomaly_newton_raphson(
|
175
|
-
mean_anomaly,
|
176
|
-
orbital_eccentricity.degrees,
|
177
|
-
2e-06,
|
178
|
-
10
|
179
|
-
)
|
180
|
-
|
181
|
-
tan = Math.sqrt(
|
182
|
-
(1 + orbital_eccentricity.degrees) / (1 - orbital_eccentricity.degrees)
|
183
|
-
) * Math.tan(eccentric_anomaly.radians / 2)
|
184
|
-
|
185
|
-
Angle.from_degrees(
|
186
|
-
(Angle.atan(tan).degrees * 2) % Constants::DEGREES_PER_CIRCLE
|
187
|
-
)
|
188
|
-
end
|
189
|
-
|
190
|
-
# @return [Astronoby::Angle] Sun's mean anomaly
|
191
|
-
def mean_anomaly
|
192
|
-
Angle.from_degrees(
|
193
|
-
(longitude_at_base_epoch - longitude_at_perigee).degrees %
|
194
|
-
Constants::DEGREES_PER_CIRCLE
|
195
|
-
)
|
196
|
-
end
|
197
|
-
|
198
|
-
# @return [Astronoby::Angle] Sun's longitude at perigee
|
199
|
-
def longitude_at_perigee
|
200
|
-
Angle.from_degrees(
|
201
|
-
(281.2208444 + 1.719175 * centuries + 0.000452778 * centuries**2) %
|
202
|
-
Constants::DEGREES_PER_CIRCLE
|
203
|
-
)
|
204
|
-
end
|
205
|
-
|
206
|
-
# @return [Astronoby::Angle] Sun's orbital eccentricity
|
207
|
-
def orbital_eccentricity
|
208
|
-
Angle.from_degrees(
|
209
|
-
(0.01675104 - 0.0000418 * centuries - 0.000000126 * centuries**2) %
|
210
|
-
Constants::DEGREES_PER_CIRCLE
|
211
|
-
)
|
212
|
-
end
|
213
|
-
|
214
|
-
private
|
215
|
-
|
216
|
-
def true_longitude
|
217
|
-
Angle.from_degrees(
|
218
|
-
(true_anomaly + longitude_at_perigee).degrees %
|
219
|
-
Constants::DEGREES_PER_CIRCLE
|
220
|
-
)
|
221
|
-
end
|
222
|
-
|
223
|
-
def days_since_epoch
|
224
|
-
Epoch::DEFAULT_EPOCH - epoch
|
225
|
-
end
|
226
|
-
|
227
|
-
def centuries
|
228
|
-
@centuries ||= (epoch - Epoch::J1900) / Constants::DAYS_PER_JULIAN_CENTURY
|
229
|
-
end
|
230
|
-
|
231
|
-
def longitude_at_base_epoch
|
232
|
-
Angle.from_degrees(
|
233
|
-
(279.6966778 + 36000.76892 * centuries + 0.0003025 * centuries**2) %
|
234
|
-
Constants::DEGREES_PER_CIRCLE
|
235
|
-
)
|
236
|
-
end
|
237
|
-
|
238
|
-
def distance_angular_size_factor
|
239
|
-
term1 = 1 + orbital_eccentricity.degrees * true_anomaly.cos
|
240
|
-
term2 = 1 - orbital_eccentricity.degrees**2
|
241
|
-
|
242
|
-
term1 / term2
|
243
|
-
end
|
244
40
|
end
|
245
41
|
end
|
data/lib/astronoby/constants.rb
CHANGED
@@ -15,8 +15,8 @@ module Astronoby
|
|
15
15
|
|
16
16
|
SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR
|
17
17
|
SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY
|
18
|
-
SECONDS_PER_DEGREE = SECONDS_PER_MINUTE * MINUTES_PER_DEGREE
|
19
18
|
RADIAN_PER_HOUR = Math::PI / 12.0
|
19
|
+
MICROSECOND_IN_DAYS = 1.0 / SECONDS_PER_DAY / 1e6
|
20
20
|
|
21
21
|
PI_IN_DEGREES = 180.0
|
22
22
|
|
@@ -26,6 +26,18 @@ module Astronoby
|
|
26
26
|
ASTRONOMICAL_UNIT_IN_METERS = 149_597_870_700
|
27
27
|
EARTH_EQUATORIAL_RADIUS_IN_METERS = 6378140
|
28
28
|
|
29
|
+
# WGS84 Earth Constants
|
30
|
+
WGS84_EARTH_EQUATORIAL_RADIUS_IN_METERS = 6378137
|
31
|
+
WGS84_INVERSE_FLATTENING = 298.257223563
|
32
|
+
WGS84_FLATTENING = 1.0 / WGS84_INVERSE_FLATTENING
|
33
|
+
WGS84_ECCENTICITY_SQUARED = 2.0 * WGS84_FLATTENING - WGS84_FLATTENING * WGS84_FLATTENING
|
34
|
+
|
35
|
+
LIGHT_SPEED_M_PER_S = 299_792_458
|
36
|
+
|
29
37
|
EARTH_FLATTENING_CORRECTION = 0.996647
|
38
|
+
|
39
|
+
EARTH_ANGULAR_VELOCITY_RAD_PER_S = 7.2921159e-5
|
40
|
+
|
41
|
+
TAI_TT_OFFSET = 32.184
|
30
42
|
end
|
31
43
|
end
|
@@ -10,43 +10,8 @@ module Astronoby
|
|
10
10
|
@longitude = longitude
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
# Author: J. L. Lawrence
|
16
|
-
# Edition: MIT Press
|
17
|
-
# Chapter: 4 - Orbits and Coordinate Systems
|
18
|
-
|
19
|
-
def to_true_equatorial(epoch:)
|
20
|
-
mean_obliquity = MeanObliquity.for_epoch(epoch)
|
21
|
-
to_equatorial(obliquity: mean_obliquity, epoch: epoch)
|
22
|
-
end
|
23
|
-
|
24
|
-
def to_apparent_equatorial(epoch:)
|
25
|
-
apparent_obliquity = TrueObliquity.for_epoch(epoch)
|
26
|
-
to_equatorial(obliquity: apparent_obliquity, epoch: epoch)
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def to_equatorial(obliquity:, epoch:)
|
32
|
-
y = Angle.from_radians(
|
33
|
-
@longitude.sin * obliquity.cos -
|
34
|
-
@latitude.tan * obliquity.sin
|
35
|
-
)
|
36
|
-
x = Angle.from_radians(@longitude.cos)
|
37
|
-
r = Angle.atan(y.radians / x.radians)
|
38
|
-
right_ascension = Util::Trigonometry.adjustement_for_arctangent(y, x, r)
|
39
|
-
|
40
|
-
declination = Angle.asin(
|
41
|
-
@latitude.sin * obliquity.cos +
|
42
|
-
@latitude.cos * obliquity.sin * @longitude.sin
|
43
|
-
)
|
44
|
-
|
45
|
-
Equatorial.new(
|
46
|
-
right_ascension: right_ascension,
|
47
|
-
declination: declination,
|
48
|
-
epoch: epoch
|
49
|
-
)
|
13
|
+
def self.zero
|
14
|
+
new(latitude: Angle.zero, longitude: Angle.zero)
|
50
15
|
end
|
51
16
|
end
|
52
17
|
end
|
@@ -17,6 +17,30 @@ module Astronoby
|
|
17
17
|
@epoch = epoch
|
18
18
|
end
|
19
19
|
|
20
|
+
def self.zero
|
21
|
+
new(declination: Angle.zero, right_ascension: Angle.zero)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.from_position_vector(position)
|
25
|
+
return zero if position.zero?
|
26
|
+
|
27
|
+
term1 = position.z.m
|
28
|
+
term2 = position.magnitude.m
|
29
|
+
declination = Angle.asin(term1 / term2)
|
30
|
+
|
31
|
+
term1 = position.y.m
|
32
|
+
term2 = position.x.m
|
33
|
+
angle = Angle.atan(term1 / term2)
|
34
|
+
right_ascension =
|
35
|
+
Astronoby::Util::Trigonometry.adjustement_for_arctangent(
|
36
|
+
term1,
|
37
|
+
term2,
|
38
|
+
angle
|
39
|
+
)
|
40
|
+
|
41
|
+
new(declination: declination, right_ascension: right_ascension)
|
42
|
+
end
|
43
|
+
|
20
44
|
def compute_hour_angle(time:, longitude:)
|
21
45
|
lst = GreenwichSiderealTime
|
22
46
|
.from_utc(time.utc)
|
@@ -38,6 +62,7 @@ module Astronoby
|
|
38
62
|
|
39
63
|
t1 = @declination.sin - latitude.sin * altitude.sin
|
40
64
|
t2 = t1 / (latitude.cos * altitude.cos)
|
65
|
+
t2 = t2.clamp(-1, 1)
|
41
66
|
azimuth = Angle.acos(t2)
|
42
67
|
|
43
68
|
if ha.sin.positive?
|
@@ -78,13 +103,6 @@ module Astronoby
|
|
78
103
|
longitude: longitude
|
79
104
|
)
|
80
105
|
end
|
81
|
-
|
82
|
-
def to_epoch(epoch)
|
83
|
-
Precession.for_equatorial_coordinates(
|
84
|
-
coordinates: self,
|
85
|
-
epoch: epoch
|
86
|
-
)
|
87
|
-
end
|
88
106
|
end
|
89
107
|
end
|
90
108
|
end
|
@@ -14,52 +14,6 @@ module Astronoby
|
|
14
14
|
@altitude = altitude
|
15
15
|
@observer = observer
|
16
16
|
end
|
17
|
-
|
18
|
-
def to_equatorial(time:)
|
19
|
-
t0 = @altitude.sin * latitude.sin +
|
20
|
-
@altitude.cos * latitude.cos * @azimuth.cos
|
21
|
-
|
22
|
-
declination = Angle.asin(t0)
|
23
|
-
|
24
|
-
t1 = @altitude.sin - latitude.sin * declination.sin
|
25
|
-
|
26
|
-
hour_angle_degrees = Angle
|
27
|
-
.acos(t1 / (latitude.cos * declination.cos))
|
28
|
-
.degrees
|
29
|
-
|
30
|
-
if @azimuth.sin.positive?
|
31
|
-
hour_angle_degrees = Angle
|
32
|
-
.from_degrees(Constants::DEGREES_PER_CIRCLE - hour_angle_degrees)
|
33
|
-
.degrees
|
34
|
-
end
|
35
|
-
|
36
|
-
hour_angle_hours = Angle.from_degrees(hour_angle_degrees).hours
|
37
|
-
lst = GreenwichSiderealTime
|
38
|
-
.from_utc(time.utc)
|
39
|
-
.to_lst(longitude: longitude)
|
40
|
-
right_ascension_decimal = lst.time - hour_angle_hours
|
41
|
-
|
42
|
-
if right_ascension_decimal.negative?
|
43
|
-
right_ascension_decimal += Constants::HOURS_PER_DAY
|
44
|
-
end
|
45
|
-
|
46
|
-
right_ascension = Angle.from_hours(right_ascension_decimal)
|
47
|
-
|
48
|
-
Equatorial.new(
|
49
|
-
right_ascension: right_ascension,
|
50
|
-
declination: declination
|
51
|
-
)
|
52
|
-
end
|
53
|
-
|
54
|
-
private
|
55
|
-
|
56
|
-
def latitude
|
57
|
-
@observer.latitude
|
58
|
-
end
|
59
|
-
|
60
|
-
def longitude
|
61
|
-
@observer.longitude
|
62
|
-
end
|
63
17
|
end
|
64
18
|
end
|
65
19
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Astronoby
|
4
|
+
module Correction
|
5
|
+
class LightTimeDelay
|
6
|
+
LIGHT_SPEED_CORRECTION_MAXIMUM_ITERATIONS = 10
|
7
|
+
LIGHT_SPEED_CORRECTION_PRECISION = 1e-12
|
8
|
+
|
9
|
+
def self.compute(center:, target:, ephem:)
|
10
|
+
new(center: center, target: target, ephem: ephem).compute
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(center:, target:, ephem:)
|
14
|
+
@center = center
|
15
|
+
@target = target
|
16
|
+
@ephem = ephem
|
17
|
+
end
|
18
|
+
|
19
|
+
def delay
|
20
|
+
@_delay ||= begin
|
21
|
+
compute
|
22
|
+
@delay
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def compute
|
27
|
+
@corrected_position ||= begin
|
28
|
+
corrected_position = Vector[
|
29
|
+
Distance.zero,
|
30
|
+
Distance.zero,
|
31
|
+
Distance.zero
|
32
|
+
]
|
33
|
+
corrected_velocity = Vector[
|
34
|
+
Velocity.zero,
|
35
|
+
Velocity.zero,
|
36
|
+
Velocity.zero
|
37
|
+
]
|
38
|
+
@delay = initial_delta_in_seconds
|
39
|
+
|
40
|
+
LIGHT_SPEED_CORRECTION_MAXIMUM_ITERATIONS.times do
|
41
|
+
new_instant = Instant.from_terrestrial_time(
|
42
|
+
instant.tt - @delay / Constants::SECONDS_PER_DAY
|
43
|
+
)
|
44
|
+
corrected = @target
|
45
|
+
.target_body
|
46
|
+
.geometric(ephem: @ephem, instant: new_instant)
|
47
|
+
corrected_position = corrected.position
|
48
|
+
corrected_velocity = corrected.velocity
|
49
|
+
|
50
|
+
corrected_distance_in_km = Math.sqrt(
|
51
|
+
(corrected_position.x.km - position.x.km)**2 +
|
52
|
+
(corrected_position.y.km - position.y.km)**2 +
|
53
|
+
(corrected_position.z.km - position.z.km)**2
|
54
|
+
)
|
55
|
+
|
56
|
+
new_delay = corrected_distance_in_km / Velocity.light_speed.kmps
|
57
|
+
|
58
|
+
break if (new_delay - @delay).abs < LIGHT_SPEED_CORRECTION_PRECISION
|
59
|
+
|
60
|
+
@delay = new_delay
|
61
|
+
end
|
62
|
+
|
63
|
+
[corrected_position, corrected_velocity]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def position
|
70
|
+
@position ||= @center.position
|
71
|
+
end
|
72
|
+
|
73
|
+
def instant
|
74
|
+
@center.instant
|
75
|
+
end
|
76
|
+
|
77
|
+
def initial_delta_in_seconds
|
78
|
+
distance_between_bodies_in_km / Velocity.light_speed.kmps
|
79
|
+
end
|
80
|
+
|
81
|
+
def distance_between_bodies_in_km
|
82
|
+
Math.sqrt(
|
83
|
+
(@target.position.x.km - position.x.km)**2 +
|
84
|
+
(@target.position.y.km - position.y.km)**2 +
|
85
|
+
(@target.position.z.km - position.z.km)**2
|
86
|
+
)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|