diff --git a/img/vector_to_node.png b/img/vector_to_node.png new file mode 100644 index 0000000..d317200 Binary files /dev/null and b/img/vector_to_node.png differ diff --git a/launch.ks b/launch.ks index b25a262..067c56e 100644 --- a/launch.ks +++ b/launch.ks @@ -1,12 +1,11 @@ @LAZYGLOBAL off. -run once "lib/equations". -run once "lib/node". +run once "lib/orbital_equations". +run once "lib/orbital_maneuvers". run once "lib/rocket". run once "lib/util". run once "lib/vectors". run once "lib/warp". -run once "maneuvers". function launch { @@ -70,14 +69,14 @@ function launch { return true. // preserve trigger } - print "----------------- VERTICAL CLIMB -----------------". + print "==> VERTICAL CLIMB". print "Waiting for pitchover altitude or velocity". wait until ALTITUDE > pitchover_altitude or VELOCITY:surface:mag > pitchover_velocity. - print "------------------- PITCHOVER --------------------". + print "==> PITCHOVER". // Once a certain altitude or velocity is reached, a slight turn is made, called the pitchover maneuver lock STEERING to heading(launch_azimuth, 90-pitchover_tilt). @@ -85,7 +84,7 @@ function launch { wait until actual_prograde_pitch() > pitchover_tilt. - print "------------------ GRAVITY TURN ------------------". + print "==> GRAVITY TURN". // TODO: the angle of the launch azimuth will not account for the fact that our compass will change as we move north/south. lock STEERING to heading(launch_azimuth, 90-actual_prograde_pitch()). // Follow prograde pitch to get 0 deg angle of attack, but force compass heading at launch azimuth. @@ -94,7 +93,7 @@ function launch { lock THROTTLE TO 0. - print "------------------ CIRCULARIZE -------------------". + print "==> CIRCULARIZE". // Don't create maneuver node until we are out of the atmosphere; otherwise the apoapsis' altitude and eta will change due to drag print "Waiting for ship to leave the atmosphere". warp_for(atmosphere_exit_eta()). // we'll lose some velocity due to drag, so the warp will exit a few seconds before we actually exit the atmosphere @@ -116,7 +115,7 @@ function launch { circularize_at_apoapsis(). - print "------------ LAUNCH SEQUENCE COMPLETE ------------". + print "==> LAUNCH SEQUENCE COMPLETE". unlock_control(). } diff --git a/lib/node.ks b/lib/node.ks index 5b819d4..b069e8c 100644 --- a/lib/node.ks +++ b/lib/node.ks @@ -6,56 +6,92 @@ run once "lib/warp". function estimated_burn_duration { // - // Calculate estimated burn duration for a maneuver node. + // Calculate estimated burn duration of a vector or node. // Based on: // https://en.wikipedia.org/wiki/Tsiolkovsky_rocket_equation // https://space.stackexchange.com/questions/27375/how-do-i-calculate-a-rockets-burn-time-from-required-velocity // - parameter node is NEXTNODE. - + parameter burn. + + if burn:istype("Node") { + set burn to burn:deltav. + } + local exhaust_velocity is isp_sum() * (CONSTANT:G * KERBIN:mass). - return ((SHIP:mass * exhaust_velocity) / SHIP:maxthrust) * (1 - CONSTANT:E^(-node:deltav:mag/exhaust_velocity)). + return ((SHIP:mass * exhaust_velocity) / SHIP:maxthrust) * (1 - CONSTANT:E^(-burn:mag/exhaust_velocity)). } -function execute_node { +function vector_to_node { // - // Execute given maneuver node (the next one by default). + // Convert given vector to a maneuver node, optionally at the given time. + // See vector_to_node.png. + // Based on + // https://www.reddit.com/r/Kos/comments/701k7w/dmzmwwj/ // - parameter node is NEXTNODE. + parameter vec. + parameter time is TIME:seconds. // now + + local position_at_time is positionat(SHIP, time) - BODY:POSITION. // from the body's center + + local prograde_at_time is velocityat(SHIP, time):orbit. + local normal_at_time is vcrs(prograde_at_time, position_at_time). // vector cross product is a vector that is normal to the plane containing them (see image) + local radial_at_time is vcrs(normal_at_time, prograde_at_time). + + // vdot input vector with components at given time to get its magnitude in these directions + local vec_prograde_at_time is vdot(vec, prograde_at_time:normalized). + local vec_normal_at_time is vdot(vec, normal_at_time:normalized). + local vec_radial_at_time is vdot(vec, radial_at_time:normalized). + + return node(time, vec_radial_at_time, vec_normal_at_time, vec_prograde_at_time). +} + + +function execute_burn { + // + // Execute given burn vector or node. + // + parameter burn. // Vector or Node + + local node is burn. + if burn:istype("Vector") { + set node to vector_to_node(burn). + add node. + } + + local lock burn_duration to estimated_burn_duration(node). - local burn_duration is estimated_burn_duration(node). - - print "=== EXECUTE MANEUVER NODE ===". - print "Estimated burn duration: " + ROUND(burn_duration, 1) + "s". + print "==> EXECUTING MANEUVER NODE". + print "Estimated burn duration: " + round(burn_duration, 1) + "s". print "Aligning ship with burn vector". - SAS off. - lock STEERING to node:deltav. - wait until vang(SHIP:facing:vector, node:deltav) < 0.5. - - print "Initializing warp". - warp_for(max(0, node:eta - (burn_duration/2) - 5)). // 5s before we need to start burn - - print "Approaching". - wait until node:eta <= ceiling(burn_duration/2). // ceiling since we'd rather start the burn too soon to have time for perfecting it - + align_with(node). // parsing node instead of its burnvector allows the steering lock to dynamically update + + local warp_time is max(0, node:eta - (burn_duration/2) - 5). // 5s before we need to start burn + if warp_time { + print "Warping to maneuver node". + warp_for(warp_time). + + print "Approaching maneuver node". + wait until node:eta <= ceiling(burn_duration/2). // ceiling since we'd rather start the burn too soon to have time for perfecting it + } + print "Burn!". lock THROTTLE to 1.0. // Decrease throttle linearly when the burn duration is less than 1 second - wait until estimated_burn_duration(node) <= 1. - lock THROTTLE to max(0.01, estimated_burn_duration(node)). // ensure we always finish the burn by burning with at least 1% power at all times + wait until burn_duration <= 1. + lock THROTTLE to max(0.01, burn_duration). // ensure we always finish the burn by burning with at least 1% power at all times // The burn vector will start to drift once we have very little left to burn. Therefore, save the burn vector as it is right now, and lock steering to it, instead of the dynamic vector - local dv0 is node:deltav. + local dv0 is node:burnvector. lock STEERING to dv0. // Stop the burn once the saved vector, dv0, and current burn vector start facing opposite directions - wait until vdot(dv0, node:deltav) < 0. + wait until vdot(dv0, node:burnvector) < 0. set THROTTLE to 0.0. - print "=== MANEUVER NODE EXECUTED ===". + print "==> MANEUVER NODE EXECUTED". print round(node:deltav:mag, 3) + "m/s delta-v remaining". unlock_control(). wait 1. diff --git a/lib/equations.ks b/lib/orbital_equations.ks similarity index 100% rename from lib/equations.ks rename to lib/orbital_equations.ks diff --git a/maneuvers.ks b/lib/orbital_maneuvers.ks similarity index 94% rename from maneuvers.ks rename to lib/orbital_maneuvers.ks index 9775b40..2c41059 100644 --- a/maneuvers.ks +++ b/lib/orbital_maneuvers.ks @@ -1,12 +1,12 @@ @LAZYGLOBAL OFF. -run once "lib/equations". +run once "lib/orbital_equations". run once "lib/node". function change_orbit { // - // Change current orbit. Set parameter to -1 to maintain the current value + // Change current orbit. Set parameter to -1 to maintain the current value (TODO: all of this) // parameter inclination is ORBIT:inclination. // vertical tilt of the orbit with respect to the equator parameter eccentricity is ORBIT:eccentricity. // how circular the orbit is (e=0 circular) @@ -35,7 +35,7 @@ function circularize { set node:prograde to required_velocity - velocityat(SHIP, TIME:seconds + eta):orbit:mag. add node. - execute_node(node). + execute_burn(node). } function circularize_at_apoapsis { @@ -47,5 +47,3 @@ function circularize_at_periapsis { print "Circularizing at periapsis". return circularize(PERIAPSIS, ETA:PERIAPSIS). } - -circularize_at_periapsis(). \ No newline at end of file diff --git a/lib/util.ks b/lib/util.ks index 1e7e6c1..5ab9c35 100644 --- a/lib/util.ks +++ b/lib/util.ks @@ -15,6 +15,6 @@ function atmosphere_exit_eta { // // Return the number of seconds until the vessel exists the atmosphere. // - // the vdot gives us the magnitude of the orbital velocity vector in the UP direction because UP is a unit vector + // The vdot gives us the magnitude of the orbital velocity vector in the UP direction because UP is a unit vector return (BODY:atm:height - ALTITUDE) / vdot(velocity:orbit, UP:vector). }