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

primary_body[RW]

The body being orbited (required) Expected to be an instance of Planetoid.

secondary_body[RW]

The body in orbit (optional) Expected to be an instance of Planetoid.

Public Class Methods

circular_orbit(primary_body, radius) click to toggle source

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
circular_orbit_of_period(primary_body, period) click to toggle source

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
escape_orbit(primary_body, periapsis) click to toggle source

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
from_string(string) click to toggle source

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
geostationary_orbit(primary_body) click to toggle source

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
new(primary_body, options={}) click to toggle source

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

make(planet_ref) click to toggle source

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

angular_momentum()
apoapsis() click to toggle source

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
apoapsis_velocity() click to toggle source

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
circularize() click to toggle source

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
classification(delta=0.000000001) click to toggle source

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
Also aliased as: kind
closed?() click to toggle source

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
eccentricity() click to toggle source

The orbit eccentricity.

# File lib/kerbaldyn/orbit.rb, line 288
def eccentricity
  return (self.periapsis * self.periapsis_velocity**2 / self.gravitational_parameter) - 1
end
equivalent_gravity_sphere_of_influence() click to toggle source

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
gravitational_parameter() click to toggle source

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
hill_sphere_radius() click to toggle source

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
kind(delta=0.000000001)
Alias for: classification
laplace_sphere_of_influence()
mean_angular_velocity() click to toggle source

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
mean_motion() click to toggle source

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
mean_velocity() click to toggle source

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
open?() click to toggle source

Returns false if the orbit is closed.

# File lib/kerbaldyn/orbit.rb, line 253
def open?
  return !self.closed?
end
period() click to toggle source

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
primary_body_sphere_of_influence() click to toggle source

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

# 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
secondary_body_sphere_of_influence() click to toggle source

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
semimajor_axis() click to toggle source

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
semiminor_axis() click to toggle source

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
soi()
Alias for: sphere_of_influence
specific_angular_momentum() click to toggle source

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
Also aliased as: angular_momentum
specific_energy() click to toggle source

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
Also aliased as: vis_viva_energy
specific_kinetic_energy(v) click to toggle source

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
specific_potential_energy(r) click to toggle source

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
sphere_of_influence()

Alias to the sphere of influence used in game.

Also aliased as: soi
vis_viva_energy()
Alias for: specific_energy

Private Instance Methods

replace_orbital_parameters(options) click to toggle source

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

↑ top

Public Class Methods

bop() click to toggle source
# File lib/kerbaldyn/orbit.rb, line 95
def self.bop
  return @bop ||= make(__method__)
end
duna() click to toggle source
# File lib/kerbaldyn/orbit.rb, line 65
def self.duna
  return @duna ||= make(__method__)
end
eve() click to toggle source
# File lib/kerbaldyn/orbit.rb, line 55
def self.eve
  return @eve ||= make(__method__)
end
gilly() click to toggle source
# File lib/kerbaldyn/orbit.rb, line 60
def self.gilly
  return @gilly ||= make(__method__)
end
ike() click to toggle source
# File lib/kerbaldyn/orbit.rb, line 70
def self.ike
  return @ike ||= make(__method__)
end
jool() click to toggle source
# File lib/kerbaldyn/orbit.rb, line 75
def self.jool
  return @jool ||= make(__method__)
end
kerbin() click to toggle source
# File lib/kerbaldyn/orbit.rb, line 35
def self.kerbin
  return @kerbin ||= make(__method__)
end
laythe() click to toggle source
# File lib/kerbaldyn/orbit.rb, line 80
def self.laythe
  return @laythe ||= make(__method__)
end
minmus() click to toggle source
# File lib/kerbaldyn/orbit.rb, line 45
def self.minmus
  return @minmus ||= make(__method__)
end
moho() click to toggle source
# File lib/kerbaldyn/orbit.rb, line 50
def self.moho
  return @moho ||= make(__method__)
end
mun() click to toggle source
# File lib/kerbaldyn/orbit.rb, line 40
def self.mun
  return @mun ||= make(__method__)
end
tylo() click to toggle source
# File lib/kerbaldyn/orbit.rb, line 90
def self.tylo
  return @tylo ||= make(__method__)
end
vall() click to toggle source
# File lib/kerbaldyn/orbit.rb, line 85
def self.vall
  return @vall ||= make(__method__)
end