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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -0
  3. data/.standard.yml +1 -0
  4. data/CHANGELOG.md +116 -0
  5. data/Gemfile.lock +45 -23
  6. data/README.md +42 -285
  7. data/UPGRADING.md +238 -0
  8. data/lib/astronoby/aberration.rb +56 -31
  9. data/lib/astronoby/angle.rb +20 -16
  10. data/lib/astronoby/angles/dms.rb +2 -2
  11. data/lib/astronoby/angles/hms.rb +2 -2
  12. data/lib/astronoby/bodies/earth.rb +56 -0
  13. data/lib/astronoby/bodies/jupiter.rb +11 -0
  14. data/lib/astronoby/bodies/mars.rb +11 -0
  15. data/lib/astronoby/bodies/mercury.rb +11 -0
  16. data/lib/astronoby/bodies/moon.rb +50 -290
  17. data/lib/astronoby/bodies/neptune.rb +11 -0
  18. data/lib/astronoby/bodies/saturn.rb +11 -0
  19. data/lib/astronoby/bodies/solar_system_body.rb +122 -0
  20. data/lib/astronoby/bodies/sun.rb +16 -220
  21. data/lib/astronoby/bodies/uranus.rb +11 -0
  22. data/lib/astronoby/bodies/venus.rb +11 -0
  23. data/lib/astronoby/constants.rb +13 -1
  24. data/lib/astronoby/coordinates/ecliptic.rb +2 -37
  25. data/lib/astronoby/coordinates/equatorial.rb +25 -7
  26. data/lib/astronoby/coordinates/horizontal.rb +0 -46
  27. data/lib/astronoby/corrections/light_time_delay.rb +90 -0
  28. data/lib/astronoby/deflection.rb +187 -0
  29. data/lib/astronoby/distance.rb +9 -0
  30. data/lib/astronoby/ephem.rb +39 -0
  31. data/lib/astronoby/equinox_solstice.rb +21 -18
  32. data/lib/astronoby/errors.rb +4 -0
  33. data/lib/astronoby/events/moon_phases.rb +2 -1
  34. data/lib/astronoby/events/rise_transit_set_calculator.rb +352 -0
  35. data/lib/astronoby/events/rise_transit_set_event.rb +13 -0
  36. data/lib/astronoby/events/rise_transit_set_events.rb +13 -0
  37. data/lib/astronoby/events/twilight_calculator.rb +166 -0
  38. data/lib/astronoby/events/twilight_event.rb +28 -0
  39. data/lib/astronoby/instant.rb +171 -0
  40. data/lib/astronoby/mean_obliquity.rb +23 -10
  41. data/lib/astronoby/nutation.rb +227 -42
  42. data/lib/astronoby/observer.rb +55 -0
  43. data/lib/astronoby/precession.rb +91 -17
  44. data/lib/astronoby/reference_frame.rb +49 -0
  45. data/lib/astronoby/reference_frames/apparent.rb +60 -0
  46. data/lib/astronoby/reference_frames/astrometric.rb +21 -0
  47. data/lib/astronoby/reference_frames/geometric.rb +20 -0
  48. data/lib/astronoby/reference_frames/mean_of_date.rb +38 -0
  49. data/lib/astronoby/reference_frames/topocentric.rb +82 -0
  50. data/lib/astronoby/true_obliquity.rb +2 -1
  51. data/lib/astronoby/util/maths.rb +70 -73
  52. data/lib/astronoby/util/time.rb +454 -31
  53. data/lib/astronoby/vector.rb +36 -0
  54. data/lib/astronoby/velocity.rb +116 -0
  55. data/lib/astronoby/version.rb +1 -1
  56. data/lib/astronoby.rb +26 -5
  57. metadata +61 -16
  58. data/.tool-versions +0 -1
  59. data/lib/astronoby/astronomical_models/ephemeride_lunaire_parisienne.rb +0 -143
  60. data/lib/astronoby/events/observation_events.rb +0 -285
  61. data/lib/astronoby/events/rise_transit_set_iteration.rb +0 -218
  62. data/lib/astronoby/events/twilight_events.rb +0 -121
  63. data/lib/astronoby/util/astrodynamics.rb +0 -60
@@ -1,29 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
- class Sun
5
- SEMI_MAJOR_AXIS_IN_METERS = 149_598_500_000
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
- TWILIGHTS = [
10
- CIVIL = :civil,
11
- NAUTICAL = :nautical,
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 self.equation_of_time(date_or_time:)
37
- noon = Time.utc(date_or_time.year, date_or_time.month, date_or_time.day, 12)
38
- time = date_or_time.is_a?(Time) ? date_or_time : noon
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.for_ecliptic_longitude(epoch: epoch)
53
- obliquity = TrueObliquity.for_epoch(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
- .from_degrees(
58
- l0 -
59
- Constants::EQUATION_OF_TIME_CONSTANT -
60
- right_ascension.degrees +
61
- nutation.degrees * obliquity.cos
62
- ).hours * Constants::SECONDS_PER_HOUR
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
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ class Uranus < SolarSystemBody
5
+ EQUATORIAL_RADIUS = Distance.from_meters(25_559_000)
6
+
7
+ def self.ephemeris_segments(_ephem_source)
8
+ [[SOLAR_SYSTEM_BARYCENTER, URANUS_BARYCENTER]]
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Astronoby
4
+ class Venus < SolarSystemBody
5
+ EQUATORIAL_RADIUS = Distance.from_meters(6_051_800)
6
+
7
+ def self.ephemeris_segments(_ephem_source)
8
+ [[SOLAR_SYSTEM_BARYCENTER, VENUS_BARYCENTER]]
9
+ end
10
+ end
11
+ end
@@ -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
- # Source:
14
- # Title: Celestial Calculations
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