Skip to main content

Сеть

Для работы с фреймворком без компиляции в пакете network написан ряд демонстрационных серверов и клиентов. Соответствующие исходники находятся в пакете network.servers.demo и network.clients.demo.

Базовый сервер

Все серверы наследуются от базового класса network.servers.BaseServer. Пока что все серверы позволяют одновременно подключаться только одному клиенту.

Демонстрационные серверы написаны двух видов: с предустановленными параметрами планирования и с консольными ключами. Первые имеют префикс demo_, вторые - console_.

Чтобы сервер сокетов не отваливался после отключения клиента в Linux, необходимо вызвать ряд команд при старте приложения. Эти команды объединены в метод

/**
* без вызова этого метода отваливается север после отключения клиента
*/
void BaseServer::initLinuxServerSocket() {
// без этих четырёх строк вылетает сервер
sigset_t set;
sigaddset(&set, SIGPIPE);
int retcode = sigprocmask(SIG_BLOCK, &set, NULL);
if (retcode == -1) bmpf::errMsg("sigprocmask");
}

Для реализации сервера, необходимо переопределить две чисто виртуальные функции:

/**
* Обработка команды от клиента
* @param clientSocket fd клиента
* @param command код команды
* @param jsonData данные json
*/
virtual void processCommand(int clientSocket, int command, Json::Value jsonData) = 0;

/**
* Обработка подключения нового клиента
* @param clientSocket fd клиента
*/
virtual void onSocketConnected(int clientSocket) = 0;

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

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

Каждая из команд состоит из кода команды и данных:

{
"command": 0,
"data": {
...
}
}

Внутри сервера происходит накопление символов ответа, пока не будет встречена *.

Т. к. это сервер - это многопоточное приложение, то для синхронизации данных добавлено семафор:

/**
* Семафор, синхронизирующий доступ
*/
sem_t _sem;

Планирование пути

Для серверов планирования написан базовый сервер network.servers.PathFindingServer

Для его использования необходимо реализовать в потомке чисто виртуальную функцию:

/**
* Создать новый планировщик
* @param clientSocket fd клиента
* @return новый планировщик
*/
virtual std::shared_ptr<bmpf::PathFinder> createPathFinder(int clientSocket) = 0;

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

  • COMMAND_IS_READY - Проверка, готов ли планировщик
  • COMMAND_START_FIND_PATH - Запуск планирования
  • COMMAND_FIND_PATH_RESULT - Запрос результата

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

{
"scene": "my/scene/path.json",
"states": [
...
]
}

Для непрерывного планировщика и планировщика в режиме multirobot написаны серверы ContinuousPFServer и MultiRobotPFServer соответственно.

Дополнительные серверы

Для оптимизации пути написан сервер network.servers.PathOptimisingServer По логике он похож на сервер планирования. Но в качестве задания он принимает путь и работает с медианным оптимизатором MedianPathOptimizer. Однако вместо стартового и конечного состояний в качестве задания передаётся спланированный путь.

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

  • COMMAND_GET_POSITIONS - получить положения траектории
  • COMMAND_GET_SPEED - получить скорости траектории
  • COMMAND_GET_ACCELERATIONS - получить ускорения траектории

Данная логика реализована в классе network.servers.TrajectoryFindingServer

Клиенты

Все клиенты должны наследоваться от базового класса network.clients.BaseClient.

Важная информация

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

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

Исходники клиентов дополнительно лежат в отдельном репозитории