Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e1b65e95b9 |
1
.gitignore
vendored
|
@ -19,4 +19,3 @@
|
|||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.vscode
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
image: node:16.15.1-alpine3.16
|
||||
image: node:16.14.2-alpine3.15
|
||||
|
||||
stages:
|
||||
- test
|
||||
|
|
|
@ -25,10 +25,10 @@ tags: [robossembler, milestone, summary]
|
|||
|
||||
Сейчас можно уверенно сказать, что команда проекта в значительной степени сформирована конструкторами, технологами, системными инженерами. Найдена кандидатура для программирования под Unreal Engine. Проект на данный момент насчитывает 8 участников, четверо из которых принимают активное участие в разработке.
|
||||
|
||||
Команда осваивает git в качестве основного инструмента коллективной разработки, что не является типичным для мира 3D-моделирования. Репозитории размещаются в группе gitlab https://gitlab.com/robossembler
|
||||
Команда осваивает git в качестве основного инструмента коллективной разработки, что не является типичным для мира 3D-моделирования. Репозитории размещаются в группе gitlab https://gitlab.com/robosphere
|
||||
|
||||
В качестве системы управления знаний создан портал документации, который служит единой точкой входа и местом ключевых публикаций по проекту.
|
||||
https://robossembler.gitlab.io/docs
|
||||
https://robosphere.gitlab.io/robossembler-docs/docs
|
||||
|
||||
Мы регулярно публикуем записи совещаний и образовательные материалы по теме на нашем Youtube-канале.
|
||||
https://www.youtube.com/channel/UC32Xgbsw9XQlN1QH59pe8HA/videos
|
||||
|
@ -36,33 +36,33 @@ https://www.youtube.com/channel/UC32Xgbsw9XQlN1QH59pe8HA/videos
|
|||
## Теория и исследования
|
||||
|
||||
Самовоспроизводящаяся фабрика: от простого - к сложному
|
||||
https://robossembler.gitlab.io/docs/replication
|
||||
https://robosphere.gitlab.io/robossembler-docs/docs/replication
|
||||
|
||||
Информационное обеспечение автоматического производства
|
||||
https://robossembler.gitlab.io/docs/information/information_support
|
||||
https://robosphere.gitlab.io/robossembler-docs/docs/information/information_support
|
||||
|
||||
Концепция планировщика производственных операций
|
||||
https://robossembler.gitlab.io/docs/information/planner
|
||||
https://robosphere.gitlab.io/robossembler-docs/docs/information/planner
|
||||
|
||||
Какие сущности из мира программного обеспечения можно сопоставить с материальными объектами производства
|
||||
https://robossembler.gitlab.io/docs/analogy
|
||||
https://robosphere.gitlab.io/robossembler-docs/docs/analogy
|
||||
|
||||
Сравнительное исследование симуляторов робототехники
|
||||
https://gitlab.com/robossembler/robossembler.gitlab.io/-/issues/1
|
||||
https://gitlab.com/robosphere/robossembler-docs/-/issues/1
|
||||
|
||||
## Технологии
|
||||
|
||||
Описан полный алгоритм сборки робота манипулятора, состоящий на текущий момент из 32-х операций
|
||||
https://robossembler.gitlab.io/docs/techinstruction
|
||||
https://robosphere.gitlab.io/robossembler-docs/docs/techinstruction
|
||||
|
||||
Разработана технология хранения и транспортировки робофабрики
|
||||
https://robossembler.gitlab.io/docs/autostorage
|
||||
https://robosphere.gitlab.io/robossembler-docs/docs/autostorage
|
||||
|
||||
## Конструкторские решения
|
||||
|
||||
Разработаны приспособления для манипулятора
|
||||
* сварка https://gitlab.com/robossembler/arm-tools/welding-tool
|
||||
* пайка https://gitlab.com/robossembler/arm-tools/soldering-tool
|
||||
* сварка https://gitlab.com/robosphere/arm-tools/welding-tool
|
||||
* пайка https://gitlab.com/robosphere/arm-tools/soldering-tool
|
||||
|
||||
## Предстоящие три месяца
|
||||
|
||||
|
|
|
@ -1,119 +0,0 @@
|
|||
---
|
||||
slug: robossembler-1st-year-summary
|
||||
title: Итоги первого года
|
||||
author: Игорь Брылёв
|
||||
author_title: Team Lead @ Robossembler
|
||||
author_url: https://gitlab.com/movefasta
|
||||
author_image_url: https://gitlab.com/uploads/-/system/user/avatar/4249760/avatar.png
|
||||
tags: [robossembler, milestone, summary]
|
||||
---
|
||||
|
||||
[Видео-версия](https://www.youtube.com/watch?v=AFROcGW73j0)
|
||||
[Обзор всех репозиториев проекта](https://robossembler.gitlab.io/docs/)
|
||||
|
||||
Итак, миновал год с момента начала проекта и наступает время отметить данное событие подведением итогов.
|
||||
|
||||
В самом начале мы ставили главной задачей проектирование полностью автоматической и частично самовоспроизводящейся линии для роботов манипуляторов. Исследовав все существующие открытые конструкции роботов-манипуляторов, мы пришли к выводу, что все они не годятся для автоматической сборки. В них присутствовало, как правило, большое количество проводных соединений, которые обладают сложным недетерминированным поведением, сложно проектируются и симулируются, а также разнообразный крепеж очень широкой номенклатуры, использование которого при помощи автоматизированных средств затруднительно (знаменитая задача peg in the hole, для эффективного решения которой бьются учёные-робототехники многие годы). А значит они не подходят для частичного самовоспроизводства. Мы поняли, что придётся разработать собственные аппаратные решения, адаптированные для автоматической сборки и сосредоточились на этом.
|
||||
|
||||
## Аппаратное обеспечение
|
||||
|
||||
Мы проработали два заметно отличающихся друг от друга технических решения, каждое из которых по-своему решало поставленную задачу.
|
||||
|
||||
Первое решение базировалось на идее изготавливать роботов-манипуляторов с помощью технологии литья под давлением. Для данного концепта были разработаны соответствующая модульная конструкция звеньев, прессформа, с помощью которой звенья будут последовательно отливаться, и приспособление для подачи компаунда, так как по нашей идее литьё под давлением осуществлялось тем же самым манипулятором.
|
||||
|
||||

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

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

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

|
||||
|
||||
Сначала мы запроектировали манипулятор с китайскими моторами для стабилизации камер для фото и видео-съёмки, но потом поняли, что с ними автоматическая сборка будет затруднительна - ведь такой мотор сложно захватить и правильно позиционировать. В общем, пришлось разработать собственный электродвигатель, который роботу будет удобно собирать, хватать и встраивать в манипулятор, а также электрическую схему и плату для его управления. В итоге получился почти полный комплект конструкторской документации для робота-манипулятора, по которому можно изготовить прототип и отлаживать встроенное программное обеспечение.
|
||||
|
||||
Как и в случае с первым вариантом манипулятора, была проработана и соответствующая оснастка, необходимая для создания и масштабирования роботизированных ячеек. На этот раз мы попытались обеспечить возможность более гибкого монтажа манипуляторов. Теперь, благодаря специальным модулям стало возможным установить манипулятор почти в любом месте (сбоку, сверху) и использовать объём всего доступного пространства, что весьма полезно в случаях, когда мы не располагаем просторными площадями и вынуждены расти, что называется, вверх. Модули, подобно кубикам в конструкторе LEGO позволяют создавать разные конфигурации роботизированных ячеек, обеспечивают жёсткость конструкции и электрическую связность компонентов. Сами пластины или основания манипулятора предполагают несколько исполнений - для монтажа манипулятора или приспособления, для установки туда вычислительного узла или просто в качестве поверхности рабочего стола.
|
||||
|
||||

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

|
||||
|
||||
В механическом захвате используется тот же самый мотор и плата управления, что и в самом манипуляторе. Остальные приспособления проработаны на уровне эскизов и будут дорабатываться по мере появления прикладных задач.
|
||||
|
||||
## Программное обеспечение
|
||||
|
||||
Программное обеспечение долго отставало от аппаратного по причине отсутствия разработчиков. Но мы не простаивали зря и пытались как можно глубже изучить актуальные научные исследования по проблемам, связанным с автоматизированной сборкой промышленных изделий, какие уже существуют проекты с открытым кодом, реализующие в какой-то степени данный функционал, а также пытались моделировать поведение самовоспроизводящихся систем на самом высоком уровне.
|
||||
|
||||
Научные исследования:
|
||||
- Автоматическое планирование последовательности сборки
|
||||
- Методы машинного обучения в промышленной робототехнике
|
||||
- Применение блокчейн-технологий в управлении кибер-физическими системами
|
||||
- Совмещённое планирование движений и задач
|
||||
|
||||
Все исследования были тщательно отобраны и размещены на портале документации. Некоторые исследования были переведены полностью, по некоторым были составлены краткие описания.
|
||||
|
||||
Со временем программисты нашлись и мы взялись за интеграцию тех программных компонентов, которые были найдены нами в ходе исследований. Самые основные из которых - это планировщик движений MoveIt, планировщик операций PlanSys и симулятор Gazebo.
|
||||
|
||||
Также, при разработке архитектуры, мы перенимали лучший мировой опыт в области роботизированной сборки, в чём нам очень сильно помог конкурс на Всемирном саммите по робототехнике, который проходит в Японии с 2017 года. Это такой конкурс, где команды из разных университетов и компаний мира выполняют задание по автоматической сборке роботами специально подготовленного стенда и соревнуются в скорости, точности и безопасности. Так вот - по имеющимся в публичном доступе материалам конкурса мы сделали подробный обзор работ двух команд и попытались учесть извлечённые ими уроки при проектировании архитектуры программного обеспечения. Некоторые выводы подтвердили правильность избранных нами решений. Например, выводы исследователей из университета Сан-Хосе подтвердили правильность выбора второй версии ROS, которая лучше подходит для использования в системах жёсткого реального времени, а ROS первой версии показал себя не очень хорошо в соревнованиях; а опыт команды O2AC подтвердил правильность нашего подхода сборочно-ориентированного дизайна - когда конструктор изначально проектирует изделие с учётом удобства захвата и сборки, а не с учётом своих представлений об эстетике и эргономике, что, в общем-то говоря, не очень актуально для автономных систем.
|
||||
|
||||
Есть и ряд наших оригинальных решений. Например, мы архитектурно предусмотрели возможности управления уровнями восприятия среды, ведь, помимо реальности, для робота есть и виртуальность, где он также, пользуясь возможностями физического движка может отлаживаться управляющая программа. Так вот мы разделили фазы восприятия на три условных уровня:
|
||||
* когда робот знает всё о состоянии мира - положение всех объектов в симуляции
|
||||
* когда робот знает о состоянии мира неполную информацию - получает информацию от только виртуальных датчиков
|
||||
* когда робот знает только о состоянии тех датчиков, которые подключены к нему в реальной кибер-физической установке.
|
||||
|
||||

|
||||
|
||||
Возможность управлять уровнями восприятия делает удобным постепенную адаптацию управляющих программ к физическому миру с возможностью доучиться в виртуальных средах. Например, робот, прежде чем приступить к выполнению задачи в реальном мире, может внутри себя переключить уровень восприятия на один из двух виртуальных и отладить работу там. При этом сама управляющая программа работает одна и та же - она просто меняет поставщика данных о состоянии среды.
|
||||
|
||||
Итоговая архитектура программного фреймворка Робосборщик представляет собой набор компонентов, которые пытаются реализовать процесс подготовки производства в автоматическом режиме.
|
||||
|
||||

|
||||
|
||||
Все эти компоненты можно подразделить на основные категории, каждая из которых отвечает за свою часть работы.
|
||||
1. Первая категория (Assembly Preparation) - это комплекс подготовки изделий для автоматизированной сборки и необходимых данных для удобства симуляции. Ключевой компонент здесь - это плагин ARBench, существенно нами дополненный, который служит для разметки геометрических примитивов, формирования последовательности сборки, задания позиций захвата вручную и экспорта моделей в виде поддерживаемых симулятором пакетов. Плагин может работать как через графический интерфейс FreeCAD, что удобно для разметки моделей конструктором, так и через консоль, что удобно для автоматической генерации пакетов в системе непрерывной интеграции Gitlab. Далее пакеты могут быть помещены в базу данных, из которой уже подгружаться в симулятор.
|
||||
2. Вторая категория (ROS2) - то, что исполняется непосредственно на вычислительном узле робота. Это набор пакетов ROS2, включающий планировщики движений и задач, конфигурацию робота, пакеты для взаимодействия с узлами Робономики и симулятором.
|
||||
3. И, наконец третья категория (Simulation & Learning) - это программное обеспечение для виртуальных сред исполнения - игровых движков, симуляторов, а также модули поддержки машинного обучения, генерации наборов данных и виртуальных датчиков. Здесь ключевым компонентом является наш модуль управления восприятием среды, упомянутый выше.
|
||||
|
||||
По нашей задумке такая модульная архитектура позволит в будущем пробовать применять различные алгоритмы генерации последовательности сборки, обучения с подкреплением, системы распознавания, планировщики движений и задач, не затрагивая остальные компоненты системы.
|
||||
|
||||
А ещё мы постарались сделать этот комплекс из компонентов с открытым кодом и, кажется, что у нас это получилось.
|
||||
|
||||
|
||||
## Интеграция с Robonomics
|
||||
|
||||
Ну и нельзя не отметить, что на протяжении всего этого времени, мы думали о том как можно взаимно усилить разработки Робосборщика и те возможности, которые предоставляет сеть Робономики.
|
||||
|
||||
Поначалу пришлось хорошенько подумать над тем "а что в принципе может заставить пользователей подключать их роботов к блокчейн-сети?". Я сам по опыту работу из мира АСУТП и это, конечно, в каком-то смысле консервативная отрасль - ведь на кону безопасность людей и подключать автоматические системы критически важной инфраструктуры к интернету без особой необходимости мало кто рискует - и без того полно дыр. Ну и самое главное - зачем? В этом нет какой-то особой выгоды. Что ж, пришлось эту выгоду поискать... и мы её нашли. Во многом благодаря тому, что ранее погрузились в машинное обучение роботов и поняли, что эффективность обучения в существенной степени будет зависеть от объёма и качества входных данных. Чем больше данных, тем лучше. Вот, например, Google в одном из первых своих исследований по теме привлекли 14 роботов-манипуляторов с их помощью совершили более 800 тысяч операций захвата, чтобы получить достаточное количество данных для обучения! Разумеется, мало у каких компаний есть такие возможности. Но тут мы вспоминаем о нашей сети Робономики, которая создаёт предпосылки для безопасного взаимодействия роботов через интернет, а значит можно собрать такой же стенд как у Google, но только из роботов, разнесённых между собой географически! Тут замечательно сочетаются идеи и блокчейна, и робототехники, и открытого кода, ведь пользователи могут собирать информацию и для того, чтобы вносить изменения в его конструкцию, улучшать железо и софт. И даже есть возможность совместно обучать роботов, не раскрывая конфиденциальности благодаря методике федеративного обучения, когда агенты обмениваются не самими данными, а своими предобученными моделями, которые в дальнейшем собираются и как-то усредняются, чтобы получить итоговую модель.
|
||||
|
||||
Ну что ж, уже намного лучше. Но остаётся ещё одна загвоздка - на каждом производстве робот выполняет специфичные для данного производства операции и даже если остановиться только на операции сборки, то в каждом конкретном случае роботы будут собирать разное. А значит теряется смысл кооперации роботов. Нет общего навыка - нет смысла совместно его обучать. И тут в очередной раз на помощь приходят новшества их мира машинного обучения, а именно такая методология как мета-обучение. Это подход, при котором робот учится не работать непосредственно, а учится учиться, то есть формирует не очень специализированный мета-навык. Например, вместо того, чтобы обучаться вставлять конкретный разъём - скажем, USB - он обучается быстро осваивать операцию вставки в общем виде, а под конкретную операцию доучиваться в гораздо меньшем объёме. И это решение позволяет устранить ту самую специализированность роботов. Мы можем дать возможность роботам собирать огромные массивы данных, обучать на них мета-навыки, передавать мета-навыки обратно роботам в виде награды и далее, на базе этих мета-навыков, осваивать прикладные операция для отдельных производств. Пазл сошёлся.
|
||||
|
||||
Именно эта идея легла в основу идеи так называемого рынка навыков, где роботы могли бы извлекать пользу из взаимодействия друг с другом за счёт сетевых эффектов.
|
||||
|
||||
Напоследок мы интегрировали наш ROS2 проект в Робономику классическим методом - с помощью передачи плана исполнения в блокчейне через команду launch и записали поясняющее этот процесс [видео](https://youtu.be/J3m5hXf-cro).
|
||||
|
||||
## Заключение
|
||||
|
||||
Вряд ли можно сказать, что мы полностью выполнили те задачи, которые ставили. Уж слишком они были амбициозные и объёмные. Тем не менее, каждый компонент нашей системы, хоть и небольшой, но всё-таки вполне работоспособный, а значит фундамент для дальнейших улучшений заложен.
|
||||
|
||||
|
||||
Команда проекта:
|
||||
- Игорь Брылёв
|
||||
- Станислав Сгонов
|
||||
- Алексей Топтун
|
||||
- Александр Оликевич
|
||||
- Ярослав Ефремов
|
||||
- Роман Андрианов
|
||||
- Илья Ураев
|
||||
- Марк Вольтов
|
||||
- Илья Курочкин
|
|
@ -1,216 +0,0 @@
|
|||
---
|
||||
slug: 2nd-year-summary
|
||||
title: Итоги 2023 года
|
||||
author: Игорь Брылёв
|
||||
author_title: Team Lead @ Robossembler
|
||||
author_url: https://gitlab.com/movefasta
|
||||
author_image_url: https://gitlab.com/uploads/-/system/user/avatar/4249760/avatar.png
|
||||
tags: [robossembler, milestone, summary]
|
||||
---
|
||||
|
||||
[Видео-версия](https://youtu.be/vWpaZ8DRftI)
|
||||
|
||||
В этом обзоре мы расскажем о разработках в рамках проекта Робосборщик в 2022-2023 годах.
|
||||
|
||||
## Аппаратное обеспечение
|
||||
|
||||
### Robossembler Arm и его двигатели
|
||||
|
||||
Самая главная аппаратная разработка этих полутора лет — рука Робосборщика или [Robossembler Arm](https://gitlab.com/robossembler/roboarm-diy-version).
|
||||
|
||||

|
||||
|
||||
Это шести-осевой робот манипулятор, который существенно изменился - сокращены габаритные размеры, вес, снижено общее количество деталей и крепежа.
|
||||
|
||||

|
||||
|
||||
Всего в конструкции теперь 66 деталей и 32 соединителя, которые достаточно крупные, чтобы вставлять их вручную, без помощи вспомогательного инструмента, или даже автоматически - разработанным нами захватным устройством. Все детали содержат специальные пазы для удобства захвата.
|
||||
|
||||

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

|
||||
|
||||
Одной из ключевых особенностей робота является [симметричный стыковочный интерфейс](https://gitlab.com/robossembler/arm-tools/connection-tool), который позволяет роботу перемещаться между совместимыми с ним посадочными местами и, тем самым, расширять доступную для работы зону.
|
||||
|
||||

|
||||
|
||||
Стыковочный интерфейс претерпел уже 8 модификаций, прошёл первичные испытания на прочность соединения и готов к интеграционным испытаниям с остальной частью робота.
|
||||
|
||||

|
||||
|
||||
Мы его упростили, облегчили, при этом сохранив его достаточно жёстким; конструкция препятствует повреждению контактов при ручной установке.
|
||||
|
||||
Ключевым узлом робота является разработанный нами с нуля серводвигатель. На данный момент изготовлен его прототип вместе с контроллерами и ведётся разработка программного обеспечения для управления.
|
||||
|
||||

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

|
||||

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

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

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

|
||||
|
||||
Датчик реализован на кондуктометрическом принципе и обладает чрезвычайно низкой себестоимостью.
|
||||
|
||||
### Опорный каркас
|
||||
|
||||
[Опорный каркас](https://gitlab.com/robossembler/cnc/cubic-modular-workspace), который мы показывали в прошлый раз, тоже претерпел большие изменения. Мы убрали дополнительные соединители и теперь весь каркас состоит из практически одних и тех же универсальных сборочных единиц - опорных пластин. Пластины могут быть двух типов.
|
||||
|
||||

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

|
||||
|
||||

|
||||
|
||||
### Источик питания
|
||||
|
||||
Также разработан совместимый с опорным каркасом [источник питания](https://gitlab.com/robossembler/arm-tools/power-supply-box) от сети переменного тока.
|
||||
|
||||
### Оснастка для производства
|
||||
|
||||
Мы стремимся сделать робота максимально простым в изготовлении, поэтому помимо конструктивных решений для удобства сборки, разрабатываем и вспомогательную оснастку для автоматизации производства. Мы активно разрабатываем [станок для намотки катушек индуктивности двигателя](https://gitlab.com/robossembler/cnc/motor-wire-winder).
|
||||
|
||||

|
||||
|
||||
Опробованы два варианта намоточного станка - ручной и полуавтоматический, сейчас разрабатывается третий вариант. Станок позволит нам обеспечить серийное производство моторов и сервоприводов. Как и во всех остальных случаях, конструкторская документация на станок будет открыта.
|
||||
|
||||
### Приспособление для захвата
|
||||
|
||||
Существенно изменена конструкция [приспособления для захвата](https://gitlab.com/robossembler/arm-tools/grip-tool), в котором теперь используются те же самые узлы, что и в манипуляторе - двигатель с контроллером, стыковочный интерфейс.
|
||||
|
||||

|
||||
|
||||
В новой версии улучшены передаточные механизмы, добавлены редукторы, изменён корпус. Новая конструкция позволяет вращать пальцы на угол 360 градусов, а новая форма пальцев - "захватывать" объекты внешней стороной.
|
||||
|
||||
## Программные решения
|
||||
|
||||
### Robonomics Bridge
|
||||
|
||||
В 2022 году нашей командой разработан [мост между Робономикой и ROS2](https://gitlab.com/robossembler/robonomics_bridge), который решает проблему взаимодействия различных кибер-физических систем через публичную сеть интернет.
|
||||
|
||||

|
||||
|
||||
Фреймворк ROS2 основан на протоколе под названием DDS или Data Distrubution Service, который обеспечивает взаимодействие узлов ROS друг с другом. Этот протокол ориентирован на работу в локальной сети, в нём заложены механизмы автоматического обнаружения устройств и очень интенсивное взаимодействие между ними. Однако, в случах когда требуется обеспечить работу отдельных узлов ROS с каким-то внешним сервисом или системой, то возникает проблема безопасности - получив доступ к одному узлу, сторонний сервис получает доступ и ко всем остальным - он может полностью прослушивать весь внутренний трафик DDS.
|
||||
|
||||
Чтобы решить проблему доступа узлов друг к другу можно использовать пакет ROS2 Security, который настраивает политики доступа к данным. Однако, этот подход обладает большим минусом - весь трафик в системе шифруется, что может сказаться на быстродействии при той нагрузке на сеть, которую создаёт DDS. Другое решение заключается в создании так называемых шлюзов, которые публикуют нужные данные, сохраняя всё остальное приватным. Как правило, это достигается при помощи тоннелей VPN или SSH между взаимодействующими узлами. Такой подход применён в таких проектах как Husarnet, Integration Service и Zenoh, но и он не лишён недостатков. В этом случае вам нужно создать защищённый канал связи, который жёстко привязан к IP-адресу или доменному имени контрагента, а они имеют свойство меняться, блокироваться и подвергаться атакам.
|
||||
|
||||
Проблему можно обойти с помощью технологий p2p, на которых построен блокчейн [Robonomics](https://robonomics.network/). По сути блокчейн может являться в этом случае очень защищённой таблицей маршрутизации, адресами контрагентов в которой являются публичные ключи узлов. Вам нужен локальный узел блокчейна и знание о том какой публичный ключ у вашего контрагента, чтобы далее не зависеть от системы DNS и блокировок IP-адресов. Библиотека libp2p, на которой построен блокчейн Робономики, может использовать разные транспортные протоколы для доставки сообщений. Однако, это не все возможности, которые может дать блокчейн. Помимо простого коммутирования потоков сообщений, в блокчейне в будущем может быть реализована и более сложная логика на смарт-контрактах, подразумевающая взаимодействие большого количества агентов. Например, принятие решение о запуске производства какого-то продукта может быть привязано к голосованию в организации потенциальных потребителей этого продукта, с учётом экономической целесообразности. Сейчас решение о запуске какого-либо производства принимается с помощью механизма инвестиций, когда инвесторы, получив информацию о потенциальном спросе, могут приобретать акции отдельных компаний, которые этот спрос смогут в будущем удовлетворить. То есть инвесторы являются лишним передаточным звеном между потребителями и производителями. Если потребители смогут более активно участвовать в разработке и ценообразовании новых продуктов, то мы сможем в перспективе перейти на такую схему работы, когда производство будет автоматически перестраиваться на удовлетворение спроса по данным, предоставляемым в блокчейн потребителями.
|
||||
|
||||
### Robossembler Framework
|
||||
|
||||
Основной разработкой проекта по-прежнему является Фреймворк Робосборщик, в котором можно выделить два основных блока - Offline и Online.
|
||||
|
||||

|
||||
|
||||
[Оффлайн-часть](https://gitlab.com/robossembler/framework) связана с подготовкой моделей для симуляции, машинному обучению, взаимодействию с системами контроля версий и непрерывной интеграции. По сути она представляет собой конвейер подготовки трёхмерных моделей и инструменты анализа статической структуры изделия. Одним из важнейших узлов в этом конвейере является разработанный нами планировщик сборки или планировщик последовательности сборки — Assembly Sequence Planner.
|
||||
|
||||

|
||||
|
||||
Этот программный компонент анализирует сборку в формате STEP, проверяет наличие дефектов в геометрии, которые делают проблематичным подготовку моделей в формат пригодный для симуляции. Также он проверяет требуемые допуски между деталями и строит так называемую матрицу смежности, которая содержит полную информацию о сопряжениях между деталями. Чтобы построить всю последовательность сборки. Дальше сформированные подсборки проверяются на стабильность в гравитационном поле и алгоритм генерирует подходящие варианты для отладки в симуляции. В 2023 году мы дополнили нашу [коллекцию исследований](https://robossembler.org/docs/technologies/ASP-overview) по генерации последовательности сборки. Найдены новые исследователи, работающие в направлении автоматизации планирования сборки - в частности, доктор технических наук Божко Аркадий Николаевич, преподаватель из Бауманского университета, с достаточно оригинальным подходом к решению задачи через использование гипер-графов, который мы планируем поддержать в нашей программной части.
|
||||
|
||||
Далее работу принимает часть конвейера, отвечающая за компьютерную графику.
|
||||
|
||||

|
||||
|
||||
Детали, входящие в сборки, преобразовываются в так называемые ассеты компьютерной графики разной степени полигональности. Для преобразования ассетов используется свободный редактор компьютерной графики Blender и разработанный нами аддон. Аддон формирует три типа ассетов. Высоко-полигональные модели содержат много деталей и могут использоваться для качественной визуализации. Для симуляции требуется обратное - чтобы количество полигонов было как можно меньшим. Поэтому производится оптимизация полигональной сети и в некоторых случаях склейка отдельных компонентов в монолитный кусок. Также аддон, используя информацию об материалах деталей из CAD, генерирует так называемые физически реалистичные текстуры, производит так называемое запекание текстур. Чтобы познакомиться с конвейером компьютерной графики подробнее, рекомендую прочесть статью на нашем сайте.
|
||||
|
||||
Онлайн-часть или рантайм [Robossembler ROS2](https://gitlab.com/robossembler/robossembler-ros2) непосредственно выполняется на железе в момент работы робота. За прошедший год мы перевели проект с ROS2 Foxy, поддержка которой была прекращена в 2023 году, на ROS 2 Humble. ROS2 Humble является так называемым долгоживущим релизом или LTS, который будет поддерживаться еще три года.
|
||||
|
||||
### Архитектура runtime
|
||||
|
||||
В рантайме у нас реализована архитектура из нескольких разных уровней планирования.
|
||||
|
||||

|
||||
|
||||
Самый верхний уровень стека - уровень миссии. Там происходит по сути планирование производственных заданий, подобно ERP-системе, где определяется сколько чего мы производим. Далее следует уровень планирования задач - разбиение процесса сборки отдельного изделия на кванты - логические операции, которые, в свою очередь, опираются на уровень поведения, где работают соответствующие задаче комбинации навыков в виде деревьев поведения. Это поведение стоится на базе атомарных навыков, например, движение к точке, движение по траектории, различные типы восприятия изображений, из которых собирается более сложное поведение. Атомарные навыки работают с аппаратным слоем, то есть с железом, через драйвера устройств. Там решается как именно мы получаем данные, через какие интерфейсы, топики или сервисы, как сигналы преобразовываем и куда передаем.
|
||||
|
||||
### Деревья поведения и управление жизненным циклом навыков
|
||||
|
||||
В основе рантайма у нас лежат деревья поведения. Изначально деревья поведения появились в сфере разработки компьютерных игр для того, чтобы программировать персонажей NPC. Однако, со временем данный подход был предложен также для использования и в робототехнике, в частности Петером Оргеном, который популяризирует и всячески пытается приладить к задачам робототехники. Очень хорошо данный подход себя зарекомендовал себя в области мобильной робототехники - это разнообразная навигация по помещениям. В основе популярнейшего пакета ROS Navigation лежат именно деревья поведения. Мы увидели преимущества этого подхода прежде всего в модульности. Мы заранее не знаем какие именно методы подойдут лучше всего для тех или иных задач, поэтому от фреймворка требуется обеспечить изменяемость - чтобы не надо было менять всю остальную программу при изменениях в отдельном навыке или дереве поведения. Также этому подходу присуща и нужная для производства отказоустойчивость.
|
||||
|
||||

|
||||
|
||||
В проекте Robossembler ROS2 разработан BT-executor, в котором реализованы первые узлы или навыки - в частности, движения к точке пространства через решение обратной задачи кинематики, обнаружение объектов в сцене - Object Detection, а также оценка 6D позиции объектов - Pose Estimation для распознавания положения деталей в пространстве перед захватом и сборкой.
|
||||
|
||||
Помимо деревьев поведения, нами также внедрён один из важных концептов, появившихся в ROS2 под названием Lifecycle Nodes или Managed Nodes. Это такой тип узлов ROS2, который позволяет их включать, выключать, конфигурировать, когда надо убирать, добавлять. Это делает удобным подмену, конфигурацию и запуск отдельных навыков в ходе исполнения программы.
|
||||
|
||||

|
||||
|
||||
Например, навык Object Detection у нас используется в нескольких вариантах. В ходе работы программы часто возникает ситуация, когда нужно переключиться на другую реализацию навыка, если текущая не сработала. Разумеется, мы не можем держать всех их в памяти одновременно. Особенно это актуально когда для работы навыка требуется много ресурсов, что часто бывает с нейронными сетями. Здесь на помощь приходят Lifecycle Nodes. Почти все имеющиеся на данный момент навыки в фреймворке реализованы в виде Lifecycle Nodes.
|
||||
|
||||
### Управление виртуальными средами
|
||||
|
||||
Одним из нововведений, которые мы сделали в фреймворке, является Environment Manager или менеджер управления виртуальными средами. Это модуль, который соединяет рантайм с разнообразными средами - как виртуальными, так и не очень. Виртуальной средой может быть игровой движок или симулятор.
|
||||
|
||||

|
||||
|
||||
Environment Manager реализует абстрактный интерфейс, который позволяет соединять рантайм, его драйвера с виртуальной средой. Например, мы можем получать изображение от реальной камеры через какой-то топик, а в этот же топик Environment Manager может нам в дальнейшем, когда мы переключимся на режим симуляции, передавать данные не с камеры, а с симулятора. В этом случае сама программа останется прежней, ничего переписывать не надо. В качестве первой среды мы выбрали симулятор Gazebo, архитектура которого предусматривает разбиение на отдельные компоненты, которые реализовывают физику, рендеринг и многое другое, что делает удобными применение нашего подхода. По нашей задумке Environment Manager должен оказать большое влияние на сам подход к разработке управляющих программ роботов, делая более простым и доступным обучение с подкреплением.
|
||||
|
||||
## Прикладные решения
|
||||
|
||||
### Растениеводство
|
||||
|
||||
Продвигается и разработка прикладных решений на базе наших модулей. Одним из таких решений является роботизированный комплекс для размножения растений методом микроклонирования, который разрабатывается вместе с нашими коллегами из компании [Фито Слим](https://agrostab.ru/).
|
||||
|
||||

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

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

|
||||
|
||||
Комплекс включает в себя камеры для разносторонней съёмки процесса, чтобы собирать данные и в дальнейшем использовать их для научной и инженерной работы.
|
||||
|
||||

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

|
||||
|
||||
## Вместо заключения
|
||||
|
||||
В заключение хотелось бы отметить, что мы кардинально изменили наш статус - открыли предприятие. Теперь Робосборщик — это не только кружок или клуб единомышленников, а полноценная организация с юридическим статусом. Организация оформлена после победы в конкурсе соискателей финансирования для открытых проектов библиотек программного обеспечения под названием «Код цифровые технологии», организованного Фондом содействия инновациям.
|
||||
|
||||
В 2024 году мы планируем завершить разработку программного обеспечения контроллера серводвигателя, запустить манипулятор и испытать его вместе с нашим рантайм модулем. Параллельно этой работе будет вестись и проект фреймворка для отладки программ через симуляцию.
|
||||
|
||||
Подписывайтесь на наши каналы в [Telegram](https://t.me/robossembler_ru) и [Youtube](https://www.youtube.com/channel/UC32Xgbsw9XQlN1QH59pe8HA). Если у Вас есть идеи как можно помочь проекту, то Вы можете непосредственно зайти в [GitLab](https://gitlab.com/robossembler), выбрать нужный подпроект и просто написать там issue, где поделиться своими мыслями.
|
||||
|
||||
## Команда
|
||||
|
||||
В работе участвовали:
|
||||
|
||||
- Игорь Брылёв
|
||||
- Станислав Сгонов
|
||||
- Алексей Топтун
|
||||
- Александр Оликевич
|
||||
- Роман Андрианов
|
||||
- Илья Ураев
|
||||
- Марк Вольтов
|
||||
- Илья Курочкин
|
||||
- Никита Молканов
|
||||
- Андрей Ермаков
|
||||
- Вячеслав Македонский
|
||||
- Александр Шевеленко
|
||||
- Иван Ершов
|
||||
- Михаил Якушкин
|
||||
- Степан Воронов
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
slug: rbs-framework-videos
|
||||
title: Видео-демонстрации работы программных модулей Фреймворка Робосборщик
|
||||
author: Игорь Брылёв
|
||||
author_title: Team Lead @ Robossembler
|
||||
author_url: https://gitlab.com/movefasta
|
||||
author_image_url: https://gitlab.com/uploads/-/system/user/avatar/4249760/avatar.png
|
||||
tags: [robossembler, milestone, summary]
|
||||
---
|
||||
|
||||
Краткие ознакомительные видео-демонстрации работы программных модулей Robossembler Framework (https://robossembler.org/docs/robossembler-framework/), который сейчас разрабатывается нашей командой.
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/OR-pSsiaEF0?si=EYauUCESIGjsND0L" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
Before Width: | Height: | Size: 497 KiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 2 MiB |
Before Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 1.8 MiB |
Before Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 671 KiB |
Before Width: | Height: | Size: 359 KiB |
Before Width: | Height: | Size: 659 KiB |
Before Width: | Height: | Size: 584 KiB |
Before Width: | Height: | Size: 391 KiB |
Before Width: | Height: | Size: 448 KiB |
Before Width: | Height: | Size: 448 KiB |
Before Width: | Height: | Size: 567 KiB |
Before Width: | Height: | Size: 462 KiB |
Before Width: | Height: | Size: 320 KiB |
Before Width: | Height: | Size: 507 KiB |
Before Width: | Height: | Size: 566 KiB |
Before Width: | Height: | Size: 401 KiB |
Before Width: | Height: | Size: 401 KiB |
Before Width: | Height: | Size: 416 KiB |
Before Width: | Height: | Size: 988 KiB |
Before Width: | Height: | Size: 665 KiB |
Before Width: | Height: | Size: 355 KiB |
Before Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 1.9 MiB |
Before Width: | Height: | Size: 2.3 MiB |
Before Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 1.9 MiB |
Before Width: | Height: | Size: 613 KiB |
Before Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 127 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 82 KiB |
|
@ -1,4 +1,5 @@
|
|||
---
|
||||
id: beehive
|
||||
title: 'Улей'
|
||||
---
|
||||
---
|
||||
Добавляю какойто текст
|
||||
|
|
Before Width: | Height: | Size: 91 KiB |
|
@ -1,104 +0,0 @@
|
|||
---
|
||||
id: cfs-models-pub-in-nix
|
||||
title: Стандарт публикации моделей на базе пакетного менеджера nix
|
||||
---
|
||||
|
||||
## Предпосылки
|
||||
|
||||
### Модель open source для распространения любых текстов, а не только исходных кодов программ
|
||||
|
||||
Любая информация в компьютере может быть представлена текстами на алфавитах определённой размерности. Некоторые тексты могут быть прочитанными людьми, остальные - только машинами. Развитие кибер-физических систем позволило использовать информацию не только для интерпретации людьми, но и для непосредственного материального производства в виде программ для устройств, а производство исходных текстов этих программ также претерпело значительные изменения в связи с появлением высокоскоростных сетей связи, позволяющих обмениваться информацией между множеством авторов. Так, в сфере разработки программного обеспечения появилось движение за открытые исходники (open source). Во многом благодаря тому, что в программах есть большой плюс - они могут быть применены, в отличие от аппаратных систем, всеми, у кого есть вычислительно устройство (ЭВМ) или компьютер. Именно этим обусловлено стремительно развитие ПО с открытым кодом - оно использует сетевые эффекты и мудрость толпы для получения более эффективных и быстро распространяющихся инноваций. В мире аппаратных систем данный подход пока не получил должного распространения, что обусловлено централизацией производств и невозможностью воспользоваться ими большими группами разработчиков. Опубликованная в общий доступ модель спутника не окажет почти никакого влияния на окружающий мир, потому что для её воплощения в жизнь потребуются редкое сырьё, высококвалифицированные рабочие и дорогостоящее оборудование. Однако стандартизация/унификация и удешевление средств производства постепенно решают эту проблему. Во многом именно этим обусловлена популярность 3D-печати. Изделия для 3D-печати могут быть произведены каждым владельцем принтера, тем самым создаются предпосылки роста популярности open source в мире "железа" - модель изделия для 3D-печати может быть передана по сети, произведена и приносить пользу. Даже в том случае, если модель не может быть изготовлена у непосредственно у пользователя, то всегда можно объединиться с другими пользователями вокруг одной потребности и заказать партию по минимально возможной цене (см. *crowd supply*). Постепенно появляются сообщества разработчиков вокруг контроллеров электродвигателей, роботов-манипуляторов, 3D-принтеров, биореакторов, специализированных АСУ и многого другого. Со временем станут появляться и более сложные системы с открытым кодом.
|
||||
|
||||
### Сложности в распространении исходных файлов аппаратных систем.
|
||||
|
||||
В отличии от легковесных инструментов для написания и отладки кода в мире разработки аппаратных систем доминируют громоздкие `CAD`/`PDM`/`PLM` системы, которые, как правило, включают различные функции (в том числе контроль версий) в состав своих программных пакетов, делая затруднительным взаимодействие разработчиков между собой или ограничивая их какой-то конкретной экосистемой. Открытые стандарты обмена инженерными данными об изделиях (`ISO`/`STEP`) пытаются преодолеть эту проблему, но широкого распространения они так и не получили, потому что в проектах всегда содержится специфическая для конкретной `CAD`-системы информация, а также смешение разных предметных областей (`domain`) - свойства материалов, геометрия, технологическая информация. Наличие таких систем существенно ограничивает open source модель распространения - нет смысла в исходных файлах, если менять их можно только в специальном коммерческом ПО высокой стоимости. В мире разработки программного обеспечения такой проблемы никогда не существовало - стандартом обмена данными там всегда являлся определённый формат файла, который можно редактировать в любом текстовом редакторе, тогда как дополнительное удобство разработки программисты обеспечивали себе сами с помощью настройки окружения под себя. Таким образом наличие доступных средств проектирования является необходимым условием развития открытых проектов кибер-физических систем. Постепенно, такие средства приобретают черты чего-то пригодного к прикладной деятельности и возникают предпосылки для интеграции данных инструментов в полноценную инфраструктуру для разработки.
|
||||
|
||||
## Управление зависимостями как инструмент коллаборации
|
||||
|
||||
### Роль инфраструктуры для развития open source
|
||||
|
||||
git и сервисы, построенные вокруг него стали краеугольным камнем стремительного роста сообществ вокруг открытого кода. Это говорит о большой важности стандартов взаимодействия и, разумеется, git в какой-то степени является таким стандартом для текстовых файлов. Этот стандарт описывает способ взаимодействия большого количества разработчиков в децентрализованным способом, что очень важно для развития. Новым разработчикам не нужно уговаривать авторов исходной работы внести в неё изменения - они имеют возможность сделать копию - ветку(`fork`) - и внести изменения независимо от желания авторов, а git лишь обеспечивает способ безопасного слияния веток разработки. Это позволяет избежать в таких онлайн-сообществах свойственных корпоративному миру административной волокиты и бюрократии. Так, широко известный по книге "Социальная архитектура" популяризатор открытого ПО Питер Хинтьенс когда-то в своём проекте применял практику принятия запросов на изменения без ревью, несмотря на рискованность такой практики. Благодаря этому все новые разработчики чувствовали причастность к проекту и быструю обратную связь, что не менее важно. Появление инструментов непрерывной интеграции (`continuous integration`, `CI`) позволяет снизить риски при использовании такого подхода.
|
||||
|
||||
### Роль инструментов управления зависимостями
|
||||
|
||||
Однако, одного инструмента контроля версии git оказалось недостаточно для сложных проектов разработки. Подход моно-репозитория, когда все компоненты сложной системы размещались в одном хранилище кода, упирался в административные барьеры (у репозитория один владелец) и технические возможности git. Новые функции git, такие как `подмодули`(`submodules`), не решили задачу управления зависимостями так, как это требует современная индустрия разработки. Вокруг каждого нового языка стали вырастать специальные инструменты управления зависимостями - `npm`, `pip` и многие другие. Это вывело возможности коллаборации на новый уровень. Например, сейчас в `Github` можно просмотреть в каких других проектах используется та или иная библиотека по `Network Graph`, что делает поиск аналогов простым и доступным. Ведь в open source зачастую важнее найти уже существующее, чем писать своё собственное, "изобретая велисипед". Тем не менее, специфичность отдельного пакетного менеджера для своих языков не облегчило процесс управления зависимостями в проектах, в состав которых входят программы на разных языках. К таким проектам относятся и `кибер-физические системы` (КФС), где используются слишком разнообразные инструменты разработки, форматы файлов и сборочные системы. Так сложилась потребность в независимом от языков и IDE способе управлять зависимостями, без которой проектирование много-сложных техническим систем затруднительно.
|
||||
|
||||
### Пакетный менеджер общего назначения
|
||||
|
||||
В качестве способа управления зависимостями в моделях кибер-физических систем можно рассмотреть nix, который обладает рядом свойств, делающих его подходящим инструментом для этой задачи:
|
||||
* Стремление к чистоте/детерминированности процесса вычисления/сборки/разворачивания
|
||||
* Независимость от языков программирования и отдельных экосистем; подходит для работы не только с исполняемыми программами, но и с другими файлами.
|
||||
* Использование git и некоторых других систем контроля версий в качестве базового слоя для хранения исходных файлов
|
||||
|
||||
Помимо децентрализованного git, ставшего стандартом индустрии для управления изменениями, и декларативного пакетного менеджера nix для управления зависимостями, в инфраструктуре может потребоваться хранение тех данных, которые предназначены для машин - это файлы для станков, скомпилированные бинарники, прошивки микроконтроллеров. С этой задачей справляется binary cache сервис, который входит в состав nix.
|
||||
|
||||
## Базисное разбиение системы
|
||||
|
||||
Современная системная инженерия (например, согласно стандарту IEC 81346—1:2022) выделяет несколько типов декомпозиции систем: функциональное, конструктивное, пространственное, стоимостное. Функциональное разбиение строится по иерархии функциональных компонентов, которые именуются по их роли и могут быть реализованы различными физическими объектами. Конструктивное - по ссылкам на конкретные классы оборудования или их модели. Пространственное - по локализации в пространстве надсистемы. Стоимостное - по стоимости работ и оборудования.
|
||||
|
||||
Система всегда имеет воплощение в физическом мире, занимает место в пространстве, что нельзя упускать из виду при любой разработке, а потому в качестве базиса для разбиения систем и их отражения в структуре зависимостей nix должна использоваться модульная/конструктивная/синтетическая структура системы в виде дерева/графа с рёбрами типа `является-частью` (в англоязычной литературе по онтологии `is-part-of`). Дополнительным обоснованием этого решения является тот факт, что производство/сборка/модульный синтез осуществляется по конструктивным описаниям. По мере роста степени автоматизации возможна ситуация, когда машина сможет преобразовывать декларативное описание функций системы от человека в императивное описание способа построения, но при этом само преобразование не исчезнет - изменится актор, который будет это преобразование осуществлять.
|
||||
|
||||
Функциональное разбиение является более "субъективным" и часто формируется в контексте т.н. "сценариев использования". Например, в роли молотка может выступать множество предметов - да, в том числе микроскоп. Поэтому идентификация объектов по выполняемой функции может быть затруднительной.
|
||||
|
||||
В функциональном разбиении часто нет общепринятых стандартов описаний, тогда как в конструктивных описаниях их много. Например, форматы файлов для представления формы геометрических объектов в разных видах. Со временем эти форматы появятся и их можно будет сопоставить с конструктивными разбиениями, как это делается в IEC 81346—1:2022.
|
||||
|
||||
Одна и та же функция может быть распределена по множеству конструктивных компонентов - так, например, функция обмена данными с любым электронным устройством реализовывается с помощью
|
||||
* разъёма для подключения кабеля
|
||||
* проводящего слоя/дорожки на печатной плате
|
||||
* аппаратного приёмопередатчика с обвязкой
|
||||
* аппаратного периферийного блока микроконтроллера
|
||||
* программного драйвера управляющей программы микроконтроллера
|
||||
* программной библиотеки, реализующей протоколы взаимодействия.
|
||||
|
||||
Данная структура разбиения является инвариантом, которому должны соответствовать разнообразные описания. Дерево схем, дерево mesh-ей, дерево геометрических объектов, дерево документации, дерево модулей ПО - все они занимают место в пространстве и времени. Например, процессор является сложным изделием, которое можно описать одновременно как геометрическую модель, электрическую схему, исходный код программы. Каждое такое описание превращается в физическую сущность - механический корпус микросхемы, топологию проводящего рисунка или литографических слоёв, бинарный код программы, занимающий место в памяти - в ходе производства/компиляции/сборки, а введено в эксплуатацию в ходе размещения/деплоя/установки/инсталляции.
|
||||
|
||||
## Стандарт публикации пакетов
|
||||
|
||||
Каждый компонент/объект/целевая система, потенциально занимающий пространство в реальном мире, имеющий временной экстент и который может быть потенциально использован повторно, размещается в отдельной директории или корне репозитория вместе с файлом `flake.nix`, который отвечает за воспроизводимость всего проекта кибер-физической системы и служит корневой конфигурацией системы, отвечающей за все поступающие извне зависимости и генерируемые артефакты. Имя каждого объекта является уникальным в контексте конфигурации и задаётся в nix-выражениях, из которых с помощью nix-функции `mkDerivation` формируются уравнения сборки. В выражении описываются необходимые для работы с ним инструменты/зависимости.
|
||||
|
||||
Связь между исходным и производным пакетом является зависимостью. Если компонент не может быть получен в результате вычисления чистой функции и требуется изменение состояния вручную, то к нему добавляется соответствующий `patch` из git-репозитория. Также компонент может быть задан полностью вручную, то есть формироваться без процесса сборки/компиляции/вычисления. В этом случае он должен быть задан через параметр `src` в функции формирования пакета или параметр inputs в `flake.nix`.
|
||||
|
||||
Структура корневой конфигурации репозитория в формате `flake.nix`
|
||||
|
||||
* *inputs*: Входными переменными flake.nix являются *исходные файлы* также содержащие `flake.nix`, которые редактируются человеком в репозитории git и из которых создаются другие файлы с помощью вычислений. В момент генерации/сборки конкретные версии *inputs* фиксируются и записываются в flake.lock файл (подобно package/yarn.lock в npm/yarn), чтобы обеспечить воспроизводимость данного процесса независимо от окружения другого пользователя. Исходные файлы - по определению, те файлы которые создаются или редактируются человеком. К ним можно отнести как инженерные модели и исходные коды, так и другие описания - например, требования к системе, которые в дальнейшем могут быть проработаны в рамках эскизного и технического проектов.
|
||||
* *outputs*: выходные пакеты для целевой системы, исполняемые файлы - `bin`, `exe`, представления 3D-моделей в виде `BREP`, `STL`, `G-code` для заданной конкретной модели принтера (который должен быть указан в качестве зависимости для данного артефакта), BOM-лист с составом деталей, PDF-версии чертежей, изображения, текстовые описания.
|
||||
|
||||
Структура внутреннего пакета/компонента КФС:
|
||||
* `{ inputs ... }:`. Пакет в nix является чистой функцией, аргументом которой является входное множество `{ inputs }` из других функций, которые необходимы для сборки и исполнения данного пакета (см. ниже `buildInputs`, `nativeBuildInputs`), которые наследуются из корневой конфигурации `flake.nix` и других nix-файлов. К ним могут относиться CAD, EDA, IDE, компиляторы, библиотеки, пакетные менеджеры, операционные системы, репозитории с пакетами типа nixpkgs, внешние зависимости.
|
||||
* `name`. Уникальное имя компонента в пространстве имён проекта.
|
||||
* `src`. Путь/url к исходным файлам - архиву, директории, конкретному файлу в репозитории. Для детерминированности сборки указывается с хеш-суммой от него.
|
||||
* `buildInputs`. Зависимости времени исполнения . В случае программного обеспечения, если для работы исполняемого файла используется какая-то внешняя библиотека (в случае языка Си это *.so), то использующее этот исполняемый файл приложение не обязано знать об этой библиотеке, поэтому её следует указывать в `buildInputs`. В случае с пакетов с моделями аппаратных систем такого рода зависимостями являются устройства, без которых невозможна работа данного модуля - например, источник энергии. Также к данному типу относятся зависимости времени исполнения, которые также передаются и по цепочке зависимостей дальше (downstream), то есть доступны при запуске пакетов, использующих данный пакет как зависимость. В nix они имеют название `propagatedBuildInputs`. В случае программного обеспечения ими могут быть python-пакеты, которые используют зависимости своих зависимостей в runtime, а потому должны быть указаны в `propagatedBuildInputs`. В случае с аппаратным обеспечением такого рода зависимостью может быть какой-то сервер, к которому обращаются отдельные модули.
|
||||
* `nativeBuildInputs`. Зависимости времени сборки или производства - buildtime-зависимости, которые необходимы во время сборки, но не нужны во время исполнения. В случае с программным обеспечением это разнообразные компиляторы, библиотеки для тестирования, линтинга. В случае с аппаратным обеспечением этими зависимостями являются цифровые модели средств производств - станков, принтеров, оснастки, камер. Подобно `propagatedBuildInputs` для зависимостей времени исполнения тут также есть `propagatedNativeBuildInputs` - зависимости времени сборки, которые также передаются по цепочке зависимостей дальше (downstream), то есть доступны при сборке пакетов, использующих данный пакет как зависимость. В случае с аппаратным обеспечением такого рода зависимостями могут являться средства производства, единые для всех этапов технологического процесса - например, робот-манипулятор для сборки изделия или камера, распознающая все объекты в сцене. Создать окружение со всеми сборочными зависимостями можно с помощью команты `nix-shell`. Runtime-зависимости в этом окружении будут отсутствовать, если явно не заданы в `nativeBuildInputs`. Поэтому, если какие-то зависимости нужны как во время сборки, так и во время работы, то их нужно указывать в обоих опциях.
|
||||
`outputs`. Каждое nix-выражение генерирует уравнение сборки пакета (`derivation`), в ходе которого формируются артефакты разных типов, которые выражены специальной формой вывода в виде файла или директории с файлами с заданной структурой. Параметр `outputs` задаётся в виде списка строковых значений. Например, `outputs = [ "brep" "stl" "md" "png" "bin" ]` для пакета с `name = package` будет преобразовано в ходе сборки в следующий набор пакетов: `package-brep`, `package-stl`, `package-md`, `package-png`, `package-bin`.
|
||||
|
||||
Компонент может быть описан множеством способов (*views* или *viewpoints* с точки зрения системной инженерии), поэтому каждый пакет хранит в себе информацию о методе вывода (`view`), что эквивалентно ассоциациям к типам файлов в операционных системах. Метод вывода является ссылкой на некоторое программное обеспечение (тоже пакет), выполняющее роль ПО для работы с данным артефактом. Инженер-электроник видит систему как принципиальную схему или spice-модель, конструктор - как набор тел геометрической формы, гейм-дизайнер видит как набор текстурированных mesh'ей для движка, программист как набор исходных кодов. Все эти способы представления прилагаются ко всем модулям, сама структура разбиения изделия на компоненты сохраняется. Структура разбиения позволяет получать агрегируемые и генерируемые автоматически пакеты документации с большим количеством уровней вложенности.
|
||||
|
||||
На рисунке ниже показана инвариантность разбиения в предметных областях схемотехники (`sch`-пакет), трёхмерного моделирования (`stl`-пакет), документации (`doc`-пакет) на примере сборки изделия.
|
||||
|
||||

|
||||
|
||||
Все артефакты, которые создаются в рамках сборки с помощью nix-выражений, можно проверить на консистентность или соответствие, так как хранилище nix (`/nix/store`) располагает всей доступной информацией для выбранной целевой системы. Наличие общего хранилища для всех артефактов проекта кибер-физической системы позволяет *согласовывать (consistency)* их между собой и, тем самым, эффективно управлять конфигурацией системы. Процесс согласования обеспечивают практики *Непрерывной интеграции (Continuous Integration, CI)*, где изменения в каком-то из описаний проверяются на согласованность с требуемыми допусками. При этом мы разделяем непрерывную интеграцию, выполняемую людьми и непрерывную интеграцию, выполняемую с помощью автоматизированных вычислений.
|
||||
|
||||
## Порядок вычислений и генерации производных артефактов
|
||||
|
||||
Компонент системы имеет условное графическое обозначение, геометрическую форму, материалы, вес, металлизацию, текстуру, параметры электрических соединений. Так, например, проектируя робота, необходимо опираться на модель материала (пластик, медь, железо, кремний), принципиальную эл.схему и некоторые другие параметры, которые будут влиять на результат вычисления. Результатом вычисления будет, например, вес или центр масс, который определён в зависимости от геометрических параметров изделия и свойств его материала:
|
||||
* Получение веса, центра масс и параметров соединений с помощью геометрии детали и спецификации материала (`Geometry` + `Material` -> `Weight`, `CenterOfMass`, `Joints`)
|
||||
* Получение полигональной сети из геометрической модели (`Geometry` -> `Mesh`)
|
||||
* Получение итогового описания робототехнической системы в формате Universal Robot Desctiption Format из полученных выше весов и полигональных сетей (`Weight` + `CenterOfMass` + `Mesh` + `Joints` -> `URDF`)
|
||||
|
||||
Описания системы на разных системных уровнях и уровнях детализации описываются с помощью разных исходных файлов. Модель для игрового движка будет сверх-оптимизированной (до разумного предела) полигональной сетью (`mesh`) с PBR-текстурой для высокой производительности в симуляторе, в которой не будет никакой внутренней структуры, а только габариты и какие-то параметры поведения - например, триггер для запуска какого-то события. Эта модель будет связана чистой функцией преобразования с моделью инженерной, где будет отражена внутренняя структура системы. Если рассмотреть разработку твердотельных изделий, то часто полигональная сеть STL генерируется из первичной геометрической модели в формате BREP и геометрическое представление будет являться в данном случае первичным. Так как модели могут развиваться параллельно и независимо друг от друга, то конкретная последовательность вычисления может быть разной, так как нет какого-то пред-определённого конвейера, где за инженерной моделью следует модель игровая. Сначала может появиться игровая модель, а уже потом разработана конструкция изделия. То есть эти модели развиваются параллельно, описывая, тем не менее, один и тот же физический предмет. Тот факт, что отдельные модели могут быть получены друг из друга с помощью вычисления, не обязывает нас следовать этому порядку, описывая связи. Однако, очевидно, что из модели с высокой степенью детализации проще получить модель с низкой степенью детализации (абстрагирование, убираем ненужное в данном контексте), чем наоборот (рендеринг, инженерия, добавляем детали для лучшего соответствия действительности).
|
||||
|
||||
Например, в отношении видимых свойств объекта может быть реализована последовательность: `Требования` -> `Рисунок на салфетке` -> `Эскиз художника` -> `Эскиз 3D mesh` -> `CAD модель изделия` -> `Mesh для рендера` -> `Mesh для игрового движка или симулятора`. Однако, последовательность может быть и другой - например, прежде чем начать прорабатывать полную инженерную модель изделия, нам необходимо сделать эскиз для игрового движка, загрузить в виртуальную реальность, где бы пользователи могли ознакомиться с ней и понять удовлетворяет ли она их требованиям.
|
||||
|
||||
## Пример. Артефакты и модели полигональной сети (mesh)
|
||||
|
||||
Ретопология - это процесс подготовки трёх-мерной модели для использования в игровых движках и симуляторов с целью обеспечить высокую производительность. По умолчанию, те mesh, которые генерируются автоматически из CAD-моделей, не отвечают требованиям игровых движков, содержат избыточную информацию.
|
||||
|
||||
Сейчас ретопология выполняется вручную, поэтому для неё создаётся отдельный репозиторий, который в качестве входных данных (зависимостей) получает сгенерированный алгоритмом mesh и грузит его напрямую из кэша на сервере, либо вычисляет самостоятельно по BREP-представлению, указывая mesh алгоритм в качестве зависимости. После этого он вносит изменения в этот mesh. Человек, осуществляющий подготовку модели для игрового движка или симулятора, ссылается на `flake.nix` репозитория редактора mesh'а и накладывает текстуру, указывая в качестве зависимости спецификацию материала, так как от неё текстура зависит. Таким образом, когда мы используем эту модель в библиотеке ассетов игрового движка, мы видим всё историю изменений, вплоть до изначальной геометрии.
|
||||
|
||||
Процедуры, производимые вручную могут быть проиндексированы, а полученные после индексации данные могут использоваться для обучения нейронной сети или каких-то алгоритмов. Для этого описанные процедуры должны быть специфицированы. Та же ретопология может быть специфицирована как функция, принимающая геометрию в BREP и возвращающая MESH. Если нам приходится вручную редактировать mesh после работы имеющегося несовершенного алгоритма генерации, то мы имеем цепочку: `eval (BREP -> MESH) |> edit (MESH -> MESH)`, где количество полигонов уменьшено. Таким образом мы можем видеть общую картину степени автоматизированности процесса, а также механизм учёта вклада отдельных пользователей в дело обучения машины.
|
||||
|
||||
Итак, процесс ретопологии может выглядеть следующим образом. Мы ищем в реестре геометрических моделей нужную нам (по каким-то критериям) модель в нужном формате (например, BREP). Если над BREP нужно проделать предварительное вычисление, то нам нужно явно это указать - ссылкой на конкретный алгоритм. Дерево зависимостей может выглядеть следующим образом
|
||||
|
||||
* *inputs*: blender, sverchok, mesher (генератор полигональных сетей), brep flake, blend file с отредактированным mesh или конкретная последовательность действий над полигональной сетью(запись действий пользователя, типа rosbag или макроса) для удобства обучения
|
||||
* *outputs*: stl, obj, dae, blend.
|
|
@ -1,33 +0,0 @@
|
|||
---
|
||||
id: auto-assembly
|
||||
title: 'Фреймворк Auto-Assembly'
|
||||
---
|
||||
|
||||
*Оригинал: [Auto-Assembly'2023](https://arxiv.org/pdf/2301.02643.pdf)*
|
||||
|
||||

|
||||
|
||||
## Генерация артефактов (Artifacts generation)
|
||||
|
||||
Состоит из следующих этапов
|
||||
- _Анализ конструкции (design analysis)_. Из CAD экспортируется два дизайн-файла:
|
||||
- Детали целевой сборки и их соединения (joints). Крепёжные детали помечаются специальными ярлыками.
|
||||
- Та же сборка уже с позициями захватных устройств, приспособлений, кондукторов. В работе используется Fusion API (при этом говорится о CAD-agnostic; наверное, подразумевается, что все другие CAD'ы это API поддерживают). Из этой сборки экспортируется информация о позициях захватных устройств, кондукторов и отвёрток (с их типами) относительно деталей, которые они удерживают и помещается в Tooling Database.
|
||||
- _Генерация последовательности сборки (assembly sequence generation)_ (В работе используется подход из работы 2012 года - [Assembly planning with automated retrieval of assembly sequences from CAD model information](https://www.researchgate.net/publication/235296802_Assembly_planning_with_automated_retrieval_of_assembly_sequences_from_CAD_model_information))
|
||||
- Генерация матрицы смежности
|
||||
- Генерация последовательности на базе матрицы
|
||||
- Вычисление геометрической осуществимости по модели сборки
|
||||
- _Генерация спецификации процесса сборки (bill-of-process, BOP)_. Сначала описание роботизированной ячейки передаётся одновременно как в симулятор, так и в рантайм. Потом происходит сверка заданий на сборку и имеющимся в сцене инструментарием. Если нет подходящих инструментов, то задание не выполняется. Каждая последовательность сборки проходит проверку на согласованность с моделью роботизированной ячейкой, в результате чего формируется валидный bill-of-process, BOP
|
||||
- _Преобразование BOP в управляющий программный код_ - PL-script, который исполняется сначала в симуляторе, а потом и в runtime.
|
||||
|
||||
## Развёртывание (Deploy)
|
||||
|
||||
Реализует исполнение кода для сборки даталей в физической среде. Ключевым компонентом в этой части является высокоуровневый язык описания процессов (Process language, PL), где описаны функции для взаимодействия с различными сервисами в runtime:
|
||||
- _Motion Planner_ - осуществляет планирование траекторий движения
|
||||
- _Robot Controller_ - управление роботом на низком уровне (уровень звеньев и углов поворота)
|
||||
- _Jig Controller_ - возвращает позицию детали относительно позиции кондуктора или приспособления для захвата
|
||||
- _Assembly Service_ - предоставляет информацию о крепеже и итоговые позиции деталей относительно начала координат робоячейки
|
||||
- _Transform Service_ - сервис, возвращающий позицию любого объекта в внутри робоячейки относительно любых других объектов в ней.
|
||||
- _3D Simulator_ - загружает объекты в из описания робоячейки и визуализирует её состояние
|
||||
- _Database and Message Bus_ - шина данных для публикации JSON сообщений и хранилище публикация и их хранилище.
|
||||
Взаимодействие осуществляется в соответствии со входящей в фреймворк схемой данных Factory Control Model (FCM).
|
Before Width: | Height: | Size: 185 KiB |
|
@ -1,114 +0,0 @@
|
|||
;; Modified domain taken from
|
||||
;; "Knowledge transfer in robot manipulation tasks" by Jacob O. Huckaby 2014
|
||||
(define (domain assembly_domain_hackaby)
|
||||
(:requirements :strips :typing :adl :fluents)
|
||||
(:types
|
||||
arm ; robotic manipulator arm
|
||||
workspace ; workspace for assembly operations and storage
|
||||
grip weld scan - tool ; manipulator tool for grip, weld, solder and other operations
|
||||
part ; solid part, that cannot be disassembled
|
||||
assembly ; assembly - can dissassembled
|
||||
)
|
||||
|
||||
(:predicates
|
||||
(arm-canreach ?a - arm ?s - workspace)
|
||||
(arm-at ?a - arm ?s - workspace)
|
||||
(arm-capabilities ?a - arm ?t - tool)
|
||||
(arm-active ?a - arm ?t - tool)
|
||||
(arm-holding ?a - arm ?p - part)
|
||||
(part-at ?p - part ?s - workspace)
|
||||
(part-state ?p - part ?t - tool)
|
||||
(pose-detected ?a - arm ?p - part ?s - workspace)
|
||||
)
|
||||
|
||||
(:action activate
|
||||
:parameters (?a - arm ?old - tool ?new - tool)
|
||||
:precondition (and
|
||||
(arm-capabilities ?a ?new)
|
||||
(arm-active ?a ?old))
|
||||
:effect (and
|
||||
(arm-active ?a ?new)
|
||||
(not (arm-active ?a ?old))) )
|
||||
|
||||
(:action detect-pose-part
|
||||
:parameters (?a - arm ?p - part ?s - workspace ?t - scan)
|
||||
:precondition (and
|
||||
(arm-at ?a ?s)
|
||||
(arm-active ?a ?t)
|
||||
(part-at ?p ?s))
|
||||
:effect (pose-detected ?a ?p ?s)
|
||||
)
|
||||
|
||||
(:action detect-pose-workspace
|
||||
:parameters (?a - arm ?p - part ?s - workspace)
|
||||
:precondition (and
|
||||
(arm-at ?a ?s)
|
||||
(arm-active ?a detect)
|
||||
(arm-holding ?a ?p))
|
||||
:effect (pose-detected ?a ?p ?s)
|
||||
)
|
||||
|
||||
(:action grasp
|
||||
:parameters (?a - arm ?p - part ?s - workspace)
|
||||
:precondition (and
|
||||
(arm-at ?a ?s)
|
||||
(arm-active ?a grip)
|
||||
(arm-holding ?a no-part)
|
||||
(part-at ?p ?s)
|
||||
(pose-detected ?a ?p ?s))
|
||||
:effect (and
|
||||
(arm-holding ?a ?p)
|
||||
(not (arm-holding ?a no-part))
|
||||
(not (part-at ?p ?s))
|
||||
(not (pose-detected ?a ?p ?s)))
|
||||
)
|
||||
|
||||
(:action ungrasp
|
||||
:parameters (?a - arm ?p - part ?s - workspace)
|
||||
:precondition (and
|
||||
(arm-at ?a ?s)
|
||||
(arm-active ?a grip)
|
||||
(arm-holding ?a ?p)
|
||||
(pose-detected ?a ?p ?s))
|
||||
:effect (and
|
||||
(arm-holding ?a no-part)
|
||||
(not (arm-holding ?a ?p))
|
||||
(part-at ?p ?s)
|
||||
(not (pose-detected ?a ?p ?s)))
|
||||
)
|
||||
|
||||
(:action move
|
||||
:parameters (?a - arm ?from - workspace ?to - workspace)
|
||||
:precondition (and
|
||||
(arm-at ?a ?from)
|
||||
(arm-canreach ?a ?to)
|
||||
(arm-holding ?a no-part))
|
||||
:effect (and
|
||||
(arm-at ?a ?to)
|
||||
(not (arm-at ?a ?from)))
|
||||
)
|
||||
|
||||
(:action carry
|
||||
:parameters (?a - arm ?p - part ?from - workspace ?to - workspace)
|
||||
:precondition (and
|
||||
(arm-at ?a ?from)
|
||||
(arm-canreach ?a ?to)
|
||||
(arm-holding ?a ?p))
|
||||
:effect (and
|
||||
(arm-at ?a ?to)
|
||||
(not (arm-at ?a ?from)))
|
||||
)
|
||||
|
||||
(:action employ
|
||||
:parameters (?a - arm ?t - tool ?p - part ?s - workspace)
|
||||
:precondition (and
|
||||
(arm-at ?a ?s)
|
||||
(arm-active ?a ?t)
|
||||
(arm-holding ?a no-part)
|
||||
(part-at ?p ?s)
|
||||
(pose-detected ?a ?p ?s))
|
||||
:effect (and
|
||||
(part-state ?p ?t)
|
||||
(not (pose-detected ?a ?p ?s)))
|
||||
)
|
||||
)
|
|
@ -1,102 +0,0 @@
|
|||
;; Assembly domain in ADL (from the SGP distribution).
|
||||
|
||||
(define (domain assembly_soar)
|
||||
(:requirements :adl)
|
||||
(:types
|
||||
assembly
|
||||
resource
|
||||
) ;; individual parts are atomic assemblies
|
||||
(:predicates
|
||||
(available ?x - (either resource assembly))
|
||||
(complete ?a - assembly)
|
||||
(requires ?a - assembly ?r - resource)
|
||||
(committed ?r - resource ?a - assembly)
|
||||
(incorporated ?part ?whole - assembly)
|
||||
(part-of ?part ?whole - assembly)
|
||||
(to-be-removed ?part ?whole - assembly)
|
||||
(assemble-order ?part1 ?part2 ?whole - assembly)
|
||||
(transient-part ?part ?whole - assembly)
|
||||
;; after ?part1 is included, ?part2 must be removed
|
||||
;; for the ?whole to be complete:
|
||||
(remove-order ?part1 ?part2 ?whole - assembly))
|
||||
|
||||
(:action detect
|
||||
:parameters (?res - resource ?as - assembly)
|
||||
:precondition (available ?res)
|
||||
:effect (and (not (available ?res))
|
||||
(object-detected ?res ?as)))
|
||||
|
||||
(:action commit
|
||||
:parameters (?res - resource ?as - assembly)
|
||||
:precondition (available ?res)
|
||||
:effect (and (not (available ?res))
|
||||
(committed ?res ?as)))
|
||||
|
||||
(:action release
|
||||
:parameters (?res - resource ?as - assembly)
|
||||
:precondition (committed ?res ?as)
|
||||
:effect (and (not (committed ?res ?as))
|
||||
(available ?res)))
|
||||
|
||||
(:action assemble
|
||||
:parameters (?part ?whole - assembly)
|
||||
:precondition (and (forall (?res - resource)
|
||||
(imply (requires ?whole ?res)
|
||||
(committed ?res ?whole)))
|
||||
(or (part-of ?part ?whole)
|
||||
(transient-part ?part ?whole))
|
||||
(available ?part)
|
||||
(forall (?prev - assembly)
|
||||
(imply (assemble-order ?prev ?part ?whole)
|
||||
(incorporated ?prev ?whole))))
|
||||
:effect (and (incorporated ?part ?whole)
|
||||
(not (available ?part))
|
||||
(when (and (not (exists (?p - assembly)
|
||||
(and (part-of ?p ?whole)
|
||||
(not (= ?p ?part))
|
||||
(not (incorporated ?p ?whole)))))
|
||||
(not (exists (?tp - assembly)
|
||||
(and (transient-part ?tp ?whole)
|
||||
(incorporated ?tp ?whole)))))
|
||||
(and (complete ?whole)
|
||||
(available ?whole)))))
|
||||
|
||||
;; you can remove the last part added, or a cleanup part at the
|
||||
;; end.
|
||||
(:action remove
|
||||
:parameters (?part ?whole - assembly)
|
||||
:precondition (and (forall (?res - resource)
|
||||
(imply (requires ?whole ?res)
|
||||
(committed ?res ?whole)))
|
||||
(incorporated ?part ?whole)
|
||||
(or (and (transient-part ?part ?whole)
|
||||
(forall (?prev1 - assembly)
|
||||
(imply
|
||||
(remove-order ?prev1 ?part ?whole)
|
||||
(incorporated ?prev1 ?whole))))
|
||||
(and (part-of ?part ?whole)
|
||||
(not (exists (?prev2 - assembly)
|
||||
(and (assemble-order
|
||||
?prev2 ?part ?whole)
|
||||
(incorporated
|
||||
?prev2 ?whole)))))))
|
||||
:effect (and (not (incorporated ?part ?whole))
|
||||
(available ?part)
|
||||
(when (and (not (exists (?p - assembly)
|
||||
(and (part-of ?p ?whole)
|
||||
(not (incorporated ?p ?whole))
|
||||
)
|
||||
)
|
||||
)
|
||||
(not (exists (?tp - assembly)
|
||||
(and (transient-part ?tp ?whole)
|
||||
(not (= ?tp ?part))
|
||||
(incorporated ?tp ?whole))
|
||||
)
|
||||
)
|
||||
)
|
||||
(and (complete ?whole)
|
||||
(available ?whole))
|
||||
)
|
||||
))
|
||||
)
|
|
@ -1,27 +0,0 @@
|
|||
(define (problem p1) (:domain assembly_domain_hackaby)
|
||||
(:objects
|
||||
arm1 arm2 - arm
|
||||
gearbox - part
|
||||
part-bin workspace - workspace
|
||||
grip - tool )
|
||||
(:init
|
||||
(arm-canreach arm1 part-bin)
|
||||
(arm-canreach arm1 workspace)
|
||||
(arm-canreach arm2 part-bin)
|
||||
(arm-canreach arm2 workspace)
|
||||
(arm-at arm1 part-bin)
|
||||
(arm-at arm2 workspace)
|
||||
(arm-capabilities arm1 grip)
|
||||
(arm-capabilities arm1 detect)
|
||||
(arm-capabilities arm2 grip)
|
||||
(arm-capabilities arm2 detect)
|
||||
(arm-active arm1 grip)
|
||||
(arm-active arm2 grip)
|
||||
(arm-holding arm1 no-part)
|
||||
(arm-holding arm2 no-part)
|
||||
(part-at gearbox part-bin))
|
||||
(:goal
|
||||
(and (part-state gearbox glue)
|
||||
(part-state gearbox weld)
|
||||
(part-at gearbox assembly-line)))
|
||||
)
|
|
@ -1,39 +0,0 @@
|
|||
(define (problem assembly_problem_soar)
|
||||
(:domain assembly_soar)
|
||||
(:objects input_shaft_aSiduw19sd bracket whatsis sprocket doodad contraption
|
||||
wire gimcrack plug hoozawhatsie thingumbob coil fastener
|
||||
widget - assembly
|
||||
grip-tool1 grip-tool2 arm1 arm2 equipment - resource)
|
||||
(:init (available sprocket)
|
||||
(available doodad)
|
||||
(available contraption)
|
||||
(available wire)
|
||||
(available plug)
|
||||
(available hoozawhatsie)
|
||||
(available thingumbob)
|
||||
(available fastener)
|
||||
(available widget)
|
||||
(available charger)
|
||||
(available pliers)
|
||||
(requires bracket charger)
|
||||
(requires whatsis pliers)
|
||||
(requires gimcrack pliers)
|
||||
(requires coil pliers)
|
||||
(part-of bracket kludge)
|
||||
(part-of coil kludge)
|
||||
(part-of whatsis bracket)
|
||||
(part-of gimcrack bracket)
|
||||
(part-of sprocket whatsis)
|
||||
(part-of doodad whatsis)
|
||||
(part-of contraption whatsis)
|
||||
(part-of wire whatsis)
|
||||
(part-of plug gimcrack)
|
||||
(part-of hoozawhatsie gimcrack)
|
||||
(part-of thingumbob gimcrack)
|
||||
(part-of fastener coil)
|
||||
(part-of widget coil)
|
||||
(assemble-order bracket coil kludge)
|
||||
(assemble-order whatsis gimcrack bracket)
|
||||
(assemble-order wire contraption whatsis)
|
||||
(assemble-order plug thingumbob gimcrack))
|
||||
(:goal (complete kludge)))
|
|
@ -1,30 +0,0 @@
|
|||
;;!domain: assembly_soar
|
||||
;;!problem: assembly_problem_soar
|
||||
|
||||
0.00100: (commit charger bracket)
|
||||
0.00200: (commit pliers coil)
|
||||
0.00300: (assemble fastener coil) : SDF (fastener, coil) + + skill -> SDF (fastenercoil)
|
||||
(print bracket-1) - sdf model-gazebo: "bracket"
|
||||
(print bracket-2)
|
||||
0.00400: (assemble braket-1 bracket-2)
|
||||
0.00500: (release pliers coil)
|
||||
0.00600: (commit pliers gimcrack)
|
||||
0.00700: (assemble plug gimcrack)
|
||||
0.00800: (assemble thingumbob gimcrack)
|
||||
0.00900: (assemble hoozawhatsie gimcrack)
|
||||
0.01000: (release pliers gimcrack)
|
||||
0.01100: (commit pliers whatsis)
|
||||
0.01200: (assemble sprocket whatsis)
|
||||
0.01300: (assemble doodad whatsis)
|
||||
0.01400: (assemble wire whatsis)
|
||||
0.01500: (assemble contraption whatsis)
|
||||
0.01600: (assemble whatsis bracket)
|
||||
0.01700: (assemble gimcrack bracket)
|
||||
0.01800: (assemble bracket kludge)
|
||||
0.01900: (assemble coil kludge)
|
||||
|
||||
; Makespan: 0.019
|
||||
; Metric: 0.019
|
||||
|
||||
assemble_fastener_coil
|
||||
assemble_coil_kludge
|
|
@ -1,89 +0,0 @@
|
|||
---
|
||||
id: robossembler-framework
|
||||
title: Фреймворк Робосборщик
|
||||
---
|
||||
|
||||
Фреймворк Робосборщик (Robossembler) представляет собой комплекс открытого программного обеспечения и предназначен для автоматизации сборки произвольных изделий роботами-манипуляторами. Идея проекта родилась из попыток решить задачу автоматизации сборки и отсутствия необходимых для этого инструментов и наборов данных. Фреймворк призван решить эту проблему путём предоставления широкому кругу специалистов инструмента, позволяющего создавать адаптированные для виртуальных сред 3D-модели образцов промышленной продукции, генерировать технологические карты сборки в удобном для автоматического планирования формате, производить симуляцию, использовать её для получения синтетических наборов данных (датасетов) и адаптировать данные решения к реальным производственным процессам. Планируемый функционал фреймворка снизит порог требований к квалификации и позволит широкому кругу исследователей поучаствовать во внедрении технологий ИИ в промышленность.
|
||||
|
||||
Фреймворк состоит из двух основных частей:
|
||||
1. [Robossembler Framework](https://gitlab.com/robossembler/framework) (_Offline-часть_). Представляет собой комплекс ПО для предварительной подготовки моделей и робота к сборке.
|
||||
2. [Robossembler ROS2](https://gitlab.com/robossembler/robossembler-ros2) (_Online-часть_). Представляет собой комплекс ПО для исполнения на роботизированной установке в режиме реального времени. Используется ROS2 и основанные на нём фреймворки планирования движений MoveIt и задач PlanSys.
|
||||
|
||||
Для работы с обоими частями разработан специализированный [веб-сервис](software/webservice), который позволяет работать как с Offline, так и с Online-частами фреймворка.
|
||||
|
||||
## Актуальность и востребованность
|
||||
|
||||
Многие, производственные предприятия не рассматривают применение роботов. Это происходит не столько по причине высокой стоимости самих роботов, сколько из-за высокой стоимости их программирования, внедрения и эксплуатации, которые, по данным проекта [SMERobotics](/docs/papers/smerobotics), составляют около 63% от общего количество затрат на внедрение. При отсутствии широкого рынка сбыта высокие начальные затраты делают роботизацию нерентабельной для малого и среднего бизнеса.
|
||||
|
||||
Внедрению робототехники препятствует и сложность самих задач. Например, автоматизация сборки изделий требует компетенций в таких предметных областях как:
|
||||
- Генерация последовательности сборки (assembly sequence generation)
|
||||
- Распознавание объектов и их позиций (CV & AI)
|
||||
- Координация роботов между собой (multi-robot manipulation)
|
||||
- Планирование сборочных операций (task planning, general planning, AI planning)
|
||||
- Сборка изделий манипуляторами (manipulation for assembly)
|
||||
- Планирование движений (motion planning).
|
||||
|
||||
По каждому из этих направлений в научной литературе можно найти десятки разнообразных методов и алгоритмов, различное сочетание которых порождает бесконечное количество комбинаций для решения конкретных задач. R&D-компаний, которые могут предложить такой комплекс услуг и компетенций очень немного и стоимость их услуг может быть слишком высокой для отдельно взятого производственного предприятия.
|
||||
|
||||
## Способы решения
|
||||
|
||||
Виртуализация. Фреймворк позволит существенно сократить затраты на внедрение за счёт отладки программы преимущественно в виртуальной среде на базе открытого ПО. Он даст дизайнерам и разработчикам изделий возможность адаптировать их для автоматического производства ещё на этапе эскизного проектирования и облегчить наиболее трудоёмкий, долгий и дорогостоящий этап в жизненном цикле изделия - постановку на производство.
|
||||
|
||||
Декомпозиция. Сложная задача сборки изделия декомпозируется на множество небольших. Созданные из примитивов программы в виде _Деревьев Поведения (Behaviour Tree)_ могут быть переиспользованы для написания других подпрограмм (переиспользование конечных автоматов сложнее). Также это даёт гибкость - можно заменять как подпрограммы для отдельных навыков, так и программы, реализующие сложное поведение целиком. Это позволит предприятиям избежать контрактов с поставщиками сложных решений по типу "чёрный ящик". Для этого предлагается сформировать среду(информационную сеть), где можно было бы решать сложные робототехнические задачи децентрализовано - с помощью как физических, так и юридических лиц, специализирующихся на отдельных областях знаний, обмениваясь информационными артефактами (ассетами) своей работы внутри сети.
|
||||
|
||||
Применение фреймворка в научных исследованиях для проверки новых алгоритмов генерации последовательности сборки и машинного обучения сократит дистанцию между академическим сообществом и прикладным коммерческим производством.
|
||||
|
||||
## Новизна предлагаемых в инновационном проекте решений
|
||||
|
||||
- На данный момент в мире не существует открытой библиотеки для планирования последовательности сборки (assembly sequence planner, ASP), в которой были бы доступны разные алгоритмы вычислений. Первая новизна состоит в том, чтобы разработать данную библиотеку, сделать её удобной в использовании и интегрировать в системы управления роботами.
|
||||
- Вторая новизна предлагаемого решения заключается в интеграции открытых стандартов и программных компонентов для решения сложной прикладной задачи, что может ускорить внедрение передовых исследований ИИ в актуальную производственную практику. Как правило, объектами исследований учёных становятся отдельные области - _генерация графа сборки, планирование движений, управление задачами, методы контроля, sim2real-трансфер, машинное обучение_. Однако для решения прикладных задач необходимо наличие и слаженное взаимодействие всех указанных методов, поэтому их интеграция в рамках фреймворка сделает доступным применение на производстве результатов новейших исследований.
|
||||
- Третьей новизной является специальный модуль переключения сред восприятия в [реально-виртуальном континууме](https://en.wikipedia.org/wiki/Reality%E2%80%93virtuality_continuum). Возможность управлять уровнями восприятия сделает удобным постепенную адаптацию управляющих программ к физическому миру с возможностью доучиться в виртуальных и смешанных средах. Например, робот, прежде чем приступить к выполнению задачи в реальном мире, может внутри себя переключить уровень восприятия на один из двух виртуальных и отладить работу там. При этом сама управляющая программа работает одна и та же - она просто меняет поставщика данных о состоянии среды. Это существенно упрощает перенос ПО из виртуальных сред в реальность.
|
||||
|
||||
## Способы и методы решения поставленных задач
|
||||
|
||||
- Для извлечения информации о геометрии объекта будет использоваться API геометрического ядра OpenCascade или его обёрток (CadQuery, FreeCAD).
|
||||
- Для разработки GUI (настройки экспорта моделей, привязка материалов, разметка геометрических моделей, позиций захвата, порядка сборки) будет использоваться интерфейс системы проектирования FreeCAD.
|
||||
- Для генерации последовательности сборки предлагается разработать обобщённый API на языке высокого уровня и включить туда, как минимум, два алгоритма - основанного на информации из CAD и без неё. Также разработать инструкции по включению туда новых алгоритмов.
|
||||
- Для обмена моделями или пакетами между разнородными системами предлагается использовать пакетный менеджер общего назначения nix или подобный ему, предлагающий декларативный способ задания алгоритма сборки и кеширование уже собранных пакетов, что существенно снизит затраты вычислительных мощностей на генерацию сцен.
|
||||
- Для адаптации моделей к рендерингу и высокопроизводительной симуляции предлагается использовать Python API системы трёх-мерного моделирования Blender.
|
||||
- Для обеспечения версионирования моделей, запуска процедуры сборки и контроля за её исполнением предлагается использовать самую распространённую в мире систему контроля версий git и систему непрерывной интеграции gitlab-ci.
|
||||
- Система управления роботом и запуска алгоритмов исполнения заданий на базе фреймворков: общего назначения ROS2, планирования движений MoveIt2, планирования задач Plansys2.
|
||||
|
||||
## Порядок работы фреймворка
|
||||
|
||||
- Автор изделия публикует CAD-модель с метаданными деталей и их свойств в системе контроля версий (STEP)
|
||||
- Производство публикует описание своей автоматизированной производственной инфраструктуры (Scene format - SDF, USD, MJCF)
|
||||
- Специалисты по генерации последовательности сборки формируют граф сборки на базе информации из CAD модели
|
||||
- Специалисты по планированию (AI Planning) на базе модели производства и графа сборки могут подобрать оптимальный план сборки (PDDL plan или Behaviour Tree)
|
||||
- Специалист-робототехник декомпозирует задачи из плана на конкретные навыки (skills - detect/pose_estimate/move/align/grasp), формирует запрос на решающие эти задачи и отсутствующие у него подпрограммы (подпрограммы - узлы Дерева Поведения)
|
||||
- Специалисты по multi-robot, assembly/motion planning и CV формируют предложение по каждой конкретной операции - робот получает недостающие подпрограммы и производит тестирование сборки, давая обратную связь разработчикам, чтобы те скорректировали подпрограммы, созданные в симуляции.
|
||||
|
||||
## Аналоги
|
||||
|
||||
[ConnTact](https://github.com/swri-robotics/ConnTact). Создан при поддержке Национального института стандартов и технологий США (NIST). Этому фреймворку присущи следующие недостатки:
|
||||
- Акцент на контактных операциях, что существенно ограничивает спектр его применения для прикладных задач
|
||||
- Поддерживаются только роботы с датчиками силы, нет других источников обратной связи в роботизированной системе
|
||||
- Не имеет инструментов интеграции с CAD-системами и системами планирования. Последовательность сборки задаётся вручную
|
||||
- Не поддерживает ROS2
|
||||
- Не поддерживает алгоритмы машинного обучения.
|
||||
|
||||
__AutoAssembly__. Разрабатывается командой робототехников из компании Arrival, известного производителя электромобилей с R&D командой из Санкт-Петербурга. Фреймворк предназначен для автоматической роботизированной сборки напрямую из CAD. В научной публикации с описанием фреймворка представлена практическая реализация на примере двух манипуляторов Universal Robotics. Исходный код проекта не публикуется; многие технические решения (спецификации, схемы данных, описания языков, тип базы данных) неизвестны. Более подробный обзор см. по [ссылке](/docs/papers/auto-assembly).
|
||||
|
||||
## Минимальные технические требования
|
||||
|
||||
Минимальные системные требования для запуска модуля исполнения планов:
|
||||
|
||||
1. **Важно!** Совместимо только с операционной системой Ubuntu 22.04.
|
||||
2. Процессор: 64-разрядный процессор с поддержкой SSE4.2 (например, Intel Core i3 или AMD Ryzen 3).
|
||||
3. Оперативная память: не менее 8 ГБ RAM.
|
||||
4. Свободное место на диске: не менее 50 ГБ свободного места на диске.
|
||||
5. Графический процессор: не требуется, но рекомендуется для визуализации и симуляции; для ускорения инференса моделей весов искусственных нейронных сетей может быть использован графический ускоритель.
|
||||
6. ROS 2 версия: Humble.
|
||||
|
||||
Минимальные системные требования для запуска остальных модулей:
|
||||
|
||||
1. Операционная система: Ubuntu 18.04 (Bionic Beaver) или более новая версия, либо Windows 10 или более новая версия.
|
||||
2. Процессор: 64-разрядный процессор с поддержкой SSE4.2 (например, Intel Core i5 или AMD Ryzen 5).
|
||||
3. Оперативная память: не менее 16 ГБ RAM.
|
||||
4. Свободное место на диске: не менее 150 ГБ свободного места на диске.
|
||||
5. Графический процессор: NVIDIA GeForce RTX 2060 Super с поддержкой CUDA 10.0 или более новой версии.
|
|
@ -10,43 +10,43 @@ slug: /
|
|||
Роботы-манипуляторы Robossembler со сменными инструментами покрывают большой класс производственных задач. Они проектируются для автономной сборки и эксплуатации, поэтому к ним не предъявляются характерные для коллаборативных роботов требования безопасности, эстетичности и быстродействия.
|
||||
|
||||
В проекте разрабатываются два варианта исполнения манипулятора:
|
||||
- [Манипулятор](https://gitlab.com/robossembler/roboarm) с 6-ю степенями свободы для изготовления с помощью литья в [прессформе](https://gitlab.com/robossembler/cnc/roboarm-link-mold). Звено данного манипулятора состоит из двух оригинальных [сервоприводов](https://gitlab.com/robossembler/servo) и производится методом заливки компаундом, перестановкой оснастки на позицию будущего звена и дальнейшей закладкой приводов и кабелей. Данное технологические решение позволяет избавиться от крепёжных, кабельных и ременных соединений, а также необходимости отдельно производить корпус. Материал компаунда подбирается таким образом, чтобы обеспечить оптимальный теплоотвод, дешевизну, удобную утилизацию и повторную переработку компонентов манипулятора. Типы компаунда могут варьироваться в зависимости от нагрузок на конкретные разновидности звеньев.
|
||||
- [Манипулятор](https://gitlab.com/robossembler/roboarm-diy-version) с 6-ю степенями свободы для изготовления с помощью 3D-печати. Все детали манипулятора, кроме электрических плат, проводов и катушек индуктивности, изготавливаются с помощью технологии трёхмерной печати, но могут и отливаться в прессформах. Конструкция манипулятора адаптирована для автономной автоматической сборки.
|
||||
- [Манипулятор](https://gitlab.com/robosphere/roboarm) с 6-ю степенями свободы для изготовления с помощью литья в [прессформе](https://gitlab.com/robosphere/cnc/roboarm-link-mold). Звено данного манипулятора состоит из двух оригинальных [сервоприводов](https://gitlab.com/robosphere/servo) и производится методом заливки компаундом, перестановкой оснастки на позицию будущего звена и дальнейшей закладкой приводов и кабелей. Данное технологические решение позволяет избавиться от крепёжных, кабельных и ременных соединений, а также необходимости отдельно производить корпус. Материал компаунда подбирается таким образом, чтобы обеспечить оптимальный теплоотвод, дешевизну, удобную утилизацию и повторную переработку компонентов манипулятора. Типы компаунда могут варьироваться в зависимости от нагрузок на конкретные разновидности звеньев.
|
||||
- [Манипулятор](https://gitlab.com/robosphere/roboarm-diy-version) с 6-ю степенями свободы для изготовления с помощью 3D-печати. Все детали манипулятора, кроме электрических плат, проводов и катушек индуктивности, изготавливаются с помощью технологии трёхмерной печати, но могут и отливаться в прессформах. Конструкция манипулятора адаптирована для автономной автоматической сборки.
|
||||
|
||||
### Приспособления для манипуляторов
|
||||
Все приспособления монтируются к манипулятору через [стыковочный интерфейс](https://gitlab.com/robossembler/arm-tools/connection-tool). Для смены и хранения двух и более приспособлений используется [Библиотека приспособлений](https://gitlab.com/robossembler/arm-tools/tools-library), к которой в дальнейшем будут присоединяться узлы подачи материалов.
|
||||
Все приспособления монтируются к манипулятору через [стыковочный интерфейс](https://gitlab.com/robosphere/arm-tools/connection-tool). Для смены и хранения двух и более приспособлений используется [Библиотека приспособлений](https://gitlab.com/robosphere/arm-tools/tools-library), к которой в дальнейшем будут присоединяться узлы подачи материалов.
|
||||
|
||||
Полный перечень приспособлений
|
||||
- [Механический захват](https://gitlab.com/robossembler/arm-tools/grip-tool)
|
||||
- [3D-печать](https://gitlab.com/robossembler/arm-tools/3d-print-tool)
|
||||
- [Подача компаунда](https://gitlab.com/robossembler/arm-tools/extrude-melt-tool)
|
||||
- [Пайка](https://gitlab.com/robossembler/arm-tools/soldering-tool) с [картриджем](https://gitlab.com/robossembler/arm-tools/solder-cartridge)
|
||||
- [Сварка](https://gitlab.com/robossembler/arm-tools/welding-tool)
|
||||
- [Фрезерная и пост-обработка](https://gitlab.com/robossembler/arm-tools/post-processing-tool)
|
||||
- [Сканирование и съёмка](https://gitlab.com/robossembler/arm-tools/scan-tool)
|
||||
- [Механический захват](https://gitlab.com/robosphere/arm-tools/grip-tool)
|
||||
- [3D-печать](https://gitlab.com/robosphere/arm-tools/3d-print-tool)
|
||||
- [Подача компаунда](https://gitlab.com/robosphere/arm-tools/extrude-melt-tool)
|
||||
- [Пайка](https://gitlab.com/robosphere/arm-tools/soldering-tool) с [картриджем](https://gitlab.com/robosphere/arm-tools/solder-cartridge)
|
||||
- [Сварка](https://gitlab.com/robosphere/arm-tools/welding-tool)
|
||||
- [Фрезерная и пост-обработка](https://gitlab.com/robosphere/arm-tools/post-processing-tool)
|
||||
- [Сканирование и съёмка](https://gitlab.com/robosphere/arm-tools/scan-tool)
|
||||
|
||||
Рабочий стол и подключённые к нему манипуляторы с приспособлениями формируют Автоматизированное рабочее место (АРМ), которое может быть объединено с другими рабочими местами, формируя сложные производственные комплексы. Конфигурация конкретного АРМ формируется исходя из требований к производственному процессу.
|
||||
|
||||
### Оборудование для формирования модульных рабочих пространств
|
||||
- [Шестигранные рабочие столы](https://gitlab.com/robossembler/cnc/roboarm-workspace). Роботы-манипуляторы оснащаются рабочими столами - местами, где будет осуществляться сборка и другие технологические операции. Рабочий стол имеет форму пчелиной соты и содержит в себе вычислительный узел для управления рабочим местом. Столы предполагают:
|
||||
- [Шестигранные рабочие столы](https://gitlab.com/robosphere/cnc/roboarm-workspace). Роботы-манипуляторы оснащаются рабочими столами - местами, где будет осуществляться сборка и другие технологические операции. Рабочий стол имеет форму пчелиной соты и содержит в себе вычислительный узел для управления рабочим местом. Столы предполагают:
|
||||
- Легкое подключение к ним манипуляторов с помощью специальных надёжных электрических разъемов
|
||||
- Электропитание и управление - рабочий стол будет включать в себя систему управления для всех подключаемых к нему манипуляторов
|
||||
- Подключение к себе других рабочих столов для создания связанной локальной сети и производственной линии
|
||||
- Подключение к рабочим столам [транспортных модулей](https://gitlab.com/robossembler/transport-module) для превращения их в передвижные платформы.
|
||||
- [Модульный каркас для роботизированных ячеек](https://gitlab.com/robossembler/cnc/cubic-modular-workspace). Состоит из компонентов двух типов:
|
||||
- Подключение к рабочим столам [транспортных модулей](https://gitlab.com/robosphere/transport-module) для превращения их в передвижные платформы.
|
||||
- [Модульный каркас для роботизированных ячеек](https://gitlab.com/robosphere/cnc/cubic-modular-workspace). Состоит из компонентов двух типов:
|
||||
- *Пластины* служат стыковочным интерфейсом для подключения роботов манипуляторов и их приспособлений. Также в них могут размещаться компоненты встраиваемой электроники для управления подключаемым оборудованием.
|
||||
- *Стойки* обеспечивают электрическое соединение между пластинами для передачи электронергии и управляющих сигналов. Модульная архитектура каркаса позволяет собирать разноообразные роботизированные ячейки под нужды технологического процесса и объединять их в производственные линии.
|
||||
|
||||
## Программные компоненты
|
||||
Все программные компоненты в совокупности составляют собой *фреймворк* для симуляции и отладки алгоритмов сборки сложных многосоставных изделий манипуляторами.
|
||||
|
||||
- [ARBench](https://gitlab.com/robossembler/forks/ARBench) - плагин для *FreeCAD*. Основные функции:
|
||||
- [ARBench](https://gitlab.com/robosphere/forks/ARBench) - плагин для *FreeCAD*. Основные функции:
|
||||
- разметка CAD моделей изделий - геометрические фреймы, позиции захвата, материалы
|
||||
- парсинг моделей сборок CAD и представление их в виде моделей отдельных деталей и мета-информации об их взаимном расположении (матрица смежности или подобное представление)
|
||||
- преобразование моделей в последовательность сборки (*Assembly Sequence, AS*) с помощью *Assembly Sequence Planner*
|
||||
- формирование спецификации задачи в формате *Planning Domain Definition Language (PDDL)*
|
||||
- экспорт деталей и подсборок в виде пакетов формата *Simulation Description Format (SDF)* для загрузки в симулятор *Gazebo*
|
||||
* [Robossembler](https://gitlab.com/robossembler/robossembler-ros2) - набор пакетов для *ROS2*. Основные функции:
|
||||
* [Robossembler](https://gitlab.com/robosphere/robossembler-ros2) - набор пакетов для *ROS2*. Основные функции:
|
||||
- отслеживание событий в блокчейне *Robonomics* с помощью python-библиотеки *robonomics-interface*
|
||||
- загрузка данных из сети IPFS с помощью python-библиотеки *ipfshttpclient*
|
||||
- формирование плана исполнения (*Task Plan, TP*) в соответствии со спецификациями предметной области (*domain*) и задачи (*problem*) на языке PDDL
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
# Презентация "Nix/NixOS - ОС-независимая сборка пакетов ROS" на ROS-Meetup'2023
|
||||
|
||||
Для просмотра скопируйте содержимое директории и откройте `ros-meetup-slides.html` в любом браузере.
|
Before Width: | Height: | Size: 99 KiB |
Before Width: | Height: | Size: 4.4 KiB |
|
@ -1,751 +0,0 @@
|
|||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1140" height="800">
|
||||
<defs>
|
||||
<marker id="arrow" markerWidth="10" markerHeight="10" refX="2" refY="3" orient="auto" markerUnits="strokeWidth">
|
||||
<path d="M0,0 L2,3 L0,6 L9,3 z" fill="#000" />
|
||||
</marker>
|
||||
</defs>
|
||||
<rect width="1140" height="800" fill="#f0f0f0" />
|
||||
<line x1="40.5" x2="40.5" y1="780.5" y2="15.5" stroke="#000" marker-end="url(#arrow)" />
|
||||
<line x1="40.5" x2="1115.5" y1="780.5" y2="780.5" stroke="#000" marker-end="url(#arrow)" />
|
||||
<g fill="#000" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="13" font-weight="bold">
|
||||
<text x="565.5" y="793.5" text-anchor="middle">Number of packages in repository</text>
|
||||
|
||||
<text x="0" y="0" text-anchor="middle" transform="translate(20.5, 405.5),rotate(-90)">Number of fresh packages in repository</text>
|
||||
</g>
|
||||
<g fill="#000" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
||||
<text x="1093.5" y="793.5" text-anchor="middle">44000</text>
|
||||
<text x="40.5" y="790.5" text-anchor="middle">0</text>
|
||||
|
||||
<text x="35.5" y="783.5" text-anchor="end">0</text>
|
||||
<text x="35.5" y="33.5" text-anchor="end">30000</text>
|
||||
</g>
|
||||
|
||||
|
||||
<g font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11" text-anchor="start">
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="650.5" y="410.5">DPorts</text>
|
||||
<text fill="#000000" x="650.5" y="410.5">DPorts</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="51.5" y="781.5">MX Linux MX-17</text>
|
||||
<text fill="#000000" x="51.5" y="781.5">MX Linux MX-17</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="61.5" y="773.5">LEDE trunk AArch64 generic</text>
|
||||
<text fill="#000000" x="61.5" y="773.5">LEDE trunk AArch64 generic</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="53.5" y="778.5">RPM Fusion Fedora 27</text>
|
||||
<text fill="#000000" x="53.5" y="778.5">RPM Fusion Fedora 27</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="45.5" y="782.5">PlayDeb Yakkety Testing</text>
|
||||
<text fill="#000000" x="45.5" y="782.5">PlayDeb Yakkety Testing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="45.5" y="782.5">GetDeb Zesty Testing</text>
|
||||
<text fill="#000000" x="45.5" y="782.5">GetDeb Zesty Testing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="59.5" y="779.5">MX Linux MX-15 Testing</text>
|
||||
<text fill="#000000" x="59.5" y="779.5">MX Linux MX-15 Testing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="47.5" y="781.5">RPM Fusion EL 7</text>
|
||||
<text fill="#000000" x="47.5" y="781.5">RPM Fusion EL 7</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="151.5" y="699.5">Linuxbrew</text>
|
||||
<text fill="#000000" x="151.5" y="699.5">Linuxbrew</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="104.5" y="729.5">Stackage LTS Haskell</text>
|
||||
<text fill="#000000" x="104.5" y="729.5">Stackage LTS Haskell</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="51.5" y="779.5">Libregamewiki</text>
|
||||
<text fill="#000000" x="51.5" y="779.5">Libregamewiki</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="205.5" y="698.5">GNU Guix</text>
|
||||
<text fill="#000000" x="205.5" y="698.5">GNU Guix</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="76.5" y="762.5">CRUX 3.3</text>
|
||||
<text fill="#000000" x="76.5" y="762.5">CRUX 3.3</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="643.5" y="614.5">Ubuntu 16.04</text>
|
||||
<text fill="#000000" x="643.5" y="614.5">Ubuntu 16.04</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="60.5" y="773.5">openSUSE Games Tumbleweed</text>
|
||||
<text fill="#000000" x="60.5" y="773.5">openSUSE Games Tumbleweed</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="502.5" y="597.5">Funtoo</text>
|
||||
<text fill="#000000" x="502.5" y="597.5">Funtoo</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="715.5" y="558.5">Raspbian Stable</text>
|
||||
<text fill="#000000" x="715.5" y="558.5">Raspbian Stable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="48.5" y="780.5">Arch Testing</text>
|
||||
<text fill="#000000" x="48.5" y="780.5">Arch Testing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="48.5" y="782.5">Sabayon</text>
|
||||
<text fill="#000000" x="48.5" y="782.5">Sabayon</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="540.5" y="655.5">Debian Oldstable</text>
|
||||
<text fill="#000000" x="540.5" y="655.5">Debian Oldstable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="345.5" y="468.5">CRAN</text>
|
||||
<text fill="#000000" x="345.5" y="468.5">CRAN</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="78.5" y="770.5">CRUX 3.2</text>
|
||||
<text fill="#000000" x="78.5" y="770.5">CRUX 3.2</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="60.5" y="781.5">SteamOS alchemist</text>
|
||||
<text fill="#000000" x="60.5" y="781.5">SteamOS alchemist</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="67.5" y="774.5">Debian Stable Backports</text>
|
||||
<text fill="#000000" x="67.5" y="774.5">Debian Stable Backports</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="61.5" y="771.5">Scoop</text>
|
||||
<text fill="#000000" x="61.5" y="771.5">Scoop</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="46.5" y="782.5">Trisquel 8.0 backports</text>
|
||||
<text fill="#000000" x="46.5" y="782.5">Trisquel 8.0 backports</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="57.5" y="782.5">KDE neon Dev Unstable</text>
|
||||
<text fill="#000000" x="57.5" y="782.5">KDE neon Dev Unstable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="49.5" y="780.5">UnitedRPMs Fedora 25</text>
|
||||
<text fill="#000000" x="49.5" y="780.5">UnitedRPMs Fedora 25</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="552.5" y="664.5">Trisquel 7.0</text>
|
||||
<text fill="#000000" x="552.5" y="664.5">Trisquel 7.0</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="644.5" y="578.5">Pardus</text>
|
||||
<text fill="#000000" x="644.5" y="578.5">Pardus</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="61.5" y="773.5">LEDE trunk ARM XScale</text>
|
||||
<text fill="#000000" x="61.5" y="773.5">LEDE trunk ARM XScale</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="296.5" y="632.5">openSUSE Tumbleweed</text>
|
||||
<text fill="#000000" x="296.5" y="632.5">openSUSE Tumbleweed</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="55.5" y="782.5">Linux Mint 17.2</text>
|
||||
<text fill="#000000" x="55.5" y="782.5">Linux Mint 17.2</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="45.5" y="782.5">Tails stable</text>
|
||||
<text fill="#000000" x="45.5" y="782.5">Tails stable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="53.5" y="779.5">RPM Fusion Fedora 25</text>
|
||||
<text fill="#000000" x="53.5" y="779.5">RPM Fusion Fedora 25</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="140.5" y="753.5">Astra Linux Orel</text>
|
||||
<text fill="#000000" x="140.5" y="753.5">Astra Linux Orel</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="56.5" y="780.5">MX Linux MX-15</text>
|
||||
<text fill="#000000" x="56.5" y="780.5">MX Linux MX-15</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="45.5" y="782.5">GetDeb Yakkety Testing</text>
|
||||
<text fill="#000000" x="45.5" y="782.5">GetDeb Yakkety Testing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="87.5" y="756.5">KaOS</text>
|
||||
<text fill="#000000" x="87.5" y="756.5">KaOS</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="89.5" y="762.5">HaikuPorts master</text>
|
||||
<text fill="#000000" x="89.5" y="762.5">HaikuPorts master</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="699.5" y="438.5">Kali Linux Rolling</text>
|
||||
<text fill="#000000" x="699.5" y="438.5">Kali Linux Rolling</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="93.5" y="776.5">Debian Oldstable Backports</text>
|
||||
<text fill="#000000" x="93.5" y="776.5">Debian Oldstable Backports</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="61.5" y="773.5">LEDE trunk ARM Cortex A9 VFPv3</text>
|
||||
<text fill="#000000" x="61.5" y="773.5">LEDE trunk ARM Cortex A9 VFPv3</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="46.5" y="782.5">Ubuntu 18.04 Proposed</text>
|
||||
<text fill="#000000" x="46.5" y="782.5">Ubuntu 18.04 Proposed</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="382.5" y="612.5">pkgsrc current</text>
|
||||
<text fill="#000000" x="382.5" y="612.5">pkgsrc current</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="60.5" y="779.5">LEDE 17.01 x86_64</text>
|
||||
<text fill="#000000" x="60.5" y="779.5">LEDE 17.01 x86_64</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="560.5" y="663.5">Ubuntu 14.04</text>
|
||||
<text fill="#000000" x="560.5" y="663.5">Ubuntu 14.04</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="49.5" y="782.5">Linux Mint 18.2</text>
|
||||
<text fill="#000000" x="49.5" y="782.5">Linux Mint 18.2</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="681.5" y="445.5">PureOS landing</text>
|
||||
<text fill="#000000" x="681.5" y="445.5">PureOS landing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="732.5" y="544.5">Deepin</text>
|
||||
<text fill="#000000" x="732.5" y="544.5">Deepin</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="185.5" y="683.5">OpenMandriva Cooker</text>
|
||||
<text fill="#000000" x="185.5" y="683.5">OpenMandriva Cooker</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="46.5" y="782.5">Rudix</text>
|
||||
<text fill="#000000" x="46.5" y="782.5">Rudix</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="53.5" y="777.5">Deb Multimedia Unstable</text>
|
||||
<text fill="#000000" x="53.5" y="777.5">Deb Multimedia Unstable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="962.5" y="147.5">nixpkgs stable</text>
|
||||
<text fill="#000000" x="962.5" y="147.5">nixpkgs stable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="689.5" y="443.5">Debian Testing</text>
|
||||
<text fill="#000000" x="689.5" y="443.5">Debian Testing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="535.5" y="523.5">Fedora 27</text>
|
||||
<text fill="#000000" x="535.5" y="523.5">Fedora 27</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="254.5" y="627.5">Manjaro Unstable</text>
|
||||
<text fill="#000000" x="254.5" y="627.5">Manjaro Unstable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="106.5" y="721.5">RubyGems</text>
|
||||
<text fill="#000000" x="106.5" y="721.5">RubyGems</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="485.5" y="605.5">Rosa 2016.1</text>
|
||||
<text fill="#000000" x="485.5" y="605.5">Rosa 2016.1</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="45.5" y="782.5">Tails devel</text>
|
||||
<text fill="#000000" x="45.5" y="782.5">Tails devel</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="55.5" y="782.5">Linux Mint 17.3</text>
|
||||
<text fill="#000000" x="55.5" y="782.5">Linux Mint 17.3</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="61.5" y="773.5">LEDE trunk x86_64</text>
|
||||
<text fill="#000000" x="61.5" y="773.5">LEDE trunk x86_64</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="540.5" y="655.5">Devuan Stable</text>
|
||||
<text fill="#000000" x="540.5" y="655.5">Devuan Stable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="60.5" y="778.5">OpenWrt trunk x86</text>
|
||||
<text fill="#000000" x="60.5" y="778.5">OpenWrt trunk x86</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="58.5" y="780.5">HaikuPorts release</text>
|
||||
<text fill="#000000" x="58.5" y="780.5">HaikuPorts release</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="46.5" y="782.5">PlayDeb Xenial Testing</text>
|
||||
<text fill="#000000" x="46.5" y="782.5">PlayDeb Xenial Testing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="379.5" y="632.5">pkgsrc-2018Q1</text>
|
||||
<text fill="#000000" x="379.5" y="632.5">pkgsrc-2018Q1</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="728.5" y="478.5">Ubuntu 18.04</text>
|
||||
<text fill="#000000" x="728.5" y="478.5">Ubuntu 18.04</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="254.5" y="637.5">Manjaro Testing</text>
|
||||
<text fill="#000000" x="254.5" y="637.5">Manjaro Testing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="369.5" y="663.5">pkgsrc-2017Q2</text>
|
||||
<text fill="#000000" x="369.5" y="663.5">pkgsrc-2017Q2</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="49.5" y="781.5">UnitedRPMs Fedora 24</text>
|
||||
<text fill="#000000" x="49.5" y="781.5">UnitedRPMs Fedora 24</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="48.5" y="782.5">antiX-16</text>
|
||||
<text fill="#000000" x="48.5" y="782.5">antiX-16</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="50.5" y="781.5">Sparky</text>
|
||||
<text fill="#000000" x="50.5" y="781.5">Sparky</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="59.5" y="777.5">Vcpkg</text>
|
||||
<text fill="#000000" x="59.5" y="777.5">Vcpkg</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="320.5" y="668.5">MacPorts</text>
|
||||
<text fill="#000000" x="320.5" y="668.5">MacPorts</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="52.5" y="780.5">MX Linux MX-17 Testing</text>
|
||||
<text fill="#000000" x="52.5" y="780.5">MX Linux MX-17 Testing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="56.5" y="776.5">KDE neon User LTS</text>
|
||||
<text fill="#000000" x="56.5" y="776.5">KDE neon User LTS</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="1086.5" y="523.5">AUR</text>
|
||||
<text fill="#000000" x="1086.5" y="523.5">AUR</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="74.5" y="781.5">Maemo Fremantle</text>
|
||||
<text fill="#000000" x="74.5" y="781.5">Maemo Fremantle</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="205.5" y="729.5">EPEL 7</text>
|
||||
<text fill="#000000" x="205.5" y="729.5">EPEL 7</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="45.5" y="782.5">Parabola Testing</text>
|
||||
<text fill="#000000" x="45.5" y="782.5">Parabola Testing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="53.5" y="774.5">crates.io</text>
|
||||
<text fill="#000000" x="53.5" y="774.5">crates.io</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="471.5" y="697.5">Trisquel 6.0</text>
|
||||
<text fill="#000000" x="471.5" y="697.5">Trisquel 6.0</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="67.5" y="779.5">SteamOS brewmaster beta</text>
|
||||
<text fill="#000000" x="67.5" y="779.5">SteamOS brewmaster beta</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="49.5" y="782.5">Linux Mint 18.3</text>
|
||||
<text fill="#000000" x="49.5" y="782.5">Linux Mint 18.3</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="45.5" y="782.5">F-Droid</text>
|
||||
<text fill="#000000" x="45.5" y="782.5">F-Droid</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="254.5" y="637.5">Manjaro Stable</text>
|
||||
<text fill="#000000" x="254.5" y="637.5">Manjaro Stable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="48.5" y="782.5">Trisquel 7.0 backports</text>
|
||||
<text fill="#000000" x="48.5" y="782.5">Trisquel 7.0 backports</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="223.5" y="718.5">Hyperbola</text>
|
||||
<text fill="#000000" x="223.5" y="718.5">Hyperbola</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="47.5" y="782.5">Calculate</text>
|
||||
<text fill="#000000" x="47.5" y="782.5">Calculate</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="58.5" y="777.5">Debian Experimental</text>
|
||||
<text fill="#000000" x="58.5" y="777.5">Debian Experimental</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="61.5" y="773.5">Entware</text>
|
||||
<text fill="#000000" x="61.5" y="773.5">Entware</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="787.5" y="413.5">Raspbian Testing</text>
|
||||
<text fill="#000000" x="787.5" y="413.5">Raspbian Testing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="154.5" y="726.5">AOSC</text>
|
||||
<text fill="#000000" x="154.5" y="726.5">AOSC</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="49.5" y="780.5">UnitedRPMs Fedora 26</text>
|
||||
<text fill="#000000" x="49.5" y="780.5">UnitedRPMs Fedora 26</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="365.5" y="668.5">pkgsrc-2017Q1</text>
|
||||
<text fill="#000000" x="365.5" y="668.5">pkgsrc-2017Q1</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="48.5" y="782.5">Linux Mint 17</text>
|
||||
<text fill="#000000" x="48.5" y="782.5">Linux Mint 17</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="59.5" y="775.5">Gentoo overlay Pentoo</text>
|
||||
<text fill="#000000" x="59.5" y="775.5">Gentoo overlay Pentoo</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="96.5" y="772.5">CentOS 6</text>
|
||||
<text fill="#000000" x="96.5" y="772.5">CentOS 6</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="153.5" y="713.5">Alpine Linux Edge</text>
|
||||
<text fill="#000000" x="153.5" y="713.5">Alpine Linux Edge</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="716.5" y="441.5">Parrot</text>
|
||||
<text fill="#000000" x="716.5" y="441.5">Parrot</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="49.5" y="781.5">Sabayon for-gentoo</text>
|
||||
<text fill="#000000" x="49.5" y="781.5">Sabayon for-gentoo</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="49.5" y="781.5">Antergos Main</text>
|
||||
<text fill="#000000" x="49.5" y="781.5">Antergos Main</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="50.5" y="777.5">DistroWatch.com</text>
|
||||
<text fill="#000000" x="50.5" y="777.5">DistroWatch.com</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="373.5" y="655.5">pkgsrc-2017Q3</text>
|
||||
<text fill="#000000" x="373.5" y="655.5">pkgsrc-2017Q3</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="46.5" y="782.5">RPM Fusion EL 6</text>
|
||||
<text fill="#000000" x="46.5" y="782.5">RPM Fusion EL 6</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="642.5" y="579.5">Devuan Testing</text>
|
||||
<text fill="#000000" x="642.5" y="579.5">Devuan Testing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="236.5" y="629.5">Arch</text>
|
||||
<text fill="#000000" x="236.5" y="629.5">Arch</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="48.5" y="782.5">Linux Mint 18</text>
|
||||
<text fill="#000000" x="48.5" y="782.5">Linux Mint 18</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="53.5" y="777.5">RPM Fusion Fedora Rawhide</text>
|
||||
<text fill="#000000" x="53.5" y="777.5">RPM Fusion Fedora Rawhide</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="48.5" y="781.5">GetDeb Yakkety</text>
|
||||
<text fill="#000000" x="48.5" y="781.5">GetDeb Yakkety</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="48.5" y="779.5">UnitedRPMs Fedora 28</text>
|
||||
<text fill="#000000" x="48.5" y="779.5">UnitedRPMs Fedora 28</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="723.5" y="420.5">Debian Unstable</text>
|
||||
<text fill="#000000" x="723.5" y="420.5">Debian Unstable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="61.5" y="773.5">LEDE trunk MIPS 24Kc</text>
|
||||
<text fill="#000000" x="61.5" y="773.5">LEDE trunk MIPS 24Kc</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="112.5" y="764.5">CentOS 7</text>
|
||||
<text fill="#000000" x="112.5" y="764.5">CentOS 7</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="385.5" y="590.5">Mageia Cauldron</text>
|
||||
<text fill="#000000" x="385.5" y="590.5">Mageia Cauldron</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="256.5" y="635.5">Parabola</text>
|
||||
<text fill="#000000" x="256.5" y="635.5">Parabola</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="53.5" y="778.5">RPM Fusion Fedora 28</text>
|
||||
<text fill="#000000" x="53.5" y="778.5">RPM Fusion Fedora 28</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="92.5" y="752.5">YACP</text>
|
||||
<text fill="#000000" x="92.5" y="752.5">YACP</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="375.5" y="647.5">pkgsrc-2017Q4</text>
|
||||
<text fill="#000000" x="375.5" y="647.5">pkgsrc-2017Q4</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="53.5" y="778.5">RPM Fusion Fedora 26</text>
|
||||
<text fill="#000000" x="53.5" y="778.5">RPM Fusion Fedora 26</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="120.5" y="765.5">Rosa Server 7.3</text>
|
||||
<text fill="#000000" x="120.5" y="765.5">Rosa Server 7.3</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="47.5" y="782.5">MX Linux MX-16</text>
|
||||
<text fill="#000000" x="47.5" y="782.5">MX Linux MX-16</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="48.5" y="780.5">PlayDeb Zesty</text>
|
||||
<text fill="#000000" x="48.5" y="780.5">PlayDeb Zesty</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="305.5" y="695.5">PCLinuxOS</text>
|
||||
<text fill="#000000" x="305.5" y="695.5">PCLinuxOS</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="709.5" y="543.5">Ubuntu 17.10</text>
|
||||
<text fill="#000000" x="709.5" y="543.5">Ubuntu 17.10</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="586.5" y="644.5">Raspbian Oldstable</text>
|
||||
<text fill="#000000" x="586.5" y="644.5">Raspbian Oldstable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="324.5" y="635.5">openSUSE Leap 15.0</text>
|
||||
<text fill="#000000" x="324.5" y="635.5">openSUSE Leap 15.0</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="60.5" y="781.5">SteamOS alchemist beta</text>
|
||||
<text fill="#000000" x="60.5" y="781.5">SteamOS alchemist beta</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="109.5" y="770.5">Rosa Server 6.9</text>
|
||||
<text fill="#000000" x="109.5" y="770.5">Rosa Server 6.9</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="45.5" y="782.5">PlayDeb Zesty Testing</text>
|
||||
<text fill="#000000" x="45.5" y="782.5">PlayDeb Zesty Testing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="630.5" y="616.5">Trisquel 8.0</text>
|
||||
<text fill="#000000" x="630.5" y="616.5">Trisquel 8.0</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="57.5" y="776.5">KDE neon User</text>
|
||||
<text fill="#000000" x="57.5" y="776.5">KDE neon User</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="151.5" y="698.5">Homebrew</text>
|
||||
<text fill="#000000" x="151.5" y="698.5">Homebrew</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="247.5" y="673.5">OpenBSD Ports</text>
|
||||
<text fill="#000000" x="247.5" y="673.5">OpenBSD Ports</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="553.5" y="481.5">Fedora 28</text>
|
||||
<text fill="#000000" x="553.5" y="481.5">Fedora 28</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="246.5" y="576.5">CPAN</text>
|
||||
<text fill="#000000" x="246.5" y="576.5">CPAN</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="483.5" y="695.5">Ubuntu 12.04</text>
|
||||
<text fill="#000000" x="483.5" y="695.5">Ubuntu 12.04</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="278.5" y="708.5">openSUSE Leap 42.3</text>
|
||||
<text fill="#000000" x="278.5" y="708.5">openSUSE Leap 42.3</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="98.5" y="728.5">Stackage Nightly</text>
|
||||
<text fill="#000000" x="98.5" y="728.5">Stackage Nightly</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="723.5" y="420.5">Devuan Unstable</text>
|
||||
<text fill="#000000" x="723.5" y="420.5">Devuan Unstable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="49.5" y="780.5">PlayDeb Xenial</text>
|
||||
<text fill="#000000" x="49.5" y="780.5">PlayDeb Xenial</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="54.5" y="773.5">KaOS Build</text>
|
||||
<text fill="#000000" x="54.5" y="773.5">KaOS Build</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="342.5" y="471.5">Hackage</text>
|
||||
<text fill="#000000" x="342.5" y="471.5">Hackage</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="641.5" y="579.5">Debian Stable</text>
|
||||
<text fill="#000000" x="641.5" y="579.5">Debian Stable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="49.5" y="781.5">GetDeb Xenial</text>
|
||||
<text fill="#000000" x="49.5" y="781.5">GetDeb Xenial</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="48.5" y="780.5">PlayDeb Yakkety</text>
|
||||
<text fill="#000000" x="48.5" y="780.5">PlayDeb Yakkety</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="372.5" y="661.5">Mageia 6</text>
|
||||
<text fill="#000000" x="372.5" y="661.5">Mageia 6</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="502.5" y="559.5">Gentoo</text>
|
||||
<text fill="#000000" x="502.5" y="559.5">Gentoo</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="57.5" y="780.5">OpenWrt 15.05.01 ar71xx</text>
|
||||
<text fill="#000000" x="57.5" y="780.5">OpenWrt 15.05.01 ar71xx</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="57.5" y="782.5">KDE neon Dev Stable</text>
|
||||
<text fill="#000000" x="57.5" y="782.5">KDE neon Dev Stable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="485.5" y="626.5">Rosa 2014.1</text>
|
||||
<text fill="#000000" x="485.5" y="626.5">Rosa 2014.1</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="109.5" y="763.5">BlackArch</text>
|
||||
<text fill="#000000" x="109.5" y="763.5">BlackArch</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="521.5" y="551.5">Fedora 26</text>
|
||||
<text fill="#000000" x="521.5" y="551.5">Fedora 26</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="90.5" y="737.5">Ravenports</text>
|
||||
<text fill="#000000" x="90.5" y="737.5">Ravenports</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="67.5" y="779.5">SteamOS brewmaster</text>
|
||||
<text fill="#000000" x="67.5" y="779.5">SteamOS brewmaster</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="49.5" y="780.5">UnitedRPMs Fedora 27</text>
|
||||
<text fill="#000000" x="49.5" y="780.5">UnitedRPMs Fedora 27</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="47.5" y="782.5">Trisquel 6.0 backports</text>
|
||||
<text fill="#000000" x="47.5" y="782.5">Trisquel 6.0 backports</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="53.5" y="782.5">Linux Mint 17.1</text>
|
||||
<text fill="#000000" x="53.5" y="782.5">Linux Mint 17.1</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="77.5" y="768.5">OpenIndiana packages</text>
|
||||
<text fill="#000000" x="77.5" y="768.5">OpenIndiana packages</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="50.5" y="782.5">antiX-17</text>
|
||||
<text fill="#000000" x="50.5" y="782.5">antiX-17</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="49.5" y="782.5">Linux Mint 18.1</text>
|
||||
<text fill="#000000" x="49.5" y="782.5">Linux Mint 18.1</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="213.5" y="693.5">SlackBuilds</text>
|
||||
<text fill="#000000" x="213.5" y="693.5">SlackBuilds</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="697.5" y="388.5">FreeBSD Ports</text>
|
||||
<text fill="#000000" x="697.5" y="388.5">FreeBSD Ports</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="45.5" y="782.5">Antergos Staging</text>
|
||||
<text fill="#000000" x="45.5" y="782.5">Antergos Staging</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="78.5" y="770.5">Chocolatey</text>
|
||||
<text fill="#000000" x="78.5" y="770.5">Chocolatey</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="57.5" y="780.5">OpenWrt 15.05.01 x86</text>
|
||||
<text fill="#000000" x="57.5" y="780.5">OpenWrt 15.05.01 x86</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="52.5" y="780.5">RPM Fusion Fedora 24</text>
|
||||
<text fill="#000000" x="52.5" y="780.5">RPM Fusion Fedora 24</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="185.5" y="745.5">EPEL 6</text>
|
||||
<text fill="#000000" x="185.5" y="745.5">EPEL 6</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="129.5" y="762.5">GoboLinux</text>
|
||||
<text fill="#000000" x="129.5" y="762.5">GoboLinux</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="478.5" y="565.5">ALT Sisyphus</text>
|
||||
<text fill="#000000" x="478.5" y="565.5">ALT Sisyphus</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="81.5" y="774.5">OpenMandriva 3.x</text>
|
||||
<text fill="#000000" x="81.5" y="774.5">OpenMandriva 3.x</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="69.5" y="766.5">Wikidata</text>
|
||||
<text fill="#000000" x="69.5" y="766.5">Wikidata</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="676.5" y="461.5">PureOS green</text>
|
||||
<text fill="#000000" x="676.5" y="461.5">PureOS green</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="253.5" y="722.5">openSUSE Leap 42.2</text>
|
||||
<text fill="#000000" x="253.5" y="722.5">openSUSE Leap 42.2</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="48.5" y="781.5">GetDeb Zesty</text>
|
||||
<text fill="#000000" x="48.5" y="781.5">GetDeb Zesty</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="47.5" y="782.5">GetDeb Xenial Testing</text>
|
||||
<text fill="#000000" x="47.5" y="782.5">GetDeb Xenial Testing</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="63.5" y="773.5">freshcode.club</text>
|
||||
<text fill="#000000" x="63.5" y="773.5">freshcode.club</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="60.5" y="778.5">OpenWrt trunk ar71xx</text>
|
||||
<text fill="#000000" x="60.5" y="778.5">OpenWrt trunk ar71xx</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="990.5" y="33.5">nixpkgs unstable</text>
|
||||
<text fill="#000000" x="990.5" y="33.5">nixpkgs unstable</text>
|
||||
<text fill="#f0f0f0" stroke="#f0f0f0" stroke-width="3" stroke-linecap="round" x="557.5" y="451.5">Fedora Rawhide</text>
|
||||
<text fill="#000000" x="557.5" y="451.5">Fedora Rawhide</text>
|
||||
</g>
|
||||
<circle cx="645.5" cy="407.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="645.5" cy="407.5" r="4" fill="#9eff11" />
|
||||
<circle cx="46.5" cy="778.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="46.5" cy="778.5" r="4" fill="#6693d6" />
|
||||
<circle cx="56.5" cy="770.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="56.5" cy="770.5" r="4" fill="#8f5902" />
|
||||
<circle cx="48.5" cy="775.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="48.5" cy="775.5" r="4" fill="#000000" />
|
||||
<circle cx="40.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="40.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="40.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="40.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="54.5" cy="776.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="54.5" cy="776.5" r="4" fill="#6693d6" />
|
||||
<circle cx="42.5" cy="778.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="42.5" cy="778.5" r="4" fill="#000000" />
|
||||
<circle cx="146.5" cy="696.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="146.5" cy="696.5" r="4" fill="#fdb130" />
|
||||
<circle cx="99.5" cy="726.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="99.5" cy="726.5" r="4" fill="#293845" />
|
||||
<circle cx="46.5" cy="776.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="46.5" cy="776.5" r="4" fill="#000000" />
|
||||
<circle cx="200.5" cy="695.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="200.5" cy="695.5" r="4" fill="#000000" />
|
||||
<circle cx="71.5" cy="759.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="71.5" cy="759.5" r="4" fill="#000000" />
|
||||
<circle cx="638.5" cy="611.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="638.5" cy="611.5" r="4" fill="#e95420" />
|
||||
<circle cx="55.5" cy="770.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="55.5" cy="770.5" r="4" fill="#6da741" />
|
||||
<circle cx="497.5" cy="594.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="497.5" cy="594.5" r="4" fill="#4e4e71" />
|
||||
<circle cx="710.5" cy="555.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="710.5" cy="555.5" r="4" fill="#d6264f" />
|
||||
<circle cx="43.5" cy="777.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="43.5" cy="777.5" r="4" fill="#0088cc" />
|
||||
<circle cx="43.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="43.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="535.5" cy="652.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="535.5" cy="652.5" r="4" fill="#c70036" />
|
||||
<circle cx="340.5" cy="465.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="340.5" cy="465.5" r="4" fill="#000000" />
|
||||
<circle cx="73.5" cy="767.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="73.5" cy="767.5" r="4" fill="#000000" />
|
||||
<circle cx="55.5" cy="778.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="55.5" cy="778.5" r="4" fill="#d6264f" />
|
||||
<circle cx="62.5" cy="771.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="62.5" cy="771.5" r="4" fill="#c70036" />
|
||||
<circle cx="56.5" cy="768.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="56.5" cy="768.5" r="4" fill="#000000" />
|
||||
<circle cx="41.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="41.5" cy="779.5" r="4" fill="#669fe7" />
|
||||
<circle cx="52.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="52.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="44.5" cy="777.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="44.5" cy="777.5" r="4" fill="#261d22" />
|
||||
<circle cx="547.5" cy="661.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="547.5" cy="661.5" r="4" fill="#669fe7" />
|
||||
<circle cx="639.5" cy="575.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="639.5" cy="575.5" r="4" fill="#ffcc00" />
|
||||
<circle cx="56.5" cy="770.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="56.5" cy="770.5" r="4" fill="#8f5902" />
|
||||
<circle cx="291.5" cy="629.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="291.5" cy="629.5" r="4" fill="#6da741" />
|
||||
<circle cx="50.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="50.5" cy="779.5" r="4" fill="#87cf3e" />
|
||||
<circle cx="40.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="40.5" cy="779.5" r="4" fill="#56347c" />
|
||||
<circle cx="48.5" cy="776.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="48.5" cy="776.5" r="4" fill="#000000" />
|
||||
<circle cx="135.5" cy="750.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="135.5" cy="750.5" r="4" fill="#000000" />
|
||||
<circle cx="51.5" cy="777.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="51.5" cy="777.5" r="4" fill="#6693d6" />
|
||||
<circle cx="40.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="40.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="82.5" cy="753.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="82.5" cy="753.5" r="4" fill="#1d6fa5" />
|
||||
<circle cx="84.5" cy="759.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="84.5" cy="759.5" r="4" fill="#ffc245" />
|
||||
<circle cx="694.5" cy="435.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="694.5" cy="435.5" r="4" fill="#32638f" />
|
||||
<circle cx="88.5" cy="773.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="88.5" cy="773.5" r="4" fill="#c70036" />
|
||||
<circle cx="56.5" cy="770.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="56.5" cy="770.5" r="4" fill="#8f5902" />
|
||||
<circle cx="41.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="41.5" cy="779.5" r="4" fill="#e95420" />
|
||||
<circle cx="377.5" cy="609.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="377.5" cy="609.5" r="4" fill="#ff6600" />
|
||||
<circle cx="55.5" cy="776.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="55.5" cy="776.5" r="4" fill="#8f5902" />
|
||||
<circle cx="555.5" cy="660.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="555.5" cy="660.5" r="4" fill="#e95420" />
|
||||
<circle cx="44.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="44.5" cy="779.5" r="4" fill="#87cf3e" />
|
||||
<circle cx="676.5" cy="442.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="676.5" cy="442.5" r="4" fill="#000000" />
|
||||
<circle cx="727.5" cy="541.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="727.5" cy="541.5" r="4" fill="#949393" />
|
||||
<circle cx="180.5" cy="680.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="180.5" cy="680.5" r="4" fill="#045e9d" />
|
||||
<circle cx="41.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="41.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="48.5" cy="774.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="48.5" cy="774.5" r="4" fill="#c70036" />
|
||||
<circle cx="957.5" cy="144.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="957.5" cy="144.5" r="4" fill="#7eb2dd" />
|
||||
<circle cx="684.5" cy="440.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="684.5" cy="440.5" r="4" fill="#c70036" />
|
||||
<circle cx="530.5" cy="520.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="530.5" cy="520.5" r="4" fill="#294172" />
|
||||
<circle cx="249.5" cy="624.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="249.5" cy="624.5" r="4" fill="#34be5b" />
|
||||
<circle cx="101.5" cy="718.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="101.5" cy="718.5" r="4" fill="#e9573f" />
|
||||
<circle cx="480.5" cy="602.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="480.5" cy="602.5" r="4" fill="#3757a1" />
|
||||
<circle cx="40.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="40.5" cy="779.5" r="4" fill="#56347c" />
|
||||
<circle cx="50.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="50.5" cy="779.5" r="4" fill="#87cf3e" />
|
||||
<circle cx="56.5" cy="770.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="56.5" cy="770.5" r="4" fill="#8f5902" />
|
||||
<circle cx="535.5" cy="652.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="535.5" cy="652.5" r="4" fill="#88839c" />
|
||||
<circle cx="55.5" cy="775.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="55.5" cy="775.5" r="4" fill="#5d6993" />
|
||||
<circle cx="53.5" cy="777.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="53.5" cy="777.5" r="4" fill="#ffc245" />
|
||||
<circle cx="41.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="41.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="374.5" cy="629.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="374.5" cy="629.5" r="4" fill="#ff6600" />
|
||||
<circle cx="723.5" cy="475.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="723.5" cy="475.5" r="4" fill="#e95420" />
|
||||
<circle cx="249.5" cy="634.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="249.5" cy="634.5" r="4" fill="#34be5b" />
|
||||
<circle cx="364.5" cy="660.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="364.5" cy="660.5" r="4" fill="#ff6600" />
|
||||
<circle cx="44.5" cy="778.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="44.5" cy="778.5" r="4" fill="#261d22" />
|
||||
<circle cx="43.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="43.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="45.5" cy="778.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="45.5" cy="778.5" r="4" fill="#949393" />
|
||||
<circle cx="54.5" cy="774.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="54.5" cy="774.5" r="4" fill="#000000" />
|
||||
<circle cx="315.5" cy="665.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="315.5" cy="665.5" r="4" fill="#1f79e9" />
|
||||
<circle cx="47.5" cy="777.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="47.5" cy="777.5" r="4" fill="#6693d6" />
|
||||
<circle cx="51.5" cy="773.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="51.5" cy="773.5" r="4" fill="#000000" />
|
||||
<circle cx="1081.5" cy="520.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="1081.5" cy="520.5" r="4" fill="#0088cc" />
|
||||
<circle cx="69.5" cy="778.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="69.5" cy="778.5" r="4" fill="#f68500" />
|
||||
<circle cx="200.5" cy="726.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="200.5" cy="726.5" r="4" fill="#ff0000" />
|
||||
<circle cx="40.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="40.5" cy="779.5" r="4" fill="#787dab" />
|
||||
<circle cx="48.5" cy="771.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="48.5" cy="771.5" r="4" fill="#e8ad39" />
|
||||
<circle cx="466.5" cy="694.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="466.5" cy="694.5" r="4" fill="#669fe7" />
|
||||
<circle cx="62.5" cy="776.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="62.5" cy="776.5" r="4" fill="#d6264f" />
|
||||
<circle cx="44.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="44.5" cy="779.5" r="4" fill="#87cf3e" />
|
||||
<circle cx="40.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="40.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="249.5" cy="634.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="249.5" cy="634.5" r="4" fill="#34be5b" />
|
||||
<circle cx="43.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="43.5" cy="779.5" r="4" fill="#669fe7" />
|
||||
<circle cx="218.5" cy="715.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="218.5" cy="715.5" r="4" fill="#c0c0c0" />
|
||||
<circle cx="42.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="42.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="53.5" cy="774.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="53.5" cy="774.5" r="4" fill="#c70036" />
|
||||
<circle cx="56.5" cy="770.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="56.5" cy="770.5" r="4" fill="#000000" />
|
||||
<circle cx="782.5" cy="410.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="782.5" cy="410.5" r="4" fill="#d6264f" />
|
||||
<circle cx="149.5" cy="723.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="149.5" cy="723.5" r="4" fill="#000000" />
|
||||
<circle cx="44.5" cy="777.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="44.5" cy="777.5" r="4" fill="#261d22" />
|
||||
<circle cx="360.5" cy="665.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="360.5" cy="665.5" r="4" fill="#ff6600" />
|
||||
<circle cx="43.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="43.5" cy="779.5" r="4" fill="#87cf3e" />
|
||||
<circle cx="54.5" cy="772.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="54.5" cy="772.5" r="4" fill="#62548f" />
|
||||
<circle cx="91.5" cy="769.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="91.5" cy="769.5" r="4" fill="#932279" />
|
||||
<circle cx="148.5" cy="710.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="148.5" cy="710.5" r="4" fill="#000000" />
|
||||
<circle cx="711.5" cy="438.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="711.5" cy="438.5" r="4" fill="#95b8c8" />
|
||||
<circle cx="44.5" cy="778.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="44.5" cy="778.5" r="4" fill="#000000" />
|
||||
<circle cx="44.5" cy="778.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="44.5" cy="778.5" r="4" fill="#000000" />
|
||||
<circle cx="45.5" cy="774.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="45.5" cy="774.5" r="4" fill="#000000" />
|
||||
<circle cx="368.5" cy="652.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="368.5" cy="652.5" r="4" fill="#ff6600" />
|
||||
<circle cx="41.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="41.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="637.5" cy="576.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="637.5" cy="576.5" r="4" fill="#88839c" />
|
||||
<circle cx="231.5" cy="626.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="231.5" cy="626.5" r="4" fill="#0088cc" />
|
||||
<circle cx="43.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="43.5" cy="779.5" r="4" fill="#87cf3e" />
|
||||
<circle cx="48.5" cy="774.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="48.5" cy="774.5" r="4" fill="#000000" />
|
||||
<circle cx="43.5" cy="778.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="43.5" cy="778.5" r="4" fill="#000000" />
|
||||
<circle cx="43.5" cy="776.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="43.5" cy="776.5" r="4" fill="#261d22" />
|
||||
<circle cx="718.5" cy="417.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="718.5" cy="417.5" r="4" fill="#c70036" />
|
||||
<circle cx="56.5" cy="770.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="56.5" cy="770.5" r="4" fill="#8f5902" />
|
||||
<circle cx="107.5" cy="761.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="107.5" cy="761.5" r="4" fill="#932279" />
|
||||
<circle cx="380.5" cy="587.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="380.5" cy="587.5" r="4" fill="#262f45" />
|
||||
<circle cx="251.5" cy="632.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="251.5" cy="632.5" r="4" fill="#787dab" />
|
||||
<circle cx="48.5" cy="775.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="48.5" cy="775.5" r="4" fill="#000000" />
|
||||
<circle cx="87.5" cy="749.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="87.5" cy="749.5" r="4" fill="#000000" />
|
||||
<circle cx="370.5" cy="644.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="370.5" cy="644.5" r="4" fill="#ff6600" />
|
||||
<circle cx="48.5" cy="775.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="48.5" cy="775.5" r="4" fill="#000000" />
|
||||
<circle cx="115.5" cy="762.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="115.5" cy="762.5" r="4" fill="#3757a1" />
|
||||
<circle cx="42.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="42.5" cy="779.5" r="4" fill="#6693d6" />
|
||||
<circle cx="43.5" cy="777.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="43.5" cy="777.5" r="4" fill="#000000" />
|
||||
<circle cx="300.5" cy="692.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="300.5" cy="692.5" r="4" fill="#1c5482" />
|
||||
<circle cx="704.5" cy="540.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="704.5" cy="540.5" r="4" fill="#e95420" />
|
||||
<circle cx="581.5" cy="641.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="581.5" cy="641.5" r="4" fill="#d6264f" />
|
||||
<circle cx="319.5" cy="632.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="319.5" cy="632.5" r="4" fill="#6da741" />
|
||||
<circle cx="55.5" cy="778.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="55.5" cy="778.5" r="4" fill="#d6264f" />
|
||||
<circle cx="104.5" cy="767.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="104.5" cy="767.5" r="4" fill="#3757a1" />
|
||||
<circle cx="40.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="40.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="625.5" cy="613.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="625.5" cy="613.5" r="4" fill="#669fe7" />
|
||||
<circle cx="52.5" cy="773.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="52.5" cy="773.5" r="4" fill="#000000" />
|
||||
<circle cx="146.5" cy="695.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="146.5" cy="695.5" r="4" fill="#fdb130" />
|
||||
<circle cx="242.5" cy="670.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="242.5" cy="670.5" r="4" fill="#f8e808" />
|
||||
<circle cx="548.5" cy="478.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="548.5" cy="478.5" r="4" fill="#294172" />
|
||||
<circle cx="241.5" cy="573.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="241.5" cy="573.5" r="4" fill="#000000" />
|
||||
<circle cx="478.5" cy="692.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="478.5" cy="692.5" r="4" fill="#e95420" />
|
||||
<circle cx="273.5" cy="705.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="273.5" cy="705.5" r="4" fill="#6da741" />
|
||||
<circle cx="93.5" cy="725.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="93.5" cy="725.5" r="4" fill="#293845" />
|
||||
<circle cx="718.5" cy="417.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="718.5" cy="417.5" r="4" fill="#88839c" />
|
||||
<circle cx="44.5" cy="777.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="44.5" cy="777.5" r="4" fill="#000000" />
|
||||
<circle cx="49.5" cy="770.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="49.5" cy="770.5" r="4" fill="#000000" />
|
||||
<circle cx="337.5" cy="468.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="337.5" cy="468.5" r="4" fill="#293845" />
|
||||
<circle cx="636.5" cy="576.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="636.5" cy="576.5" r="4" fill="#c70036" />
|
||||
<circle cx="44.5" cy="778.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="44.5" cy="778.5" r="4" fill="#000000" />
|
||||
<circle cx="43.5" cy="777.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="43.5" cy="777.5" r="4" fill="#000000" />
|
||||
<circle cx="367.5" cy="658.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="367.5" cy="658.5" r="4" fill="#262f45" />
|
||||
<circle cx="497.5" cy="556.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="497.5" cy="556.5" r="4" fill="#62548f" />
|
||||
<circle cx="52.5" cy="777.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="52.5" cy="777.5" r="4" fill="#5d6993" />
|
||||
<circle cx="52.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="52.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="480.5" cy="623.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="480.5" cy="623.5" r="4" fill="#3757a1" />
|
||||
<circle cx="104.5" cy="760.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="104.5" cy="760.5" r="4" fill="#000000" />
|
||||
<circle cx="516.5" cy="548.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="516.5" cy="548.5" r="4" fill="#294172" />
|
||||
<circle cx="85.5" cy="734.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="85.5" cy="734.5" r="4" fill="#00bcd4" />
|
||||
<circle cx="62.5" cy="776.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="62.5" cy="776.5" r="4" fill="#d6264f" />
|
||||
<circle cx="44.5" cy="777.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="44.5" cy="777.5" r="4" fill="#261d22" />
|
||||
<circle cx="42.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="42.5" cy="779.5" r="4" fill="#669fe7" />
|
||||
<circle cx="48.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="48.5" cy="779.5" r="4" fill="#87cf3e" />
|
||||
<circle cx="72.5" cy="765.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="72.5" cy="765.5" r="4" fill="#000000" />
|
||||
<circle cx="45.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="45.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="44.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="44.5" cy="779.5" r="4" fill="#87cf3e" />
|
||||
<circle cx="208.5" cy="690.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="208.5" cy="690.5" r="4" fill="#000000" />
|
||||
<circle cx="692.5" cy="385.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="692.5" cy="385.5" r="4" fill="#990000" />
|
||||
<circle cx="40.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="40.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="73.5" cy="767.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="73.5" cy="767.5" r="4" fill="#000000" />
|
||||
<circle cx="52.5" cy="777.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="52.5" cy="777.5" r="4" fill="#5d6993" />
|
||||
<circle cx="47.5" cy="777.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="47.5" cy="777.5" r="4" fill="#000000" />
|
||||
<circle cx="180.5" cy="742.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="180.5" cy="742.5" r="4" fill="#ff0000" />
|
||||
<circle cx="124.5" cy="759.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="124.5" cy="759.5" r="4" fill="#000000" />
|
||||
<circle cx="473.5" cy="562.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="473.5" cy="562.5" r="4" fill="#baccdd" />
|
||||
<circle cx="76.5" cy="771.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="76.5" cy="771.5" r="4" fill="#045e9d" />
|
||||
<circle cx="64.5" cy="763.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="64.5" cy="763.5" r="4" fill="#339966" />
|
||||
<circle cx="671.5" cy="458.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="671.5" cy="458.5" r="4" fill="#000000" />
|
||||
<circle cx="248.5" cy="719.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="248.5" cy="719.5" r="4" fill="#6da741" />
|
||||
<circle cx="43.5" cy="778.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="43.5" cy="778.5" r="4" fill="#000000" />
|
||||
<circle cx="42.5" cy="779.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="42.5" cy="779.5" r="4" fill="#000000" />
|
||||
<circle cx="58.5" cy="770.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="58.5" cy="770.5" r="4" fill="#000000" />
|
||||
<circle cx="55.5" cy="775.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="55.5" cy="775.5" r="4" fill="#5d6993" />
|
||||
<circle cx="985.5" cy="30.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="985.5" cy="30.5" r="4" fill="#7eb2dd" />
|
||||
<circle cx="552.5" cy="448.5" r="5" fill="#f0f0f0" />
|
||||
<circle cx="552.5" cy="448.5" r="4" fill="#294172" />
|
||||
</svg>
|
Before Width: | Height: | Size: 53 KiB |
|
@ -1,513 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="141.5919mm"
|
||||
height="122.80626mm"
|
||||
viewBox="0 0 501.70361 435.14028"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.0 r15299"
|
||||
sodipodi:docname="nix-snowflake.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5562">
|
||||
<stop
|
||||
style="stop-color:#699ad7;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop5564" />
|
||||
<stop
|
||||
id="stop5566"
|
||||
offset="0.24345198"
|
||||
style="stop-color:#7eb1dd;stop-opacity:1" />
|
||||
<stop
|
||||
style="stop-color:#7ebae4;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop5568" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5053">
|
||||
<stop
|
||||
style="stop-color:#415e9a;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop5055" />
|
||||
<stop
|
||||
id="stop5057"
|
||||
offset="0.23168644"
|
||||
style="stop-color:#4a6baf;stop-opacity:1" />
|
||||
<stop
|
||||
style="stop-color:#5277c3;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop5059" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5960"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop5962"
|
||||
offset="0"
|
||||
style="stop-color:#637ddf;stop-opacity:1" />
|
||||
<stop
|
||||
style="stop-color:#649afa;stop-opacity:1"
|
||||
offset="0.23168644"
|
||||
id="stop5964" />
|
||||
<stop
|
||||
id="stop5966"
|
||||
offset="1"
|
||||
style="stop-color:#719efa;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5867">
|
||||
<stop
|
||||
style="stop-color:#7363df;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop5869" />
|
||||
<stop
|
||||
id="stop5871"
|
||||
offset="0.23168644"
|
||||
style="stop-color:#6478fa;stop-opacity:1" />
|
||||
<stop
|
||||
style="stop-color:#719efa;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop5873" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="515.97058"
|
||||
x2="282.26105"
|
||||
y1="338.62445"
|
||||
x1="213.95642"
|
||||
gradientTransform="translate(983.36076,601.38885)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient5855"
|
||||
xlink:href="#linearGradient5960"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="515.97058"
|
||||
x2="282.26105"
|
||||
y1="338.62445"
|
||||
x1="213.95642"
|
||||
gradientTransform="translate(-197.75174,-337.1451)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient5855-8"
|
||||
xlink:href="#linearGradient5867"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="247.58188"
|
||||
x2="-702.75317"
|
||||
y1="102.74675"
|
||||
x1="-775.20807"
|
||||
gradientTransform="translate(983.36076,601.38885)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4544"
|
||||
xlink:href="#linearGradient5960"
|
||||
inkscape:collect="always" />
|
||||
<clipPath
|
||||
id="clipPath4501"
|
||||
clipPathUnits="userSpaceOnUse">
|
||||
<circle
|
||||
r="241.06563"
|
||||
cy="686.09473"
|
||||
cx="335.13995"
|
||||
id="circle4503"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#adadad;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clipPath5410"
|
||||
clipPathUnits="userSpaceOnUse">
|
||||
<circle
|
||||
r="241.13741"
|
||||
cy="340.98975"
|
||||
cx="335.98114"
|
||||
id="circle5412"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5053"
|
||||
id="linearGradient5137"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(864.55062,-2197.497)"
|
||||
x1="-584.19934"
|
||||
y1="782.33563"
|
||||
x2="-496.29703"
|
||||
y2="937.71399" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5053"
|
||||
id="linearGradient5147"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(864.55062,-2197.497)"
|
||||
x1="-584.19934"
|
||||
y1="782.33563"
|
||||
x2="-496.29703"
|
||||
y2="937.71399" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5562"
|
||||
id="linearGradient5162"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(70.505061,-1761.3076)"
|
||||
x1="200.59668"
|
||||
y1="351.41116"
|
||||
x2="290.08701"
|
||||
y2="506.18814" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5562"
|
||||
id="linearGradient5172"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(70.505061,-1761.3076)"
|
||||
x1="200.59668"
|
||||
y1="351.41116"
|
||||
x2="290.08701"
|
||||
y2="506.18814" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5562"
|
||||
id="linearGradient5182"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(70.505061,-1761.3076)"
|
||||
x1="200.59668"
|
||||
y1="351.41116"
|
||||
x2="290.08701"
|
||||
y2="506.18814" />
|
||||
<linearGradient
|
||||
y2="506.18814"
|
||||
x2="290.08701"
|
||||
y1="351.41116"
|
||||
x1="200.59668"
|
||||
gradientTransform="translate(70.505061,-1761.3076)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient5201"
|
||||
xlink:href="#linearGradient5562"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="937.71399"
|
||||
x2="-496.29703"
|
||||
y1="782.33563"
|
||||
x1="-584.19934"
|
||||
gradientTransform="translate(864.55062,-2197.497)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient5205"
|
||||
xlink:href="#linearGradient5053"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5562"
|
||||
id="linearGradient4328"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(70.650339,-1055.1511)"
|
||||
x1="200.59668"
|
||||
y1="351.41116"
|
||||
x2="290.08701"
|
||||
y2="506.18814" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5053"
|
||||
id="linearGradient4330"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(864.69589,-1491.3405)"
|
||||
x1="-584.19934"
|
||||
y1="782.33563"
|
||||
x2="-496.29703"
|
||||
y2="937.71399" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.98318225"
|
||||
inkscape:cx="113.58176"
|
||||
inkscape:cy="-45.193301"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer3"
|
||||
showgrid="false"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1577"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-global="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer7"
|
||||
inkscape:label="bg"
|
||||
style="display:none"
|
||||
transform="translate(-23.75651,-24.84972)">
|
||||
<rect
|
||||
transform="translate(-132.5822,958.04022)"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect5389"
|
||||
width="1543.4283"
|
||||
height="483.7439"
|
||||
x="132.5822"
|
||||
y="-957.77832" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer6"
|
||||
inkscape:label="logo-guide"
|
||||
style="display:none"
|
||||
transform="translate(-156.33871,933.1905)">
|
||||
<rect
|
||||
y="-958.02759"
|
||||
x="132.65129"
|
||||
height="484.30399"
|
||||
width="550.41602"
|
||||
id="rect5379"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5c201e;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
inkscape:export-filename="/home/tim/dev/nix/homepage/logo/nix-wiki.png"
|
||||
inkscape:export-xdpi="22.07"
|
||||
inkscape:export-ydpi="22.07" />
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c24a46;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect5372"
|
||||
width="501.94415"
|
||||
height="434.30405"
|
||||
x="156.12303"
|
||||
y="-933.02759"
|
||||
inkscape:export-filename="/home/tim/dev/nix/homepage/logo/nixos-logo-only-hires-print.png"
|
||||
inkscape:export-xdpi="212.2"
|
||||
inkscape:export-ydpi="212.2" />
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#d98d8a;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect5381"
|
||||
width="24.939611"
|
||||
height="24.939611"
|
||||
x="658.02826"
|
||||
y="-958.04022" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:label="print-logo"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="display:inline"
|
||||
transform="translate(-156.33871,933.1905)"
|
||||
sodipodi:insensitive="true">
|
||||
<path
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5277c3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 309.40365,-710.2521 122.19683,211.6751 -56.15706,0.5268 -32.6236,-56.8692 -32.85645,56.5653 -27.90237,-0.011 -14.29086,-24.6896 46.81047,-80.4902 -33.22946,-57.8256 z"
|
||||
id="path4861"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccc" />
|
||||
<path
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#7ebae4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 353.50926,-797.4433 -122.21756,211.6631 -28.53477,-48.37 32.93839,-56.6875 -65.41521,-0.1719 -13.9414,-24.1698 14.23637,-24.721 93.11177,0.2939 33.46371,-57.6903 z"
|
||||
id="use4863"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccc" />
|
||||
<path
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#7ebae4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 362.88537,-628.243 244.41439,0.012 -27.62229,48.8968 -65.56199,-0.1817 32.55876,56.7371 -13.96098,24.1585 -28.52722,0.032 -46.3013,-80.7841 -66.69317,-0.1353 z"
|
||||
id="use4865"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccc" />
|
||||
<path
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#7ebae4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 505.14318,-720.9886 -122.19683,-211.6751 56.15706,-0.5268 32.6236,56.8692 32.85645,-56.5653 27.90237,0.011 14.29086,24.6896 -46.81047,80.4902 33.22946,57.8256 z"
|
||||
id="use4867"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4873"
|
||||
d="m 309.40365,-710.2521 122.19683,211.6751 -56.15706,0.5268 -32.6236,-56.8692 -32.85645,56.5653 -27.90237,-0.011 -14.29086,-24.6896 46.81047,-80.4902 -33.22946,-57.8256 z"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5277c3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="use4875"
|
||||
d="m 451.3364,-803.53264 -244.4144,-0.012 27.62229,-48.89685 65.56199,0.18175 -32.55875,-56.73717 13.96097,-24.15851 28.52722,-0.0315 46.3013,80.78414 66.69317,0.13524 z"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5277c3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="use4877"
|
||||
d="m 460.87178,-633.8425 122.21757,-211.66304 28.53477,48.37003 -32.93839,56.68751 65.4152,0.1718 13.9414,24.1698 -14.23636,24.7211 -93.11177,-0.294 -33.46371,57.6904 z"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5277c3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
<g
|
||||
id="layer2"
|
||||
inkscape:label="guides"
|
||||
style="display:none"
|
||||
transform="translate(72.039038,-1799.4476)">
|
||||
<path
|
||||
d="M 460.60629,594.72881 209.74183,594.7288 84.309616,377.4738 209.74185,160.21882 l 250.86446,1e-5 125.43222,217.255 z"
|
||||
inkscape:randomized="0"
|
||||
inkscape:rounded="0"
|
||||
inkscape:flatsided="true"
|
||||
sodipodi:arg2="1.5707963"
|
||||
sodipodi:arg1="1.0471976"
|
||||
sodipodi:r2="217.25499"
|
||||
sodipodi:r1="250.86446"
|
||||
sodipodi:cy="377.47382"
|
||||
sodipodi:cx="335.17407"
|
||||
sodipodi:sides="6"
|
||||
id="path6032"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.23600003;fill:#4e4d52;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
sodipodi:type="star" />
|
||||
<path
|
||||
transform="translate(0,-308.26772)"
|
||||
sodipodi:type="star"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#4e4d52;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
|
||||
id="path5875"
|
||||
sodipodi:sides="6"
|
||||
sodipodi:cx="335.17407"
|
||||
sodipodi:cy="685.74158"
|
||||
sodipodi:r1="100.83495"
|
||||
sodipodi:r2="87.32563"
|
||||
sodipodi:arg1="1.0471976"
|
||||
sodipodi:arg2="1.5707963"
|
||||
inkscape:flatsided="true"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 385.59154,773.06721 -100.83495,0 -50.41747,-87.32564 50.41748,-87.32563 100.83495,10e-6 50.41748,87.32563 z" />
|
||||
<path
|
||||
transform="translate(0,-308.26772)"
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5851"
|
||||
d="m 1216.5591,938.53395 123.0545,228.14035 -42.6807,-1.2616 -43.4823,-79.7725 -39.6506,80.3267 -32.6875,-19.7984 53.4737,-100.2848 -37.1157,-73.88955 z"
|
||||
style="fill:url(#linearGradient5855);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.41499999;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#c53a3a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect5884"
|
||||
width="48.834862"
|
||||
height="226.22897"
|
||||
x="-34.74221"
|
||||
y="446.17056"
|
||||
transform="rotate(-30)" />
|
||||
<path
|
||||
transform="translate(0,-308.26772)"
|
||||
sodipodi:type="star"
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.50899999;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="path3428"
|
||||
sodipodi:sides="6"
|
||||
sodipodi:cx="223.93674"
|
||||
sodipodi:cy="878.63831"
|
||||
sodipodi:r1="28.048939"
|
||||
sodipodi:r2="24.291094"
|
||||
sodipodi:arg1="0"
|
||||
sodipodi:arg2="0.52359878"
|
||||
inkscape:flatsided="true"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 251.98568,878.63831 -14.02447,24.29109 h -28.04894 l -14.02447,-24.29109 14.02447,-24.2911 h 28.04894 z" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#rect5884"
|
||||
id="use4252"
|
||||
transform="rotate(60,268.29786,489.4515)"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.6507937;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect4254"
|
||||
width="5.3947482"
|
||||
height="115.12564"
|
||||
x="545.71014"
|
||||
y="467.07007"
|
||||
transform="rotate(30,575.23539,-154.13386)" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="gradient-logo"
|
||||
style="display:inline;opacity:1"
|
||||
sodipodi:insensitive="true"
|
||||
transform="translate(-156.33871,933.1905)">
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3336-6"
|
||||
d="m 309.54892,-710.38827 122.19683,211.67512 -56.15706,0.5268 -32.6236,-56.8692 -32.85645,56.5653 -27.90237,-0.011 -14.29086,-24.6896 46.81047,-80.4901 -33.22946,-57.8257 z"
|
||||
style="opacity:1;fill:url(#linearGradient4328);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<use
|
||||
height="100%"
|
||||
width="100%"
|
||||
transform="rotate(60,407.11155,-715.78724)"
|
||||
id="use3439-6"
|
||||
inkscape:transform-center-y="151.59082"
|
||||
inkscape:transform-center-x="124.43045"
|
||||
xlink:href="#path3336-6"
|
||||
y="0"
|
||||
x="0" />
|
||||
<use
|
||||
height="100%"
|
||||
width="100%"
|
||||
transform="rotate(-60,407.31177,-715.70016)"
|
||||
id="use3445-0"
|
||||
inkscape:transform-center-y="75.573958"
|
||||
inkscape:transform-center-x="-168.20651"
|
||||
xlink:href="#path3336-6"
|
||||
y="0"
|
||||
x="0" />
|
||||
<use
|
||||
height="100%"
|
||||
width="100%"
|
||||
transform="rotate(180,407.41868,-715.7565)"
|
||||
id="use3449-5"
|
||||
inkscape:transform-center-y="-139.94592"
|
||||
inkscape:transform-center-x="59.669705"
|
||||
xlink:href="#path3336-6"
|
||||
y="0"
|
||||
x="0" />
|
||||
<path
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient4330);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 309.54892,-710.38827 122.19683,211.67512 -56.15706,0.5268 -32.6236,-56.8692 -32.85645,56.5653 -27.90237,-0.011 -14.29086,-24.6896 46.81047,-80.4901 -33.22946,-57.8256 z"
|
||||
id="path4260-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccc" />
|
||||
<use
|
||||
height="100%"
|
||||
width="100%"
|
||||
transform="rotate(120,407.33916,-716.08356)"
|
||||
id="use4354-5"
|
||||
xlink:href="#path4260-0"
|
||||
y="0"
|
||||
x="0"
|
||||
style="display:inline" />
|
||||
<use
|
||||
height="100%"
|
||||
width="100%"
|
||||
transform="rotate(-120,407.28823,-715.86995)"
|
||||
id="use4362-2"
|
||||
xlink:href="#path4260-0"
|
||||
y="0"
|
||||
x="0"
|
||||
style="display:inline" />
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 54 KiB |
|
@ -1,268 +0,0 @@
|
|||
---
|
||||
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?
|
||||
---
|
||||
<!--
|
||||
С проблемой сталкиваются нууууу почти все - от первой линии службы технической поддержки до программистов. Это проблема состояния окружения - если ваша программа или приложение в какой-то степени опирается на него, то неизбежно будут возникать проблемы с его корректной работы на компьютерах с другим окружением.
|
||||
-->
|
||||

|
||||
|
||||
---
|
||||
<!-- Как добиться того, чтобы программа запущенная успешно на одном компьютере, была также успешно запущена на другом? Современные проекты представляют собой зачастую сложную комбинацию инструментов, библиотек и обеспечить воспроизводимость в этих условиях непросто. Классическое управление зависимостями в 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 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
|
||||
|
||||
---
|
||||
<!-- Собственно этот хэш и получается с помощью криптографической хэш-функции применённой ко всем входным зависимостям -->
|
||||

|
||||
|
||||
---
|
||||
<!-- Вы не полагаетесь на apt, можете при желании собрать систему полностью из исходников. -->
|
||||
|
||||
# Что это даёт для ROS?
|
||||
|
||||
* Возможность запустить проект ROS на любой ОС, даже без apt
|
||||
* Контролируемое управление зависимостями
|
||||
* Возможность использования разных версий одних и тех же пакетов и библиотек
|
||||
* Детерминированные сборки одной командой
|
||||
* CACHE!!!
|
||||
|
||||
---
|
||||
<!--
|
||||
|
||||
-->
|
||||
|
||||
# Основные компоненты nix
|
||||
|
||||
* Nix (менеджер пакетов и язык программирования)
|
||||
* Nixpkgs (репозиторий пакетов и стандартная библиотека)
|
||||
* NixOS (операционная система)
|
||||
* NixOps (DevOps инструмент)
|
||||
|
||||
---
|
||||
<!--
|
||||
# Текущее состояние nixpkgs -->
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
* Необходимость сборки мусора
|
||||
|
||||
|
||||
---
|
||||
# Полезные ресурсы
|
||||
|
||||

|
||||
Русскоязычное сообщество Telegram
|
||||
@ru_nixos
|
||||
|
||||
Туториал для новичков
|
||||
zero-to-nix.com
|
|
@ -1,412 +0,0 @@
|
|||
---
|
||||
title: Генерация датасетов
|
||||
---
|
||||
|
||||
Одной из подзадач управления робототехнической системой является задача обнаружения и классификации объектов в сцене, реализуемая с помощью камеры (машинного зрения). Одним из методов решения данной задачи является использование нейросетевой модели, полученной в ходе обучения на предварительно подготовленных наборах данных. Разработанный модуль генерации наборов данных (датасетов) позволяет автоматизировать процесс их подготовки. Полигональные модели экспортируются из CAD-системы - в результате получается mesh-файл формата `obj`. В ходе генерации формируется сцена для симуляции окружения робота (файл сцены в формате blend). В модуле используется пакет создания синтетических изображений BlenderProc, с помощью которого подготавливается набора данных для обучения нейросети.
|
||||
|
||||
## Обнаружение объектов (Object Detection)
|
||||
|
||||
### Описание API навыка
|
||||
|
||||
Вначале попытаемся описать полную последовательность действий по подготовке и использованию навыка обнаружения объектов. Задача обнаружения объектов сенсорами робота (в частности, RGB камерой в нашем случае) ставится в случае, например, когда необходимо в заданном окружении (сцене) определить наличие или отсутствие необходимых деталей для сборки изделия. Такие детали представлены в информационной среде в виде ассетов, хранимых в базе данных с заданными характеристиками. Поэтому входным параметром навыка обнаружения объектов является список ассетов, экземпляры которых в текущей задаче необходимо обнаруживать. Результатом использования навыка в информационной системе будет являться получение данных о заданном ассете на конкретном изображении, полученном с помощью RGB камеры.
|
||||
|
||||
Начальным этапом навыка является создание датасета, состоящего из синтетических изображений, полученных с использованием пакета [BlenderProc](https://github.com/DLR-RM/BlenderProc). Этот датасет представляет из себя набор файлов изображений и файлов меток к ним, а также файл аннотации, описывающий весь датасет в целом. Он имеет определённую структуру папок и будет использован для обучения нейросетевой модели обнаружения объектов на реальных изображениях в работе (runtime-режим). После создания такой датасет должен быть помещён в базу данных, как единый объект, с заданными характеристиками. В дальнейшем датасет может быть пополнен другими изображениями (например, фото из реального окружения робота), позволяющими произвести дообучение нейросети и улучшить качество работы навыка.
|
||||
|
||||
На втором этапе происходит обучение нейросетевой модели [YOLOv8](https://github.com/ultralytics/ultralytics). На выходе получаем файл весов модели, который также помещается в базу данных, с указанием версии этого файла и параметров обучения.
|
||||
|
||||
Теперь мы имеем всё необходимое для использования навыка обнаружения объектов (Object Detection) в реальном сценарии при управлении роботом в режиме runtime.
|
||||
|
||||
Рассмотрим наиболее общий вариант использования этого навыка в среде ROS2.
|
||||
|
||||
Первым шагом будет являться первоначальный запуск lifecycle-узла ROS2, отвечающего за работу навыка. Чтобы начать процесс обнаружения конкретной детали на изображении нужно выполнить стартовые действия по шаблону в дереве поведения, задав необходимые параметры процесса (топики получения изображения и выдачи результатов обнаружения, режим работы и другие). После решения поставленной задачи обнаружения конкретного объекта выполняются действия по шаблону приостановки работы навыка. Данные шаблоны деревьев поведения выполняются с помощью исполнителя [BehaviorTree](https://github.com/BehaviorTree/BehaviorTree.ROS2). Затем можно начать обнаружение другого объекта, вновь выполнив стартовый шаблон действий и подготовив новые параметры процесса.
|
||||
|
||||
Теперь перейдём к полному описанию данного API.
|
||||
|
||||
### Генерация датасета в формате COCO
|
||||
|
||||
Для создания датасета используется модуль на Python для BlenderProc. Внешними параметрами для модуля являются:
|
||||
- файл, описывающий параметры рандомизиции, а также объекты сцены с подготовленными мешами (файл *.json)
|
||||
- выходной каталог.
|
||||
|
||||
Формируется сцена для случайного размещения в ней объектов из описания. Затем производится рендеринг полученной сцены с рандомизацией параметров освещения, текстур и размещением камеры. Имена объектов должны совпадать с именами ассетов в нашей базе данных.
|
||||
В результате будет получен датасет в формате [BOP](../technologies/cv-perception-methods#соревнование-bop-benchmark-of-pose-estimation)
|
||||
|
||||
Пример запуска модуля генерации датасета:
|
||||
```bash
|
||||
blenderproc run renderBOPdataset2.py --form description.json --path /home/user/path/to/dataset
|
||||
```
|
||||
Пример файла description.json:
|
||||
```json
|
||||
{"output":{
|
||||
"datasetObjects":{
|
||||
"details":[
|
||||
{"name":"star",
|
||||
"inertia":{
|
||||
"ixx":0.1,"ixy":0,"ixz":0,"iyy":0.1,"iyz":0,"izz":0.1
|
||||
},
|
||||
"mass":"0",
|
||||
"visual":"/assets/libs/objects/star.dae",
|
||||
"collision":"/assets/libs/objects/star.stl",
|
||||
"type":"env",
|
||||
"material_path":"",
|
||||
"part_path":"/libs/objects/star.stl",
|
||||
"fbx":"/home/webservice/server/build/public/4c4f3909-74b0-4206-aec1-fc4acd3a1081/assets/libs/objects/star.fbx",
|
||||
"solidType":"active",
|
||||
"isSelect":true
|
||||
}
|
||||
]
|
||||
},
|
||||
"typedataset":"ObjectDetection",
|
||||
"models_randomization":{
|
||||
"loc_range_low":[-1,-1,0],"loc_range_high":[1,1,2]
|
||||
},
|
||||
"scene":{
|
||||
"objects":[
|
||||
{"name":"floor","collision_shape":"BOX","loc_xyz":[0,0,0],"rot_euler":[0,0,0],"material_randomization":{"specular":[0,1],"roughness":[0,1],"metallic":[0,1],"base_color":[[0,0,0,1],[1,1,1,1]}}},
|
||||
{"name":"star","collision_shape":"BOX","loc_xyz":[0,0,0.2],"rot_euler":[0,0,0],"material_randomization":{"specular":[0,1],"roughness":[0,1],"metallic":[0,1],"base_color":[[0,0,0,1],[1,1,1,1]}}
|
||||
],
|
||||
"lights":[
|
||||
{"id":1,"type":"SUN","loc_xyz":[5,5,5],"rot_euler":[-0.06,0.61,-0.19],"color_range_low":[0.5,0.5,0.5],"color_range_high":[1,1,1],"energy_range":[2,9]}
|
||||
]
|
||||
},
|
||||
"camera_position":{
|
||||
"center_shell":[0,0,0],
|
||||
"radius_range":[0.3,0.65],
|
||||
"elevation_range":[10,90]
|
||||
},
|
||||
"generation":{
|
||||
"n_cam_pose":3,
|
||||
"n_sample_on_pose":3,
|
||||
"n_series":222,
|
||||
"image_format":"JPEG",
|
||||
"image_size_wh":[640,480]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
В результате работы модуля в папке '/home/user/path/to/dataset' будет создана файловая структура с датасетом.
|
||||
|
||||
### Генерация датасета в формате BOP Challenge
|
||||
|
||||
Внешними параметрами для модуля являются:
|
||||
1. Файл, описывающий параметры рандомизиции, а также объекты сцены с подготовленными мешами (файл *.json)
|
||||
2. Выходной каталог.
|
||||
|
||||
Формируется сцена для случайного размещения в ней объектов из описания. Затем производится рендеринг полученной сцены с рандомизацией параметров освещения, текстур и размещением камеры. Имена объектов должны совпадать с именами ассетов в нашей базе данных.
|
||||
|
||||
Пример запуска модуля генерации датасета:
|
||||
```bash
|
||||
blenderproc run renderBOPdataset2.py --form description.json --path /home/user/path/to/dataset
|
||||
```
|
||||
|
||||
Пример файла description.json:
|
||||
```json
|
||||
{"output":{
|
||||
"datasetObjects":{
|
||||
"details":[
|
||||
{"name":"star",
|
||||
"inertia":{
|
||||
"ixx":0.1,"ixy":0,"ixz":0,"iyy":0.1,"iyz":0,"izz":0.1
|
||||
},
|
||||
"mass":"0",
|
||||
"visual":"/assets/libs/objects/star.dae",
|
||||
"collision":"/assets/libs/objects/star.stl",
|
||||
"type":"env",
|
||||
"material_path":"",
|
||||
"part_path":"/libs/objects/star.stl",
|
||||
"fbx":"/home/webservice/server/build/public/4c4f3909-74b0-4206-aec1-fc4acd3a1081/assets/libs/objects/star.fbx",
|
||||
"solidType":"active",
|
||||
"isSelect":true
|
||||
}
|
||||
]
|
||||
},
|
||||
"typedataset":"ObjectDetection",
|
||||
"models_randomization":{
|
||||
"loc_range_low":[-1,-1,0],"loc_range_high":[1,1,2]
|
||||
},
|
||||
"scene":{
|
||||
"objects":[
|
||||
{"name":"floor","collision_shape":"BOX","loc_xyz":[0,0,0],"rot_euler":[0,0,0],"material_randomization":{"specular":[0,1],"roughness":[0,1],"metallic":[0,1],"base_color":[[0,0,0,1],[1,1,1,1]}}},
|
||||
{"name":"star","collision_shape":"BOX","loc_xyz":[0,0,0.2],"rot_euler":[0,0,0],"material_randomization":{"specular":[0,1],"roughness":[0,1],"metallic":[0,1],"base_color":[[0,0,0,1],[1,1,1,1]}}
|
||||
],
|
||||
"lights":[
|
||||
{"id":1,"type":"SUN","loc_xyz":[5,5,5],"rot_euler":[-0.06,0.61,-0.19],"color_range_low":[0.5,0.5,0.5],"color_range_high":[1,1,1],"energy_range":[2,9]}
|
||||
]
|
||||
},
|
||||
"camera_position":{
|
||||
"center_shell":[0,0,0],
|
||||
"radius_range":[0.3,0.65],
|
||||
"elevation_range":[10,90]
|
||||
},
|
||||
"generation":{
|
||||
"n_cam_pose":3,
|
||||
"n_sample_on_pose":3,
|
||||
"n_series":222,
|
||||
"image_format":"JPEG",
|
||||
"image_size_wh":[640,480]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
В результате работы модуля в папке '/home/user/path/to/dataset' будет создана файловая структура с датасетом.
|
||||
|
||||
### Обучение модели Yolov8
|
||||
|
||||
Для обучения модели используется модуль на Python. Внешним параметром для модуля является:
|
||||
- каталог с датасетом, сгенерированный на первом этапе.
|
||||
|
||||
Пример запуска модуля обучения:
|
||||
```bash
|
||||
python train_Yolo.py --path /home/user/path/to/dataset --epoch 11 --outpath /home/user/path/to/weights
|
||||
```
|
||||
- path: путь к каталогу с датасетом
|
||||
- epoch 11: количество эпох обучения (пока рекомендуем 30-50)
|
||||
В результате работы создается файл весов нейросети с лучшими характеристиками обнаружения best.pt
|
||||
|
||||
### Использование навыка в ROS2 для обнаружения объекта на изображении (runtime)
|
||||
|
||||
1. Подготовить папку с файлами BT v.4
|
||||
* Папка /path/to/bt/
|
||||
* bt.xml
|
||||
```xml
|
||||
<root BTCPP_format="4">
|
||||
<BehaviorTree ID="Main">
|
||||
<Sequence>
|
||||
<Action ID="RbsAction" do="ObjectDetection" command="odConfigure" sid="a"></Action>
|
||||
</Sequence>
|
||||
</BehaviorTree>
|
||||
</root>
|
||||
```
|
||||
* skills.json
|
||||
```json
|
||||
{"skills": [
|
||||
{
|
||||
"sid": "a",
|
||||
"SkillPackage": {
|
||||
"name": "Robossembler", "version": "1", "format": "1.0"
|
||||
},
|
||||
"Module": {
|
||||
"node_name": "lc_yolo", "name": "ObjectDetection", "description": "Object detection skill with YOLOv8"
|
||||
},
|
||||
"BTAction": [
|
||||
{
|
||||
"name": "odConfigure",
|
||||
"type": "run",
|
||||
"param": [
|
||||
{
|
||||
"type": "weights",
|
||||
"dependency": {"object_name": "board", "weights_file": "/home/shalenikol/0_rbs/w_od_board.pt"}
|
||||
},
|
||||
{
|
||||
"type": "topic",
|
||||
"dependency": {
|
||||
"type": "topic",
|
||||
"topicType": "sensor_msgs/msg/Image",
|
||||
"sid": "7b832b17-3030-4758-aab5-96a5046797f7",
|
||||
"topicOut": "/robot_camera/image"
|
||||
},
|
||||
"isFilled": true
|
||||
}
|
||||
],
|
||||
"result": [],
|
||||
"typeAction": "ACTION"
|
||||
}
|
||||
],
|
||||
"topicsOut": [
|
||||
{
|
||||
"name": "lc_yolo/object_detection",
|
||||
"type": "rbs_skill_interfaces/msg/BoundBox"
|
||||
}
|
||||
],
|
||||
"Launch": {
|
||||
"executable": "od_yolo_lc.py",
|
||||
"package": "rbss_objectdetection"
|
||||
}
|
||||
}
|
||||
]}
|
||||
```
|
||||
|
||||
2. Запуск интерфейсной ноды с сервером навыка, реализующего алгоритм обнаружения объектов.
|
||||
|
||||
```bash
|
||||
ros2 launch rbs_bt_executor interface.launch.py bt_path:=/path/to/bt
|
||||
```
|
||||
|
||||
3. Запуск процесса обнаружения заданного объекта через дерево поведения.
|
||||
Выполняется командой:
|
||||
```bash
|
||||
ros2 launch rbs_bt_executor rbs_executor.launch.py bt_path:=/path/to/bt
|
||||
```
|
||||
После этого узел начинает публиковать в выходной топик информацию об обнаружении объекта на каждом полученном с камеры изображении.
|
||||
|
||||
4. Прекращение процесса обнаружения объекта.
|
||||
|
||||
Для завершения навыка нужно выполнить дерево поведения:
|
||||
```xml
|
||||
<root BTCPP_format="4">
|
||||
<BehaviorTree ID="Main">
|
||||
<Sequence>
|
||||
<Action ID="RbsAction" do="ObjectDetection" command="odStop" sid="b"></Action>
|
||||
</Sequence>
|
||||
</BehaviorTree>
|
||||
</root>
|
||||
```
|
||||
Файл skills.json
|
||||
```json
|
||||
{"skills": [
|
||||
{
|
||||
"sid": "b",
|
||||
"SkillPackage": { "name": "Robossembler", "version": "1", "format": "1.0" },
|
||||
"Module": {"node_name": "lc_yolo", "name": "ObjectDetection", "description": "Object detection skill with YOLOv8"},
|
||||
"BTAction": [
|
||||
{
|
||||
"name": "odStop",
|
||||
"type": "stop",
|
||||
"param": [],
|
||||
"result": [],
|
||||
"typeAction": "ACTION"
|
||||
}
|
||||
],
|
||||
"topicsOut": [
|
||||
{
|
||||
"name": "lc_yolo/object_detection",
|
||||
"type": "rbs_skill_interfaces/msg/BoundBox"
|
||||
}
|
||||
],
|
||||
"Launch": {
|
||||
"executable": "od_yolo_lc.py",
|
||||
"package": "rbss_objectdetection"
|
||||
}
|
||||
}
|
||||
]}
|
||||
```
|
||||
Команда запуска этого дерева та же, что и в пункте 3.
|
||||
После выполнения этих действий lifecycle-узел навыка перейдёт в начальное состояние и можно, повторив пункт 1-3, вновь запустить процесс обнаружения уже с другим объектом.
|
||||
ного модуля являются: модель объекта в формате `obj`, файл описания сцены в формате `blend` и параметры генерации. Интерфейс реализован через параметры командной строки (Command Line Interface — CLI):
|
||||
- `scene` (путь к файлу описания сцены в формате blend);
|
||||
- `obj_path`: путь к каталогу с файлами описания детектируемых объектов в формате `obj`;
|
||||
- `output_dir`: выходной каталог;
|
||||
- `vhacd_path`: каталог, в котором должен быть установлен или уже установлен vhacd;
|
||||
- `-imgs`: количество серий рендеринга (по 15 изображений в каждой серии) на выходе
|
||||
|
||||
Пример вызова:
|
||||
```bash
|
||||
blenderproc run objs2Yolov4dataset.py [scene] [obj_path] [output_dir] [vhacd_path] [–imgs 1]
|
||||
```
|
||||
|
||||
Пример полученных синтетических изображений из набора:
|
||||
|
||||

|
||||
|
||||
### Производительность
|
||||
|
||||
Процесс создания набора изображений для одной детали в количестве 3000 шт. занимает около 10 часов машинного времени (1 CPU Ryzen 3700X + 1 GPU Nvidia RTX 2060 Super), поэтому для снижения ресурсоёмкости работы алгоритма применяется оригинальный метод - на вход программы подаются вместе со сценой также набор 3D-моделей заданных объектов для их совместного включения в изображения, что соответствует реальным условиям работы, где необходимо обнаруживать и распознавать сразу множество различных объектов, представляющих детали сборки или оснастку. Помимо этого, данный подход позволяет сократить размер общего дискового пространства, занимаемого файлами с весами нейросетевых моделей всех деталей, что также полезно для прикладных применений.
|
||||
|
||||
## Оценка 6D положения объекта (Pose Estimation)
|
||||
|
||||
### Создание датасета
|
||||
|
||||
Этот этап точно такой же, как и в случае с Object Detection. Так как синтетический датасет формата [BOP](https://github.com/thodan/bop_toolkit/blob/master/docs/bop_datasets_format.md) содержит в аннотации истинные позиции заданных объектов в сцене (ground true pose), поэтому его можно использовать также и при обучения модели [DOPE](https://github.com/NVlabs/Deep_Object_Pose) для оценки 6D положения объекта.
|
||||
|
||||
|
||||
### Обучение модели [DOPE](https://github.com/NVlabs/Deep_Object_Pose/tree/master/train)
|
||||
|
||||
Для обучения модели используется скрипт на Python. Аргументом для скрипта является:
|
||||
- каталог с датасетом, сгенерированный на первом этапе.
|
||||
В ходе работы скрипта исходный датасет предварительно конвертируется в формат, который используется непосредственно при обучении модели DOPE.
|
||||
|
||||
Пример запуска модуля обучения:
|
||||
```bash
|
||||
python train_Dope.py --path /home/user/path/to/dataset --epoch 44 --outpath /home/user/path/to/weights --name weightsX
|
||||
```
|
||||
- path: путь к каталогу с датасетом
|
||||
- epoch: количество эпох обучения
|
||||
- name: наименование файла весов модели на выходе
|
||||
- outpath: выходной каталог
|
||||
В результате работы создается файл весов модели с лучшими характеристиками обнаружения weightsX.pth
|
||||
|
||||
### Использование навыка в ROS2 для оценки 6D-положения объекта на изображении (runtime)
|
||||
|
||||
Этот процесс аналогичен такому же при обнаружении объекта (YoloV8), здесь приведу лишь дерево (bt.xml) и файл описания скилов в дереве (skills.json).
|
||||
* Папка /path/to/bt/
|
||||
* bt.xml
|
||||
```xml
|
||||
<root BTCPP_format="4">
|
||||
<BehaviorTree ID="Main">
|
||||
<Sequence>
|
||||
<Action ID="RbsAction" do="PoseEstimation" command="peConfigure" sid="a"></Action>
|
||||
</Sequence>
|
||||
</BehaviorTree>
|
||||
</root>
|
||||
```
|
||||
* skills.json
|
||||
```json
|
||||
{"skills": [
|
||||
{
|
||||
"sid": "a",
|
||||
"SkillPackage": {"name": "Robossembler","version": "1.0","format": "1"},
|
||||
"Module": {"node_name": "lc_dope","name": "PoseEstimation","description": "Pose Estimation skill with DOPE"},
|
||||
"BTAction": [
|
||||
{
|
||||
"name": "peConfigure",
|
||||
"type": "run",
|
||||
"param": [
|
||||
{
|
||||
"type": "weights",
|
||||
"dependency": { "object_name": "knight", "weights_file": "/home/shalenikol/0_rbs/w_knight.pth", "dimensions": [0.03, 0.026, 0.065] }
|
||||
},
|
||||
{
|
||||
"type": "topic",
|
||||
"dependency": {
|
||||
"type": "topic",
|
||||
"topicType": "sensor_msgs/msg/Image",
|
||||
"topicOut": "/rgbd_camera/image"
|
||||
},
|
||||
"isFilled": true
|
||||
},
|
||||
{
|
||||
"type": "topic",
|
||||
"dependency": {
|
||||
"type": "topic",
|
||||
"topicType": "sensor_msgs/msg/CameraInfo",
|
||||
"topicOut": "/rgbd_camera/camera_info"
|
||||
},
|
||||
"isFilled": true
|
||||
}
|
||||
],
|
||||
"result": [],
|
||||
"typeAction": "ACTION"
|
||||
}
|
||||
],
|
||||
"topicsOut": [
|
||||
{
|
||||
"name": "lc_dope/pose_estimation",
|
||||
"type": "geometry_msgs/msg/Pose"
|
||||
}
|
||||
],
|
||||
"Launch": {
|
||||
"executable": "pe_dope_lc.py",
|
||||
"package": "rbss_poseestimation"
|
||||
},
|
||||
"Settings": {
|
||||
"output": {
|
||||
"params": [
|
||||
{
|
||||
"name": "publishDelay",
|
||||
"value": "0.5"
|
||||
},
|
||||
{
|
||||
"name": "tf2_send_pose",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"name": "mesh_scale",
|
||||
"value": "0.001"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "formBuilder"
|
||||
}
|
||||
}
|
||||
]}
|
||||
```
|
|
@ -1,56 +0,0 @@
|
|||
---
|
||||
title: Модуль управления виртуальными средами
|
||||
---
|
||||
|
||||
При управлении роботами в симуляторе Gazebo через фреймворк ROS2 возникает необходимость конфигурировать не только робота-манипулятора, но и саму сцену. Однако стандартный подход, основанный на конфигурационных файлах Gazebo, зачастую оказывается избыточным и недостаточно гибким для динамических сценариев, к которым относится обучение с подкреплением.
|
||||
|
||||
**env_manager** — это пакет, предназначенный для конфигурирования сцен в симуляторе Gazebo, предоставляющий более удобный и гибкий подход к созданию и настройке симуляционных сред.
|
||||
|
||||
## Возможности пакета
|
||||
|
||||
С последнего обновления модуль был полностью переработан. Если ранее его функции ограничивались указанием объектов, находящихся в среде, для работы в ROS2, то теперь он предоставляет инструменты для:
|
||||
- полного конфигурирования сцены,
|
||||
- настройки объектов наблюдения для ROS2.
|
||||
|
||||
Конфигурация осуществляется с использованием **датаклассов** или **YAML-файлов**, что соответствует декларативному подходу описания сцены. Это делает процесс настройки интуитивно понятным и легко масштабируемым. Пример файла описания сцены, а также файл с конфигурацией по умолчанию доступны [здесь](https://git.robossembler.org/nodes/seed.robossembler.org/rad:z46gtVRpXaXrGQM7Fxiqu7pLy7kip/tree/env_manager/rbs_runtime/config/default-scene-config.yaml).
|
||||
|
||||
## Возможности конфигурации
|
||||
|
||||
Модуль поддерживает добавление различных типов объектов в сцену, включая:
|
||||
- **Модель**
|
||||
- **Меш**
|
||||
- **Бокс**
|
||||
- **Цилиндр**
|
||||
- **Сферу**
|
||||
|
||||
Различие между "моделью" и "мешем" заключается в том, находится ли объект в библиотеке **rbs_assets_library** (подробнее о ней см. [соответствующий раздел](https://robossembler.org/docs/software/ros2#rbs_assets_library)). Дополнительно поддерживается **рандомизация объектов**, позволяющая случайным образом изменять их цвет и положение в сцене.
|
||||
|
||||
Помимо объектов, с помощью пакета можно настраивать:
|
||||
- **Источники света**
|
||||
- **Сенсоры**
|
||||
- **Роботов**
|
||||
- **Рабочие поверхности**
|
||||
|
||||
Каждый тип объекта обладает как параметрами размещения, так и параметрами рандомизации. Для камер предусмотрены настройки публикации данных:
|
||||
- изображения глубины
|
||||
- цветного изображения
|
||||
- облаков точек.
|
||||
|
||||
Параметры рандомизации могут включать в себя положение, ориентацию в заданных пользователем пределах, а также. Для рабочей поверхности также включается возможность рандомизации текстуры, а для робота имеется возможность рандомизировать его положения, в том числе конфигурацию и расположение базы робота.
|
||||
|
||||
## Архитектура и спецификации
|
||||
|
||||
Основная структура модуля включает обертки для добавления объектов в сцену. Полная спецификация доступных параметров и взаимосвязей между классами представлена в папке конфигураций. Для каждой категории объектов используются отдельные датаклассы, что упрощает организацию и модификацию параметров.
|
||||
|
||||
Диаграмма классов конфигурации сцены представлена ниже:
|
||||
|
||||

|
||||
*Диаграмма классов конфигурации сцены*
|
||||
|
||||
## Примеры
|
||||
|
||||
Ниже представлены различные сцены, созданные с использованием возможностей **env_manager**:
|
||||
|
||||
| **Сценарий 1** | **Сценарий 2** | **Сценарий 3** |
|
||||
|-----------------|-----------------|-----------------|
|
||||
|  |  |  |
|
Before Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 779 KiB |
Before Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 752 KiB |
Before Width: | Height: | Size: 750 KiB |
Before Width: | Height: | Size: 474 KiB |
Before Width: | Height: | Size: 463 KiB |
Before Width: | Height: | Size: 508 KiB |
Before Width: | Height: | Size: 243 KiB |
Before Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 270 KiB |
Before Width: | Height: | Size: 935 KiB |
Before Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 176 KiB |
Before Width: | Height: | Size: 628 KiB |
Before Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 267 KiB |
Before Width: | Height: | Size: 19 KiB |
|
@ -1,264 +0,0 @@
|
|||
<mxfile host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.7.17 Chrome/130.0.6723.59 Electron/33.0.2 Safari/537.36" version="24.7.17">
|
||||
<diagram name="Page-1" id="5otglrqMj2LtwML2cxqW">
|
||||
<mxGraphModel dx="927" dy="1094" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-2" value="" style="rounded=1;whiteSpace=wrap;html=1;arcSize=3;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
|
||||
<mxGeometry x="970" y="712.5" width="620" height="137.5" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-3" value="" style="rounded=1;whiteSpace=wrap;html=1;arcSize=1;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
|
||||
<mxGeometry x="970" y="315" width="620" height="345" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-4" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;arcSize=6;" parent="1" vertex="1">
|
||||
<mxGeometry x="990" y="560" width="580" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#CC0000;startArrow=classic;startFill=1;" parent="1" source="WfpB3c1-lRLewIncIU-h-7" target="WfpB3c1-lRLewIncIU-h-8" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="1140" y="715" />
|
||||
<mxPoint x="1140" y="715" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-7" value="realsense camera" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="1077.5" y="600" width="120" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-8" value="camera" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1085" y="760" width="120" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#CC0000;startArrow=classic;startFill=1;" parent="1" source="WfpB3c1-lRLewIncIU-h-10" target="WfpB3c1-lRLewIncIU-h-24" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-10" value="robot 1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="1215" y="600" width="120" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-12" value="robot 2" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="1357.5" y="600" width="120" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-13" value="ROS 2" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontStyle=1;fontSize=22;" parent="1" vertex="1">
|
||||
<mxGeometry x="1510" y="275" width="90" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-14" value="Аппаратные интерфейсы (Hardware interfaces) / Цифровые двойники (Digital Twins)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontStyle=1" parent="1" vertex="1">
|
||||
<mxGeometry x="1035" y="560" width="490" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-16" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;arcSize=6;" parent="1" vertex="1">
|
||||
<mxGeometry x="990" y="380" width="580" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;startArrow=classic;startFill=1;dashed=1;dashPattern=1 1;strokeColor=#001933;" parent="1" source="WfpB3c1-lRLewIncIU-h-18" target="WfpB3c1-lRLewIncIU-h-22" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-18" value="Skill N" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="1220" y="410" width="120" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-19" value="Дерево поведения (Behaviour Tree)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontStyle=1" parent="1" vertex="1">
|
||||
<mxGeometry x="1167.5" y="380" width="220" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;startArrow=classic;startFill=1;dashed=1;dashPattern=1 1;strokeColor=#001933;" parent="1" source="WfpB3c1-lRLewIncIU-h-21" target="WfpB3c1-lRLewIncIU-h-18" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-21" value="Skill M" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="1000" y="410" width="120" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-22" value="Move to Pose" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="1440" y="410" width="120" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-23" value="usb" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="1095" y="670" width="40" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-24" value="servodrive" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1215" y="760" width="120" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-25" value="" style="rounded=1;whiteSpace=wrap;html=1;arcSize=5;fillColor=#fff2cc;strokeColor=#d6b656;" parent="1" vertex="1">
|
||||
<mxGeometry x="970" y="130" width="620" height="135" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-26" value="Web" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontStyle=1;fontSize=22;" parent="1" vertex="1">
|
||||
<mxGeometry x="1520" y="90" width="70" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-98" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;startArrow=open;startFill=0;strokeColor=#4D4D4D;endArrow=open;endFill=0;" parent="1" source="WfpB3c1-lRLewIncIU-h-28" target="WfpB3c1-lRLewIncIU-h-40" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-32" value="can" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="1227.5" y="670" width="40" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-38" value="websocket" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="1282.5" y="280" width="80" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-40" value="Серверная часть (Backend)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
|
||||
<mxGeometry x="990" y="230" width="580" height="25" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-41" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="1" vertex="1">
|
||||
<mxGeometry x="990" y="145" width="580" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-44" value="Linux" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontStyle=1;fontSize=22;" parent="1" vertex="1">
|
||||
<mxGeometry x="1510" y="670" width="80" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-46" value="ros2 launch + [ args ]" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1430" y="730" width="140" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-49" value="rbs" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="1155" y="400" width="40" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-50" value="rbs" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="1365" y="400" width="40" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="V1WyhFd76DXo4EdTU4iS-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="WfpB3c1-lRLewIncIU-h-58" target="jR0a6fk9G7gRTK2krb-A-1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-58" value="Оператор-технолог" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="1447.5" y="40" width="30" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-59" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;arcSize=6;" parent="1" vertex="1">
|
||||
<mxGeometry x="990" y="465" width="580" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-61" value="zmq" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="1135" y="280" width="50" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-62" value="Серверы навыков (Skill Servers)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontStyle=1" parent="1" vertex="1">
|
||||
<mxGeometry x="1180" y="465" width="200" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-63" value="Dope 6D" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="1000" y="495" width="120" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-64" value="Cartesian" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="1310" y="495" width="120" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-65" value="MoveIt" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="1440" y="495" width="120" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-66" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=classic;startFill=1;dashed=1;dashPattern=1 1;strokeColor=#001933;endArrow=none;endFill=0;entryX=0.21;entryY=0.072;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="WfpB3c1-lRLewIncIU-h-59" target="WfpB3c1-lRLewIncIU-h-14" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="450" y="430" as="sourcePoint" />
|
||||
<mxPoint x="1140" y="610" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="1138" y="550" />
|
||||
<mxPoint x="1138" y="550" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-69" value="BT Builder" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFCCE6;" parent="1" vertex="1">
|
||||
<mxGeometry x="1392.5" y="182.5" width="80" height="25" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-70" value="Сцена" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFCCE6;" parent="1" vertex="1">
|
||||
<mxGeometry x="1300" y="182.5" width="82.5" height="25" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-76" value="Модели" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFCCE6;" parent="1" vertex="1">
|
||||
<mxGeometry x="1220" y="182.5" width="70" height="25" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-77" value="Датасеты" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFCCE6;" parent="1" vertex="1">
|
||||
<mxGeometry x="1142.5" y="182.5" width="65" height="25" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-78" value="Детали" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFCCE6;" parent="1" vertex="1">
|
||||
<mxGeometry x="1077.5" y="182.5" width="52.5" height="25" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-79" value="Проекты" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFCCE6;" parent="1" vertex="1">
|
||||
<mxGeometry x="1002.5" y="182.5" width="60" height="25" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-80" value="Object Detection YOLOv7" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" vertex="1">
|
||||
<mxGeometry x="1130" y="495" width="165" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-86" value="Мониторинг" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1482.5" y="182.5" width="80" height="25" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-88" value="Клиентская часть (Frontend)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;fontStyle=1" parent="1" vertex="1">
|
||||
<mxGeometry x="1187.5" y="145" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-89" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;curved=0;fillColor=#e1d5e7;strokeColor=#9673a6;strokeWidth=2;startArrow=classic;startFill=1;" parent="1" source="WfpB3c1-lRLewIncIU-h-70" target="WfpB3c1-lRLewIncIU-h-46" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="1370" y="160" />
|
||||
<mxPoint x="1630" y="160" />
|
||||
<mxPoint x="1630" y="740" />
|
||||
</Array>
|
||||
<mxPoint x="700" y="730" as="sourcePoint" />
|
||||
<mxPoint x="660" y="110" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-90" value="Разработчик<br>&nbsp;серверов<br>навыков" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="910" y="535" width="30" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-91" value="<span style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: center; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(251, 251, 251); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">args</span>" style="text;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1600" y="712.5" width="40" height="25" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-95" value="<span style="text-align: center;">topic list</span>" style="text;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1600" y="130" width="60" height="37.5" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-96" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;startArrow=classic;startFill=1;strokeColor=#333333;" parent="1" source="WfpB3c1-lRLewIncIU-h-21" target="WfpB3c1-lRLewIncIU-h-63" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-99" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=open;startFill=0;strokeColor=#4D4D4D;endArrow=open;endFill=0;exitX=0.26;exitY=-0.016;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="WfpB3c1-lRLewIncIU-h-16" target="WfpB3c1-lRLewIncIU-h-40" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="1110" y="280" as="sourcePoint" />
|
||||
<mxPoint x="1290" y="265" as="targetPoint" />
|
||||
<Array as="points">
|
||||
<mxPoint x="1141" y="270" />
|
||||
<mxPoint x="1140" y="270" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-28" value="Мост ROS 2 - Web" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;arcSize=9;" parent="1" vertex="1">
|
||||
<mxGeometry x="987.5" y="335" width="585" height="25" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-100" value="<span style="text-wrap: nowrap;">get_interfaces.py</span>" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1430" y="770" width="140" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<UserObject label="" id="WfpB3c1-lRLewIncIU-h-102">
|
||||
<mxCell style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1430" y="810" width="140" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
</UserObject>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-103" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;curved=0;fillColor=#e1d5e7;strokeColor=#9673a6;strokeWidth=2;" parent="1" source="WfpB3c1-lRLewIncIU-h-86" target="WfpB3c1-lRLewIncIU-h-102" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="1650" y="195" />
|
||||
<mxPoint x="1650" y="825" />
|
||||
</Array>
|
||||
<mxPoint x="1590" y="150" as="sourcePoint" />
|
||||
<mxPoint x="1580" y="790" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-106" value="simulate" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
|
||||
<mxGeometry x="1585" y="820" width="70" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="WfpB3c1-lRLewIncIU-h-109" style="edgeStyle=orthogonalEdgeStyle;rounded=1;orthogonalLoop=1;jettySize=auto;html=1;curved=0;fillColor=#e1d5e7;strokeColor=#9673a6;strokeWidth=2;startArrow=classic;startFill=1;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" parent="1" source="WfpB3c1-lRLewIncIU-h-100" target="WfpB3c1-lRLewIncIU-h-91" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="1630" y="785" />
|
||||
</Array>
|
||||
<mxPoint x="1343" y="153" as="sourcePoint" />
|
||||
<mxPoint x="1580" y="750" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="jR0a6fk9G7gRTK2krb-A-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="jR0a6fk9G7gRTK2krb-A-1" target="WfpB3c1-lRLewIncIU-h-77" edge="1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="1175" y="150" />
|
||||
<mxPoint x="1175" y="150" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="jR0a6fk9G7gRTK2krb-A-1" value="Модель предметной области (domain)" style="rounded=1;whiteSpace=wrap;html=1;verticalAlign=top;" parent="1" vertex="1">
|
||||
<mxGeometry x="970" y="40" width="410" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="jR0a6fk9G7gRTK2krb-A-5" value="Метод работы&nbsp;2" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1115" y="70" width="120" height="20" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="jR0a6fk9G7gRTK2krb-A-6" value="Метод работы&nbsp;3" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="1245" y="70" width="120" height="20" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="jR0a6fk9G7gRTK2krb-A-7" value="Метод работы 1" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="987.5" y="70" width="120" height="20" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="jR0a6fk9G7gRTK2krb-A-8" value="Инженер <br>машинного<br>&nbsp;обучения" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="910" y="145" width="30" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="V1WyhFd76DXo4EdTU4iS-5" value="Разработчик<br>&nbsp;драйверов" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="910" y="737.5" width="30" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="V1WyhFd76DXo4EdTU4iS-8" value="Разработчик<br>&nbsp;сценариев<br>поведения" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="910" y="380" width="30" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
Before Width: | Height: | Size: 250 KiB |
Before Width: | Height: | Size: 602 KiB |
Before Width: | Height: | Size: 73 KiB |
Before Width: | Height: | Size: 373 KiB |
Before Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 126 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 111 KiB |