При разработке IMU/AHRS для своего самолета, существует необходимость в достаточном количестве испытаний, точнее - полетов с записью телеметрии.

Зачастую испытания на столе в лаборатории проходят успешно и окрыленный результатами, бежишь на аэродром, но стоит установить блок датчиков на самолет и полетать, как тут же начинаются проблемы с вибрациями, температурным дрейфом и влияние координированного разворота, а именно центробежных и гравитационных сил на результат определения ориентации датчиком MEMS.

Поэтому, чтобы исключать полеты с недоработанными алгоритмами - должны быть испытания в высоко-динамичной среде, которой не является вращение блока с датчиками на проигрывателе грампластинок или поездка на автомобиле.

Не сразу пришел к идее использовать авиасимулятор, но все же это случилось и выбор пал на FlightGear, который к тому же является свободным ПО, что позволяет подсмотреть некоторые решения кода, для реализации собственного функционала.

https://sourceforge.net/p/flightgear/flightgear/ci/next/tree/src/Instrumentation/

Хотя это не полноценная Hardware In The Loop, но некоторым подобием назвать можно.

Интерес к этому симулятору был не из-за его визуальной составляющей, которая откровенно убогая, но мы здесь собственно за интегрированной моделью динамики полета JSBSim, ниже очень классная статья.

Модель динамики полёта (FDM) — это набор математических уравнений, используемых для расчёта физических сил, действующих на моделируемый летательный аппарат , таких как тяга, подъёмная сила и сопротивление.

Каждый летательный аппарат, моделируемый FlightGear, должен использовать одну из этих моделей. 

FlightGear поддерживает несколько различных типов моделей динамики полёта.

FDM JSBSim настолько хороша, что ее можно использовать вне графического симулятора, правда для меня это показалось сложным, да и работать с ней через FlightGear комфортнее.

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

Для работы с симулятором, разработчики создали файл .fgfsrc, который является конфигуратором запуска симулятора.

  1. помещаем файл в C:\Users\xxxx\ .Fgfsrc, где xxxx — имя пользователя Windows.

  2. Запускаем обычным способом через консоль C:\Program Files\FlightGear 2020.3\bin>fgfs

Пример содержания файла .fgfsrc

--geometry=800x640
--generic=serial,out,50,\.\COM5,230400,accel-gyro
--aircraft=A320neo-PW
--airport=UUEE
--runway=24R
--timeofday=morning
--language=en

Также создается файл xxxx.xml с названием, указанным в строке

--generic=serial,out,50,\.\COM5,230400,xxxx

И помещается здесь C:\Program Files\FlightGear 2020.3\data\Protocol

Пример содержания файла, для вывода нужных параметров

<?xml version="1.0"?>

<!-- Example usage: <dash><dash>generic=file,out,50,fgfs.imu,insgns-imu -->
<!-- fgfs --generic=serial,out,40,\\.\COM15,230400,insgns-imu2 -->

<PropertyList>

 <generic>

  <output>
   <line_separator>newline</line_separator>
   <var_separator>tab</var_separator>

   <!-- <chunk> -->
    <!-- <name>time (sec)</name> -->
    <!-- <type>float</type> -->
    <!-- <format>%.4f</format> -->
    <!-- <node>/sim/time/elapsed-sec</node> -->
   <!-- </chunk> -->
   
<!-- Gyro rates -->
   <chunk>
    <name>roll rate ("p" rad/sec)</name>
    <type>float</type>
    <format>%.6f</format>
    <node>/fdm/jsbsim/velocities/pi-rad_sec</node>
   </chunk>

   <chunk>
    <name>pitch rate ("q" rad/sec)</name>
    <type>float</type>
    <format>%.6f</format>
    <node>/fdm/jsbsim/velocities/qi-rad_sec</node>
   </chunk>

   <chunk>
    <name>yaw rate ("r" rad/sec)</name>
    <type>float</type>
    <format>%.6f</format>
    <node>/fdm/jsbsim/velocities/ri-rad_sec</node>
   </chunk>
   
<!-- Orientation angles -->
   <chunk>
    <name>yaw angle</name>
    <type>float</type>
    <format>%.5f</format>
    <node>/orientation/heading-deg</node>
   </chunk>

   <chunk>
    <name>pitch angle</name>
    <type>float</type>
    <format>%.5f</format>
    <node>/orientation/pitch-deg</node>
   </chunk>

   <chunk>
    <name>roll angle</name>
    <type>float</type>
    <format>%.5f</format>
    <node>/orientation/roll-deg</node>
   </chunk>
   
