kerbaldyn 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 (50) hide show
  1. data/.rspec +2 -0
  2. data/Gemfile +11 -0
  3. data/README.rdoc +57 -0
  4. data/Rakefile +23 -0
  5. data/kerbaldyn.gemspec +30 -0
  6. data/lib/kerbaldyn.rb +14 -0
  7. data/lib/kerbaldyn/body.rb +48 -0
  8. data/lib/kerbaldyn/constants.rb +12 -0
  9. data/lib/kerbaldyn/data.rb +56 -0
  10. data/lib/kerbaldyn/data/planet_data.json +249 -0
  11. data/lib/kerbaldyn/mixin.rb +2 -0
  12. data/lib/kerbaldyn/mixin/options_processor.rb +17 -0
  13. data/lib/kerbaldyn/mixin/parameter_attributes.rb +38 -0
  14. data/lib/kerbaldyn/orbit.rb +379 -0
  15. data/lib/kerbaldyn/orbital_maneuver.rb +6 -0
  16. data/lib/kerbaldyn/orbital_maneuver/base.rb +159 -0
  17. data/lib/kerbaldyn/orbital_maneuver/bielliptic.rb +61 -0
  18. data/lib/kerbaldyn/orbital_maneuver/burn_event.rb +57 -0
  19. data/lib/kerbaldyn/orbital_maneuver/hohmann.rb +48 -0
  20. data/lib/kerbaldyn/orbital_maneuver/inclination_change.rb +0 -0
  21. data/lib/kerbaldyn/part.rb +15 -0
  22. data/lib/kerbaldyn/part/base.rb +154 -0
  23. data/lib/kerbaldyn/part/fuel_tank.rb +11 -0
  24. data/lib/kerbaldyn/part/generic.rb +10 -0
  25. data/lib/kerbaldyn/part/liquid_fuel_engine.rb +69 -0
  26. data/lib/kerbaldyn/part/mixin.rb +1 -0
  27. data/lib/kerbaldyn/part/mixin/fuel_tank.rb +35 -0
  28. data/lib/kerbaldyn/part/rcs_fuel_tank.rb +10 -0
  29. data/lib/kerbaldyn/part/solid_rocket.rb +30 -0
  30. data/lib/kerbaldyn/part_library.rb +55 -0
  31. data/lib/kerbaldyn/planetoid.rb +214 -0
  32. data/lib/kerbaldyn/version.rb +13 -0
  33. data/spec/bielliptic_orbital_maneuver_spec.rb +60 -0
  34. data/spec/constants_spec.rb +9 -0
  35. data/spec/hohmann_orbital_maneuver_spec.rb +385 -0
  36. data/spec/options_processor_spec.rb +33 -0
  37. data/spec/orbit_spec.rb +357 -0
  38. data/spec/orbital_maneuver_base_spec.rb +74 -0
  39. data/spec/parameter_attributes_spec.rb +82 -0
  40. data/spec/part_library_spec.rb +21 -0
  41. data/spec/part_spec.rb +218 -0
  42. data/spec/planetoid_spec.rb +117 -0
  43. data/spec/spec_helper.rb +110 -0
  44. data/spec/support/parts/RCSFuelTank/part.cfg +42 -0
  45. data/spec/support/parts/fuelTank/part.cfg +48 -0
  46. data/spec/support/parts/liquidEngine1/part.cfg +60 -0
  47. data/spec/support/parts/liquidEngine2/part.cfg +64 -0
  48. data/spec/support/parts/solidBooster/part.cfg +67 -0
  49. data/spec/support/planet_test_data.json +340 -0
  50. metadata +95 -0
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rake'
6
+ gem 'rdoc'
7
+
8
+ group :test do
9
+ gem 'rspec'
10
+ gem 'debugger'
11
+ end
@@ -0,0 +1,57 @@
1
+ = Overview
2
+
3
+ A library for Kerbal Space Program (KSP) calculation and simulation tools.
4
+
5
+ <b>All units are mks (meters-kilograms-seconds) and all angles are radians.</b>
6
+
7
+ = Major Classes
8
+
9
+ [Planetoid] - Encapsulates parameters relating to suns, planets, and moons, such as Kerbal and Mun.
10
+ [Orbit] - Encapsulates parameters relating to orbits about a body.
11
+ [Maneuver] - Encapsulates parameters for orbit changes.
12
+
13
+ = Author
14
+
15
+ Jeff Reinecke
16
+ jeff@paploo.net
17
+
18
+ = TODO
19
+
20
+ * Refactor planetoid and orbit tests to use a JSON data file from a game dump.
21
+ * Add bielliptic transfer and tests.
22
+ * Build a tool for calculating lead angles: kerbaldyn leadangle kerbin@100a mun
23
+ * Build a tool for outputting body information in standard units: kerbaldyn info minmus
24
+ * Build a tool for calculating the delta-v of hohmann vs various bielliptic transfers: kerbaldyn transfer kerbin@900r minmus
25
+ * Build a tool for listing parts of a type with important specs, sorted in useful ways: kerbaldyn partlist --type liquidfuelengine --sort isp
26
+
27
+ Notes:
28
+ * Remember that bielliptic transfer high altitudes are theoretically limited by the SOI.
29
+ * Can specify orbits by planet@400a or planet@400r for 400km alt or 400km radius respectively.
30
+
31
+ = License
32
+
33
+ Copyright (c) 2012, Jeffrey C. Reinecke
34
+ All rights reserved.
35
+
36
+ Redistribution and use in source and binary forms, with or without
37
+ modification, are permitted provided that the following conditions are met:
38
+ * Redistributions of source code must retain the above copyright
39
+ notice, this list of conditions and the following disclaimer.
40
+ * Redistributions in binary form must reproduce the above copyright
41
+ notice, this list of conditions and the following disclaimer in the
42
+ documentation and/or other materials provided with the distribution.
43
+ * Neither the name of the copyright holders nor the
44
+ names of its contributors may be used to endorse or promote products
45
+ derived from this software without specific prior written permission.
46
+
47
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
48
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
49
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
50
+ DISCLAIMED. IN NO EVENT SHALL JEFFREY REINECKE BE LIABLE FOR ANY
51
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
52
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
53
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
54
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
55
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
56
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
57
+
@@ -0,0 +1,23 @@
1
+ require 'pathname'
2
+ require 'rdoc/task'
3
+ require 'rspec/core/rake_task'
4
+
5
+
6
+ RDoc::Task.new do |rdoc|
7
+ rdoc.rdoc_dir = 'rdoc'
8
+ rdoc.rdoc_files.add 'README.rdoc', 'LICENSE.txt', 'lib/**/*.rb'
9
+ end
10
+
11
+ RSpec::Core::RakeTask.new do |spec|
12
+ end
13
+
14
+
15
+ desc 'List all code todo lines'
16
+ task :todo do
17
+ project_path = Pathname.new(__FILE__).dirname.expand_path
18
+ search_paths = ['bin', 'lib', 'spec', 'util', 'Gemfile', 'kerbaldyn.gemspec']
19
+ cmd = "grep --color -REn 'TODO' #{search_paths.map {|sp| project_path+sp}.join(' ')}"
20
+ puts cmd
21
+ puts '-' * 72
22
+ exec(cmd)
23
+ end
@@ -0,0 +1,30 @@
1
+ require File.join(File.dirname(__FILE__), 'lib', 'kerbaldyn', 'version')
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'kerbaldyn'
5
+ s.version = KerbalDyn::VERSION
6
+
7
+ s.authors = ['Jeff Reinecke']
8
+ s.email = 'jeff@paploo.net'
9
+ s.homepage = 'http://www.github.com/paploo/kerbal-dyn'
10
+ s.summary = 'A library for Kerbal Space Program (KSP) calculation and simulation tools.'
11
+ s.description = 'A library for Kerbal Space Program (KSP) calculation and simulation tools.'
12
+ s.licenses = ['BSD']
13
+
14
+ s.required_ruby_version = '>=1.9.0'
15
+ s.require_paths = ['lib']
16
+ s.files = Dir[
17
+ 'README.rdoc',
18
+ 'Rakefile',
19
+ 'Gemfile',
20
+ 'LICENSE',
21
+ 'lib/**/*',
22
+ 'bin/**/*',
23
+ 'spec/**/*',
24
+ '.rspec',
25
+ '*.gemspec'
26
+ ]
27
+
28
+ s.has_rdoc = true
29
+ s.extra_rdoc_files = ['README.rdoc']
30
+ end
@@ -0,0 +1,14 @@
1
+ require_relative 'kerbaldyn/version'
2
+
3
+ require_relative 'kerbaldyn/data'
4
+
5
+ require_relative 'kerbaldyn/constants'
6
+ require_relative 'kerbaldyn/mixin'
7
+
8
+ require_relative 'kerbaldyn/part'
9
+ require_relative 'kerbaldyn/part_library'
10
+
11
+ require_relative 'kerbaldyn/body'
12
+ require_relative 'kerbaldyn/planetoid'
13
+ require_relative 'kerbaldyn/orbit'
14
+ require_relative 'kerbaldyn/orbital_maneuver'
@@ -0,0 +1,48 @@
1
+ module KerbalDyn
2
+ # The superclass for all Planetoid and Satellite instances.
3
+ class Body
4
+ include Mixin::ParameterAttributes
5
+ include Mixin::OptionsProcessor
6
+
7
+ # Options default. (Unlisted options will be nil)
8
+ DEFAULT_OPTIONS = {
9
+ :mass => 0.0,
10
+ :bounding_sphere_radius => 0.0,
11
+ :angular_velocity => 0.0
12
+ }
13
+
14
+ def self.test_particle
15
+ return self.new("Test Particle", :mass => 0.0, :bounding_sphere_radius => 0.0)
16
+ end
17
+
18
+ # Create a body with the given name and options.
19
+ #
20
+ # The options are:
21
+ # [mass] The mass of the body.
22
+ # [bounding_sphere_radius] The bounding sphere radius.
23
+ # [angular_velocity] The angular velocity around the axis of rotation.
24
+ def initialize(name, options={})
25
+ @name = name
26
+ process_options(options, DEFAULT_OPTIONS)
27
+ end
28
+
29
+ # The mass of the body.
30
+ attr_parameter :mass
31
+
32
+ # The bounding sphere radius
33
+ attr_parameter :bounding_sphere_radius
34
+
35
+ # The angluar velocity around the axis of rotation.
36
+ attr_parameter :angular_velocity
37
+
38
+ # The name of the body.
39
+ attr_accessor :name
40
+
41
+ # Sets the name of the body.
42
+ def name=(name)
43
+ @name = name && name.to_s
44
+ end
45
+
46
+ TEST_PARTICLE = self.test_particle
47
+ end
48
+ end
@@ -0,0 +1,12 @@
1
+ module KerbalDyn
2
+ # Definition of Physical constants.
3
+ #
4
+ # Note that known planetoid and orbital parameters are created via factory
5
+ # methods on the appropriate class.
6
+ module Constants
7
+
8
+ # Newton's gravitational constant.
9
+ G = 6.67300e-11
10
+
11
+ end
12
+ end
@@ -0,0 +1,56 @@
1
+ require 'pathname'
2
+
3
+ module KerbalDyn
4
+ # :nodoc: all
5
+ #
6
+ # A class for doing the work of getting and maintaining singletons of data resources.
7
+ #
8
+ # NOTE: There is NO reason a client to the library shoudl be in here; indeed, this
9
+ # is likely to drastically change, so using this class directly will result in
10
+ # trouble later.
11
+ class Data
12
+ # Files added here are automatically recognized by the fetch method.
13
+ # Files must be in the data directory.
14
+ FILE_MAP = {
15
+ :planet_data => 'planet_data.json'
16
+ }
17
+
18
+ # Fetch a data singleton by the stored key.
19
+ #
20
+ # If the key is unknown, then it attempts to fetch the data from disk.
21
+ def self.fetch(key)
22
+ registry = self.registry
23
+ data_obj = registry.include?(key) ? registry[key] : registry[key]=self.new(key, FILE_MAP[key])
24
+ return data_obj.data
25
+ end
26
+
27
+ # A method for directly getting the registry; this shoudl typically be treated as private.
28
+ def self.registry
29
+ return @registry ||= {}
30
+ end
31
+
32
+ # Initialize with the given key and data file name (in the data directory).
33
+ # This does NOT auto-add to the registry. Fetch will do so for entries in
34
+ # FILE_MAP.
35
+ def initialize(key, data_file_name)
36
+ # Get a handle on the file.
37
+ data_file = Pathname.new(__FILE__).dirname + 'data' + data_file_name.to_s
38
+ raise ArgumentError, "No such file #{data_file.to_s}" unless data_file.exist?
39
+
40
+ # Parse
41
+ @data = case data_file.extname
42
+ when '.json'
43
+ JSON.parse( data_file.read, :symbolize_names => true )
44
+ else
45
+ raise ArgumentError "Cannot parse files of type #{data_file.extname}"
46
+ end
47
+
48
+ # Set key and freeze
49
+ @key = key.freeze
50
+ @data.freeze
51
+ end
52
+
53
+ attr_reader :key, :data
54
+
55
+ end
56
+ end
@@ -0,0 +1,249 @@
1
+ {
2
+ "kerbin": {
3
+ "planetoid": {
4
+ "name": "Kerbin",
5
+ "gravitational_parameter": 3531600000000.0,
6
+ "radius": 600000.0,
7
+ "rotational_period": 21600.0
8
+ },
9
+ "orbit": {
10
+ "primary_body": "kerbol",
11
+ "secondary_body": "kerbin",
12
+ "semimajor_axis": 13599840256.0,
13
+ "eccentricity": 0.0,
14
+ "mean_anomaly": 3.1400001049041752,
15
+ "inclination": 0.0,
16
+ "longitude_of_ascending_node": 0.0,
17
+ "argument_of_periapsis": 0.0,
18
+ "epoch": 0.0
19
+ }
20
+ },
21
+ "mun": {
22
+ "planetoid": {
23
+ "name": "Mun",
24
+ "gravitational_parameter": 65138397520.7806,
25
+ "radius": 200000.0,
26
+ "rotational_period": 138984.376574476
27
+ },
28
+ "orbit": {
29
+ "primary_body": "kerbin",
30
+ "secondary_body": "mun",
31
+ "semimajor_axis": 12000000.0,
32
+ "eccentricity": 0.0,
33
+ "mean_anomaly": 1.7000000476837156,
34
+ "inclination": 0.0,
35
+ "longitude_of_ascending_node": 0.0,
36
+ "argument_of_periapsis": 0.0,
37
+ "epoch": 0.0
38
+ }
39
+ },
40
+ "minmus": {
41
+ "planetoid": {
42
+ "name": "Minmus",
43
+ "gravitational_parameter": 1765800026.31247,
44
+ "radius": 60000.0,
45
+ "rotational_period": 40400.0
46
+ },
47
+ "orbit": {
48
+ "primary_body": "kerbin",
49
+ "secondary_body": "minmus",
50
+ "semimajor_axis": 47000000.0,
51
+ "eccentricity": 0.0,
52
+ "mean_anomaly": 0.8999999761581429,
53
+ "inclination": 0.10471975511965977,
54
+ "longitude_of_ascending_node": 1.361356816555577,
55
+ "argument_of_periapsis": 0.6632251157578452,
56
+ "epoch": 0.0
57
+ }
58
+ },
59
+ "duna": {
60
+ "planetoid": {
61
+ "name": "Duna",
62
+ "gravitational_parameter": 301363211975.098,
63
+ "radius": 320000.0,
64
+ "rotational_period": 65517.859375
65
+ },
66
+ "orbit": {
67
+ "primary_body": "kerbol",
68
+ "secondary_body": "duna",
69
+ "semimajor_axis": 20726155264.0,
70
+ "eccentricity": 0.0509999990463257,
71
+ "mean_anomaly": 3.1400001049041752,
72
+ "inclination": 0.0010471975277899085,
73
+ "longitude_of_ascending_node": 2.3649211364523164,
74
+ "argument_of_periapsis": 0.0,
75
+ "epoch": 0.0
76
+ }
77
+ },
78
+ "ike": {
79
+ "planetoid": {
80
+ "name": "Ike",
81
+ "gravitational_parameter": 18568368573.1441,
82
+ "radius": 130000.0,
83
+ "rotational_period": 65517.8621348081
84
+ },
85
+ "orbit": {
86
+ "primary_body": "duna",
87
+ "secondary_body": "ike",
88
+ "semimajor_axis": 3200000.0,
89
+ "eccentricity": 0.0299999993294477,
90
+ "mean_anomaly": 1.7000000476837156,
91
+ "inclination": 0.00349065855600352,
92
+ "longitude_of_ascending_node": 0.0,
93
+ "argument_of_periapsis": 0.0,
94
+ "epoch": 0.0
95
+ }
96
+ },
97
+ "moho": {
98
+ "planetoid": {
99
+ "name": "Moho",
100
+ "gravitational_parameter": 245250003654.51,
101
+ "radius": 250000.0,
102
+ "rotational_period": 2215754.21968432
103
+ },
104
+ "orbit": {
105
+ "primary_body": "kerbol",
106
+ "secondary_body": "moho",
107
+ "semimajor_axis": 5263138304.0,
108
+ "eccentricity": 0.200000002980232,
109
+ "mean_anomaly": 3.1400001049041752,
110
+ "inclination": 0.12217304763960307,
111
+ "longitude_of_ascending_node": 1.2217304763960306,
112
+ "argument_of_periapsis": 0.2617993877991494,
113
+ "epoch": 0.0
114
+ }
115
+ },
116
+ "eve": {
117
+ "planetoid": {
118
+ "name": "Eve",
119
+ "gravitational_parameter": 8171730229210.85,
120
+ "radius": 700000.0,
121
+ "rotational_period": 80500.0
122
+ },
123
+ "orbit": {
124
+ "primary_body": "kerbol",
125
+ "secondary_body": "eve",
126
+ "semimajor_axis": 9832684544.0,
127
+ "eccentricity": 0.00999999977648258,
128
+ "mean_anomaly": 3.1400001049041752,
129
+ "inclination": 0.03665191262740527,
130
+ "longitude_of_ascending_node": 0.2617993877991494,
131
+ "argument_of_periapsis": 0.0,
132
+ "epoch": 0.0
133
+ }
134
+ },
135
+ "gilly": {
136
+ "planetoid": {
137
+ "name": "Gilly",
138
+ "gravitational_parameter": 8289449.81471635,
139
+ "radius": 13000.0,
140
+ "rotational_period": 28255.0
141
+ },
142
+ "orbit": {
143
+ "primary_body": "eve",
144
+ "secondary_body": "gilly",
145
+ "semimajor_axis": 31500000.0,
146
+ "eccentricity": 0.550000011920929,
147
+ "mean_anomaly": 0.8999999761581429,
148
+ "inclination": 0.20943951023931953,
149
+ "longitude_of_ascending_node": 1.3962634015954636,
150
+ "argument_of_periapsis": 0.17453292519943295,
151
+ "epoch": 0.0
152
+ }
153
+ },
154
+ "jool": {
155
+ "planetoid": {
156
+ "name": "Jool",
157
+ "gravitational_parameter": 282528004209995.0,
158
+ "radius": 6000000.0,
159
+ "rotational_period": 36000.0
160
+ },
161
+ "orbit": {
162
+ "primary_body": "kerbol",
163
+ "secondary_body": "jool",
164
+ "semimajor_axis": 68773560320.0,
165
+ "eccentricity": 0.0500000007450581,
166
+ "mean_anomaly": 0.10000000149011617,
167
+ "inclination": 0.022759093795545936,
168
+ "longitude_of_ascending_node": 0.9075712110370514,
169
+ "argument_of_periapsis": 0.0,
170
+ "epoch": 0.0
171
+ }
172
+ },
173
+ "vall": {
174
+ "planetoid": {
175
+ "name": "Vall",
176
+ "gravitational_parameter": 207481499473.751,
177
+ "radius": 300000.0,
178
+ "rotational_period": 105962.088893924
179
+ },
180
+ "orbit": {
181
+ "primary_body": "jool",
182
+ "secondary_body": "vall",
183
+ "semimajor_axis": 43152000.0,
184
+ "eccentricity": 0.0,
185
+ "mean_anomaly": 0.8999999761581429,
186
+ "inclination": 0.0,
187
+ "longitude_of_ascending_node": 0.0,
188
+ "argument_of_periapsis": 0.0,
189
+ "epoch": 0.0
190
+ }
191
+ },
192
+ "laythe": {
193
+ "planetoid": {
194
+ "name": "Laythe",
195
+ "gravitational_parameter": 1962000029236.08,
196
+ "radius": 500000.0,
197
+ "rotational_period": 52980.8790593796
198
+ },
199
+ "orbit": {
200
+ "primary_body": "jool",
201
+ "secondary_body": "laythe",
202
+ "semimajor_axis": 27184000.0,
203
+ "eccentricity": 0.0,
204
+ "mean_anomaly": 3.1400001049041752,
205
+ "inclination": 0.0,
206
+ "longitude_of_ascending_node": 0.0,
207
+ "argument_of_periapsis": 0.0,
208
+ "epoch": 0.0
209
+ }
210
+ },
211
+ "tylo": {
212
+ "planetoid": {
213
+ "name": "Tylo",
214
+ "gravitational_parameter": 2825280042099.95,
215
+ "radius": 600000.0,
216
+ "rotational_period": 211926.35802123
217
+ },
218
+ "orbit": {
219
+ "primary_body": "jool",
220
+ "secondary_body": "tylo",
221
+ "semimajor_axis": 68500000.0,
222
+ "eccentricity": 0.0,
223
+ "mean_anomaly": 3.1400001049041752,
224
+ "inclination": 0.00043633231950044,
225
+ "longitude_of_ascending_node": 0.0,
226
+ "argument_of_periapsis": 0.0,
227
+ "epoch": 0.0
228
+ }
229
+ },
230
+ "bop": {
231
+ "planetoid": {
232
+ "name": "Bop",
233
+ "gravitational_parameter": 2486834944.41491,
234
+ "radius": 65000.0,
235
+ "rotational_period": 12950.0
236
+ },
237
+ "orbit": {
238
+ "primary_body": "jool",
239
+ "secondary_body": "bop",
240
+ "semimajor_axis": 104500000.0,
241
+ "eccentricity": 0.234999999403954,
242
+ "mean_anomaly": 0.8999999761581429,
243
+ "inclination": 0.2617993877991494,
244
+ "longitude_of_ascending_node": 0.17453292519943295,
245
+ "argument_of_periapsis": 0.4363323129985824,
246
+ "epoch": 0.0
247
+ }
248
+ }
249
+ }