Прогулка по лунолётам. 1 - Пролог
Все прогулки: первая, вторая, третья и четвёртая.
Хорошей программы должно быть много. Математика, вложенная более 25 лет назад в маломощные ПМК Михаилом Пуховым, настолько привлекательна своей простотой и реализмом (за это спасибо консультанту журнала, космонавту, Герою СССР Ю.Н. Глазкову), что несомненно может стать основой игр и симуляторов на любых платформах.
Прежде всего, для повторного использования алгоритм надо привести в понятный человеку и максимально наглядный вид. Код программ для ПМК таковым не является. Тем более, оригинальный код "Лунолетов" из публикаций в "Техника молодежи".
Надо отдать авторам должное: степень достигнутого сжатия так высока, что восстановление алгоритма из кода оказывается делом весьма непростым. Даже для владеющего программированием на ПМК, понимающего использованные трюки, а не просто "знакомого с основами". Очень непростым. После трех часов "раскрутки" я пришел к выводу о нерациональности такого подхода ввиду наличия блок-схемы для "Лунолет-2". Для "Лунолет-1" она практически идентична, лишь следует исключить из рассмотрения ввод угла вектора тяги и расчет горизонтальной скорости.
Повторно выражая через десятилетия авторам "Лунолет-1" и "2" свое уважение, но оставаясь верным долгу профессии вынужден сказать, что программы эти являются своего рода "анти-образцом". То есть примером того, как не надо писать программы. Если, конечно, вы хотите их в дальнейшем изменять, переносить, передавать на сопровождение другим людям. Не надо, за исключением крайних случаев. Например, когда нужно втиснуть алгоритм в злосчастные 98 шагов (байтов) программной памяти и 14 регистров.
При этом само собой подразумевается, что "как надо писать" вы знаете хорошо и на исключение идете осознанно, как Коршунов - к перелету на "Кон-тики". Если будете писать программы для МК-152/161 - никогда не следуйте стилю авторов, если на то нет особых причин. У программистов подобный стиль издавна называется "тарелка спагетти". Как правило, затраты на модификацию такой программы выше, чем на её полное переписывание.
Однако, и блок-схема не блещет структурностью. Блоки начала и конца отсутствуют. Цепочка сравнений, из которых две стрелки в итоге попадают в один блок ввода-вывода - тоже "тяжелое наследие доструктурной эпохи". Но всё-равно, это гораздо лучше "тарелки спагетти".
В итоге, текст программы на FreePascal, объединяющей оба лунолёта, может выглядеть как на листинге ниже.
А мы перейдем к реализации модели на ПМК семейства HP 50/49/48.
program lunar_ship_1;
{$mode objfpc}{$H+}
uses
Math;
var
h_i, // altitude - vertical coordinate, m - current and next
x_i, // longitude - horizontal coordinate, m
v_i, // horizontal velocity, m/sec
u_i, // rate of climb, vertical velocity, m/sec
mf_i, // mass (amount) of the fuel, kg
ms, // mass of the ship without fuel, kg
a_lim, // acceleration limit, m/sec2
// In-flight maneuver:
d_mf, // fuel consumption, kg
t, // time, sec
ac, // angle of climb, degrees; is always 0 for vertical flight mode
g, // acceleration of gravity, m/sec2
nf, // nozzle flow, m/sec
ls, // life support, sec
a, // current acceleration
q // fuel consumption by time
: real;
FlightMode : cardinal = 1;
WillReverseOfControl: boolean = false;
WillQuitProgram : boolean = false;
procedure DoStep;
var
v_i1, u_i1: real;
begin
repeat
v_i1 := v_i;
u_i1 := u_i;
v_i := v_i + a * t * sin(ac);
x_i := x_i + (v_i1 + v_i) / 2 * t;
u_i := u_i + (a * cos(ac) - g) * t;
h_i := h_i + (u_i1 + u_i) / 2 * t;
mf_i := mf_i - q * t;
ls := ls - t;
if mf_i < 0 then
t := mf_i / q;
until mf_i >= 0;
end;
procedure OutInfo;
begin
writeln('-------------------------------------------');
writeln('Altitude : ', h_i:10:2, ' m');
if FlightMode = 2 then begin
writeln('Longitude : ', x_i:10:2, ' m');
writeln('Velocity (horizontal): ', v_i:10:2, ' m/sec');
end;
writeln('Velocity (vertical) : ', u_i:10:2, ' m/sec');
writeln('Fuel : ', mf_i:10:0, ' kg');
writeln('Life support : ', ls:10:0, ' sec');
writeln('-------------------------------------------');
end;
procedure EnterManeuver(
out WillReverseOfControl: boolean;
out WillQuitProgram : boolean);
begin
repeat
writeln('Enter in-flight maneuver');
write('Fuel consumption, kg: '); readln(d_mf);
WillQuitProgram := d_mf < 0;
if WillQuitProgram then
exit;
write('Time, sec : '); readln(t);
if FlightMode <> 2 then
ac := 0
else begin
write('Climb angle, ° : '); readln(ac);
ac := DegToRad(ac);
end;
until t <> 0;
WillReverseOfControl := t < 0;
t := abs(t);
end;
procedure CalcAcceleration(WillReverseOfControl: boolean);
begin
q := d_mf / t;
a := q * nf / (ms + mf_i);
if WillReverseOfControl then begin
a := -a;
WillReverseOfControl := false;
end;
end;
begin
writeln('Lunar ship simple simulator');
writeln('(c) 1985 "Lunolet-1", "Lunilet-2" by Mikhail PUKHOV, USSR');
writeln('(c) 2011 Serguei TARASSOV, pmk.arbinada.com');
writeln;
writeln('Enter simulator mode:');
writeln(' 1 - "Lunolet-1" - vertical flight only');
writeln(' 2 - "Lunolet-2" - vertical and horizontal flight (2-dimensional)');
readln(FlightMode);
writeln('Enter negative fuel consumption value to quit the program');
g := 1.62; // 1,62 m/sec2 for Lune
ms := 2250;
nf := 3660;
a := 0;
a_lim := 3 * 9.81; // "3g"
v_i := 0;
u_i := 0;
h_i := 0;
x_i := 0;
mf_i := 400;
ls := 3600;
repeat
if h_i < 0 then begin
t := 2 * h_i /
(sqrt(sqr(u_i) + 2 * h_i * (g - a * cos(ac))) - u_i);
end
else begin
if (h_i = 0) or ((a < a_lim) and (mf_i <> 0)) then begin
OutInfo;
EnterManeuver(WillReverseOfControl, WillQuitProgram);
if WillQuitProgram then
break;
CalcAcceleration(WillReverseOfControl);
writeln('Acceleration: ', a:8:2, ' m/sec2');
end
else begin
d_mf := 0;
if not (a < a_lim) then begin
writeln('!!! Acceleration exceeded');
t := a - a_lim;
writeln('Waiting ', t:5:1, ' sec');
end;
if mf_i <= 0 then begin
writeln('!!! Fuel exceeded');
t := nf;
end;
CalcAcceleration(false);
end;
end;
DoStep;
until WillQuitProgram;
end.
Теперь протестируем полёт Александра Перепёлкина и убедимся, что симулятор работает.
Перепёлкина и убедимся, что симулятор работает.
-------------------------------------------
Altitude : 0.00 m
Velocity (vertical) : 0.00 m/sec
Fuel : 400 kg
Life support : 3600 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 65
Time, sec : 3
Acceleration: 29.92 m/sec2
!!! Acceleration exceeded
Waiting 0.5 sec
-------------------------------------------
Altitude : 169.16 m
Velocity (vertical) : 84.11 m/sec
Fuel : 335 kg
Life support : 3597 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 0
Time, sec : 2
Acceleration: 0.00 m/sec2
-------------------------------------------
Altitude : 334.15 m
Velocity (vertical) : 80.87 m/sec
Fuel : 335 kg
Life support : 3595 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 65
Time, sec : 3
Acceleration: 30.68 m/sec2
!!! Acceleration exceeded
Waiting 1.2 sec
-------------------------------------------
Altitude : 915.81 m
Velocity (vertical) : 166.02 m/sec
Fuel : 270 kg
Life support : 3590 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 0
Time, sec : 120
Acceleration: 0.00 m/sec2
-------------------------------------------
Altitude : 9174.60 m
Velocity (vertical) : -28.38 m/sec
Fuel : 270 kg
Life support : 3470 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 25
Time, sec : 2
Acceleration: 18.15 m/sec2
-------------------------------------------
Altitude : 9150.92 m
Velocity (vertical) : 4.69 m/sec
Fuel : 245 kg
Life support : 3468 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 10
Time, sec : -10
Acceleration: -1.47 m/sec2
-------------------------------------------
Altitude : 9043.50 m
Velocity (vertical) : -26.18 m/sec
Fuel : 235 kg
Life support : 3458 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 25
Time, sec : 5
Acceleration: 7.36 m/sec2
-------------------------------------------
Altitude : 8984.42 m
Velocity (vertical) : 2.54 m/sec
Fuel : 210 kg
Life support : 3453 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 0
Time, sec : 90
Acceleration: 0.00 m/sec2
-------------------------------------------
Altitude : 2652.42 m
Velocity (vertical) : -143.26 m/sec
Fuel : 210 kg
Life support : 3363 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 100
Time, sec : 3
Acceleration: 49.59 m/sec2
!!! Acceleration exceeded
Waiting 20.2 sec
-------------------------------------------
Altitude : 2122.62 m
Velocity (vertical) : -32.00 m/sec
Fuel : 110 kg
Life support : 3340 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 10
Time, sec : 20
Acceleration: 0.78 m/sec2
-------------------------------------------
Altitude : 1313.70 m
Velocity (vertical) : -48.89 m/sec
Fuel : 100 kg
Life support : 3320 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 10
Time, sec : 15
Acceleration: 1.04 m/sec2
-------------------------------------------
Altitude : 514.89 m
Velocity (vertical) : -57.62 m/sec
Fuel : 90 kg
Life support : 3305 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 35
Time, sec : 1.5
Acceleration: 36.50 m/sec2
!!! Acceleration exceeded
Waiting 7.1 sec
-------------------------------------------
Altitude : 389.79 m
Velocity (vertical) : -16.75 m/sec
Fuel : 55 kg
Life support : 3297 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 22
Time, sec : 22
Acceleration: 1.59 m/sec2
-------------------------------------------
Altitude : 13.51 m
Velocity (vertical) : -17.46 m/sec
Fuel : 33 kg
Life support : 3275 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 22
Time, sec : 0.7
Acceleration: 50.38 m/sec2
!!! Acceleration exceeded
Waiting 21.0 sec
-------------------------------------------
Altitude : 7.05 m
Velocity (vertical) : -17.27 m/sec
Fuel : 11 kg
Life support : 3253 sec
-------------------------------------------
Enter in-flight maneuver
Fuel consumption, kg: 22
Time, sec : 0.7
Acceleration: 50.88 m/sec2
!!! Acceleration exceeded
Waiting 21.4 sec
-------------------------------------------
Altitude : 0.00 m
Velocity (vertical) : -3.61 m/sec
Fuel : 0 kg
Life support : 3250 sec
-------------------------------------------
Как видно из протокола, Перепёлкину снова удалось на последних каплях керосина посадить лунолёт, собранный спустя 25 лет по той же схеме, но новыми средствами.
Ну, а читателю можно в третий раз напомнить о квалификации авторов, сумевших сжать (хоть и с потерей сервиса) до 98 байтов и 15 регистров код ста с лишним строк программы на паскале.
blog comments powered by Disqus