<!-- Accelerations -->   
   <chunk>
    <name>X accel (body axis) (mps)</name>
    <type>float</type>
    <format>%.4f</format>
    <node>/fdm/jsbsim/accelerations/a-pilot-x-ft_sec2</node>
    <factor>0.3048</factor>  <!-- feet to meter -->
   </chunk>

   <chunk>
    <name>Y accel (body axis) (mps)</name>
    <type>float</type>
    <format>%.4f</format>
    <node>/fdm/jsbsim/accelerations/a-pilot-y-ft_sec2</node>
    <factor>0.3048</factor>  <!-- feet to meter -->
   </chunk>

   <chunk>
    <name>Z accel (body axis) (mps)</name>
    <type>float</type>
    <format>%.4f</format>
    <node>/fdm/jsbsim/accelerations/a-pilot-z-ft_sec2</node>
    <factor>0.3048</factor>  <!-- feet to meter -->
   </chunk>
 
<!-- Altitudes -->
   <chunk>
   <name>Altitude MSL (m)</name>
   <type>float</type>
   <format>%.1f</format>
   <node>/position/altitude-ft</node>
   <!-- <factor>0.3038</factor> -->
   <factor>1.0000</factor>
   </chunk> 
   
<!-- Pressures -->
   <!-- inch Hg 33,86 = mBar -->
   <!-- 29.77 inHg
33,86 = 1008 hPa QNH ICAO - BIKF-->
   <chunk>
   <name>Pressure QNH(sea-level) inHg</name>
   <type>float</type>
   <format>%.2f</format>
   <node>/environment/pressure-sea-level-inhg</node>
   <factor>1.0</factor>
   </chunk>
   
   <!-- inch Hg 33,86 = mBar -->
   <!-- 29.64 inHg
33,86 = 1003 hPa QNE ICAO - BIKF-->
   <chunk>
   <name>Pressure QNE(gnd-level) inHg</name>
   <type>float</type>
   <format>%.2f</format>
   <node>/environment/pressure-inhg</node>
   <factor>1.0</factor>
   </chunk>
   
<!-- Speeds -->
   <chunk>
   <name>Velocity IAS (kts)</name>
   <type>float</type>
   <format>%.6f</format>
   <node>/fdm/jsbsim/velocities/vias-kts</node>
   <!-- <factor>0.3038</factor> -->
   <factor>1.0000</factor>
   </chunk>

   <chunk>
   <name>Velocity true (kts)</name>
   <type>float</type>
   <format>%.6f</format>
   <node>/fdm/jsbsim/velocities/vtrue-kts</node>
   <!-- <factor>0.3038</factor> -->
   <factor>1.0000</factor>
   </chunk>
   
  </output>

 </generic>

</PropertyList>

Параграфы в файле формируются по принципу сверху-вниз, каждый chunk создает отдельный поток с выбранным параметром, который забирается из FDM jbsim

<node>/fdm/jsbsim/accelerations/a-pilot-x-ft_sec2</node>

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

Во первых у fgfs есть особенность, он не может выдавать данные из модели jbsimс частотой большей, чем выдает FPS, да-да, частота выборок этого симулятора привязана к частоте кадров графических и ничего с этим поделать нельзя, такие особенности движка.

Использовать udpили serial разницы большой нет, но udpя пока не использовал - честно?

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

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

Итак, запуская симулятор с нужным файлом, где указаны требуемые параметры из fdm, мы получаем в сериал или com-порт данные, которые выдаются с частотой 50Гц, либо меньшей.

Данные можно собирать через USB адаптер, наподобие ch340 или логическим анализатором

Но это будет мешанина с данными, среди которых сложно разобраться.

0.152998        -0.139418       -0.028368       336.73874       11.08850        -14.32830       0.5639  -1.8565 -6.6726 1745.1  29.89   28.00   115.050362      115.0575180.156726 

      -0.151063       -0.029832       336.74942       10.87917        -14.10538       0.5366  -1.8323 -6.0563 1746.3  29.89   28.00   114.963478      114.953987

Чтобы автоматизировать выборку данных, написан класс парсера на языке C++, ознакомиться с кодом можно ниже

https://github.com/brightproject/parser_flight_gear/

Для запуска кода использовался микроконтроллер stm32f411ceu6, на один UART1 подавались данные из ПК от fgfs, через другой UART2 обработанные парсером данные выдавались либо в терминальную программу CoolTerm или же в GUI на основе приложения ниже на языке Processing с небольшими доработками

https://github.com/VoxMi/MPU-9150

В динамике испытания в симуляторе выглядят так

Наиболее хороших результатов удалось добиться на основе библиотеки RTIMULib2, но довольно сильно переписанную.

Правда вопрос с влиянием центробежных сил в разворотах, при полетах на самолете с прямым крылом так до конца и не решен.

Будет хорошо, если часть читателей этой статьи повторит мои шаги и установит симулятор и произведёт испытания самостоятельно, потому как проблемы, освящённые в этой теме остаются остаются открытыми, и всегда можно улучшить результаты.

Комментарии (4)


  1. iliasam
    20.07.2025 11:55

    Я верно понял, что данные от симулятора выдавались в последовательный порт ПК, обрабатывались на MCU, который опять пересылал их на ПК по другому порту?