Я благодарен всем кто оставил конструктивный комментарии первой версии. Это помогло мне оценить всю глубину проблемы. Отдельное спасибо пользователям 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
Следующим этапом будет доббавление Луны в систему и полет к ней.
Также в планах есть многоступенчатые ракеты.
ссылка на оригинал статьи http://habrahabr.ru/post/197788/
Добавить комментарий