Найти в Дзене

Space Engineers - Пишем скрипты. Часть 3. Делаем машинку на автопилоте. Теория

Пришло время третий части нашего гайда по скриптам. В этой части руководства мы разберём основы векторной алгебры, школьной геометрии, и немного математики за первый курс ВУЗа. Будет много букв, синусов, косинусов и операций с матрицами. Вперёд! Для тех кто думал, что программирование - это натыкивание спагетти-кода, то он очень сильно заблуждается. Программирование - это в первую очередь математика, просто библиотеки помогли весь этот ужас спрятать от глаз, но ведь наша игра про кораблики, машинки и прочие движущиеся штуки, поэтому здесь математика - это главное. Основным упором у нас будет векторная алгебра, немного школьной геометрии и физики, ну а также матрицы. Применение всего этого многообразия позволит с лёгкостью переходить от скорости к ускорению или перемещению в пространстве, рассчитывать необходимые углы поворотов и скорости движения и тд, чтобы наши конструкции могли двигаться и выполнять, то что нужно, а не то что получиться. Также частенько будут встречаться элементы т
Оглавление

Пришло время третий части нашего гайда по скриптам. В этой части руководства мы разберём основы векторной алгебры, школьной геометрии, и немного математики за первый курс ВУЗа. Будет много букв, синусов, косинусов и операций с матрицами. Вперёд!

1. Математика

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

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

Ну и так ремарка, вот этот сайт ваш лучший друг и товарищ: http://www.mathprofi.ru/vektory_dlya_chainikov.html

2. Системы координат

Существует две основных системы координат: декартова и полярная:

  • Декартова система координат удобна для описания положения объекта в пространстве;
  • Полярная система координат описывает положения объекта в углах поворота и отдалённости от центра. Обычно в ней описывают повороты чего-то вокруг своей оси.

На рисунке 1 приведены обе системы координат для сравнения.

Рис. 1 - Системы координат 2D
Рис. 1 - Системы координат 2D

Системы координат бывают двухмерными (2D) и трёхмерными (3D). Часто приходится оперировать и теми и другими одновременно и переходить от одних к другим. В частности с машинкой придётся переходить от трёхмерного пространства к плоскости дороги.

Одномерные системы координат (1D) тоже существуют и это координатная прямая (рис. 2).

Рис. 2 - Координатная прямая. Через неё можно выразить положение поршня.
Рис. 2 - Координатная прямая. Через неё можно выразить положение поршня.

Также системы координат бывают глобальными и локальными:

  • Глобальная система координат - это основная система координат игрового мира, к ней привязано положение всех объектов в игровом мире.
  • Локальная система координат - это система координат относительно какого-то объекта, к примеру нашего корабля, планеты, астероида.

3. Понятие вектор, точка

Ну с точкой более менее понятно: точка - это некое место в пространстве, плоскости, которое обозначается координатой: для декартовой системы координат - это значения осей X, Y, Z; для полярной - значения угла φ и радиуса R. Такая комбинация уникальна и принадлежит только этой точке.

А вот что такое вектор? В учебнике определение трактуется так:

Вектор - это отрезок, который имеет длину и направление, то есть имеет начало и конец.

На рисунке 3 показан пример вектора.

Рис. 3 - Вектор
Рис. 3 - Вектор

Фактически это отрезок, который провели из одной точки пространства во вторую и указали направление. Для нас вектор будет полезен в двух случаях:

  1. Он позволяет показать перемещение чего-либо из точки А в точку Б;
  2. Через вектора можно выражать силы, ускорения и прочие факторы, которые воздействуют на нас в процессе. Через них же удобно рассчитывать обратные воздействия, которые нужны для компенсации (Пример: компенсация силы гравитации с помощью ускорителя).

4. Плоскость и пространство

Для машинки на автопилоте довольно часто придётся переходить от 3D мира к 2D, так как маршруты и карты - двумерные, а вот даже игровой мир - штука трёхмерная. Причём наше положение в пространстве может быть абсолютно произвольным и меняться аналогичным образом.

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

