...

воскресенье, 3 ноября 2013 г.

Симулятор солнечной системы. Ключ на старт!

В первой части симулятора я описал правила игры и простейшую их реализацию.

Я благодарен всем кто оставил конструктивный комментарии первой версии. Это помогло мне оценить всю глубину проблемы. Отдельное спасибо пользователям kahi4, Ethril, Uri и lexasss


Сейчас симулятор вырос. Все тела влияют друг на друга по общим правилам, метод Эйлера ушел в прошлое, появилась возможность выбирать системы для симуляции и т.д.


Настала пора двигаться дальше — к покорению просторов космоса управляемым аппаратом.




По траектории понятно

Что Ваш полет идет к концу

Мы помним Вас, скорбим и любим.

Ваш ЦУП.



Наша цель — коммунизм. Завод по производству ракет

Итак, симулятор звездных систем Spacesim позволяет задавать начальное состояние системы и моделировать ее поведение.


Представим теперь, что у нас есть классическая идеальная одноступенчатая ракета ракета


Пусть ракета имеет сухую массу m,

в нее залито топливо массой mf

тяга двигателя — z

и расход топлива — n

Пусть двигатель имеет неограниченный ресурс и неограниченное количество включений.


Предположим, что наша ракета находится на поверхности планеты массой М и радиусом H. Нашей основной задачей будет выведение ракеты на круговую орбиту вокруг планеты.


heaven ahead

Перед запуском на круговую орбиту запустим нашу ракету вертикально вверх и понаблюдаем за ее движением.

На ракету действуют две силы:

1. Сила тяги двигателя (вверх): F = n * z

2. Гравитация планеты (вниз): F = G*M*(m + mf) / r^2, m + mf — полная масса ракеты, r — расстояние от ракеты до центра планеты.


Далее везде будем полагать G = 1


Результирующая сила, действующая на ракету будет: n * z — G*M*(m + mf) / r^2

Отсюда можно найти ускорение ракеты:


a = n * z / (m + mf) — M / r^2


теперь легко можно рассчитать движение ракеты вертикально вверх под действием гравитации планеты:


Методом Эйлера:



H=409.0 #Start level above sea

t=0

m=2 #Mass of equipment
mf=9 #Mass of Fuel

M=600000 #Planet mass

y=H + 1 #Initial position
a=0 #accel
v=0 #speed
f=0 #engine accel

n=1 #Fuel consumption
z=40.0 #Fuel impulse

cnt = 0 #Step count

dt = .1
maxy = 0

while(y > H and cnt < 300000000):
if mf > 0:
f = n*z/(m + mf) #Engine gives acceleration to
mf -= dt*n #Fuel goes down

else:
f = 0 #Out of fuel

a = f - M/y**2 #Total = engine - gravity

v += dt*a #new speed

y += dt*v #new altitude
maxy = max(maxy, y)

print("Step: ", cnt,
" Height: ", y,
" VSpeed: ", v)

cnt += 1

print(dt ,maxy)


Методом Рунге-Кутты



H=409.0 #Start level above sea

t=0

m=2 #Mass of equipment
mf=9 #Mass of Fuel

M=600000 #Planet mass

x=H + 1 #Initial position
a=0 #accel
v=0 #speed
f=0 #engine accel

n=1 #Fuel consumption
z=40.0 #Fuel impulse

cnt = 0 #Step count

dt = .1
maxy = 0

def f(t, x, v):
global m,mf,n,z

if mf > 0:
f = n*z/(m + mf) #Engine gives acceleration to

else:
f = 0 #Out of fuel

a = f - M/x**2 #Total = engine - gravity

#We'll use Runge-Kutta method

return a #new speed

def g(t, x, v):
return v


while(x > H and cnt < 30000):
maxy = max(maxy, x)

k1 = dt * f(t, x, v)
q1 = dt * g(t, x, v)

k2 = dt * f(t + dt/2, x + q1/2, v + k1/2)
q2 = dt * g(t + dt/2, x + q1/2, v + k1/2)

k3 = dt * f(t + dt/2, x + q2/2, v + k2/2)
q3 = dt * g(t + dt/2, x + q2/2, v + k2/2)

k4 = dt * f(t + dt, x + q3, v + k3)
q4 = dt * g(t + dt, x + q3, v + k3)


v1 = v + (k1 + 2*k2 + 2*k3 + k4)/6
x1 = x + (q1 + 2*q2 + 2*q3 + q4)/6


print("Step: ", cnt,
" Height: ", x1,
" Speed: ", v1)

cnt += 1

t += dt
v = v1
x = x1

if mf > 0:
mf -= dt*n #Fuel goes down

print(dt ,maxy)


Как видим, результаты совпадают с большой точностью


Собираем все вместе



Итак, мы научились запускать реактивный двигатель и взлетать вертикально вверх.

Также у нас есть симулятор из прошлой части, в котором тела двигаются под действием сил гравитации друг относительно друга.

Объединим их! Добавим ракету в симулятор.


Добавим в ракету бортовой компьютер, работающий по программе.

Чтобы выйти на круговую орбиту, будет действовать по такому алгоритму:


1. Запускаем двигатель и ракета начинает лететь вверх.

2. Выключаем двигатель. Ракета летит вверх по инерции

3. Поворачиваем корпус ракеты на 90 градусов.

4. В тот момент, когда вертикальная скорость становится равной нулю, включаем двигатель

5. Через небольшой промежуток времени выключаем двигатель.


А так выглядит реализация:



class EarthOrbiter(Rocket):
def flightProgram(self):
#Take off and turn 90" right
if self.mode == 0:
self.engineOn()
self.mode = 1

if self.t > 12.0 and self.mode == 1:
self.engineOff()
self.setHead(90)
self.mode = 2

#Go to round orbit
if self.t > 20 and self.mode == 2:
self.engineOn()
self.mode = 3

if self.t >= 27 and self.mode == 3:
self.engineOff()
self.mode = 4




События в нашей ракете происходят в зависимости от полетного времени и предыдущего состояния.

Бинго! Полет нормальный. Траектория стабильная.


Вот короткое фидео о первом полете:

Полетное видео 1

Полетное видео 2


Следующим этапом будет доббавление Луны в систему и полет к ней.

Также в планах есть многоступенчатые ракеты.


Исходники — тут


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends:



Комментариев нет:

Отправить комментарий