Роботы
Для описания параметров звеньев написан класс core.robot.base.Link.
Он хранит внутри себя следующие поля:
- Путь к модели
 - Название
 - Матрица преобразования из СК мира в СК звена для неиерархичных звеньев (для удобства)
 - Тензор инерции звена
 - Координаты центра масс
 
Для работы с сочленениями реализовано два класса:
core.robot.base.Joint и  core.robot.base.JointParams.
Первый отвечает за преобразование угла поворота звена в матрицу перехода из системы координат (СК) предыдущего звена в СК следующего.
Второй хранит в себе неизменяемые параметры звена:
- максимальное по модулю ускорение
 - максимальная по модулю скорость
 - максимальный угол
 - минимальный угол
 - индекс сочленения
 
Матрицы преобразования
Матрица преобразования состоит из четырёх столбцов и четырёх строк

Чтобы получить координаты вектора в новой СК, нужно умножить матрицу преобразования на его значение () в исходной СК:
Т.к. каждое сочленение core.robot.base.Joint характеризуется осью вращения 
и углом поворота , то матрица преобразования  вычисляется по формуле:
Для вычисления матрицы преобразования и её производных необходимо сначала
задать угол поворота jointAngle и ось вращения axis, после чего
вызвать метод 
/**
 * Получить матрицу преобразования сочленения
 * @return матрица преобразования сочленения
 */
Eigen::Matrix4d getTransformMatrix() { return parentTransform * getRotMatrix4x4(axis, jointAngle); }
parentTransform - это матрица преобразования из СК родительского сочленения в СК текущего.
Также дополнительно хранится матрица преобразования из СК сочленения в СК следующего за ним звена
linkTransform
Некоторые сочленения могут быть виртуальными, поэтому добавлен флаг
/**
 * Флаг, что сочленение является виртуальным и не связано со звеном
 */
bool isVirtual;
Также сочленение может быть связано со звеном, но при этом не иметь возможности менять угол поворота. Чаще всего это полезно при сложной геометрии звена робота.
/**
 * Флаг, является ли сочленение фиксированным (без привода)
 */
bool isFixed;
Для решения задач динамики и оптимизации бывают полезны частные производные матриц преобразования звеньев по соответствующему углу:
в классе Joint данная логика реализована в соответствующих методах:
/**
 * Получить первую производную матрицы преобразования сочленения
 * @return первая производную матрицы преобразования сочленения
 */
Eigen::Matrix4d getDiffTransformMatrix() { return parentTransform * getDiffRotMatrix4x4(axis, jointAngle); }
/**
 * Получить вторую производную матрицы преобразования сочленения
 * @return вторая производную матрицы преобразования сочленения
 */
Eigen::Matrix4d getDiff2TransformMatrix() { return parentTransform * getDiff2RotMatrix4x4(axis, jointAngle); }
Реализация методов getDiffRotMatrix4x4, getDiff2RotMatrix4x4 и других, необходимых
для работы с матрицами, находится в core.misc.matrixMath
Иерархия классов
Для работы с роботом как с объединением звеньев и
сочленений написан базовый класс  core.robot.base.BaseRobot.
У него прописаны все базовые методы для работы с роботом, но при этом он является абстрактным. Для его использования необходимо унаследовать новый класс от него и реализовать метод загрузки из файла:
/**
 * @brief загрузить параметры робота из файла
 *
 * Загрузить параметры робота из файла, нужно заполнить следующие поля:
 * _jointParams, _links, _nonHierarchicalLinks, path
 * @param path путь к файлу описания робота
*/
virtual void loadFromFile(std::string path) = 0;
Основным классом для работы с роботами является core.robot.URDFRobot.
Он использует файлы расширения *.urdf. Подробнее с его
описанием можно ознакомиться здесь.
Для чтения модели используется немного устаревшая библиотека urdf_reader без
ROS (пакет project.urdf_reader). Более актуальную версию можно скачать здесь
Также для тестов был написан робот core.robot.DHRobot, использующий
параметры Денавита-Хартенберга.
Его описание получилось несколько громоздким. Это вызвано тем,
что необходимо было согласовать матрицы преобразования urdf робота и
робота с параметрами Денавита-Хартенберга.
Частные производные
Матрицу преобразования можно вычислить, последовательно перемножив матрицы преобразования, зависящие только от угла поворота -го звена и матрицы перехода между звеньями :
Если взять от этой формулы частную производную по , то от этой координаты зависит только соответствующая матричная функция , все остальные множители при дифференцировании можно воспринимать как постоянные.
Поэтому при вычислении достаточно просто заменить -ю матричную функцию на её производную:
Для частной производной второго порядка в случае заменить -ю и -ю матричные функции её производными (не теряя общности, будем считать, что ):
Если , то необходимо заменить только -ю матричную функцию её второй производной:
Чтобы вычислить производную по матрице преобразования того или иного звена, достаточно найти производную матрицы поворота (смещение закладывается в матрицах ).
Поворот каждого звена описывается осью и углом поворота вокруг неё. Тогда можно матрицу преобразования можно найти по формуле: