Привет! Мы - команда симулятора Союз ТМА, программы, имитирующей орбитальный полёт космического аппарата Союз и Международной Космической Станции, сближение и стыковку КА с МКС, а также расстыковку и спуск. Всё это имитируется как в автоматическом (т.е. под управлением моделями бортовой аппаратуры Системы Управления Движением), так и в ручном режимах полёта, которые по своему алгоритмическому и логическому составу идентичны тем, что использовались на борту КА Союз ТМА.
Нами разработано программное обеспечение под названием "Моделирование и Управление" в среде 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; }
...
Таким образом мы реализуем штатную логику работы с КСП и УСО, конечно если тут есть люди разбирающиеся в УСО корабля Союз, которые нашли ошибку в нашей интерпретации логики работы с КСП, прошу нас поправить, т.к. у нас не имеется материалов по УСО и данную логику мы построили изучая работу моделей ИнПУ и руководство по работу с системой Нептун-МЭ.
Я думаю это довольно много информации для одного поста, поэтому остальные форматы опишу в следующем посте.
Автор: Михаил Смирягин