korba 0.5.0 → 0.6.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.
data/lib/korba/tle.rb CHANGED
@@ -5,7 +5,10 @@ module Korba
5
5
  class Tle
6
6
  include OrbitUtils
7
7
 
8
- attr_reader :tle_json, :tle_string, :object_name, :object_id, :epoch, :mean_motion, :eccentricity, :inclination, :ra_of_asc_node, :arg_of_pericenter, :mean_anomaly
8
+ attr_reader :tle_json, :tle_string, :object_id, :object_name, :epoch_datetime, :julian_date,
9
+ :satellite_number, :classification_type, :epoch, :mean_motion_dot, :mean_motion_ddot, :bstar, :element_set_no,
10
+ :inclination, :ra_of_asc_node, :eccentricity, :arg_of_pericenter, :mean_anomaly, :mean_motion, :revolution_number,
11
+ :element_set_record, :epoch_days
9
12
 
10
13
  def initialize(tle = nil, type: :string)
11
14
  return if tle.nil?
@@ -16,6 +19,8 @@ module Korba
16
19
  when :json
17
20
  initialize_from_json(tle)
18
21
  end
22
+ set_epoch_datetime_and_julian_date
23
+ set_element_set_record_values
19
24
  end
20
25
 
21
26
  def to_kep
@@ -34,6 +39,18 @@ module Korba
34
39
  kep.to_car
35
40
  end
36
41
 
42
+ def propagate_to(minutesAfterEpoch)
43
+ r = [0, 0, 0]
44
+ v = [0, 0, 0]
45
+
46
+ @element_set_record.error = 0
47
+ SGP4.sgp4(@element_set_record, minutesAfterEpoch, r, v)
48
+ @sgp4Error = @element_set_record.error
49
+ r = r.map { _1 * 1000 }
50
+ v = v.map { _1 * 1000 }
51
+ Car.new(object_name:, epoch:, x: r[0], y: r[1], z: r[2], vx: v[0], vy: v[1], vz: v[2])
52
+ end
53
+
37
54
  private
38
55
 
39
56
  def initialize_from_string(tle_string)
@@ -46,12 +63,31 @@ module Korba
46
63
 
47
64
  def parse_line1(line1_strings)
48
65
  # TODO: object_id
66
+ @satellite_number = line1_strings[1][0..4].to_i
67
+ @classification_type = line1_strings[1][-1]
49
68
  # For now, only supports years after 2000
50
69
  epoch_year = line1_strings[3][0..1].to_i + 2000
51
- epoch_day_of_year = line1_strings[3][2..].to_f
52
- # Subtract 1 from epoch_day_of_year because January 1st is considered day 1
53
- epoch_time = Time.new(epoch_year, 1, 1, 0, 0, 0, "+00:00") + (epoch_day_of_year - 1) * 24 * 60 * 60
70
+ @epoch_days = line1_strings[3][2..].to_f
71
+ # Subtract 1 from epoch_days because January 1st is considered day 1
72
+ epoch_time = Time.new(epoch_year, 1, 1, 0, 0, 0, "+00:00") + (epoch_days - 1) * 24 * 60 * 60
54
73
  @epoch = epoch_time.strftime("%Y-%m-%dT%H:%M:%S.%6N")
74
+
75
+ mean_motion_dot_sign = line1_strings[4][0] == "-" ? -1 : 1
76
+ mean_motion_dot_value_start = line1_strings[4].size == 10 ? 1 : 0
77
+ @mean_motion_dot = mean_motion_dot_sign * "0#{line1_strings[4][mean_motion_dot_value_start..]}".to_f
78
+
79
+ mean_motion_ddot_sign = line1_strings[5][0] == "-" ? -1 : 1
80
+ mean_motion_ddot_value_start = line1_strings[5].size == 8 ? 1 : 0
81
+ mean_motion_ddot_exponent = line1_strings[5][mean_motion_ddot_value_start + 5..mean_motion_ddot_value_start + 6].to_i
82
+ @mean_motion_ddot =
83
+ mean_motion_ddot_sign * "0.#{line1_strings[5][mean_motion_ddot_value_start..mean_motion_ddot_value_start + 4]}".to_f * 10 ** mean_motion_ddot_exponent
84
+
85
+ bstar_sign = line1_strings[6][0] == "-" ? -1 : 1
86
+ bstar_value_start = line1_strings[6].size == 8 ? 1 : 0
87
+ bstar_exponent = line1_strings[6][bstar_value_start + 5..bstar_value_start + 6].to_i
88
+ @bstar = bstar_sign * "0.#{line1_strings[6][bstar_value_start..bstar_value_start + 4]}".to_f * 10 ** bstar_exponent
89
+
90
+ @element_set_no = line1_strings[8][0..2].to_i
55
91
  end
56
92
 
57
93
  def parse_line2(line2_strings)
@@ -60,20 +96,62 @@ module Korba
60
96
  @eccentricity = "0.#{line2_strings[4]}".to_f
