-
Notifications
You must be signed in to change notification settings - Fork 0
/
probefc - Copy.ks
271 lines (231 loc) · 7 KB
/
probefc - Copy.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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
@LAZYGLOBAL OFF.
// Clear ship controls
SAS OFF.
// Load libraries
RUN lib_pid.
// Ship profiles
LOCAL profileAscending IS "Ascending".
LOCAL profileDescending IS "Descending".
LOCAL profileOrbiting IS "Orbiting".
LOCAL profileStationary IS "Stationary".
// Mission modes
LOCAL modeIdle IS "Idle".
LOCAL modeAdjustLandingAngle IS "Adjust angle".
LOCAL modePreSuicideBurn IS "Approaching suicide burn".
LOCAL modeSuicideBurn IS "Suicide burn".
LOCAL modeDescent IS "Controlled descent".
LOCAL modeFreeFall IS "Free fall".
LOCAL modeLanded IS "Landed".
// Locks
LOCK surfacePrograde TO R(0,0,0) * V(0-VELOCITY:SURFACE:X, 0-VELOCITY:SURFACE:Y, 0-VELOCITY:SURFACE:Z).
LOCK midThrottle TO SHIP:SENSORS:GRAV:MAG/SHIP:AVAILABLETHRUST.
// PID Controllers
LOCAL velocity_pid IS PID_Init(0.1, 0.2, 0.005, 0, 1).
LOCAL altitude_pid IS PID_Init(0.1, 0.2, 0.005, 0, 1).
LOCAL pitch_pid IS PID_Init(2, 0.05, 0.05, -45, 45).
LOCAL yaw_pid IS PID_Init(2, 0.05, 0.05, -45, 45).
// Mission Settings
LOCAL mode IS modeIdle.
LOCAL targetBodyName IS "Mun".
LOCAL targetBodyMaxAltitude IS 5600.
LOCAL targetDescentVelocity IS -3.
LOCAL currentThrottle IS 0.
LOCAL currentSteering IS surfacePrograde.
// UI
LOCAL labelList IS LIST(
"Status:",
"Profile:",
"Mode:",
"Alt:",
"SB Alt:",
"SB Time:",
"GrndAngle:"
).
// Main Program
CLEARSCREEN.
DrawLabelList(labelList, 0, 0).
UNTIL FALSE {
IF SHIP:BODY:NAME = targetBodyName AND STATUS = "SUB_ORBITAL" AND GetProfile() = profileDescending {
LOCK STEERING TO currentSteering.
LOCK THROTTLE TO currentThrottle.
IF GetTrueAltitude() < targetBodyMaxAltitude
AND ROUND(VANG(UP:VECTOR, surfacePrograde)) > 25
AND GetTrueAltitude() > 1000 {
// Make sure we're not coming in with too steep of an angle.
SET mode TO modeAdjustLandingAngle.
} ELSE IF GetTrueAltitude() < GetSuicideBurnAltitude()*1.5 {
// We're close to the predicted burn altitude, setup to suicide burn if not already set.
IF mode <> modeSuicideBurn {
SET mode TO modePreSuicideBurn.
}
} ELSE IF GetTrueAltitude() < 1000 {
SET mode TO modeDescent.
} ELSE {
SET mode TO modeFreeFall.
}
} ELSE IF STATUS = "LANDED" OR STATUS = "SPLASHED" {
SET mode TO modeLanded.
} ELSE {
SET currentThrottle TO 0.
UNLOCK STEERING.
UNLOCK THROTTLE.
SET mode TO modeIdle.
}
IF mode = modeAdjustLandingAngle {
// Check if we're actually facing surface prograde.
IF CalculateDelta(SHIP:FACING, surfacePrograde:DIRECTION) < 0.1 {
// We're lined up, start burning gently.
SET currentThrottle TO 1.
} ELSE {
SET currentSteering TO surfacePrograde.
SET currentThrottle TO 0.
}
} ELSE IF mode = modePreSuicideBurn {
// Check if we're actually facing surface prograde.
IF CalculateDelta(SHIP:FACING, surfacePrograde:DIRECTION) < 0.1 {
// We're lined up, wait for burn time.
IF GetTimeToSuicideBurn() < 0.5 {
SET currentThrottle TO 1.
SET mode TO modeSuicideBurn.
}
} ELSE {
SET currentSteering TO surfacePrograde.
SET currentThrottle TO 0.
}
} ELSE IF mode = modeSuicideBurn {
// Keep burning until velocity is very low.
// 5m/s is a good number to check.
// Any lower and the thrust will spin the ship
// around because we're locked to the surface prograde.
IF VELOCITY:SURFACE:MAG < 15 {
SET currentThrottle TO 0.
SET mode TO modeFreeFall.
}
} ELSE IF mode = modeDescent {
LOCAL pitchOffset IS -1 * PID_Seek(pitch_pid, 0, SHIP:VELOCITY:SURFACE * SHIP:FACING:TOPVECTOR).
LOCAL yawOffset IS PID_Seek(yaw_pid, 0, SHIP:VELOCITY:SURFACE * SHIP:FACING:STARVECTOR).
LOCAL pitchAngleOffset IS 0.
LOCAL yawAngleOffset IS 0.
// Set descent velocity.
IF GetTrueAltitude() < 1000 {
SET targetDescentVelocity TO -50.
}
IF GetTrueAltitude() < 500 {
SET targetDescentVelocity TO -15.
}
IF GetTrueAltitude() < 100 {
SET targetDescentVelocity TO -7.
}
IF GetTrueAltitude() < 50 {
SET targetDescentVelocity TO -1.
}
IF GetTrueAltitude() < 50 AND GetGroundSlope() > 15 {
// Add to angle offset and hover until flat ground appears.
SET pitchAngleOffset TO 5.
SET yawAngleOffset TO 5.
SET currentThrottle TO PID_Seek(velocity_pid, 25, GetTrueAltitude()).
} ELSE {
SET currentThrottle TO PID_Seek(velocity_pid, targetDescentVelocity, VERTICALSPEED).
}
SET currentSteering TO UP + R(pitchOffset + pitchAngleOffset, yawOffset + yawAngleOffset, 0).
} ELSE IF mode = modeFreeFall {
SET currentSteering TO surfacePrograde.
SET currentThrottle TO 0.
} ELSE IF mode = modeLanded {
SET currentThrottle TO 0.
} ELSE {
SET currentThrottle TO 0.
}
// Update UI data.
LOCAL dataList IS LIST(
STATUS,
GetProfile(),
mode,
ROUND(GetTrueAltitude(), 2),
ROUND(GetSuicideBurnAltitude(), 2),
ROUND(GetTimeToSuicideBurn(), 2),
ROUND(GetGroundSlope(), 2)
).
DrawDataList(dataList, 15, 0).
WAIT 0.01.
}
// Helper Functions
FUNCTION GetGroundSlope {
LOCAL offset IS 0.001.
LOCAL cPos IS SHIP:GEOPOSITION.
LOCAL nPos IS LATLNG(cPos:LAT + offset, cPos:LNG).
LOCAL ePos IS LATLNG(cPos:LAT, cPos:LNG + offset).
LOCAL vecCN IS nPos:POSITION - cPos:POSITION.
LOCAL vecCE IS ePos:POSITION - cPos:POSITION.
LOCAL groundVector IS VCRS(vecCN, vecCE).
RETURN VANG(UP:VECTOR, groundVector).
}
FUNCTION CalculateDelta { PARAMETER directionA, directionB.
LOCAL pitchDelta IS ABS(COS(directionA:PITCH)-COS(directionB:PITCH))+ABS(SIN(directionA:PITCH)-SIN(directionB:PITCH)).
LOCAL yawDelta IS ABS(COS(directionA:YAW)-COS(directionB:YAW))+ABS(SIN(directionA:YAW)-SIN(directionB:YAW)).
RETURN pitchDelta+yawDelta.
}
FUNCTION GetSuicideBurnAltitude {
IF SHIP:AVAILABLETHRUST = 0 {
RETURN -1.
}
RETURN (VELOCITY:SURFACE:MAG^2)/(2*(SHIP:AVAILABLETHRUST/(SHIP:MASS*SHIP:SENSORS:GRAV:MAG))).
}
FUNCTION GetTimeToSuicideBurn {
LOCAL burnAltitude IS GetSuicideBurnAltitude().
IF burnAltitude < 0 {
RETURN -1.
}
RETURN (GetTrueAltitude()-burnAltitude)/VELOCITY:SURFACE:MAG.
}
FUNCTION GetProfile {
IF STATUS = "PRELAUNCH" OR STATUS = "LANDED" OR STATUS = "SPLASHED" {
RETURN profileStationary.
}
IF APOAPSIS > 0 and PERIAPSIS > 0 {
RETURN profileOrbiting.
}
IF ETA:APOAPSIS < ETA:PERIAPSIS {
RETURN profileAscending.
} ELSE {
RETURN profileDescending.
}
}
FUNCTION GetTrueAltitude {
LOCAL terrainHeight IS SHIP:GEOPOSITION:TERRAINHEIGHT.
IF ALT:RADAR = ALTITUDE {
RETURN ALTITUDE.
} ELSE {
IF terrainHeight <= 0 {
SET terrainHeight TO 0.
}
RETURN ALTITUDE - terrainHeight.
}
}
FUNCTION DrawLabelList { PARAMETER labelList, xPos, yPos.
FOR label IN labelList {
PRINT label AT (xPos, yPos).
SET yPos TO yPos + 1.
}
}
FUNCTION DrawDataList { PARAMETER dataList, xPos, yPos.
LOCAL spaces IS " ".
FOR data in dataList {
PRINT data + spaces AT (xPos, yPos).
SET yPos TO yPos + 1.
}
}
FUNCTION GetCommStatus {
IF ADDONS:RT:HASKSCCONNECTION(SHIP) = TRUE {
RETURN "Connected".
} ELSE {
RETURN "Not connection".
}
}
FUNCTION GetCommDelay {
IF ADDONS:RT:HASKSCCONNECTION(SHIP) {
RETURN ROUND(ADDONS:RT:KSCDELAY(SHIP), 2).
} ELSE {
RETURN "Not connected".
}
}