forked from ozin370/Script
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrs.ks
298 lines (236 loc) · 8.81 KB
/
rs.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
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
//rs.ks
clearvecdraws().
run lib_quad.
ag1 off. ag2 off. ag10 off.
list engines in engs.
local yawRotatrons is list().
local i is 0.
for eng in engs {
if not(eng:ignition) { eng:activate(). wait 0. }
vecs_add(eng:position,eng:facing:vector * eng:thrust,red,"",0.2).
set eng:thrustlimit to 0.
set vecs[i]:show to true.
for moduleStr in eng:parent:modules {
if moduleStr = "MuMechToggle" {
local rot is eng:parent:getmodule("MuMechToggle").
if rot:hasfield("Rotation") {
rot:setfield("Acceleration",50).
yawRotatrons:add(rot).
}
}
}
if vdot(facing:starvector,eng:position) < -0.3 { set eng_roll_pos to eng. }
else if vdot(facing:starvector,eng:position) > 0.3 { set eng_roll_neg to eng. }
else if vdot(facing:vector,eng:position) < -0.3 { set eng_pitch_pos to eng. }
else if vdot(facing:vector,eng:position) > 0.3 { set eng_pitch_neg to eng. }
set i to i + 1.
}
if yawRotatrons:length = 2 or yawRotatrons:length = 4 {
//entry("Found " + yawRotatrons:length + " servos attached to engines.").
//entry("Yaw control enabled.").
set yawControl to true.
wait 0.2.
}
else set yawControl to false.
// Vecdraws -----------------------------------------------------------
local targetVec is up:forevector.
local targetVecStar is v(0,0,0).
local targetVecTop is v(0,0,0).
local markTar is vecs_add(v(0,0,0),v(0,0,0),cyan,"",0.2).
//local markTarP is vecs_add(v(0,0,0),v(0,0,0),cyan,"TP").
//local markTarY is vecs_add(v(0,0,0),v(0,0,0),cyan,"TY").
set prediction_span to 2. //seconds to check for terrain interesect
set prediction_i to 5. //checks per second
local pList is list(). //terrain prediction vecs
pList:add(0).
local i is 1.
until i > prediction_span * prediction_i {
pList:add(vecs_add(v(0,0,0),v(0,0,0),rgb(1,0,0.0),"",0.2)).
set i to i + 1.
}
set timerFlying to time:seconds.
set inAir to false.
set vecs[markTar]:show to true.
function updateVec {
parameter targetVec.
set targetVecStar to vxcl(facing:vector, targetVec).
set targetVecTop to vxcl(facing:starvector, targetVec).
set vecs[markTar]:vec to targetVec*5.
//set vecs[markTarP]:vec to targetVecTop*5.
//set vecs[markTarY]:vec to targetVecStar*5.
}
// EO vecdraws ---------------------------------------------------------
function flightcontroller {
set gravity to -up:vector * (body:mu / body:position:mag^2).
if not(ship:status = "LANDED") {
if not(inAir) { //first tick in air
set timerFlying to time:seconds.
}
set inAir to true.
}
else {
if inAir { //first tick landed
local impactV is vdot(-shipNormal, old_vel).
if impactV > 10 {
HUDTEXT("Impact velocity: " + round(impactV,1) + "m/s", 5, 2, 40, rgb(255,200,0), false).
HUDTEXT("Pitch error: " + round(pitch_err,1), 5, 2, 35, yellow, false).
HUDTEXT(" Roll error: " + round(roll_err,1), 5, 2, 35, yellow, false).
HUDTEXT(" Yaw error: " + round(roll_err,1), 5, 2, 35, yellow, false).
}
}
set inAir to false.
}
inputs().
set shipNormal to geo_normalvector(ship:geoposition,5).
if vang(ship:facing:topvector,shipNormal) > 5 set tilting to true.
else set tilting to false.
if inAir {
set predictedPos to ship:position.
set old_vel to ship:velocity:surface.
set vel to ship:velocity:surface.
local i is 1.
local hasIntersected is false.
until i > prediction_span * prediction_i {
set predictedPos to predictedPos + (vel + 0.5 * gravity)/prediction_i.
set vel to vel + gravity/prediction_i.
set curGeo to body:geopositionof(predictedPos).
set pm to pList[i].
set terPos to curGeo:position.
set vecs[pm]:start to terPos.
set vecs[pm]:vec to predictedPos - terPos.
if hasIntersected {
set vecs[pm]:show to false.
}
else if vdot(up:vector,predictedPos - terPos) > 0 and not(i = prediction_span * prediction_i) {
set vecs[pm]:show to true.
}
else if hasIntersected = false {
set hasIntersected to true.
set targetVec to geo_normalvector(curGeo,5).
set vecs[markTar]:start to terPos.
set vecs[pm]:show to false.
}
else if i = prediction_span * prediction_i { //last iteration
set targetVec to geo_normalvector(curGeo,5).
set vecs[markTar]:start to terPos.
set vecs[pm]:show to false.
}
else set vecs[pm]:show to false.
set i to i + 1.
}
}
else {
set targetVec to shipNormal.
set vecs[markTar]:start to ship:geoposition:position.
for pm in pList {
set vecs[pm]:show to false.
}
}
updateVec(targetVec).
// ----------------------------------------------
// engine balancing
set pitch_err to vdot(facing:vector, targetVecTop).
set roll_err to vdot(facing:starvector, targetVecStar).
set pitch_vel_target to pitch_err * 2.
set roll_vel_target to roll_err * 2.
set pitch_vel to -vdot(facing:starvector, ship:angularvel).
set roll_vel to vdot(facing:vector, ship:angularvel).
set pitch_distr to PD_seek(PID_pitch, pitch_vel_target, -pitch_vel). //returns 0-100
set roll_distr to PD_seek(PID_roll, roll_vel_target, -roll_vel).
if inAir or tilting {
set eng_pitch_pos:thrustlimit to max(0, pitch_distr).
set eng_pitch_neg:thrustlimit to max(0, -pitch_distr).
set eng_roll_pos:thrustlimit to max(0, roll_distr).
set eng_roll_neg:thrustlimit to max(0, -roll_distr).
}
else {
set eng_pitch_pos:thrustlimit to 0.
set eng_pitch_neg:thrustlimit to 0.
set eng_roll_pos:thrustlimit to 0.
set eng_roll_neg:thrustlimit to 0.
}
local i is 0.
until i = 4 {
set vecs[i]:vec to engs[i]:facing:vector * engs[i]:thrustlimit/60.
set vecs[i]:start to engs[i]:position.
local c is rgb(255,200*((100 - engs[i]:thrustlimit)/100),0).
set vecs[i]:color to c.
set i to i + 1.
}
//-----------------------------------------------
// yaw control
if yawControl and not ag2 and time:seconds > timerFlying + 1 {
local vel is vxcl(targetVec,ship:velocity:surface).
local front is vxcl(targetVec,facing:vector).
global roll_err is vang(vel,front).
if vdot(-facing:starvector,vel) < 0 set roll_err to -1 * roll_err.
set yawAngVel to vdot(facing:topvector, ship:angularvel).
set yawAngVel to yawAngVel * (180/constant:pi()).
if abs(roll_err) > 2 set roll_vel_target to -3 * (abs(roll_err)^0.7) * (roll_err/abs(roll_err)).
//else set targetRot to -1 * min(20,sqrt(abs(yawAngVel)) * 5).
else set roll_vel_target to 0.
set yaw_rotation to PD_seek(PID_roll, roll_vel_target, yawAngVel).
if pitch_err > 5 * (constant:pi()/180) or roll_err > 5 * (constant:pi()/180) or not(inAir) set yaw_rotation to 0.
print "roll_err abs: " + round(roll_err) + " " at (1,terminal:height-5).
print "yawAngVel : " + round(yawAngVel,2) + " " at (1,terminal:height-4).
print "roll_vel_target: " + round(roll_vel_target,2) + " " at (1,terminal:height-2).
print "yaw_rotation : " + round(yaw_rotation,2) + " " at (1,terminal:height-1).
for servo in addons:ir:allservos {
servo:moveto(yaw_rotation,1000).
if abs(yaw_rotation) > 0 and abs(servo:position) > 0 and inAir {
set servo:part:children[0]:thrustlimit to 10 + abs(servo:position).
}
}
}
// -----------------------------------
wait 0.
}
//function that checks for user key input
function inputs {
if ag10 {
ag10 off.
set exit to true.
}
}
// parameter 1: a geoposition ( ship:GEOPOSITION / body:GEOPOSITIONOF(position) / LATLNG(latitude,longitude) )
// parameter 2: size/"radius" of the triangle. Small number gives a local normalvector while a larger one will tend to give a more average normalvector.
// returns: Normalvector of the terrain. (Can be used to determine the slope of the terrain.)
function geo_normalvector {
parameter geopos,size_.
set size to max(5,size_).
local center is geopos:position.
local fwd is vxcl(center-body:position,body:angularvel):normalized.
local right is vcrs(fwd,center-body:position):normalized.
local p1 is body:geopositionof(center + fwd * size_ + right * size_).
local p2 is body:geopositionof(center + fwd * size_ - right * size_).
local p3 is body:geopositionof(center - fwd * size_).
local vec1 is p1:position-p3:position.
local vec2 is p2:position-p3:position.
local normalVec is vcrs(vec1,vec2):normalized.
//debug vecdraw: local markNormal is vecs_add(center,normalVec * 300,rgb(1,0,1),"slope: " + round(vang(center-body:position,normalVec),1) ).
return normalVec.
}
// PID controllers -----------------------------------
global PID_pitch is PD_init(200.0,10,-100,100).
global PID_roll is PD_init(200.0,10,-100,100).
global PID_roll is PD_init(2.0,0,-90,90).
// main controller loop ------------------------------
print "Rover stability assist is running!".
set exit to false.
until exit {
flightcontroller().
}
//----------------------------------------------------
//EXIT
vecs_clear().
clearvecdraws().
for eng in engs {
eng:shutdown().
}
if yawControl {
for rotMod in yawRotatrons {
rotMod:doaction("move +",false). rotMod:doaction("move -",false).
}
}
unlock throttle.
set ship:control:pilotmainthrottle to 0.