kerbaldyn 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }