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.
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().
}

View file

@ -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.

View file

@ -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().

View file

@ -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).
}