-
Notifications
You must be signed in to change notification settings - Fork 0
/
ascent.ks
202 lines (165 loc) · 7.23 KB
/
ascent.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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// functions are in the order of flight operations
function lesAbortMonitor {
// can be triggered by manual abort or no longer being able to detect the fuel tank
if abort or not ship:partstagged("tank"):length {
output("LES abort triggered!").
// stop any ascent operations and remove locked variables related to lower stages
operations:remove("maxQmonitor").
operations:remove("ascentToPitchHold").
operations:remove("ascentToMeco").
unlock engineStatus.
unlock engineThrust.
// if there is still a decoupler, then detach it
if ship:partstagged("decoupler"):length decoupler:doevent("decouple").
// fire all LES rocket motors
lesKickMotor:doevent("activate engine").
wait 0.005.
// if kick motor did not fire, we need to light off one of the push motors first to angle the capsule away
// make sure not to light off the motor whose status we are tracking
if lesKickStatus <> "Nominal" {
lesPushMotorRight:doevent("activate engine").
wait 0.02.
lesPushMotorDw:doevent("activate engine").
lesPushMotorUp:doevent("activate engine").
lesPushMotorLeft:doevent("activate engine").
} else {
lesPushMotorRight:doevent("activate engine").
lesPushMotorDw:doevent("activate engine").
lesPushMotorUp:doevent("activate engine").
lesPushMotorLeft:doevent("activate engine").
}
// switch over to landing state and dump the tower once LES expires
when lesStatus = "Flame-Out!" then {
lesDecoupler:doevent("decouple").
set operations["chuteDeployAbort"] to chuteDeployAbort@.
set maxQ to 0.
output("LES tower burnout. Prepped for chute deploy").
}
operations:remove("lesAbortMonitor").
}
}
function terminalCount {
// set up for ignition at T-6 seconds
if time:seconds >= getter("launchTime") - 6 {
operations:remove("terminalCount").
set operations["ignition"] to ignition@.
sleepTimers:remove("monitorEcDrain").
}
}
function ignition {
// ensure we have clearance to proceed with ignition
if not launchAbort {
// ignite the engine at 10% thrust to ensure good chamber pressures
output("Ignition").
engine:doevent("activate engine").
// begin telemetry logging with an intial entry followed by one every second
logData().
sleep("datalogger", logData@, 1, true, true).
// pause a sec to allow ignition
sleep("launchThrust", launchThrust@, 1, true, false).
// ensure the LES activates in the case of any troubles
set operations["lesAbortMonitor"] to lesAbortMonitor@.
}
operations:remove("ignition").
}
function launchThrust {
// check chamber pressures over the next two seconds if ignition was successful
if engineStatus <> "Nominal" setAbort(true, "Engine ignition failure. Status: " + engineStatus).
// ensure all is still well before throttling up to launch power
if not launchAbort and time:seconds >= getter("launchTime") - 3 {
// throttle up to and maintain a TWR of 1.2
// take into account the mass of the engine clamp
output("Go for launch thrust").
lock throttle to 1.2 * (ship:mass - 0.10) * (surfaceGravity/((((ship:orbit:body:radius + ship:altitude)/1000)/(ship:orbit:body:radius/1000))^2)) / getAvailableThrust().
// move on to launch
operations:remove("launchThrust").
sleep("launch", launch@, getter("launchTime"), false, false).
}
}
function launch {
// last check for green light as this function was called after a 3s period
if not launchAbort {
// ensure we are in fact at a 1.2 TWR
set weight to ((ship:mass - 0.1) * (surfaceGravity/((((ship:orbit:body:radius + ship:altitude)/1000)/(ship:orbit:body:radius/1000))^2))).
if engineThrust / weight >= 1.2 {
// disengage engine clamp
stage.
output("Launch!").
// adjust throttle to proper TWR now that clamp is gone
lock throttle to 1.2 * ship:mass * (surfaceGravity/((((ship:orbit:body:radius + ship:altitude)/1000)/(ship:orbit:body:radius/1000))^2)) / getAvailableThrust().
// wait until we've cleared the service towers (which stand 8.1m tall)
// this is so the pad and engine clamp are not damaged by engine exhaust
set launchHeight to alt:radar.
set operations["throttleUp"] to throttleUp@.
// initial pitch over
lock steering to heading(hdgHold, pitch).
// setup some notification triggers, nested so only a few are running at any given time
when maxQ > ship:q then output("MaxQ: " + round(ship:Q * constant:ATMtokPa, 3) + "kPa @ " + round(ship:altitude/1000, 3) + "km").
when ship:orbit:apoapsis > 70000 then {
output("We are going to space!").
when ship:altitude >= 70000 then {
output("Space reached!").
when ship:verticalspeed <= 0 then {
output("Apokee achieved @ " + round(ship:altitude/1000, 3) + "km").
when ship:altitude <= 70000 then {
output("Atmospheric interface breached").
set maxQ to 0.
rcs off.
sas off.
set operations["chuteDeploy"] to chuteDeploy@.
when maxQ > ship:q then {
output("MaxQ: " + round(ship:Q * constant:ATMtokPa, 3) + "kPa @ " + round(ship:altitude/1000, 3) + "km").
}
}
}
}
}
// takeoff thrust failed to set
} else {
setAbort(true, "Engine TWR not set for launch commit. Only at " + (engineThrust / weight)).
engine:doevent("shutdown engine").
}
}
operations:remove("launch").
}
function throttleUp {
if alt:radar >= launchHeight + 8.1 {
// enable guidance
// pitch over steering taken from https://www.youtube.com/watch?v=NzlM6YZ9g4w
// https://www.wolframalpha.com/input/?i=quadratic+fit((76,89.6),+(5000,78),+(10000,69),+(20000,57),+(30000,51),+(40000,48))
lock pitch to 2.95304E-8 * ship:altitude^2 - 0.00218678 * ship:altitude + 88.8414.
lock steering to heading(hdgHold,pitch).
// throttle up to full and head for pitch hold
// also enable MECO checks in case pitch hold is not reached
lock throttle to 1.65 * ship:mass * (surfaceGravity/((((ship:orbit:body:radius + ship:altitude)/1000)/(ship:orbit:body:radius/1000))^2)) / getAvailableThrust().
set operations["ascentToPitchHold"] to ascentToPitchHold@.
set operations["ascentToMeco"] to ascentToMeco@.
set operations["maxQmonitor"] to maxQmonitor@.
output("Tower cleared, flight guidance enabled & throttle to full").
operations:remove("throttleUp").
}
}
function maxQmonitor {
if ship:q > maxQ set maxQ to ship:q.
else operations:remove("maxQmonitor").
}
function ascentToPitchHold {
// keep track of the pitch and when it reaches 48° hold there
if pitch <= 48 {
lock pitch to 48.
output("Max pitch reached, holding at 48 degrees").
operations:remove("ascentToPitchHold").
}
}
function ascentToMeco {
if engineStatus = "Flame-Out!" {
unlock throttle.
unlock steering.
output("Main engine burn complete").
operations:remove("ascentToMeco").
// decouple the capsule after 10s
sleep("payloadDecouple", payloadDecouple@, 10, true, false).
}
}
sleep("beginTCount", beginTCount@, getter("launchTime") - 120, false, false).
output("Launch/Ascent ops ready, awaiting terminal count").