-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBereshit_102.py
276 lines (232 loc) · 8.36 KB
/
Bereshit_102.py
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
import csv
import math
import os
import time
import pygame
# pygame init
from PID import PID
pygame.font.init()
pygame.mixer.init()
first_distance_from_moon = 13748 # 2:25:40 (as in the simulation) // https://www.youtube.com/watch?v=JJ0VfRL9AMs
first_dist = 181 * 1000
WIDTH, HEIGHT = 900, 900
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Simulating Bereshit's Landing")
WHITE = (255, 255, 255)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
FONT = pygame.font.SysFont('comicsans', 20)
SPACESHIP_WIDTH, SPACESHIP_HEIGHT = 55, 40
MOON_HEIGHT = 100
SPACESHIP_IMAGE = pygame.image.load(
os.path.join('images', 'spaceship.png'))
MOON_IMAGE = pygame.transform.scale(pygame.image.load(
os.path.join('images', 'moon.png')), (WIDTH, MOON_HEIGHT))
SPACE = pygame.transform.scale(pygame.image.load(
os.path.join('images', 'space.png')), (WIDTH, HEIGHT))
# landing init
WEIGHT_EMP = 165 # kg
WEIGHT_FULE = 420 # kg
WEIGHT_FULL = WEIGHT_EMP + WEIGHT_FULE # kg
MAIN_ENG_F = 430 # N
SECOND_ENG_F = 25 # N
MAIN_BURN = 0.15 # liter per sec, 12 liter per m'
SECOND_BURN = 0.009 # liter per sec 0.6 liter per m'
ALL_BURN = MAIN_BURN + 8 * SECOND_BURN
RADIUS = 3475 * 1000 # meters
ACC = 1.622 # m/s^2
EQ_SPEED = 1700 # m/s
def draw_window(spaceship, angle, data={}):
WIN.blit(SPACE, (0, 0))
text = FONT.render(f"Bereshit Spaceship", 1, RED)
center = ((WIDTH - text.get_width()) * 0.5)
WIN.blit(text, (center, 15))
text = FONT.render(f"Landing Information:", 1, WHITE)
WIN.blit(text, (10, 25))
i = 2
for k, v in data.items():
text = FONT.render(f"{k}: {v}", 1, WHITE)
WIN.blit(text, (10, i * 25))
i += 1
SPACESHIP = pygame.transform.rotate(pygame.transform.scale(SPACESHIP_IMAGE, (SPACESHIP_WIDTH, SPACESHIP_HEIGHT)),
angle)
WIN.blit(MOON_IMAGE, (0, 800))
WIN.blit(SPACESHIP, (spaceship.x, spaceship.y))
pygame.display.update()
def spaceship_movement(distance, dist, spaceship):
dx = dist / first_dist
dy = distance / first_distance_from_moon
spaceship.x = WIDTH - (WIDTH * dy) - MOON_HEIGHT
spaceship.y = HEIGHT - HEIGHT * dy - MOON_HEIGHT
def accMax(weight: float) -> float:
return acc(weight, True, 8)
def acc(weight: float, main: bool, seconds: int) -> float:
t = 0
if main:
t += MAIN_ENG_F
t += seconds * SECOND_ENG_F
ans = t / weight
return ans
def getAcc(speed):
n = abs(speed) / EQ_SPEED
ans = (1 - n) * ACC
return ans
def csv_unique_name(folder='logs'):
path = os.path.join(os.getcwd(), folder)
try:
os.mkdir(path)
except:
pass
files = os.listdir(path)
i = 1
while 1:
if f'log{i}.csv' not in files:
return f'log{i}'
i += 1
def makeCsv(l, folder='logs', csvname='bereshit_102'):
path = os.path.join(os.getcwd(), folder)
try:
os.mkdir(path)
except:
pass
f = open(f'{folder}/{csvname}.csv', 'w', newline='')
writer = csv.writer(f)
writer.writerows(l)
f.close()
print(f'{csvname} saved.')
def calcDesiredSpeed(distance_from_moon, curr_speed):
if curr_speed == 0:
return distance_from_moon
if distance_from_moon < 1000:
print(f"Dist: {distance_from_moon}")
print(f"Time: {distance_from_moon} / {curr_speed} = {distance_from_moon / curr_speed}")
print(
f"Desired: {curr_speed} - ({curr_speed} / ({distance_from_moon / curr_speed})) = {curr_speed - (curr_speed / (distance_from_moon / curr_speed))}")
print("************************************************************************************")
if distance_from_moon < 500:
return 0
time = distance_from_moon / curr_speed
desired_speed = curr_speed - (curr_speed / time)
if (desired_speed < 3): desired_speed = 0
return desired_speed
def calcError(curr_speed, desired_speed):
return curr_speed - desired_speed
def adjustAngle(curr_angle, desired_change):
if curr_angle + desired_change < 3:
return 0
elif curr_angle + desired_change > 177:
return 180
else:
return curr_angle + desired_change
def adjustSpeed(curr_NN, desired_change):
if curr_NN + desired_change > 0.997:
return 1
elif curr_NN + desired_change < 0.003:
return 0
else:
return curr_NN + desired_change
def main(simulation=1, first_distance_from_moon=first_distance_from_moon):
tocsv = []
spaceship = pygame.Rect(0, 0, SPACESHIP_WIDTH, SPACESHIP_HEIGHT)
# starting point:
vertical_speed = 24.8
horizontal_speed = 932
dist = 181 * 1000
angle = 58.3 # zero is vertical (as in landing)
distance_from_moon = first_distance_from_moon
_time = 0
dt = 1 # sec
acceleration = 0 # Acceleration rate (m/s^2)
fuel = 121
weight = WEIGHT_EMP + fuel
print(f"simulation {simulation} started")
if simulation == 1:
print("Simulating Bereshit's Landing:")
tocsv.append(
['time', 'vertical_speed', 'dvs', 'VP', 'VI', 'VD', 'VPID', 'horizontal_speed',
'dist',
'distance_from_moon', 'angle', 'weight',
'acceleration', 'fuel'])
print(tocsv[0])
NN = 0.7 # rate[0,1]
last_NN=NN
desired_ver_speed = 25
v_pid = PID(0.04, 0.0003, 0.2)
v_pid_args = v_pid.run(vertical_speed, desired_ver_speed)
vp = v_pid_args[0]
vi = v_pid_args[1]
vd = v_pid_args[2]
v_tot = v_pid_args[3]
last_v_tot = v_tot
# ***** main simulation loop ******
while distance_from_moon > 0:
if simulation == 1:
tocsv.append(
[_time, vertical_speed, desired_ver_speed, vp, vi, vd, v_tot, horizontal_speed, dist,
distance_from_moon, angle, weight, acceleration, fuel])
print(tocsv[-1])
if distance_from_moon > 1000:
if vertical_speed > 30 or vertical_speed < 20:
NN = adjustSpeed(last_NN,last_v_tot)
print("vertical PID\n")
v_pid_args = v_pid.run(vertical_speed, desired_ver_speed)
vp = v_pid_args[0]
vi = v_pid_args[1]
vd = v_pid_args[2]
v_tot = v_pid_args[3]
else:
if angle != 0:
angle = adjustAngle(angle, -3)
if vertical_speed > 20:
NN = 1
print(f"NN: {NN}")
elif 15 < vertical_speed <=20:
NN = 0.7
elif 2 < vertical_speed <= 15:
NN= 0.6
else:
NN = 0
print(f"NN: {NN}")
if horizontal_speed < 2:
horizontal_speed = 0
last_v_tot = v_tot
last_NN=NN
if distance_from_moon == 0: break
# main computations
ang_rad = math.radians(angle)
h_acc = math.sin(ang_rad) * acceleration
v_acc = math.cos(ang_rad) * acceleration
vacc = getAcc(horizontal_speed)
_time += dt
dw = dt * ALL_BURN * NN
if fuel > 0:
fuel -= dw
weight = WEIGHT_EMP + fuel
acceleration = NN * accMax(weight)
else: # ran out of fuel
acceleration = 0
v_acc -= vacc
if horizontal_speed > 0:
horizontal_speed -= h_acc * dt
dist -= horizontal_speed * dt
vertical_speed -= v_acc * dt
distance_from_moon -= dt * vertical_speed
# update gui
spaceship_movement(distance_from_moon, dist, spaceship)
data = {'time': round(_time, 2), 'vertical speed': round(vertical_speed, 2),
'horizontal speed': round(horizontal_speed, 2), 'distance': round(distance_from_moon, 2),
'weight': round(weight, 2), 'fuel': round(fuel, 2), 'angle': angle, 'NN': NN}
draw_window(spaceship, angle, data)
time.sleep(0.01)
# making a csv file of the data
if simulation == 1:
makeCsv(tocsv, csvname=csv_unique_name())
# show the results for 5 seconds
time.sleep(10)
# repeat the gui for 5 times
if simulation == 5:
pygame.quit()
return
main(simulation=simulation + 1)
if __name__ == '__main__':
main()