Advertisement
Guest User

OrbitCalculations.lua

a guest
Sep 18th, 2012
173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.49 KB | None | 0 0
  1. -- Several portions of this code are ports from MuMechLib, and as such, this code is licensed under GPL.
  2. -- Thanks to braeunig.us/space for much of the math.
  3.  
  4. --TODO: make library for calculating AN/DN, anomalies, times, etc.:
  5. -- function DOSTUFF(subjectOrbitParameters[, other arguments])
  6. -- OrbitParameters is a table of:
  7. -- semi-major axis (meters) - SMA
  8. -- periapsis (radius) (meters) - PE
  9. -- apoapsis (radius) (meters) - AP
  10. -- period (seconds) - P
  11. -- eccentricity - E
  12. -- inclination (degrees) - I
  13. -- argument of periapsis (degrees) - AoP
  14. -- Longitude of Ascending Node (degrees) - LAN
  15. -- time to periapsis (seconds) - PeM
  16. -- It should be possible to compute everything from these. Anything requiring further input should be in it's own script.
  17. -- (must be GPL for including ports of MuMechLib C# functions)
  18.  
  19. -- DEBUG
  20. --
  21.  
  22. -- TAKES: 3d vector A, 3d vector B
  23. -- RETURNS: cross-product (3d vector)
  24. function VectorCross(a, b)
  25.     local c = {0,0,0}
  26.     c[1] = a[2]*b[3] - a[3]*b[2]
  27.     c[2] = a[3]*b[1] - a[1]*b[3]
  28.     c[3] = a[1]*b[2] - a[2]*b[1]
  29.     return c
  30. end
  31.  
  32. -- TAKES: orbital position vector (3d vector)
  33. -- RETURNS: geocentric latitude and longitude? (2d vector) at given orbital element vector
  34. function LatLongofVector(vinput)
  35.     -- get the geocentric latitude and longitude of a orbital element vector
  36.     local rads = math.pi/180
  37.     local c1 = vinput[1]
  38.     local c2 = vinput[2]
  39.     local c3 = vinput[3]
  40.     local lat = math.atan(c3 / math.sqrt(c1*c1 + c2*c2))/rads
  41.     local long = math.atan2(c2, c1)/rads
  42.     if (c1 < 0) then
  43.         long = long + 90
  44.     elseif (c1 > 0) then
  45.         long = long + 270
  46.     end
  47.     local coord = {lat, long}
  48.     return coord;
  49. end
  50.  
  51. -- TAKES: Semi-major axis, eccentricity
  52. -- RETURNS: Periapsis radius
  53. function GetPe(SMA, E)
  54.     return SMA * (1 - E)
  55. end
  56.  
  57. -- TAKES: Semi-major axis, eccentricity
  58. -- RETURNS: Apoapsis radius
  59. function GetAp(SMA, E)
  60.     return SMA * (1 + E)
  61. end
  62.  
  63. -- TAKES: true anomaly (radians)
  64. -- RETURNS: eccentric anomaly (radians) at given true anomaly
  65. function GetEccentricAnomalyAtTruAnomaly(orbitParams, truAnomaly)
  66.     local anom = math.atan2(math.sqrt(1 - orbitParams.E*orbitParams.E) * math.sin(truAnomaly), orbitParams.E + math.cos(truAnomaly))
  67.     if anom < 0 then
  68.         return anom + 2*math.pi
  69.     else
  70.         return anom
  71.     end
  72. end
  73.  
  74. -- TAKES: eccentric anomaly (radians)
  75. -- RETURNS: mean anomaly (radians) at given eccentric anomaly
  76. function GetMeanAnomalyAtEccentricAnomaly(orbitParams, eccentricAnomaly)
  77.     return eccentricAnomaly - orbitParams.E*math.sin(eccentricAnomaly)
  78. end
  79.  
  80. -- TAKES: mean anomaly (radians)
  81. -- RETURNS: time (PE minus) at given anomaly
  82. function GetPeMinusAtMeanAnomaly(orbitParams, meanAnomaly)
  83.     local SpR = (orbitParams.P)/(2*math.pi) -- seconds per radian
  84.     return orbitParams.P - meanAnomaly * SpR
  85. end
  86.  
  87. -- TAKES: true anomaly (radians)
  88. -- RETURNS: time (PE minus) at given anomaly
  89. function GetPeMinusAtTruAnomaly(orbitParams, truAnomaly)
  90.     return GetPeMinusAtMeanAnomaly(orbitParams, GetMeanAnomalyAtEccentricAnomaly(orbitParams, GetEccentricAnomalyAtTruAnomaly(orbitParams, truAnomaly)))
  91. end
  92.  
  93. -- TAKES: true anomaly (radians)
  94. -- RETURNS: time (seconds) until orbit reaches true anomaly
  95. function GetTimeToTruAnomaly(orbitParams, truAnomaly)
  96.     local t = GetPeMinusAtTruAnomaly(orbitParams, truAnomaly)
  97.     local now = orbitParams.PeM
  98.     if (now > t) then
  99.         return now - t
  100.     else
  101.         return orbitParams.P - t + now
  102.     end
  103. end
  104.  
  105. -- TAKES: geocentric coordinates (latitude, longitude)
  106. -- RETURNS: true anomaly (radians) when orbit is over coordinates
  107. function GetTrueAnomalyAtGeoCoordinates(orbitParams, coords)
  108.     local temp2 = math.deg(math.atan(math.tan(math.rad(coords[2]))/math.cos(math.rad(orbitParams.I))))
  109. --  print("temp2: " .. temp2)
  110.     local truAnomaly = 180 + (temp2 - orbitParams.AoP)
  111.     if (truAnomaly > 360) then truAnomaly = truAnomaly - 360 end
  112.     return math.rad(truAnomaly)
  113. end
  114.  
  115. -- TAKES: true anomaly (radians)
  116. -- RETURNS: radius (meters)
  117. function GetRadiusAtTruAnomaly(orbitParams, truAnomaly)
  118.     return orbitParams.SMA * (1-orbitParams.E*orbitParams.E)/(1+orbitParams.E*math.cos(truAnomaly))
  119. end
  120.  
  121. -- TAKES: target orbital parameters
  122. -- RETURNS: (radians) true anomaly of ascending node
  123. -- note: does not work yet.
  124. function FindAN(orbitParams, targetParams)
  125. end
  126.  
  127. -- TAKES: target orbital parameters
  128. -- RETURNS: (radians) true anomaly of ascending node
  129. -- note: does not work yet.
  130. --function FindAN(orbitParams, targetParams)
  131. --  print("finding AN")
  132. --  local vA = math.sin(math.rad(orbitParams.I))*math.cos(math.rad(orbitParams.LAN))
  133. --  local vB = math.sin(math.rad(orbitParams.I))*math.sin(math.rad(orbitParams.LAN))
  134. --  local vC = math.cos(math.rad(orbitParams.I))
  135. --  local tA = math.sin(math.rad(targetParams.I))*math.cos(math.rad(targetParams.LAN))
  136. --  local tB = math.sin(math.rad(targetParams.I))*math.sin(math.rad(targetParams.LAN))
  137. --  local tC = math.cos(math.rad(targetParams.I))
  138.     -- vector3D.cross(v, t) inline here
  139. --  local c = {}
  140. --  c[1] = vB*tC - vC*tB
  141. --  c[2] = vC*tA - vA*tC
  142. --  c[3] = vA*tB - vB*tA
  143. --  print("end vector stuff C")
  144.  
  145. --  local coordsA = LatLongofVector(c)
  146. --  coordsA[2] = coordsA[2] - orbitParams.LAN --don't ask me.
  147. --  if (coordsA[2] < 0) then
  148. --      coordsA[2] = coordsA[2] + 360
  149. --  end
  150. --  print("AN coords: ".. coordsA[1], coordsA[2])
  151.     -- Got latitude/longitude of node A
  152. --  local latB = coordsA[1] * (-1)
  153. --  local longB = coordsA[2] + 180
  154. --  if (longB > 360) then
  155. --      longB = longB - 360
  156. --  end
  157. --  local coordsB = {latB, longB}
  158.     -- Got latitude/longitude of node B
  159. --  print("end coordinate stuff C")
  160.  
  161. --  local nodeA = GetTrueAnomalyAtGeoCoordinates(orbitParams, coordsA)
  162. --  local nodeB = GetTrueAnomalyAtGeoCoordinates(orbitParams, coordsB)
  163. --  print("end node stuff A")
  164.     -- TODO: figure out a way to distinguish ascending and descending nodes.
  165. --  if (GetRadiusAtTruAnomaly(orbitParams, nodeA) > GetRadiusAtTruAnomaly(orbitParams, nodeB)) then
  166. --      return nodeA
  167. --  else
  168. --      return nodeB
  169. --  end
  170. --end
  171.  
  172. -- TAKES: target orbital parameters
  173. -- RETURNS: (radians) angle change required to match planes
  174. function AngleChangeRequired(orbitParams, targetParams)
  175.     local vA = math.sin(math.rad(orbitParams.I))*math.cos(math.rad(orbitParams.LAN))
  176.     local vB = math.sin(math.rad(orbitParams.I))*math.sin(math.rad(orbitParams.LAN))
  177.     local vC = math.cos(math.rad(orbitParams.I))
  178.     local tA = math.sin(math.rad(targetParams.I))*math.cos(math.rad(targetParams.LAN))
  179.     local tB = math.sin(math.rad(targetParams.I))*math.sin(math.rad(targetParams.LAN))
  180.     local tC = math.cos(math.rad(targetParams.I))
  181.     local dAngle = math.acos(vA*tA + vB*tB + vC*tC)
  182.     return dAngle
  183. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement