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