61
97
  @arg_of_pericenter = line2_strings[5].to_f
62
98
  @mean_anomaly = line2_strings[6].to_f
63
- @mean_motion = line2_strings[7].to_f
99
+ @mean_motion = line2_strings[7][0..10].to_f
100
+ @revolution_number = line2_strings[7][11..15].to_i
64
101
  end
65
102
 
66
103
  def initialize_from_json(tle_json)
67
104
  @tle_json = tle_json
68
105
  @object_name = tle_json[:OBJECT_NAME]
69
106
  @object_id = tle_json[:OBJECT_ID]
107
+ @satellite_number = tle_json[:NORAD_CAT_ID]
108
+ @classification_type = tle_json[:CLASSIFICATION_TYPE]
70
109
  @epoch = tle_json[:EPOCH]
110
+ @mean_motion_dot = tle_json[:MEAN_MOTION_DOT]
111
+ @mean_motion_ddot = tle_json[:MEAN_MOTION_DDOT]
112
+ @bstar = tle_json[:BSTAR]
113
+ @element_set_no = tle_json[:ELEMENT_SET_NO]
71
114
  @mean_motion = tle_json[:MEAN_MOTION]
72
115
  @eccentricity = tle_json[:ECCENTRICITY]
73
116
  @inclination = tle_json[:INCLINATION]
74
117
  @ra_of_asc_node = tle_json[:RA_OF_ASC_NODE]
75
118
  @arg_of_pericenter = tle_json[:ARG_OF_PERICENTER]
76
119
  @mean_anomaly = tle_json[:MEAN_ANOMALY]
120
+ @revolution_number = tle_json[:REV_AT_EPOCH]
121
+ end
122
+
123
+ def set_epoch_datetime_and_julian_date
124
+ @epoch_datetime = Time.new(@epoch + " UTC")
125
+ @julian_date = SGP4.jday(
126
+ epoch_datetime.year, epoch_datetime.mon, epoch_datetime.day, epoch_datetime.hour, epoch_datetime.min, epoch_datetime.sec
127
+ )
128
+ end
129
+
130
+ def set_element_set_record_values
131
+ @element_set_record = ElsetRec.new
132
+ @element_set_record.whichconst = 3 # wgs84
133
+ @element_set_record.epochyr = epoch_datetime.year
134
+ @element_set_record.epochdays = epoch_days
135
+ @element_set_record.jdsatepoch = julian_date[0]
136
+ @element_set_record.jdsatepochF = julian_date[1]
137
+
138
+ @element_set_record.classification = classification_type
139
+ @element_set_record.elnum = element_set_no
140
+ @element_set_record.revnum = revolution_number
141
+ @element_set_record.satnum = satellite_number
142
+ @element_set_record.bstar = bstar
143
+ @element_set_record.inclo = deg_to_rad(inclination)
144
+ @element_set_record.nodeo = deg_to_rad(ra_of_asc_node)
145
+ @element_set_record.argpo = deg_to_rad(arg_of_pericenter)
146
+ @element_set_record.mo = deg_to_rad(mean_anomaly)
147
+ @element_set_record.ecco = eccentricity
148
+
149
+ xpdotp = 1440.0 / (2.0 * Math::PI)
150
+ @element_set_record.no_kozai = mean_motion / xpdotp
151
+ @element_set_record.ndot = mean_motion_dot / (xpdotp * 1440.0)
152
+ @element_set_record.nddot = mean_motion_ddot / (xpdotp * 1440.0 * 1440.0)
153
+ # update element_set_record
154
+ SGP4.sgp4init("a", @element_set_record)
77
155
  end
78
156
  end
79
157
  end
data/lib/korba/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Korba
4
- VERSION = "0.5.0"
4
+ VERSION = "0.6.0"
5
5
  end
data/lib/korba.rb CHANGED
@@ -7,6 +7,8 @@ require_relative "korba/kep"
7
7
  require_relative "korba/car"
8
8
  require_relative "korba/orbit_utils"
9
9
  require_relative "korba/kepler_equation_fucntion"
10
+ require_relative "korba/sgp4/elset_rec"
11
+ require_relative "korba/sgp4/sgp4"
10
12
 
11
13
  module Korba
12
14
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: korba
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - kk0000-kk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-12-15 00:00:00.000000000 Z
11
+ date: 2024-12-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Orbital elements calculation library
14
14
  email:
@@ -28,6 +28,8 @@ files:
28
28
  - lib/korba/kepler_equation_fucntion.rb
29
29
  - lib/korba/newton_function.rb
30
30
  - lib/korba/orbit_utils.rb
31
+ - lib/korba/sgp4/elset_rec.rb
32
+ - lib/korba/sgp4/sgp4.rb
31
33
  - lib/korba/tle.rb
32
34
  - lib/korba/version.rb
33
35
  - sig/korba.rbs