robossembler.org/docs/slides/2023-ros-meetup/ros-meetup-slides.md

268 lines
No EOL
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
marp: true
theme: uncover
paginate: true
---
<!--
Чтобы сгенерировать из этого файла презентацию в pdf, html или pptx, нужно воспользоваться утилитой Marp https://marp.app/ или одноимённым расширением VSCode https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode.
-->
# Nix/Nixos
ОС-независимая сборка пакетов ROS
|
Брылёв Игорь
robossembler.org
---
# Что же такое ROS?
<!--
В сообществе часто спорят по поводу того чем является или не является ROS. ROS звучит буквально как операционная система для роботов, однако де-факто операционной системой не является. Как правило, все сходятся на том, что ROS включает в себя много разных сущностей - это и стандарт, и фреймворк, и формат взаимодействия приложений, и непосредственно программное обеспечение - стандартная библиотека, если хотите. Но конкретно в этом докладе я бы хотел поговорить о ROS в немного другом свете - как о системе сборки и дистрибьюции программного обеспечения, что тоже имеет место быть. Причём этот аспект я считаю весьма важным, потому что почти любое ROS-приложение в среднем на 95% состоит из подгруженного из пакетных репозиториев кода, из которых на долю ROS-экосистемы приходится меньшая часть.
-->
* Стандарт
* Фреймворк
* Набор форматов
* ...
* Система сборки и дистрибьюции ПО
---
<!--
Итак метод сборки и дострибьюции пакетов в ROS в значительной опирается на пакетных менеджер apt и пакетные базы debian/ubuntu (по статистике ros index 2100 пакетов представляют собой системные зависимости, предоставляемые операционной системой), а следовательно зависит от них. Многие пакеты ROS-экосистемы представляют в качестве рекомендуемого способа установки именно установку из своих репозиториев собранных заранее бинарных пакетов. Компиляция проектов их исходников редко практикуется и достаточно сложна. В целом, apt свойственны следующие проблемы.
-->
### Проблемы пакетных менеджеров
* Апгрейд конфигурации безвозвратно изменяет состояние системы
* Сборки не детерминированы
* Не поддерживаются разные версии бинарников и библиотек
* Конфликты пакетов
---
#### Проблемы управления зависимостями в ROS
* Зависимость от Ubuntu и её системных зависимостей (apt-пакеты)
* Сложность интеграции с ПО вне ROS-экосистемы
* Подготовить для удобного запуска сложный ROS-проект - трудоёмкая задача
---
# Тренды
* Из набора библиотек для одного робота ROS становится стандартом для роботизированных кибер-физических систем
* В робототехнику проникают инструменты из других ниш: web, машинное обучение, DevOps
---
<!--
Когда рассказываешь про nix часто у инженеров возникает прочная ассциация с Docker. А не решает ли Docker ту же самую проблему? Да, действительно, эти инструменты решают одну и ту же проблему, которую можно было бы кратко сформулировать так
-->
# А как же Docker?
---
<!--
С проблемой сталкиваются нууууу почти все - от первой линии службы технической поддержки до программистов. Это проблема состояния окружения - если ваша программа или приложение в какой-то степени опирается на него, то неизбежно будут возникать проблемы с его корректной работы на компьютерах с другим окружением.
-->
![](reproducible-testing.jpg)
---
<!-- Как добиться того, чтобы программа запущенная успешно на одном компьютере, была также успешно запущена на другом? Современные проекты представляют собой зачастую сложную комбинацию инструментов, библиотек и обеспечить воспроизводимость в этих условиях непросто. Классическое управление зависимостями в Linux-системах не позволяло добиться хорошей воспроизводимости. Docker появился во многом в ответ на эту проблему плохого управления зависимостями в операционной системе. Как это решил Docker? -->
# "В"
воспроизводимость
---
<!-- Как мы знаем, Docker создаёт своеобразную песочницу вокруг вашего приложения и вы передаёте его вместе с ней, чтобы состояние машины пользователя не влияло на работоспособность. Идеальная картика выглядит так: на входе Dockerfile, на выходе Образ. Вроде всё круто -->
# Теория
Dockerfile -> Image
---
<!-- Но де-факто с одним и тем же докерфайлом вы можете получить кучу разных образов. Почему так происходит? -->
# Реальность
Dockerfile -> Image1 || Image2 ... ImageN
---
<!--
Если посмотреть вглубь, то можно обнаружить, что в типичном Docker-файле для ROS есть сразу несколько мест, которые сделают вашу сборку невоспроизводимой на другом компьютере:
1. hub.docker.com
2. apt-репозиторий
3. rosdep-репозиторий
3. файл, взятый по имени
Но есть другие недостатки:
1. Возможность комбинировать зависимости (docker позволяет создавать контейнеры только наследуя от одного базового - нельзя добавить несколько базовых контейнеров)
2. Необходимость тянуть с собой все зависимости, даже если они представлены в системе
-->
# Типичный Dockerfile для ROS
FROM ros:foxy-ros-base-focal
...
RUN rosdep update && apt-get update
...
RUN apk add --no-cache python g++ make
...
RUN curl -sSL http://get.gazebosim.org | sh
...
CMD [ "ros2", "launch", "app", "app_bringup.launch.py" ]
---
<!-- # Что предлагает Nix? -->
# Ключевая идея nix
Описывать сборку в виде _чистой функции_ или уравнения(derivation), результат исполнения строго детерминирован входными параметрами.
---
<!-- Именно эта идея и легла в основу диссертации автора nix под названием ___, где как раз и описывались недостатки классической системы использования динамических библиотек в unix-подобных системах. Данный подход получил название декларативным в противовес императивного. -->
![](eelco.jpeg)
Eelco Dolstra
## The Purely Functional Software Deployment Model
PhD Thesis'2006
https://edolstra.github.io/pubs/phd-thesis.pdf
---
# Парадигмы программирования
* Императивная (как?) - C, C++, Java
* Декларативная (что?) - Lisp, Prolog, Nix
---
<!--
nix использует функциональный язык программирования для описания процесса сборки. Тут можно сделать некоторое отступление о том, что ROS создан робототехниками для робототехников, а у них по прежнему был и остаётся доминирующим императивный подход к программированию, что обусловлено высокими требованиями к производительности и реальному времени исполнения. Собственно, императивная парадигма распространилась не только на сферу низкоуровневых программ, но и на управление операционной системой. Однако, сфера сборки ПО не требует гарантий реального времени или высокой производительности, в ней куда важнее как раз воспроизводимость, отсутствие неявных обращений к состоянию системы.
-->
# Парадигмы конфигурации
* Императивная конфигурация (apt)
- Изменение состояния (dependency hell, неконсистентные состояния)
* Декларативная конфигурация (nix)
- Пакеты = иммутабельные переменные (нельзя изменить напрямую, только через функцию)
- Одно и то же nix-выражение даёт всегда один и тот же результат
---
<!-- как выглядит типичное Nix-выражение. Это уравнение превращается в такой json-образный файл, где и прописаны все версии с хэшами конкретных зависимостей. Этот файл и является по сути инструкцией или чистой функцией, на выходе которой мы получаем конкретные артефакты в виде пакетов, бинарников, динамических библиотек и т.п. -->
{
pname = "hello";
version = "2.12.1";
src = fetchurl {
url = "http://github.com/hello-${version}.tar.bz2";
sha256 = "0x2g1jqy...";
};
buildInputs = [ libbar perl ncurses ];
buildPhase = ''gcc hello.c -o hello'';
installPhase = ''mkdir -p $out/bin && cp hello $out/bin'';
}
---
{
"builder": "/nix/store/561wgc73s0x1250hrgp7jm22hhv7yfln-bash-5.2-p15/bin/bash",
"env": {
"builder": "/nix/store/561wgc73s0x1250hrgp7jm22hhv7yfln-bash-5.2-p15/bin/bash",
"out": "/nix/store/260q5867crm1xjs4khgqpl6vr9kywql1-hello-2.12.1",
"src": "/nix/store/pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz",
"stdenv": "/nix/store/b09v23lirgvci3wzszh22mbkdfj0h0yq-stdenv-linux",
"version": "2.12.1"
},
"inputDrvs": {
"/nix/store/0hnjp6s8k71xm62157v37zg3qzwvl8lx-bash-5.2-p15.drv": [ "out" ],
"/nix/store/8n3ib41pb90nkq3vv49z520qinf4q9c0-hello-2.12.1.tar.gz.drv": [ "out" ],
"/nix/store/r2h029bx2fbyxxj84s5hf1abp2vfkah2-stdenv-linux.drv": [ "out" ]
},
"inputSrcs": [ "/nix/store/6xg259477c90a229xwmb53pdfkn6ig3g-default-builder.sh" ],
"outputs": {
"out": { "path": "/nix/store/260q5867crm1xjs4khgqpl6vr9kywql1-hello-2.12.1" }
},
"system": "x86_64-linux"
}
}
---
<!-- А вот как это выглядит на диске. Заметьте, имя каждого пакета снабжается хэшом, который позволяет избежать коллизий при совпадении имён и даже совпадении имён и версий, а ещё даёт использовать несколько версий библиотеки одновременно. Откуда берётся этот хэш? -->
$ ls /nix/store/ | grep humble
00z4hg8q0cxhsl5jq4s7iq81zz54j8vy-ros-humble-ament-lint-common-0.12.5-r1
01nvrmwbf0zbchb3d25kb49rl8jzspv6-ros-humble-ament-cmake-cppcheck-0.12.5-r1
02gdrzn2yrngmqih4hq0j17vj2hgiiz3-ros-humble-unique-identifier-msgs-2.2.1-r3
08s5gvg7gaypllyxvzd17w21ijqx3hgd-ros-humble-tf2-msgs-0.25.2-r1
0hwva9zk3250hd6spwq11ayk0aq4flnm-ros-humble-control-msgs-4.1.0-r1
---
<!-- Собственно этот хэш и получается с помощью криптографической хэш-функции применённой ко всем входным зависимостям -->
![width:900px](drv-cryptohash.png)
---
<!-- Вы не полагаетесь на apt, можете при желании собрать систему полностью из исходников. -->
# Что это даёт для ROS?
* Возможность запустить проект ROS на любой ОС, даже без apt
* Контролируемое управление зависимостями
* Возможность использования разных версий одних и тех же пакетов и библиотек
* Детерминированные сборки одной командой
* CACHE!!!
---
<!--
-->
# Основные компоненты nix
* Nix (менеджер пакетов и язык программирования)
* Nixpkgs (репозиторий пакетов и стандартная библиотека)
* NixOS (операционная система)
* NixOps (DevOps инструмент)
---
<!--
# Текущее состояние nixpkgs -->
![width:1000px](map_repo_size_fresh-2018-06-08.svg)
---
## Nix ROS Overlay
https://github.com/lopsided98/nix-ros-overlay
Автоматическая генерация nix-выражений для сборки пакетов ROS из официальных репозиториев (github:ros/rosdistro).
---
{ lib, buildRosPackage, fetchurl, ament-cmake ... }:
buildRosPackage {
pname = "ros-rolling-std-msgs";
version = "4.6.1-r1";
src = fetchurl {
url = "https://github.com/ros2-gbp/common_interfaces/std_msgs/4.6.1-1.tar.gz";
name = "4.6.1-1.tar.gz";
sha256 = "87eee895c2c60a8335ae2a63b05f99773f0897e451e5bf7f45a14a6c36295640";
};
buildType = "ament_cmake";
buildInputs = [ ament-cmake rosidl-default-generators ];
checkInputs = [ ament-lint-common ];
propagatedBuildInputs = [ builtin-interfaces rosidl-default-runtime ];
nativeBuildInputs = [ ament-cmake rosidl-default-generators ];
meta = {
description = ''A package containing some standard message definitions.'';
license = with lib.licenses; [ asl20 ];
};
}
---
# Недостатки
* Пологая кривая обучения
* Некоторая разрозненность документации
* Не все пакеты ROS адаптированы в nix
* Необходимость сборки мусора
---
# Полезные ресурсы
![width:200px](nix-snowflake.svg)
Русскоязычное сообщество Telegram
@ru_nixos
Туториал для новичков
zero-to-nix.com