Привет! Мы — команда симулятора Союз ТМА, программы, имитирующей орбитальный полёт космического аппарата Союз и Международной Космической Станции, сближение и стыковку КА с МКС, а также расстыковку и спуск. Всё это имитируется как в автоматическом (т.е. под управлением моделями бортовой аппаратуры Системы Управления Движением), так и в ручном режимах полёта, которые по своему алгоритмическому и логическому составу идентичны тем, что использовались на борту КА Союз ТМА.
Нами разработано программное обеспечение под названием «Моделирование и Управление» в среде C++ Builder 6. Почему именно в ней, а не в VS — это наш первый проект и ранее никто из нас не имел опыта в программировании, а тем более в тренажёростроении, поэтому для «пробы пера» была выбрана наиболее простая среда, но при этом код разрабатывается так, чтобы его можно было максимально быстро интегрировать в другую среду (Qt, VS).
В первую очередь мы решили разработать основные оконные формы для отладки работы алгоритмов ПО — журнал протоколирования событий, а также форматы, имитирующие бортовую аппаратуру, с которой взаимодействует космонавт во время выполнения программы полёта.
Первой формой была — «Ввод начальных условий». На данной форме вводятся все необходимые параметры для выставления начального состояния КА и МКС, минимальный набор начальных параметров состояния бортовых систем, оскулирующие элементы и др. параметры, необходимые для начала режима. Сам список какие именно параметры необходимы для моделирования столь сложной системы нам были неизвестны, но изучив статьи на данную тему, имеющиеся в интернете, а также пообщавшись с разработчиками тренажёров подготовки космонавтов мы выяснили приблизительный набор параметров, которые использует ЦПК им. Гагарина и НАСА для задания начальных условий режимов полёта.
В этот список входят несколько групп параметров:
-
Основные характеристики:
-
Массив моментов инерции (Jxx, Jyy, Jzz, Jxy, Jyz, Jzx) — который необходим для математической модели движения. Вводится как для корабля, так и для станции.
-
Масса корабля и станции (в кг).
-
Координаты центра масс корабля и станции.
-
-
Параметры орбиты:
-
Параметры орбиты в виде набора Кеплеровых элементов.
-
Параметры орбиты в виде векторов в J2000.
-
-
Параметры ориентации:
-
Начальная система координат корабля и станции (инерциальная текущая или орбитальная СК).
-
Углы (тангаж, крен, рыскание).
-
Угловые скорости (Wx, Wy, Wz).
-
-
Параметры режима:
-
Признаки занятости стыковочных узлов (наличие пристыкованных кораблей).
-
Начальный режим работы Системы Управления Движением и Навигации.
-
Конфигурация станции.
-
Набор состояния признаков состояния бортовых систем корабля и станции.
-
Дата и время начала режима.
-
Пользовательский интерфейс данного формата выглядит следующим образом:
Пользовательский интерфейс, а также набор и расположение параметров были позаимствованы у тренажёра ДОН Союз-ТМА, как единственные известные нам, по ходу разработки мы от них откажемся и разработаем свой пользовательский интерфейс, основываясь на задачах, поставленных перед симулятором и необходимых параметрах для моделирования.
Из-за обширного количества вводимых значений, в данный формат мы добавили возможность загрузки и сохранения параметров начальных условий в файл. Принцип сохранения и загрузки прост и использует дефолтные компоненты, такие как TSaveDialog и TOpenDialog. Данные сохраняются и загружаются в ini файл (TIniFile), что довольно удобно. Структура файла также разделена на группы в соответствии с логикой набора параметров начальных условий.
Все действия оператора (загрузка и сохранение, а также все возможные ошибки) протоколируются в журнал событий с указанием времени и описанием действия.
Разработка данного формата позволила нам сформировать структуру начальных условий, для последующей работы с ними.
// Структура для математических моделей struct{ //// Д А Т А //// TDateTime nu_day; // 2 Модельное время/дата //// М К С //// double vec_j2000_mks[3]; // 8 Массив вектора положения Ц.М. МКС в J2000 (X, Y, Z) double vel_j2000_mks[3]; // 11 Массив скорости Ц.М. МКС в J2000 (X, Y, Z) double Q_mks[4]; // 14 Массив компонентов кватерниона МКС 0 1 2 double w_j2000_mks[3]; // 18 Массив вектора угловой скорости МКС относительно J2000 в проекциях на ССК РС (Wx Wy Wz) double vec_mks_PC[3]; // 21 Массив координат Ц.М. МКС в РС (X, Y, Z) double m_mk; // 24 Масса МКС double mi_mks[3][3]; // 25 Двумерный массив моментов инерции МКС (Jxx, Jxy, Jxz...) //// Т К //// double vec_j2000_tk[3]; // 34 Массив вектора положения Ц.М. ТК в J2000 (X, Y, Z) double vel_j2000_tk[3]; // 37 Массив скорости Ц.М. ТК в J2000 (X, Y, Z) 0 1 2 3 double Q_tk[4]; // 40 Массив компонентов кватерниона разворота ССК ТК относительно J2000 (Qs, Qx, Qy, Qz) double w_j2000_tk[3]; // 44 Массив вектора угловой скорости ТК относительно J2000 в проекциях на ССК ТК (Wx Wy Wz) double vec_tk_TPK[3]; // 47 Массив координат Ц.М. ТГК/ТПК в РС (X, Y, Z) double m_tk; // 50 Масса ТК double mi_tk[3][3]; // 51 Двумерный массив моментов инерции ТК (Jxx, Jxy, Jxz...) //// M I S C //// double vec_solar[3]; // 60 Единичный вектор из центра J2000 на Солнце в проекциях на J2000 (ex, ey, ez) unsigned long r_st_mks; // 63 Режим стабилизации МКС unsigned long n_su_4_dk; // 64 Номер стыковочного узла МКС, к которому выполняется причаливание ТК (резерв, не используется) unsigned long nu_otor_switch_styk_dk; // 65 № СУ, к которому пристыкован ТК (для задания состояния состыкованного ТК) double tk_top_zap; // 66 Запас топлива ТК (КДУ О+Г) double mks_top_zap; // 67 Запас топлива МКС (РС ОДУ О+Г) unsigned long pr_doking; // 68 Признак состыкованного состояния ТК и МКС по НУ unsigned long nr_sudn; // 69 Начальный режим работы СУДН ТК } NU_temp; // Массив признаков УСО static bool USO_Booled[20][16]; // Матрица УСО (разблюдовка в ТО_УСО п.п. 3.7)
После этого мы изучили некоторые статьи по разработке математических моделей бортовых систем космических аппаратов (Е. А. Микрин — Бортовые комплексы управления космическими аппаратами ISBN 5-7038-2178-9), а также различные технические документы на Союз ТМА (в основном SoyCOM) и составили список основного приборного состава оборудования, которое необходимо реализовать для минимального функционирования системы и отладки основных алгоритмов управления.
В качестве математической модели движения на первом этапе было решено использовать модель SGP4, переработанную под нужды симулятора (вместо входных параметров TLE — массив параметров НУ).
Из приборного состава в первую очередь был реализован Пульт Ручного Ввода Информации (ПРВИ) в UI исполнении, как он был реализован на пульте космонавтов «Нептун» корабля Союз-ТМ
Данный пульт предназначен для информационного обмена оператора с БЦВК «Аргон-16». На кораблях серии ТМА данный пульт был исполнен в программном обеспечении Интегрированного Пульта управления (ИнПУ).
Так как на первом этапе разработки симулятора не предполагалось использовать обмен с моделью ИнПУ, то было решено использовать встроенную модель пульта ПРВИ с сам симулятор.
Логика работы с пультом следующая: оператор последовательно заполняет цифровые Индикаторы Ручного Ввода Информации (ИРВИ) кроме 15-го индикатора (знак + / -), после чего выдает команду на исполнение кнопкой «ИСП» и после обработки введённой информации наблюдает ответ-квитанцию от БЦВК на ИРВИ. Все действия с данным прибором также логируются в журнал. С помощью ПРВИ можно:
-
Произвести чтение/запись уставочной информации (состояние логических признаков управляющих слов 16-разрядной ячейки памяти Аргона).
-
Управлять форматами дисплея (форматы отображения Блока Формирования Изображения).
-
Организовать динамический вывод информации на ИРВИ.
-
Чтение/запись восьмеричных или десятичных чисел в память Аргона.
Исходя из вышеперечисленного можно сказать, что данный формат позволяет производить полный информационный обмен с памятью БЦВК, что на этапе отладки модели БЦВК крайне важно.
Для облегчения восприятия информации и ввода вывода уставочной информации, начиная с кораблей серии Союз ТМА-М работу с ПРВИ упразднили, оставив лишь формат отображения ИнПУ «ПРВИ» (индекс 2Ф46), на который выведены основные управляющие слова (В1-ТА1) для контроля их состояния (при выполнении штатной программы полёта, изменение состояния логических признаков происходит по Командной Радио Линии (КРЛ) с Земли группой ГОГУ). Ниже представлен скриншот формата ПРВИ корабля Союз МС с выведенным на экран состоянием логических признаков управляющего слова А20.
Для удобства работы с кодом и последующей миграции кода из C++ Builder 6 в среду Visual Studio (планируется, что итоговое приложение будет MFC + OpenGL в качестве графического движка для системы визуализации) каждый формат имеет помимо своего файла формы (***_form.cpp) также файл с логикой, где описаны все процедуры и функции для данной системы/прибора. Логика работы прибора ПРВИ в симуляторе следующая:
Вначале пользователь должен включить прибор, нажав клавишу ON, тем самым он выставит логический признак brvi_on = true;
void __fastcall TIrBrForm::brvi_on_btnClick(TObject *Sender) { brvi_on=true; // Признак включения ПРВИ Panel1->Color=clLime; // Зажигаем индикатор состояния прибора зеленым цветом }
Далее используя один из кодов ввода-вывода необходимо ввести последовательно режим, адрес и число, а также, если необходимо, то и знак. Знак можно ввести на любом этапе заполнения цифровых индикаторов. Ниже описаны коды ввода-вывода информации, актуальные для ПрО Союз ТМА №228
Операция |
Код |
Одиночный ввод десятичных чисел |
14 |
Одиночный ввод восьмеричных чисел |
15 |
Групповой ввод десятичных чисел |
17 |
Групповой ввод восьмеричных чисел |
18 |
Запись «0» в заданный разряд ячейки ОЗУ |
30 |
Запись «1» в заданный разряд ячейки ОЗУ |
31 |
Операция |
Код |
Одиночный вывод десятичных чисел |
24 |
Одиночный вывод восьмеричных чисел |
25 |
Групповой вывод десятичных чисел |
27 |
Групповой вывод восьмеричных чисел |
28 |
Динамический вывод десятичных чисел |
04 |
Динамический вывод восьмеричных чисел |
05 |
В ПО каждый индикатор является компонентом TPanel, где заполняется свойство Caption. При нажатии на какую-либо цифровую клавишу последовательно проверяется занятость каждого индикатора и заполняется последний свободный индикатор. Ниже приведен участок кода обработки нажатия цифровой клавиши «1»:
void __fastcall TIrBrForm::brvi_btn_1Click(TObject *Sender) { if(brvi_on){ USO_BitType[16][3] = 0111; if(i1->Caption=="") i1->Caption="1"; else if(i2->Caption=="") i2->Caption="1"; else if(i3->Caption=="") i3->Caption="1"; else if(i4->Caption=="") i4->Caption="1"; else if(i5->Caption=="") i5->Caption="1"; else if(i6->Caption=="") i6->Caption="1"; else if(i7->Caption=="") i7->Caption="1"; else if(i8->Caption=="") i8->Caption="1"; else if(i9->Caption=="") i9->Caption="1"; else if(i10->Caption=="") i10->Caption="1"; else if(i11->Caption=="") i11->Caption="1"; else if(i12->Caption=="") i12->Caption="1"; else if(i13->Caption=="") i13->Caption="1"; else if(i14->Caption=="") i14->Caption="1"; else {} } }
Мы не смогли разобраться, как записать это в виде цикла for, поэтому сделали таким образом. По такой же логике работают обработчики и на остальных клавишах. Если необходимо очистить индикаторы, то для этого надо нажать клавишу «СБР», а если убрать последний введенный индикатор, то клавишу «ГАШ».
После окончания заполнения индикаторов необходимо отправить введенные значения на обработку в БЦВК, ниже представлен код обработчика клавиши ИСП:
void __fastcall TIrBrForm::isp_btnClick(TObject *Sender) { if(brvi_on) { // Если БРВИ вкл if(i1->Caption==""&&i2->Caption==""){ // Если первый и второй индикаторы пустые, i1->Caption=="A"; // Тогда сообщение АА i2->Caption=="A"; JPS(3,is_irvi,is_operator,"АА",""); // и лог в журнал } else { // или (если 1И и 2И не пустые) AnsiString brvi_msg = i1->Caption+i2->Caption+i3->Caption+i4->Caption+ // Создаем строку текущего состояния И ИРВИ i5->Caption+i6->Caption+i7->Caption+i8->Caption+i9->Caption+i10->Caption+ i11->Caption+i12->Caption+i13->Caption+i14->Caption+i15->Caption; JPS(1,is_operator,is_irvi,brvi_msg,""); Timer1->Enabled=true; // Включаем таймер задержки индикации // Обнуляем индикаторы перед индикацией i1->Caption=""; i2->Caption=""; i3->Caption=""; i4->Caption=""; i5->Caption=""; i6->Caption=""; i7->Caption=""; i8->Caption=""; i9->Caption=""; i10->Caption=""; i11->Caption=""; i12->Caption=""; i13->Caption=""; i14->Caption=""; i15->Caption=""; irvi_string = brvi_msg; // Присваиваем глобальной переменной значение ИРВИ ChekIrvi(irvi_string); }} else // Если БРВИ выключен JPS(3,is_miu,is_operator,cmd_brvi_error,""); // Ошибка в Журнал }
Здесь мы собираем из индикаторов строку, которую после присваиваем глобальной AnsiString переменной irvi_string. Процедура ChekIrvi принимает в качестве аргумента сформированную строку и производит с ней следующие операции:
void ChekIrvi (AnsiString irvi_str){ if(irvi_str.IsEmpty())JPS(3,is_miu,is_operator,"Пустой ввод!",""); else { irvi_type.mode = StrToInt(irvi_str.SubString(1,2)); // Вырезаем первые два символа строки ирви "режим" switch (irvi_type.mode) { // Обработчик режима case 00: /* Приоритетный или принудительный режим выдачи пр-м 1 - 4 */ break; case 04: /* Динамический вывод 10-х чисел */ break; case 05: /* Динамический вывод 8-х чисел */ break; case 10: /* Ввод уставки РУС */ break; // Arg addr RUS AUS data? case 11: /* Ввод уставки АУС 1-й группы */ break; case 12: /* Ввод уставки АУС 2-й группы */ break; case 14: /* Одиночный ввод 10-х чисел */ // Если режим 14, то if((irvi_str.SubString(3,5)).IsEmpty())JPS(3,is_miu,is_operator,"Пустой адрес!",""); else { irvi_type.addr = StrToInt(irvi_str.SubString(3,5)); // Присваиваем значение адреса if(CorrectAddr(irvi_type.addr)) { // Проверяем корректность адреса, если корректен, то if((irvi_str.SubString(8,7)).IsEmpty())JPS(3,is_miu,is_operator,"Пустое число!",""); else { irvi_type.value = StrToInt(irvi_str.SubString(8,7)); // Присваиваем значение ArgonMemoryType[irvi_type.addr] = irvi_type.value; // Записываем его в ячейку памяти Аргона SetItvi(irvi_type.mode,irvi_type.addr,ArgonMemoryType[irvi_type.addr], irvi_type.z ); // Выставляем результат на ИРВИ JPS(4,is_argon,is_irvi,"Запись числа "+ // Логируем результат (от имени Аргона) IntToStr(irvi_type.value)+" по адресу "+IntToStr(irvi_type.addr),"");}} else { // Если адрес не корректен ,то irvi_err = true; JPS(3,is_argon,is_operator,arg_addr_error,""); } } // Логируем превышение допустимого значения памяти А16 break; case 15: /* Одиночный ввод 8-х чисел */ break; case 17: /* Групповой ввод 10-х чисел */ break; case 18: /* Групповой ввод 8-х чисел */ // irvi_type.addr = StrToInt(irvi_str.SubString(3,5)); // Присваиваем значение адреса // if(CorrectAddr(irvi_type.addr)) { // Проверяем корректность адреса, если корректен, то //irvi_type.value = StrToInt(irvi_str.SubString(8,7)); // Присваиваем значение // ArgonMemoryType[irvi_type.addr] = irvi_type.value; // Записываем его в ячейку памяти Аргона //SetItvi(irvi_type.mode,(irvi_type.addr)+1,ArgonMemoryType[irvi_type.addr], irvi_type.z ); // Выставляем результат на ИРВИ //mode18act=true; break; case 21: /* Вывод уставки АУС 1-й группы */ break; case 22: /* Вывод уставки АУС 2-й группы */ break; case 24: /* Одиночный вывод 10-х чисел */ // Если режим 24, то irvi_type.addr = StrToInt(irvi_str.SubString(3,5)); // Присваиваем значение адреса временной переменной if(CorrectAddr(irvi_type.addr)) { // Проверяем корректность адреса, если корректен, то SetItvi(irvi_type.mode,irvi_type.addr,ArgonMemoryType[irvi_type.addr], irvi_type.z ); } // Выставляем результат на ИРВИ else { // Если адрес не корректен ,то irvi_err = true; JPS(3,is_argon,is_operator,arg_addr_error,""); } // Логируем превышение допустимого значения памяти А16 break; case 25: /* Одиночный вывод 8-х чисел */ break; case 27: /* Групповой вывод 10-х чисел */ break; case 28: /* Групповой вывод 8-х чисел */break; case 30: /* Изменение состояния признака в слове - запись единицы */ irvi_type.addr = StrToInt(irvi_str.SubString(3,5)); // Присваиваем значение адреса временной переменной if(CorrectAddr(irvi_type.addr)) { // Проверяем корректность адреса, если корректен, то irvi_type.value = StrToInt(irvi_str.SubString(8,7)); // Присваиваем значение mode_30(irvi_type.addr,irvi_type.value); } // Выставляем результат на ИРВИ else { // Если адрес не корректен ,то irvi_err = true; JPS(3,is_argon,is_operator,arg_addr_error,""); } // Логируем превышение допустимого значения памяти А16 break; case 31: /* Изменение состояния признака в слове - запись нуля */ irvi_type.addr = StrToInt(irvi_str.SubString(3,5)); // Присваиваем значение адреса временной переменной if(CorrectAddr(irvi_type.addr)) { // Проверяем корректность адреса, если корректен, то irvi_type.value = StrToInt(irvi_str.SubString(8,7)); // Присваиваем значение mode_31(irvi_type.addr,irvi_type.value); } // Выставляем результат на ИРВИ else { // Если адрес не корректен ,то irvi_err = true; JPS(3,is_argon,is_operator,arg_addr_error,""); } // Логируем превышение допустимого значения памяти А16 break; case 40: /* */ break; case 41: /* */ break; case 42: /* */ break; case 43: /* */ break; case 44: /* */ break; case 45: /* */ break; case 46: /* */ break; case 48: /* Сверка времени */ break; default: irvi_err = true; // Флаг ошибки (для индикации на ИРВИ) JPS(3,is_argon,is_irvi,"АА",""); // Логируем ошибку о несуществующем режиме JPS(3,is_miu,is_operator,"Несуществующий режим!",""); irvi_type.addr = StrToInt(irvi_str.SubString(3,5)); irvi_type.value = StrToInt(irvi_str.SubString(8,7)); break; } } }
Все эти операции позволяют нам организовать стандартную логику работы с ПРВИ и контролировать/изменять состояние уставочной информации штатным образом, как это было реализовано на корабле серии ТМА. Все действия оператора также логируются в журнал, что позволяет производить анализ действий по окончанию режима на соответствие требованиям бортовой документации:
Вся необходимая информация (инструкции, аварии, состояние логических признаков и др.) хранится в ячейках памяти и мы можем ее вызвать в любое время используя формат ПРВИ.
Это был первый формат относящийся к модели БЦВК «Аргон-16», но его оказалось недостаточно и в последствии был разработан еще один формат для отладки модели БЦВК «Отладка А16», скриншот которого представлен ниже:
На нём можно наблюдать виртуальные клавиши принудительной выдачи команд в БЦВК (имитации релейных команд для отладки некоторых процедур и алгоритмов), вывести число из ОЗУ без использования ПРВИ (если ПРВИ занят, т.к. с ним могут работать 2 оператора — обмен по UDP), наблюдать текущее значение глобальной переменной ИРВИ, наблюдать статусное окно выбранных каналов БЦВК (т.к. он работает по мажоритарной схеме 2 из 3) и др. Пустые поля по мере разработки будут заполнятся отладочными командами. Все компоненты TLabel выводятся в обработчике таймера, который каждый тик присваивает им состояние переменных.
Этот формат позволит нам отслеживать работу алгоритмов БЦВК (как самых сложных в реализации) и прерывать работу модели при нештатной работе (отклонении от нормы).
Следующими основными форматами, без которых невозможно управление кораблём Союз, являются — КСПл и КСПп. Около половины времени работы космонавта с ПрО пульта «Нептун-МЭ» приходится именно на эти форматы. На них представлены основные команды выдаваемые оператором в бортовые системы корабля — включение и пуск БЦВК, команды управления двигательной установкой, управление ССВП и др. Ниже представлены форматы КСПл и КСПп разработанные для симулятора:
Данные форматы по своему информационному обеспечению идентичны одноименным форматам используемым в ПрО и ИО ИнПУ, что также позволяет работать с ними как с штатными форматами отображения, для сравнения — ниже скриншот штатного формата КСПл корабля Союз ТМА №219 (ПО № 5.19, ИО № 5.1)
Логика работы с данным форматом уникальна и разработана Тяпченко Ю.А. Основным преимуществом данного типа пульта является матричный способ выдачи команд и развернутая форма представления информации. С точки зрения эргономики это довольно удобный способ представления большого количества команд, при малом количестве органов взаимодействия. Логика работы с данным форматом следующая — оператор выбирает вначале строку (букву) и выдает ее, буква загорается и разрешается выбор столбца (цифры), где нечётная цифра включает команду, а чётная ее выключает. К примеру, чтобы выдать команду на включение РУД, необходимо вначале нажать клавишу «В», а потом «7». Таким образом будет подана команда на включение питания ручки управления движением, а в пульт придёт обратная квитанция об успешности исполнения команды, которая «зажжёт» транспарант светло зеленым цветом.
Также можно заметить, что на некоторых транспарантах присутствуют дополнительные символы, обозначение которых описано ниже:
Это обозначает, что если команда без сигнализации — значит обратной квитанции и загорания соответствующего транспаранта не будет, а если команда только прямая, значит при выдаче чётной цифры (выключения) команда не пройдет и транспарант не погаснет. Обычно эти команды выключаются другими командами, к примеру для снятия признака выбора К11 «РРЖ 4С» необходимо выдать Л15 «РРЖ 15С» или Л13 «РРЖ 8С».
В симуляторе логика КСП реализована следующим образом. Объявлен двумерный булевый массив
static bool KSP_Booled[16][9];
который хранит состояние команд, если мы выдаем ту или иную команду КСП, то присваиваем соответствующему элементу значение true, которое снимается обработчиком получившей его системы. К примеру при выдаче команды А7 «СДД ОТКЛ» мы выставляем признак KSP_Booled[0][6]=true;
, основной обработчик УСО каждый тик обрабатывает весь массив и при KSP_Booled[0][6]=1 сразу снимает эту команду и посылает команду в КДУ и другие системы соответствующие признаки, в это время в КСП стоит обработчик квитанций УСО, который в свою очередь опрашивает каждый элемент массива УСО и если видит ответную квитанцию об успешном отключении сигнальных датчиков СДД от системы управления, зажигает транспарант «СДД ОТКЛ», ниже представлен код обработки этой команды:
// Модуль КСПл, обработчик нажатия цифры 7 ... if (KSP_Let[0]){ // А Если выбранна буква А KSP_Booled[0][6]=true; // Тогда выставляем признак А7 - правда JPS(1,is_operator,is_miu,is_ksp,"А7"); } else // Логируем выдачу команды ... // Модуль uso_model.cpp процедура USO_work ... if(KSP_Booled[0][6]) { // A 7 KSP_Booled[0][6] = false; // 95 Исключение СДД из схемы управления USO_Booled[0][3]=true; kdu_sdd = false; } ... // Модуль КСПл - тик таймера индикации ... if(USO_Booled[0][3]){ // KSP A7 A7_LABEL->Color=clLime; A7_LABEL->Font->Color=clBlack; } else { A7_LABEL->Color=clGreen; A7_LABEL->Font->Color=clYellow; } ...
Таким образом мы реализуем штатную логику работы с КСП и УСО, конечно если тут есть люди разбирающиеся в УСО корабля Союз, которые нашли ошибку в нашей интерпретации логики работы с КСП, прошу нас поправить, т.к. у нас не имеется материалов по УСО и данную логику мы построили изучая работу моделей ИнПУ и руководство по работу с системой Нептун-МЭ.
Я думаю это довольно много информации для одного поста, поэтому остальные форматы опишу в следующем посте.
ссылка на оригинал статьи https://habr.com/ru/post/532726/
Добавить комментарий