Advertisement
sumguytwitches

match inclination copy

Jul 14th, 2022
36
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.88 KB | None | 0 0
  1. local ship_orbit is ship:orbit.
  2. local node_selector is "highest".
  3. local mode is "match_phase".
  4.  
  5. run once "util/util".
  6. run once "util/logging".
  7.  
  8. log_message("=== planning match inclination ===").
  9.  
  10. local equatorial is node_selector:matchespattern("equatorial").
  11. local polar is not equatorial and node_selector:matchespattern("polar").
  12. local targeted is not (equatorial or polar).
  13.  
  14. if targeted and not hastarget {
  15. log_error("No target selected").
  16. }
  17.  
  18. if (targeted and ship_orbit:body <> target:obt:body) {
  19. log_error("Selected orbital patch and target orbit do not share a common body.").
  20. }
  21.  
  22. local eccentricity is ship_orbit:eccentricity.
  23. if(eccentricity >= 1) {
  24. log_error("Cannot match inclination for open orbits.").
  25. }
  26. local b is ship_orbit:body.
  27. local t is ship_orbit:epoch.
  28. local epoch_pos is (positionat(ship,t)-b:position):normalized.
  29. local nrm_ship is vcrs(velocityat(ship, t):obt,positionat(ship,t)-b:position):normalized.
  30. local nrm_trgt is v(0,0,0).
  31. if targeted {
  32. set nrm_trgt to vcrs(velocityat(target, t):obt,positionat(target,t)-b:position):normalized.
  33. }
  34. else if equatorial {
  35. set nrm_trgt to -ship_orbit:body:angularvel:normalized.
  36. }
  37. else if polar {
  38. // leave it for later.
  39. }
  40. local angle_to_an is 0.
  41. local epoch_true_anomaly is 0.
  42. if targeted {
  43. local vec_to_AN is vcrs(nrm_ship,nrm_trgt):normalized.
  44. local function sign{parameter x. return choose -1 if x < 0 else 1.}
  45. local function newton {
  46. parameter f, fp, x0.
  47. local x is x0.
  48. local err is f(x).
  49. local steps is 0.
  50. until abs(err)< 1e-12 or steps > 20 {
  51. local deriv is fp(x).
  52. local step is err/deriv.
  53. // only allow a maximum change of half a radian at a time to prevent small derivatives from throwing off the
  54. // stability of the algorithm.
  55. if abs(step) > 0.5 set step to 0.5 * sign(step).
  56. set x to x - step.
  57. set steps to steps+1.
  58. set err to f(x).
  59. }
  60. log_debug("Calculated eccentric anomaly gives a mean anomaly error of " + err + " in " + steps + " step" +
  61. (choose "." if steps=1 else "s.")).
  62. return x.
  63. }
  64. local mean_anomaly_rad is ship_orbit:meananomalyatepoch * constant:DegToRad.
  65. local epoch_eccentric_anomaly is newton(
  66. {parameter e. return e-eccentricity*sin(e*constant:RadToDeg)-mean_anomaly_rad.},
  67. {parameter e. return 1-eccentricity*cos(e*constant:RadToDeg).},
  68. mean_anomaly_rad)*constant:RadToDeg.
  69. set epoch_true_anomaly to mod(360+arctan2(sqrt(1-eccentricity^2)*sin(epoch_eccentric_anomaly), cos(epoch_eccentric_anomaly)-eccentricity),360).
  70. set angle_to_an to vang(vec_to_AN,epoch_pos)*sign(vcrs(vec_to_AN,epoch_pos)*nrm_ship).
  71. }
  72.  
  73. local base_time is ship_orbit:epoch.
  74. local base_meananomaly is ship_orbit:meananomalyatepoch.
  75. if(ship_orbit:epoch < time:seconds) {
  76. set base_time to time:seconds.
  77. set base_meananomaly to mod(mod(base_time-ship_orbit:epoch, ship_orbit:period)/ship_orbit:period*360+ship_orbit:meananomalyatepoch,360).
  78. }
  79.  
  80. local AN_true_anomaly is v(0,0,0).
  81. if targeted {
  82. set AN_true_anomaly to mod(360+epoch_true_anomaly+angle_to_an,360).
  83. }
  84. else if equatorial {
  85. set AN_true_anomaly to 360-ship_orbit:argumentofperiapsis.
  86. }
  87. else if polar {
  88. set AN_true_anomaly to 180.
  89. local t_apo to mod(540-base_meananomaly, 360)*sqrt(ship_orbit:semimajoraxis^3/ship_orbit:body:mu)/constant:RadToDeg + base_time.
  90. local rs is positionat(ship,t_apo)-ship_orbit:body:position.
  91. set nrm_trgt to vcrs(rs, -body:angularvel):normalized.
  92. set ns to vcrs(velocityat(ship,t_apo):obt, rs):normalized.
  93. if vang(ns,nrm_trgt) > 90 set nrm_trgt to -nrm_trgt.
  94. }
  95. local DN_true_anomaly is mod(AN_true_anomaly+180,360).
  96. local inclination is vang(nrm_ship,nrm_trgt).
  97.  
  98. log_debug("inclination: " + inclination).
  99. log_debug("delta true anomaly: " + angle_to_an).
  100.  
  101. local AN_eccentric_anomaly is mod(360+arctan2(sqrt(1-eccentricity^2)*sin(AN_true_anomaly), eccentricity+cos(AN_true_anomaly)),360).
  102. local AN_mean_anomaly is AN_eccentric_anomaly-eccentricity*constant:RadToDeg*sin(AN_eccentric_anomaly).
  103. local AN_timestamp is mod(360+AN_mean_anomaly-base_meananomaly,360)/sqrt(b:mu/ship_orbit:semimajoraxis^3)/constant:RadToDeg + base_time.
  104. local DN_eccentric_anomaly is mod(360+arctan2(sqrt(1-eccentricity^2)*sin(DN_true_anomaly), eccentricity+cos(DN_true_anomaly)),360).
  105. local DN_mean_anomaly is DN_eccentric_anomaly-eccentricity*constant:RadToDeg*sin(DN_eccentric_anomaly).
  106. local DN_timestamp is mod(360+DN_mean_anomaly-base_meananomaly,360)/sqrt(b:mu/ship_orbit:semimajoraxis^3)/constant:RadToDeg + base_time.
  107.  
  108. log_debug("time to AN: " + format_time(AN_timestamp - time:seconds)).
  109. log_debug("time to DN: " + format_time(DN_timestamp - time:seconds)).
  110.  
  111. local AN_true_anomaly_to_AP is abs(AN_true_anomaly - 180).
  112. local DN_true_anomaly_to_AP is abs(DN_true_anomaly - 180).
  113.  
  114. log_debug("AN true anomaly: " + AN_true_anomaly).
  115. log_debug("DN true anomaly: " + DN_true_anomaly).
  116. log_debug("AN true anomaly to ap: " + AN_true_anomaly_to_AP).
  117. log_debug("DN true anomaly to ap: " + DN_true_anomaly_to_AP).
  118.  
  119. local node_timestamp is 0.
  120. if(node_selector:matchespattern("highest") or not targeted) {
  121. set node_timestamp to choose AN_timestamp if AN_true_anomaly_to_AP < DN_true_anomaly_to_AP else DN_timestamp.
  122. }
  123. else if(node_selector:matchespattern("lowest")) {
  124. set node_timestamp to choose AN_timestamp if AN_true_anomaly_to_AP > DN_true_anomaly_to_AP else DN_timestamp.
  125. }
  126. else if(node_selector:matchespattern("AN")) {set node_timestamp to AN_timestamp.}
  127. else if(node_selector:matchespattern("DN")) {set node_timestamp to DN_timestamp.}
  128. else if(node_selector:matchespattern("first")) {
  129. set node_timestamp to choose AN_timestamp if AN_timestamp < DN_timestamp else DN_timestamp.
  130. }
  131. else if(node_selector:matchespattern("last")) {
  132. set node_timestamp to choose AN_timestamp if AN_timestamp > DN_timestamp else DN_timestamp.
  133. }
  134. else log_error("Invalid node selector. Valid selectors are AN, DN, highest, lowest, first, and last.").
  135.  
  136. if(ship_orbit:transition <> "FINAL") {
  137. set t_transition to ship_orbit:nextpatcheta + time:seconds.
  138. if(t_transition < node_timestamp) {
  139. local other_timestamp is choose AN_timestamp if node_timestamp=DN_timestamp else DN_timestamp.
  140. if(other_timestamp < node_timestamp) {
  141. log_error("No node exists before the end of the orbital patch.").
  142. }
  143. else {
  144. log_debug("Orbital patch ends before chosen node! Selecting other node.").
  145. set node_timestamp to other_timestamp.
  146. }
  147. }
  148. }
  149.  
  150. log_debug("time to burn: " + format_time(node_timestamp - time:seconds)).
  151.  
  152. local rs is positionat(ship,node_timestamp)-b:position.
  153. local vs is velocityat(ship,node_timestamp):obt.
  154. local rt is 0.
  155. local vt is 0.
  156. if targeted {
  157. set rt to positionat(target,node_timestamp)-b:position.
  158. set vt to velocityat(target,node_timestamp):obt.
  159. }
  160. local ns is vcrs(vs,rs):normalized.
  161. local nt is choose vcrs(vt,rt):normalized if targeted else nrm_trgt.
  162.  
  163. local dv is v(0,0,0).
  164.  
  165. if mode="match_phase" {
  166. local v_tangential is vcrs(rs,ns):normalized * vs.
  167. local v_radial is rs:normalized * vs.
  168. set dv to v_radial * rs:normalized + v_tangential * vcrs(rs,nt):normalized - vs.
  169. }
  170. else if mode="mindv" {
  171. set dv to vxcl(nt, vs)-vs.
  172. }
  173. else if mode="direction_and_speed" {
  174. set dv to vxcl(nt, vs):normalized * vs:mag - vs.
  175. }
  176. else {
  177. log_error("Unknown argument. Known modes are: match_phase, mindv, direction_and_speed. Default is match_phase.").
  178. }
  179.  
  180. local node_radialout is dv * vxcl(vs,rs):normalized.
  181. local node_normal is dv * vcrs(vs,rs):normalized.
  182. local node_prograde is dv * vs:normalized.
  183. log_debug("Creating node (" + list(node_radialout, node_normal, node_prograde):join(",") + ").").
  184. add node(node_timestamp, node_radialout, node_normal, node_prograde).
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement