-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgeneric_launch.ks
184 lines (149 loc) · 5.54 KB
/
generic_launch.ks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/////////////////////////////////////////////////////////////////////////////
// Ascent phase of launch.
/////////////////////////////////////////////////////////////////////////////
// Ascend from a planet, performing a gravity turn and staging as necessary.
// Achieve circular orbit with desired apoapsis.
/////////////////////////////////////////////////////////////////////////////
// Final apoapsis (m altitude)
parameter apo.
parameter turn_sharpness is 2.
// Number of seconds to sleep during ascent loop
global launch_tick is 1.
// Time of SRB separation
global launch_tSrbSep is 0.
// Time of last stage
global launch_tStage is time:seconds.
// Starting/ending height of gravity turn
// TODO adjust for atmospheric pressure; this works for Kerbin
global launch_gt0 is body:atm:height * 0.02.
global launch_gt1 is body:atm:height * 0.85.
// "Sharpness" of gravity turn; we use a cosine function to modulate the
// turn, and the sharpness is a scaling factor for the input to the cosine
// function. Higher numbers are sharper, lower numbers are gentler.
// TODO get rid of this once we solve "tipping" issue
global launch_gtScale is turn_sharpness.
/////////////////////////////////////////////////////////////////////////////
// Steering function that uses the launch_gt* to perform a gravity turn.
/////////////////////////////////////////////////////////////////////////////
function ascentSteering {
// How far through our gravity turn are we? (0..1)
local gtPct is (ship:altitude - launch_gt0) / (launch_gt1 - launch_gt0).
// Ideal gravity-turn azimuth (inclination) and facing at present altitude.
local inclin is min(90, max(0, 90 * cos(launch_gtScale * 90 * gtPct))).
local gtFacing is heading(90, inclin):vector.
local prodot is vdot(ship:facing:vector, prograde:vector).
if gtPct <= 0 {
return heading(0, 90).
} else {
return lookdirup(gtFacing, ship:facing:upvector).
}
}
/////////////////////////////////////////////////////////////////////////////
// Throttle function.
/////////////////////////////////////////////////////////////////////////////
function ascentThrottle {
// angle of attack
local aoa is vdot(ship:facing:vector, ship:velocity:surface).
// how far through the soup are we?
local atmPct is ship:altitude / (body:atm:height+1).
local spd is ship:velocity:surface:mag.
return 1.
// TODO adjust cutoff for atmospheric pressure; this works for kerbin
local cutoff is 200 + (400 * max(0, atmPct)).
if spd > cutoff and launch_tSrbSep = 0 {
// going too fast during SRB ascent; avoid overheat or
// aerodynamic catastrophe by limiting throttle
return 1 - (1 * (spd - cutoff) / cutoff).
} else {
return 1.
}
}
/////////////////////////////////////////////////////////////////////////////
// Auto-stage and auto-warp logic -- performs its work as side effects vs.
// returning a value; must be called in a loop to have any effect!
/////////////////////////////////////////////////////////////////////////////
function ascentStaging {
local Neng is 0.
local Nsrb is 0.
local Nout is 0.
list engines in engs.
for eng in engs {
if eng:ignition {
set Neng to Neng + 1.
if not eng:allowshutdown {
set Nsrb to Nsrb + 1.
}
if eng:flameout {
set Nout to Nout + 1.
}
}
}
if (Nsrb > 0) and (stage:solidfuel < 10) {
stage.
set launch_tSrbSep to time:seconds.
set launch_tStage to launch_tSrbSep.
} else if (Nout = Neng) {
wait until stage:ready.
stage.
set launch_tStage to time:seconds.
}
}
function ascentWarping {
if stage:solidfuel > 10 and ship:status = "flying" {
set warp to 1.
} else if ship:altitude > body:atm:height {
set warp to 1.
} else {
set warp to 0.
}
}
/////////////////////////////////////////////////////////////////////////////
// Perform initial setup; trim ship for ascent.
/////////////////////////////////////////////////////////////////////////////
sas off.
//sas on.
if ship:status <> "prelaunch" and stage:solidfuel = 0 {
// note that there's no SRB
set launch_tSrbSep to time:seconds.
}
lock steering to ascentSteering().
lock throttle to ascentThrottle().
set ship:control:pilotmainthrottle to 0.
/////////////////////////////////////////////////////////////////////////////
// Enter ascent loop.
/////////////////////////////////////////////////////////////////////////////
when alt:radar > 70000 then {
if exists("mission_post_atmo.ks") {
runpath("mission_post_atmo.ks").
}
}
until ship:obt:apoapsis >= apo {
ascentStaging().
// ascentWarping().
wait launch_tick.
}
unlock throttle.
set ship:control:pilotmainthrottle to 0.
/////////////////////////////////////////////////////////////////////////////
// Coast to apoapsis and hand off to circularization program.
/////////////////////////////////////////////////////////////////////////////
sas on.
// Get rid of ascent stage if less that 10% fuel remains ... bit wasteful, but
// keeps our burn calculations from being erroneous due to staging mid-burn.
// TODO stop being wasteful; compute burn duration & compare to remaining dv (need fuel flow data, yech!)
//if stage:resourceslex:haskey("LiquidFuel") and stage:resourceslex["LiquidFuel"]:amount / stage:resourceslex["LiquidFuel"]:capacity < 0.1 {
// stage.
// wait until stage:ready.
//}
// Corner case: circularization stage is not bottom most (i.e. there is an
// aeroshell ejection in a lower stage).
until ship:availablethrust > 0 {
stage.
wait until stage:ready.
}
// rcs on.
until ship:altitude > body:atm:height {
ascentWarping().
}
set warp to 0.
runpath("circ.ks").