Применение плоскостей позволяет строить проекции трёхмерных величин в двухмерные и использовать их в двухмерных расчётах. Как уже я приводил пример выше: построение двухмерного маршрута по реальной трёхмерной местности.

5. Постановка задачи

Ну а теперь сама задача:

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

На рисунке 4 показана схема задачи.

Рис. 4 - Схема задачи
Рис. 4 - Схема задачи

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

Начнём с того, что нужно построить плоскость, чтобы можно было проецировать точки маршрута на нашу "карту". Для этого нам потребуется задать плоскость через перпендикуляр. Перпендикуляр возьмём из направления "Вверх" блока управления (Способ задания плоскости через вектор нормали (рис. 5)).

Рис. 5 - Задание плоскости через вектор нормали. Изображение взято с сайта mathprofi.ru
Рис. 5 - Задание плоскости через вектор нормали. Изображение взято с сайта mathprofi.ru

А теперь нужно спроецировать все точки маршрута на эту плоскость. В нашей задачи таких точек две: наша позиция и точка назначения. Забегая вперёд, наша позиция всегда будет находится в плоскости (ведь мы её и строим относительно себя), а вот точку назначения надо будет спроецировать.

Решение данной задачи достаточно сложное, тем более в C# есть уже готовая функция проекции точки на плоскость (Вообще там много математики уже реализовано, но об этом позже), поэтому оставлю лишь ссылку на материал кому интересно: https://zaochnik-com.com/spravochnik/matematika/prjamaja-ploskost/proektsija-tochki-na-ploskost-koordinaty-proektsii/?ysclid=mazqhip4s6837179726.

Если кратко, то нужно построить прямую перпендикулярную плоскости и найти точку её пересечения с плоскостью.

На данном этапе мы имеем две точки: Нашу позицию, и координаты проекции точки А на плоскость маршрута. Для дальнейшего движения нужно получить два сигнала: скорость поворота колёс исходя из угла между передом машины и вектором направления на точку и мощность вращения колёс. Ну если со вторым понятно (на первое время возьмём некий коэффициент от расстояния между машинкой и точкой и ограничим его сверху), то что делать с поворотом? Тем более колёсам нужен сигнал типа "плюс" и "минус" для поворота вправо и влево соответственно.

Тут на помощь придут тригонометрические функции синуса и косинуса. Посмотрим их графики (рис. 6).

Рис. 6 - Стандартные тригонометрические функции
Рис. 6 - Стандартные тригонометрические функции

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

Рис. 7 - Скалярное произведение векторов
Рис. 7 - Скалярное произведение векторов

В C# есть встроенная функция скалярного произведения, а вот как посчитать его правильно мы сейчас выясним.

Итак скалярное произведение даст косинус угла, причём если брать в качестве опорного вектора - вектор "Вперёд" машинки, то он будет всегда положительный (рис. 6), так как результирующий угол будет в пределах от 0 до 90 градусов и редко выходить за пределы. Для получения "плюса" и "минуса" нужно сделать переход через 90 градусов. Самый простой вариант это взять перпендикуляр к направлению "Вперёд", к примеру направление "Влево" и вычислять скалярное произведение между ним и вектором направления на точку. Тогда получим полноценный сигнал управления поворотами колёс.

6. ПИД регулятор

В машинку мы сразу постепенно будем внедрять управление через Пропорционально Интегрально Дифференциальный регулятор. Суть данного алгоритма в том, что полученный сигналы нельзя просто взять и подать, как минимум их нужно будет пропорционально отмасштабировать. К тому же машинка должна в конечном счёте иметь плавный разгон и торможение, что обеспечивается интегрирующим звеном регулятора. Для компенсации всяких слишком затяжных процессов будем использовать дифференцирующее звено.

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

Рис. 8 - Схема ПИД регулятора
Рис. 8 - Схема ПИД регулятора

Обратной связью будет выступать угол отклонения от направления и отклонение скорости от требуемой.

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

Заключение

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