Allow node-execution script to execute a burn based on a vector (in addition to a node).

This commit is contained in:
Casper V. Kristensen 2019-02-09 21:32:14 +01:00
parent 694eeac86f
commit 6de947fb18
Signed by: caspervk
GPG key ID: 289CA03790535054
6 changed files with 73 additions and 40 deletions

BIN
img/vector_to_node.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View file

@ -1,12 +1,11 @@
@LAZYGLOBAL off. @LAZYGLOBAL off.
run once "lib/equations". run once "lib/orbital_equations".
run once "lib/node". run once "lib/orbital_maneuvers".
run once "lib/rocket". run once "lib/rocket".
run once "lib/util". run once "lib/util".
run once "lib/vectors". run once "lib/vectors".
run once "lib/warp". run once "lib/warp".
run once "maneuvers".
function launch { function launch {
@ -70,14 +69,14 @@ function launch {
return true. // preserve trigger return true. // preserve trigger
} }
print "----------------- VERTICAL CLIMB -----------------". print "==> VERTICAL CLIMB".
print "Waiting for pitchover altitude or velocity". print "Waiting for pitchover altitude or velocity".
wait until ALTITUDE > pitchover_altitude wait until ALTITUDE > pitchover_altitude
or VELOCITY:surface:mag > pitchover_velocity. 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 // 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). lock STEERING to heading(launch_azimuth, 90-pitchover_tilt).
@ -85,7 +84,7 @@ function launch {
wait until actual_prograde_pitch() > pitchover_tilt. 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. // 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. 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. 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 // 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". 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 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(). circularize_at_apoapsis().
print "------------ LAUNCH SEQUENCE COMPLETE ------------". print "==> LAUNCH SEQUENCE COMPLETE".
unlock_control(). unlock_control().
} }

View file

@ -6,56 +6,92 @@ run once "lib/warp".
function estimated_burn_duration { function estimated_burn_duration {
// //
// Calculate estimated burn duration for a maneuver node. // Calculate estimated burn duration of a vector or node.
// Based on: // Based on:
// https://en.wikipedia.org/wiki/Tsiolkovsky_rocket_equation // 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 // 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). 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 burn_duration is estimated_burn_duration(node). local position_at_time is positionat(SHIP, time) - BODY:POSITION. // from the body's center
print "=== EXECUTE MANEUVER NODE ===". local prograde_at_time is velocityat(SHIP, time):orbit.
print "Estimated burn duration: " + ROUND(burn_duration, 1) + "s". 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).
print "==> EXECUTING MANEUVER NODE".
print "Estimated burn duration: " + round(burn_duration, 1) + "s".
print "Aligning ship with burn vector". print "Aligning ship with burn vector".
SAS off. align_with(node). // parsing node instead of its burnvector allows the steering lock to dynamically update
lock STEERING to node:deltav.
wait until vang(SHIP:facing:vector, node:deltav) < 0.5.
print "Initializing warp". local warp_time is max(0, node:eta - (burn_duration/2) - 5). // 5s before we need to start burn
warp_for(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". 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 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!". print "Burn!".
lock THROTTLE to 1.0. lock THROTTLE to 1.0.
// Decrease throttle linearly when the burn duration is less than 1 second // Decrease throttle linearly when the burn duration is less than 1 second
wait until estimated_burn_duration(node) <= 1. wait until burn_duration <= 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 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 // 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. lock STEERING to dv0.
// Stop the burn once the saved vector, dv0, and current burn vector start facing opposite directions // 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. set THROTTLE to 0.0.
print "=== MANEUVER NODE EXECUTED ===". print "==> MANEUVER NODE EXECUTED".
print round(node:deltav:mag, 3) + "m/s delta-v remaining". print round(node:deltav:mag, 3) + "m/s delta-v remaining".
unlock_control(). unlock_control().
wait 1. wait 1.

View file

@ -1,12 +1,12 @@
@LAZYGLOBAL OFF. @LAZYGLOBAL OFF.
run once "lib/equations". run once "lib/orbital_equations".
run once "lib/node". run once "lib/node".
function change_orbit { 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 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) 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. set node:prograde to required_velocity - velocityat(SHIP, TIME:seconds + eta):orbit:mag.
add node. add node.
execute_node(node). execute_burn(node).
} }
function circularize_at_apoapsis { function circularize_at_apoapsis {
@ -47,5 +47,3 @@ function circularize_at_periapsis {
print "Circularizing at periapsis". print "Circularizing at periapsis".
return circularize(PERIAPSIS, ETA:PERIAPSIS). return circularize(PERIAPSIS, ETA:PERIAPSIS).
} }
circularize_at_periapsis().

View file

@ -15,6 +15,6 @@ function atmosphere_exit_eta {
// //
// Return the number of seconds until the vessel exists the atmosphere. // 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). return (BODY:atm:height - ALTITUDE) / vdot(velocity:orbit, UP:vector).
} }