# File lib/kerbaldyn/orbit.rb, line 194 def primary_body_sphere_of_influence return self.semimajor_axis * (self.primary_body.mass / self.secondary_body.mass)**(0.4) end
class KerbalDyn::Orbit
The primary class for encapsulating an orbit around a primary body. At this time orbits are simplified to only consider the mass of the primary body, thus the orbit of the secondary body is around the center-of-mass of the primary body. This approximation works well for the Kerbal universe.
Constants
- BASE_PARAMETERS
A list of the independent parameters that define an orbit for this class.
- DEFAULT_OPTIONS
A map of default values for initialization parameters.
Attributes
The body being orbited (required) Expected to be an instance of Planetoid
.
The body in orbit (optional) Expected to be an instance of Planetoid
.
Public Class Methods
Convenience method for creating a circular orbit about the given body. This is redundant to calling new with the option of :radius.
# File lib/kerbaldyn/orbit.rb, line 101 def self.circular_orbit(primary_body, radius) return self.new(primary_body, :radius => radius) end
Convenience method for creating a circular orbit of a given period around a given body.
# File lib/kerbaldyn/orbit.rb, line 107 def self.circular_orbit_of_period(primary_body, period) planetoid_angular_velocity = 2.0 * Math::PI / period radius = (primary_body.gravitational_parameter / planetoid_angular_velocity**2)**(1.0/3.0) return self.circular_orbit(primary_body, radius) end
Convenience method for creating an escape orbit around the given body.
# File lib/kerbaldyn/orbit.rb, line 119 def self.escape_orbit(primary_body, periapsis) periapsis_escape_velocity = Math.sqrt(2.0 * primary_body.gravitational_parameter / periapsis) return self.new(primary_body, :periapsis => periapsis, :periapsis_velocity => periapsis_escape_velocity) end
Given a string, create an orbit for it. The string specification is one of:
- {planetoid}
-
The orbit for the planetoid around its parent body.
- {planetoid}@{number}{designator}
-
Builds an orbit around the given planetoid with the given radius or altitude in meters. The designator is one of r or a for radius or altitude. Defaults to radius.
# File lib/kerbaldyn/orbit.rb, line 129 def self.from_string(string) orbit_with_altitude_regex = /^([a-z]+)@([\d]+)([ra]{0,1})$/ expression = string.to_s.downcase case expression when /^([a-z]+)$/ planetoid_method = expression.to_sym raise ArgumentError, "Unknown planetoid: #{string}" unless Planetoid.planetoid_methods.include?(planetoid_method) self.send(planetoid_method) when orbit_with_altitude_regex matched, planetoid_name, distance, distance_designator = orbit_with_altitude_regex.match(expression).to_a planetoid_method = planetoid_name.to_sym raise ArgumentError, "Unknown planetoid: #{planetoid}" unless Planetoid.planetoid_methods.include?(planetoid_method) planetoid = Planetoid.send(planetoid_method) radius = (distance_designator=='a') ? (distance.to_f + planetoid.radius) : distance.to_f self.new(planetoid, :radius => radius) else raise ArgumentError, "Unknown orbit expression: #{string}" end end
Convenience method for creating a geostationary orbit around the given body.
# File lib/kerbaldyn/orbit.rb, line 114 def self.geostationary_orbit(primary_body) return self.circular_orbit_of_period(primary_body, primary_body.rotational_period) end
Create a new orbit.
The first argument should be the Body
(usually a Planetoid
) that is being orbited.
The second argument is a list of parameters which should include a size and eccentricity specification, and a may include other optional parameters.
To specify an orbit, at least one of the following pairs must be given:
-
periapsis, periapsis_velocity
-
periapsis, apoapsis
-
semimajor_axis
, eccentricity -
radius (assumes circular orbit)
The following additional parameters may be given:
-
inclination
-
longitude_of_ascending_node
-
argument_of_periapsis
-
mean_anomaly
-
epoch
# File lib/kerbaldyn/orbit.rb, line 169 def initialize(primary_body, options={}) # Set the primary planetoid self.primary_body = primary_body # Set the periapsis and periapsis_velocity from the options replaced_options = replace_orbital_parameters(options) # Default all the base parameters to zero if not given. process_options(replaced_options, DEFAULT_OPTIONS) end
Private Class Methods
For data read in from data files, this private method DRYs the process.
# File lib/kerbaldyn/orbit.rb, line 20 def self.make(planet_ref) # Get the data and dup it so we can muck with it. data = Data.fetch(:planet_data)[planet_ref][:orbit].dup # Get the primary/secondary body refs from it and then lookup to get the values. primary_body = Planetoid.send( data.delete(:primary_body) ) secondary_body = Planetoid.send( data.delete(:secondary_body) ) # Now construct the object. return self.new( primary_body, data.merge(:secondary_body => secondary_body) ).freeze end
Public Instance Methods
The apoapsis radius, if the eccentricity is less than one.
# File lib/kerbaldyn/orbit.rb, line 342 def apoapsis if self.closed? return self.semimajor_axis * (1 + self.eccentricity) else return nil end end
The apoapsis velocity, if the eccentricity is less than one.
# File lib/kerbaldyn/orbit.rb, line 351 def apoapsis_velocity if self.closed? e = self.eccentricity k = self.gravitational_parameter / self.semimajor_axis return Math.sqrt( (1-e)/(1+e) * k ) else return nil end end
Instantiates a new orbit with the same period and semimajor axis, zero inclination, and is circular.
This is useful for idealizing orbits for rough calculations.
# File lib/kerbaldyn/orbit.rb, line 368 def circularize return self.class.new(primary_body, { :secondary_body => self.secondary_body, :radius => self.semimajor_axis, :inclination => 0.0 }) end
Orbit
classification, returns one of :subelliptical, :circular, :elliptical, :parabolic, or :hyperbolic.
Because of how floats work, a delta is given for evaluation of “critical” points such as circular and elliptical orbits. The default value is 1e-9, however other values may be given.
# File lib/kerbaldyn/orbit.rb, line 231 def classification(delta=0.000000001) e = self.eccentricity if( e.abs < delta ) return :circular elsif( (e-1.0).abs < delta ) return :parabolic elsif( e > 0.0 && e < 1.0 ) return :elliptical elsif( e > 1.0 ) return :hyperbolic elsif( e < 0.0 ) return :subelliptical end end
Returns true if the orbit is a closed orbit (eccentricity < 1)
# File lib/kerbaldyn/orbit.rb, line 248 def closed? return self.eccentricity < 1.0 end
The orbit eccentricity.
# File lib/kerbaldyn/orbit.rb, line 288 def eccentricity return (self.periapsis * self.periapsis_velocity**2 / self.gravitational_parameter) - 1 end
This is yet another sphere of influence definition I came across, from the bottom of Wikipedia. This matched some numbers I got from a data dump, but don't match empirical data from the conic patching in game.
# File lib/kerbaldyn/orbit.rb, line 217 def equivalent_gravity_sphere_of_influence return self.periapsis * (self.secondary_body.mass / self.primary_body.mass)**(1.0/3.0) end
Returns the gravitational parameter for this orbit. Note that this currently is G*M rather than G*(M+m).
# File lib/kerbaldyn/orbit.rb, line 259 def gravitational_parameter return self.primary_body.gravitational_parameter end
The Hill Sphere radius. This comes from the approximation of L1/L2.
This is NOT the KSP SOI, for it, use kerbal_sphere_of_influence
# File lib/kerbaldyn/orbit.rb, line 210 def hill_sphere_radius return self.periapsis * (self.secondary_body.mass / (3.0*self.primary_body.mass))**(2.0/3.0) end
This is the mean angular velocity (angle change per unit time) for this orbit.
# File lib/kerbaldyn/orbit.rb, line 320 def mean_angular_velocity if self.closed? return 2.0 * Math::PI / self.period else return nil end end
This is the mean angular velocity (angle change per unit time) for this orbit.
This simply calls mean_angular_velocity
on self.
# File lib/kerbaldyn/orbit.rb, line 331 def mean_motion return self.mean_angular_velocity end
This is the velocity associated with the mean motion at the semimajor axis, This works out to be the velocity of an object in a circular orbit with the same period.
# File lib/kerbaldyn/orbit.rb, line 337 def mean_velocity return self.mean_motion * self.semimajor_axis end
Returns false if the orbit is closed.
# File lib/kerbaldyn/orbit.rb, line 253 def open? return !self.closed? end
The orbital period, if the eccentricity is less than one.
# File lib/kerbaldyn/orbit.rb, line 311 def period if self.closed? return 2.0 * Math::PI * Math.sqrt( self.semimajor_axis**3 / self.gravitational_parameter ) else return nil end end
Returns the sphere of influence (SOI) for the primary body in the context of the two-body system.
This is NOT the KSP SOI, for it, use kerbal_sphere_of_influence
Returns the sphere of influence (SOI) for the secondary body in the context of the two-body system.
In 0.17, for Mun, this matches to better than 0.015% error, while the others are way off.
# File lib/kerbaldyn/orbit.rb, line 202 def secondary_body_sphere_of_influence return self.semimajor_axis * (self.secondary_body.mass / self.primary_body.mass)**(0.4) end
The orbit semimajor-axis.
# File lib/kerbaldyn/orbit.rb, line 293 def semimajor_axis if self.closed? return self.periapsis / (1.0 - self.eccentricity) else return self.periapsis / (self.eccentricity - 1.0) end end
The orbit semiminor_axis
, if the eccentricity is less than one.
# File lib/kerbaldyn/orbit.rb, line 302 def semiminor_axis if self.closed? return self.semimajor_axis * Math.sqrt(1.0 - self.eccentricity**2) else return nil end end
The specific angular momentum for this orbit; this is constant over the entire orbit.
# File lib/kerbaldyn/orbit.rb, line 282 def specific_angular_momentum return self.periapsis * self.periapsis_velocity end
The total specific energyy of the orbit; this is constant over the entire orbit.
# File lib/kerbaldyn/orbit.rb, line 275 def specific_energy return self.specific_potential_energy(self.periapsis) + self.specific_kinetic_energy(self.periapsis_velocity) end
The specific kinetic energy for any given velocity.
# File lib/kerbaldyn/orbit.rb, line 269 def specific_kinetic_energy(v) return 0.5 * v**2 end
The specific potential energy for any given orbit radius.
# File lib/kerbaldyn/orbit.rb, line 264 def specific_potential_energy(r) return -self.gravitational_parameter / r end
Alias to the sphere of influence used in game.
Private Instance Methods
This takes one several sets of base parameters, and derives the periapsis and periapsis_velocity, and then replaces the original keys with them.
This is helper method for initialization.
# File lib/kerbaldyn/orbit.rb, line 382 def replace_orbital_parameters(options) # We don't want to mutate the options hash they passed in. opts = options.dup if( opts.include?(:periapsis) && opts.include?(:periapsis_velocity) ) return opts elsif( opts.include?(:periapsis) && opts.include?(:apoapsis) ) rp = opts[:periapsis] ra = opts.delete(:apoapsis) opts[:periapsis_velocity] = Math.sqrt( (2.0 * ra)/(ra+rp) * (self.gravitational_parameter / rp) ) elsif( opts.include?(:eccentricity) && opts.include?(:semimajor_axis) ) e = opts.delete(:eccentricity) a = opts.delete(:semimajor_axis) mu = self.gravitational_parameter opts[:periapsis] = rp = a*(1-e) opts[:periapsis_velocity] = Math.sqrt( (e+1)*mu/rp ) elsif( opts.include?(:radius) ) opts[:periapsis] = opts.delete(:radius) # This is a special case of the equation used for apoapsis/periapsis configuration, where they are equal. opts[:periapsis_velocity] = Math.sqrt( self.gravitational_parameter / opts[:periapsis] ) end return opts end
Library Methods
↑ topPublic Class Methods
# File lib/kerbaldyn/orbit.rb, line 95 def self.bop return @bop ||= make(__method__) end
# File lib/kerbaldyn/orbit.rb, line 65 def self.duna return @duna ||= make(__method__) end
# File lib/kerbaldyn/orbit.rb, line 55 def self.eve return @eve ||= make(__method__) end
# File lib/kerbaldyn/orbit.rb, line 60 def self.gilly return @gilly ||= make(__method__) end
# File lib/kerbaldyn/orbit.rb, line 70 def self.ike return @ike ||= make(__method__) end
# File lib/kerbaldyn/orbit.rb, line 75 def self.jool return @jool ||= make(__method__) end
# File lib/kerbaldyn/orbit.rb, line 35 def self.kerbin return @kerbin ||= make(__method__) end
# File lib/kerbaldyn/orbit.rb, line 80 def self.laythe return @laythe ||= make(__method__) end
# File lib/kerbaldyn/orbit.rb, line 45 def self.minmus return @minmus ||= make(__method__) end
# File lib/kerbaldyn/orbit.rb, line 50 def self.moho return @moho ||= make(__method__) end
# File lib/kerbaldyn/orbit.rb, line 40 def self.mun return @mun ||= make(__method__) end
# File lib/kerbaldyn/orbit.rb, line 90 def self.tylo return @tylo ||= make(__method__) end
# File lib/kerbaldyn/orbit.rb, line 85 def self.vall return @vall ||= make(__method__) end