104 lines
3.2 KiB
Plaintext
104 lines
3.2 KiB
Plaintext
// functions for calculating steering values.
|
|
|
|
runoncepath("/lib/node").
|
|
|
|
function GetPitch {
|
|
parameter v is SHIP:FACING:FOREVECTOR.
|
|
return 90 - vectorangle(SHIP:UP:FOREVECTOR, v).
|
|
}
|
|
|
|
function GetAscentVector {
|
|
parameter minPitch.
|
|
// face prograde, but hold a solid eastern heading and don't
|
|
// rotate the ship
|
|
local newHeading is lookdirup(SHIP:SRFPROGRADE:FOREVECTOR,
|
|
heading(90, 0, 270):TOPVECTOR).
|
|
if GetPitch(newHeading:FOREVECTOR) < minPitch {
|
|
set newHeading to heading(90, minPitch, 270).
|
|
}
|
|
return newHeading.
|
|
}
|
|
|
|
// Create a node that will circularize the orbit.
|
|
// 'where' can be one of:
|
|
// the special string "APO", for the next Apoapsis.
|
|
// the special string "PERI", for the next Periapsis.
|
|
// a time value (either a Time struct or a scalar), representing a target time.
|
|
function CreateCircularizationNode {
|
|
parameter where is "APO".
|
|
|
|
local t is TIME.
|
|
if where:IsType("String") {
|
|
if where = "APO" {
|
|
set t to TIME + SHIP:ORBIT:ETA:APOAPSIS.
|
|
} else if where = "PERI" {
|
|
set t to TIME + SHIP:ORBIT:ETA:PERIAPSIS.
|
|
} else {
|
|
print "WARNING: Invalid string passed to CreateCirculazationNode(). Node is invalid.".
|
|
}
|
|
} else {
|
|
// we've been passed a time at which to circularize.
|
|
set t to where.
|
|
}
|
|
|
|
local Vc is sqrt(SHIP:BODY:MU/(PositionAt(SHIP, t) - SHIP:BODY:POSITION):MAG).
|
|
local dV is Vc - VelocityAt(SHIP, t):ORBIT:MAG.
|
|
local n is Node(t, 0, 0, dV).
|
|
|
|
return n.
|
|
}
|
|
|
|
// The distance at which to start burning to reach a target on the ground.
|
|
// REQUIRES a circular orbit.
|
|
// TODO: it would be great to semi-automate this...
|
|
function TargetBurnDistance {
|
|
return Sqrt(StoppingDistance()^2 + (SHIP:ORBIT:SEMIMAJORAXIS - SHIP:BODY:RADIUS - TARGET:ALTITUDE)^2).
|
|
}
|
|
|
|
// Stopping distance at current velocity. For a circular orbit this is valid at any point in the orbit.
|
|
function StoppingDistance {
|
|
local dV is SHIP:VELOCITY:SURFACE:MAG.
|
|
return dV*BurnTime(dV)/2.
|
|
}
|
|
|
|
// Figure out our closest approach to our current target within the next
|
|
// N seconds. (default orbital_period * 2)
|
|
// This is a horrible, terrible, no good, very bad brute force hack.
|
|
// function timeAtClosestApproach {
|
|
// parameter maxSeconds is SHIP:ORBIT:PERIOD * 2.
|
|
|
|
// // find the closest approach to pos
|
|
// local t is TIME.
|
|
// local minD is (PositionAt(TARGET, t) - PositionAt(SHIP, t)):MAG.
|
|
// local minT is t.
|
|
// until false {
|
|
// local d is (PositionAt(TARGET, t) - PositionAt(SHIP, t)):MAG.
|
|
// if d < minD {
|
|
// set minD to d.
|
|
// set minT to t.
|
|
// }
|
|
// set t to t+1.
|
|
// }
|
|
|
|
// return minT.
|
|
// }
|
|
|
|
// function PredictGeo {
|
|
// parameter t.
|
|
|
|
// local pos is PositionAt(SHIP,t).
|
|
// local rDir is VDOT(SHIP:BODY:NORTH:FOREVECTOR,SHIP:BODY:ANGULARVEL). //the number of radians the body will rotate in one second (negative if rotating counter clockwise when viewed looking down on north
|
|
// local dT is t - TIME:SECONDS.
|
|
// local geoPos is SHIP:BODY:GeoPositionOf(pos).
|
|
// local drift is rDir * dT * CONSTANT:RADTODEG.
|
|
// local long is Mod(geoPos:LNG + drift, 360).
|
|
// if long < -180 {
|
|
// set long to long + 360.
|
|
// }
|
|
// if long > 180 {
|
|
// set long TO long - 360.
|
|
// }
|
|
|
|
// return LatLng(geoPos:LAT, long).
|
|
// }
|