Чтобы платформа знала, как устроен ваш узел или станок, его не программируют — его описывают файлом. Формат описания — URDF: звенья, шарниры, пределы, точки датчиков. На одной этой спине стоят все три рода оборудования — узел автоматики, станок и навесная голова: один дом файла, один интерфейс приёма, одна проверка. Глаголы платформы четыре: принять файл · связать имена · показать · питать позами с железа. Своего файла нет — механизм печатаем мы, и он остаётся черновиком, пока вы не принесёте свой.
| Понятие | Что это у вас на железе |
|---|---|
| Звено (link) | Твёрдое тело: рама, каретка, плечо, планшайба. Несёт видимую геометрию — примитив или меш. |
| Шарнир (joint) | Подвижная связь двух звеньев: родитель, ребёнок, положение и направление оси. У шарнира есть имя — им его зовёт программа. |
| Пределы (limit) | Границы хода, усилие и скорость. Границы — АБСОЛЮТНЫЕ координаты, а не длина хода. |
| Цвет (material) | Цвет звена берётся из файла: <material><color rgba> в URDF или материал внутри .glb. Первым спрашивается сам файл меша, и только если он о цвете промолчал — <material> визуала. Звено, цвета не назвавшее, рисуется нейтральным серым — своей палитры по номеру звена мы не подставляем. Отделка (полупрозрачность, блеск) при этом наша: копия остаётся прибором, а не картинкой, и текстуры из файла на экран не попадают. Белый цвет считается «не назван»: это умолчание и URDF, и glTF, и отличить его от молчания нечем. |
| Точка (frame) | Место датчика или исполнителя. В URDF это звено без геометрии, прикреплённое неподвижным шарниром к тому звену, на котором оно физически сидит. |
URDF — дерево: у каждого звена ровно один родитель, корень один. Из этого свойства следует всё остальное на этой странице, включая честную границу в конце.
| Тип | Что значит | У нас | Когда |
|---|---|---|---|
| revolute | вращение с объявленными границами | печатаем · читаем | Поворотный стол, ось-сустав. Требует <limit lower upper>. |
| prismatic | прямолинейный ход с границами | печатаем · читаем | Портальная ось, толкатель, мачта, подъёмная колонна. Требует <limit lower upper>. |
| continuous | вращение без границ | печатаем · читаем | Лента, шнек, шпиндель: паспортного хода у такой оси нет вовсе. Границы не объявляются — только усилие и скорость. |
| fixed | неподвижная связь | печатаем · читаем | Кожух на плече, точка датчика на каретке. Программой не зовётся. |
| floating · planar | шесть / три свободных степени | не печатаем | Подвижным считается всё, что не fixed, — значит такой шарнир на входе потребует связи с каналом наравне с остальными. Обычно это признак, что модель описывает сцену, а не механизм. |
continuous — не третий класс движения, а честная запись случая
«вращение без объявленного предела». У ленты и шнека хода в паспорте нет вовсе, и
revolute заставил бы выдумать границы либо запереть ось нулевым ходом.
Пределы — это абсолютные координаты хода, а не его длина.
Ось, которая ходит от −150 до +150 мм, пишется как
lower="-0.15" upper="0.15", а не как «300». Одно имя с двумя смыслами
однажды сделало рабочий конверт станка вдвое шире реального.
Связка «механизм ↔ управление» держится на одном имени. Поэтому имя шарнира подвижной оси — не подпись для человека, а адрес.
| Где | Имя | Что это | Где в файле | Синонимы |
|---|---|---|---|---|
| узел автоматики | srv0, srv1, … | серво: подвижный шарнир | <joint name="srv0"> | servo0 · joint0 |
| узел автоматики | di0, di1, … | дискретный вход | <link name="di0"> — точка датчика | input0 |
| узел автоматики | do0, do1, … | дискретный выход | <link name="do0"> — точка исполнителя | output0 |
| узел автоматики | ai0, ai1, … | аналоговый вход | <link name="ai0"> — точка замера | analog0 |
| станок | A · B · C · U · V · X · Y · Z | ось породы: имя шарнира — буква оси | <joint name="X"> | — |
| навесное | jaws · rotate · tilt · tool_spin · turret_index · wire | ось головы: ключ оси | <joint name="jaws">, корень механизма — tool0 | — |
Ведущих нулей нет. Подпись канала («зажим тисков») именем не является и меняется свободно — иначе переименование тихо переставляло бы шарнир под другой привод. Ваши собственные имена звеньев, материалов и неподвижных деталей — как хотите: договор касается только шарниров подвижных осей и точек каналов.
Правило одно на все три рода: имя, которым ось зовёт программа, и есть связка с механизмом. Что чем зовётся — см. типы станков.
Дом файла один (mechanisms), интерфейс приёма один, судья один.
Различается только то, чем зовутся шарниры и откуда берётся наш черновик.
| Род | Имена шарниров | Черновик печатается из | Интерфейс приёма |
|---|---|---|---|
| Узел автоматики | srv0 · di0 · do0 · ai0 | паспорта узла: цепочка по порядку приводов | /api/automation/rigs/{id}/mechanism |
| Станок | A · B · C · U · V · X · Y · Z | шаблона кинематики породы и ходов осей двойника; цепь кончается стыком tool0 | /api/machines/{id}/mechanism |
| Навесное | jaws · rotate · tilt · tool_spin · turret_index · wire | записи справочника: вид головы и вылет TCP; корень — тот же tool0 | /api/effector-configs/{id}/mechanism |
GET отдаёт принесённый файл байт в байт, а не принесён — заводской
черновик. Чем именно отвечено, говорит заголовок
X-Mechanism-Source: imported | generated: гадать по содержимому не нужно.
Тип станка пользовательским файлом не переопределяется.
Число подвижных шарниров обязано совпасть с числом осей породы: завели шестиосевой —
значит шесть. Не совпало — отказ словами, с обоими числами.
Заводской черновик — схема верных пропорций, а не чертёж.
Честно известны две вещи, и обе из двойника: ход по осям и, если порода назвала, края
звеньев. Поперечных размеров станины в двойнике нет — они выведены долей хода и названы
комментарием прямо в XML.
Чужая модельТаблица имён вместо переименования
Модель из ROS или от вендора несёт свои 7–36 имён. Переименовывать их руками —
стена, а переименовать за вас мы не имеем права: порядок звеньев в дереве и номер привода —
разные вещи, и однажды они разойдутся молча.
Поэтому файл приносится вместе с картой {канал: имя в файле}.
Судить первый пункт договора будет карта, а не написание имён внутри файла.
{
"mechanism": "mechanism.urdf",
"joints": {
"srv0": "lift_lower_joint",
"srv1": "lift_upper_joint"
}
} Карта проверяется целиком: непокрытый подвижный шарнир и канал, чьё имя ни к чему
в файле не ведёт, — это названные отказы. Карта едет на бокс отдельным файлом
рядом с механизмом, потому что пакет обязан быть самодостаточным: бокс, получив
чужой файл, должен знать, какой шарнир двигает srv0.
ГеометрияМеши: что принимаем и что показываем
Формат Хранилище Экран Замечание .glb да да предпочтительный формат: одно тело, материалы внутри .gltf да да везёт с собой буфер .bin и текстуры .png / .jpg .stl да да голая сетка, без материалов .dae да да COLLADA, родной формат мешей в донорских URDF: и хранится, и рисуется — поворот из <up_axis> берётся из файла .obj да да голая сетка без материалов: и хранится, и рисуется .step да да обменный формат CAD: тело, а не сетка — триангулируется при показе .stp да да то же, что .step — второе написание того же формата .iges да да обменный формат CAD старшего поколения: поверхности, материалов нет .igs да да то же, что .iges — второе написание того же формата .bin · .png · .jpg да — спутники glTF: URDF их не называет, тело тянет их само
Путь меша указывается ровно так, как он написан внутри URDF
(meshes/frame.stl): файлы приезжают тем же запросом, что и текст механизма, —
одна транзакция, один владелец записи. Общий предел на комплект геометрии —
30 МБ.
Принимаются меши подвижных звеньев и опорного — того самого корня
дерева, подошвы, на которой механизм стоит. «Подвижное» — это вывод, а не список
исключений: звено подвижно, если путь от корня до него содержит хотя бы один
не-fixed шарнир (кожух, прикрученный fixed к плечу, едет вместе
с плечом и потому подвижен). Не принесённый меш такого звена — отказ; меш прочего
неподвижного (кожух, декор) не кладётся, и об этом говорится строкой предупреждения,
а не молчанием.
Геометрию импорт не снимает. Запрос без поля meshes —
в том числе загрузка одного файла механизма — оставляет уже лежащие меши на месте и
говорит об этом строкой. Заменить геометрию можно тем же запросом (поле
meshes), снять — только вместе с механизмом.
На бокс уезжают три вещи: текст механизма, таблица имён и принятые меши.
Не требуемЧто мы принимаем и игнорируем
Тег Что с ним <collision> Принимаем и игнорируем: столкновений мы не считаем. Меш, названный только в <collision>, не требуется — платить десятками мегабайт за данные, которые никто не читает, мы не просим. <inertial> Динамики мы не считаем: копия питается позами с железа, а не решает уравнения движения. <mimic> НЕ поддержан: сцепленную пару (гантри, параллельный захват, пантограф) покажем как два независимых шарнира. Если в вашей модели ведомый вал идёт за ведущим — на картинке он будет стоять.
Не тратьте время на подготовку столкновительной геометрии и на массы
с тензорами инерции: мы их не читаем. Копия питается позами, приходящими с железа,
а не решает физику.
ИмпортЧто проверяет интерфейс приёма
Порядок жёсткий: судья → отказ либо запись. Молчаливого приёма нет, правки
принесённого текста нет — ни отступов, ни единиц. Отказ приходит целиком, со всеми
замечаниями сразу, а не по одному на попытку.
1Имена
Шарнир подвижной оси зовётся по договору (srv0, srv1, …) — либо приносится таблица имён. Имя, похожее на адрес, но написанное иначе (servo_0, SRV0, joint3), отвергается с подсказкой точного имени. За вас не переименовываем.
проверяется2Дерево
У звена ровно один родитель, корень один, циклов нет.
проверяется3Пределы
<limit lower upper> объявлены у revolute и prismatic и заданы абсолютными координатами хода, а не его длиной.
проверяется4Единицы
Метры и радианы: URDF — это СИ. Объявить единицы в файле нечем, поэтому проверяется правдоподобие величины — так ловятся миллиметры и градусы, положенные в СИ-поле.
проверяется5Внутри нет железа
Ни пина, ни слейва, ни шины (lcec, slave, cia402, din-, dout-, ain-). URDF описывает механику; чем канал является электрически (роль, профиль движения) — знает passport.json рядом с механизмом. Куда он подключён на конкретном стенде — не знает и паспорт: узел в каталоге один, стендов много.
проверяется Файлы xacro принимаются. Реальные модели ROS почти всегда
приходят макросами и включениями — разворачивание идёт до того же единственного судьи.
Вместе с файлом механизма присылаются его соседи (включения, макросы, параметры).
Аргументы xacro на этом шаге не задаются: берутся умолчания, а объявленные
файлом аргументы называются в ответе — у файла с $(arg …) разворачиваний
несколько, и мы взяли одно.
Пока свой файл не принесён, механизм — наш черновик, напечатанный
по паспорту узла: цепочка по порядку приводов, схематичные звенья, и каждое додуманное
число названо и в предупреждениях, и комментарием в самом XML. После импорта механизм —
ваш файл, и генератор в него больше не пишет; вернуться к черновику
можно одним движением.
ПаспортЧетвёртый файл каталога — passport.json
URDF описывает МЕХАНИКУ узла — звенья, шарниры, пределы хода. Всё, что механикой
не является — роль канала, чем он физически исполнен, профиль его движения, адресное
пространство ячеек, имя и описание узла для человека, — несёт отдельный файл рядом с
механизмом: passport.json. Узел заводится каталогом из пяти файлов,
и ни строкой кода:
mechanism.urdf — механика: звенья, шарниры, пределы хода. - меши — видимая геометрия звеньев.
mechanism_map.json — имена чужого донора, если файл принесён не наш. passport.json — роли каналов, электрика, ячейки, имя и описание узла. program.plc — логика: что узел делает.
Разграничение владения записи жёсткое: поле, которое КРУГ URDF выводит сам (тип шарнира,
ход, порядок каналов), в паспорте не дублируется — это была бы вторая правда о том же.
Паспорт несёт ровно то, чего URDF не может сказать в принципе.
Раздел Поля Почему не в URDF servos role (ось · сустав · вращение · затяжка),
kind (физический механизм: лента, мачта, вилка, шнек…), max_velocity, max_acceleration,
max_deceleration, max_torque, rated_torque_nm, lead_mm (ход винта, мм/об),
gear_num / gear_den шарнир задаёт ТИП движения и пределы хода, но не режим привода и не
физику передачи — continuous из файла читается одинаково что у ленты,
что у шпинделя завинчивания outputs role: grip, clamp, gate, valve, marker,
applicator, diverter, vacuum, glue, part_feed точка исполнителя в URDF есть, а того, ЧТО она делает, файл не говорит —
дискретных выходов в дереве звеньев нет вовсе inputs role: presence, at_position, trigger,
verdict, fill_level, force_ok, grip_ok, label_gap то же для входов: точка датчика есть, смысл сигнала — нет analogs quantity, units аналоговых каналов URDF не несёт вовсе grid cols, rows, levels (адрес: буква A,B,… → X,
число 1.. → Y, .N → Z), pitch [dx,dy,dz] мм (без умолчания), origin [x,y,z] мм —
координата ячейки A1 ячеек в URDF нет по определению: стеллаж — не звено и не шарнир,
вывести «восемь столбцов с шагом 700» из механизма не из чего. Именованные точки
(exit1 / home / input) сюда НЕ попадают —
у точки есть родитель-звено, она остаётся <link>-маркером
cell_<имя> в самом механизме; сами ячейки A1…H5 нигде не
хранятся — считаются из шага и начала name / description две строки, ровно два поля <robot name=…> в URDF — идентификатор механизма,
а не подпись узла для человека; описания в файле нет вовсе
{
"version": 1,
"name": "Кран-штабелёр (склад)",
"description": "Рельсовый ASRS-кран: рельс + мачта + вилка + захват.",
"servos": [
{ "channel": "srv0", "label": "нижняя ступень", "role": "linear_axis", "kind": "mast" },
{ "channel": "srv1", "label": "верхняя ступень", "role": "linear_axis", "kind": "mast" }
],
"outputs": [],
"inputs": [],
"analogs": [],
"grid": {
"cols": 8, "rows": 5, "levels": 1,
"pitch": [700.0, 400.0, 0.0],
"origin": [0.0, 0.0, 0.0]
}
} lead_mm умолчания не имеет. Ход винта — свойство
ЭКЗЕМПЛЯРА оборудования, не механики. Не назван в паспорте — прямая ось честно остаётся без
хода винта (в 3D не поедет, и это видно) вместо того, чтобы поехать по придуманному числу.
Образец галереи ewellix_lift ровно в этом положении: программа-пример для него
не собрана, потому что lead_mm паспортом не назван.
Чего в паспорте нет и быть не должно — фактов КОНКРЕТНОГО СТЕНДА: слейв, пин, шарнир
привода, датум нуля. Узел в каталоге один, стендов, куда его поставят, много; эти числа
называет наладчик у железа, а не карточка образца.
Ключ канала паспорта — его ИМЯ (srv0, di0), то же самое, которым
его зовут URDF и программа; отдельного порядкового номера паспорт не хранит.
ПрограммаПятый файл каталога — program.plc
URDF описывает механику, паспорт — роли и электрику, а что узел
делает называет отдельный текстовый файл рядом с ними: program.plc.
Внутри — ТЕЛО программы на языке лаборатории PLC (том же, на котором пишутся программы
рода motion в /programs/plc): состояния, переходы, движения по
дорожкам.
Объявления оборудования в файле нет. Пролог rig({ axes, outputs,
inputs }) — вторая запись состава узла — платформа ПЕЧАТАЕТ сама из паспорта и
механизма, на место метки // @rig в начале файла. Написать этот пролог рукой
нельзя: состав узла жил бы в двух местах сразу и расходился бы молча, как только один из
них поправят. Метка бывает и в форме // @rig inline — печать входит прямо в
неё, без переноса строки.
Файла нет — программы у узла нет. Не подставляется ни пустой шаблон, ни
программа по умолчанию: логика не объявлена, и вывести её из механизма с паспортом не из
чего. Это видно строкой на экране узла, а не молчанием.
// @rig
machine({
title: 'Конвейер — счёт деталей',
initial: 'ход',
states: {
'ход': {
lanes: { лента: [spin(1, 30)] },
on: { 'счётчик ↑': 'посчитали' },
},
'посчитали': {
wait: 0.4,
on: { done: 'ход' },
},
},
}) Файлом программу можно принести не у всякого узла. У
образцов, чья программа-пример ВЫЧИСЛЯЕТСЯ из <limit> принесённого
механизма (motopos_d500, flir_ptu_d46, ewellix_lift),
она остаётся вычисляемой, а не файлом: замените механизм — программа обязана поехать за
новыми пределами хода, а статический текст файла этого не умеет. Это граница формата, а
не недоделанная функция.
Шестой файл — program.spec.json, и его не пишут руками
Текст program.plc — единственный ИСТОЧНИК; рядом с ним лежит
program.spec.json — то же самое, разобранное в шаги. Он нужен потому, что
собирает шаги ОДИН движок, и живёт он в браузере: без этого файла узел из каталога
пришлось бы сперва открыть в лаборатории и сохранить, иначе играть было нечем.
Это порождённый файл, а не вторая правда. Правят только
program.plc, а спеку пересобирают — команда пересборки записана в самом
файле, в поле _source. Прогон сверяет её с исходником байт в байт и
краснеет, если текст поправили, а спеку не пересобрали.
Пересборки требует и смена СОСТАВА узла в passport.json — каналы,
выходы, входы: спека несёт отпечаток обоих входов сразу, текста программы и состава.
Поэтому «поправил паспорт — пересобери спеку» — то же правило, что и для текста.
Граница форматаЧто URDF не выражает — и мы это не скрываем
Замкнутую цепь дерево не выражает. У гексапода подвижная платформа
держится на шести штангах — это шесть родителей у одного звена, тогда как дерево
допускает ровно одного. Сферических шарниров в URDF нет вовсе.
Из этого не следует, что параллельной машине механизма не полагается.
3 породы из 15
объявлены параллельными (Гексапод (платформа Стюарта, 6 ног) · Линейная дельта (3 каретки, уровневая платформа) · Трипод (3-PRS наклонная голова, Sprint-Z3-класс)),
и механизм им печатается: их A/B/C наклоняют
платформу вокруг её же центра, поэтому совпадение пивотов — правда о машине, а не
потеря геометрии. Отказом это было до 06.09, и отказ врал.
Род цепи объявляет порода, а не число поворотных осей.
Настоящие штанги такой машины приходят готовым мешем, а не печатью тел: то, что
дерево выразить не может, приносится геометрией, а не выдумывается структурой.
Токарный станок, наоборот, ложится на дерево отлично — двумя ветвями
от станины:
станина
├── каретка Z (prismatic) → салазки X (prismatic) → резцедержка
└── шпиндель (continuous) → патрон → заготовка Осторожно, если шпиндель работает и как ось C. Тип шарнира
называется один раз: шпиндель — это continuous, вращение без границ.
Пределы и подача оси C живут отдельным полем паспорта, а не вторым шарниром на том же
валу. Иначе получится одно имя с двумя смыслами — и разъедется не значение, а смысл.
STEPМеханизм из сборки STEP
Интеграторы приносят STEP, а не робо-описания. Договор жёсткий и проверяется
интерфейсом: структура сборки — это кинематическое дерево. Подсборка цепи
становится звеном, её трансформация — положением шарнира; всё, что внутри подсборки, —
тело звена.
Родитель и origin приходят из структуры даром. Человеку остаются три вещи:
тип шарнира, ось и пределы. Дальше — тот же единственный судья и тот же
дом, что у принесённого URDF.
Отказ говорит, что сделать, и называет узлы из вашей же модели: «в корне 47 деталей и
ноль подсборок — сгруппируйте подвижные узлы». Замкнутую цепь договор не спасает:
у платформы гексапода шесть родителей, дерева нет в принципе, и здесь отказ честен.
Ручки: POST /api/automation/rigs/{id}/mechanism/from-step
и POST /api/machines/{id}/step. Сегодняшние входы механизма — URDF,
xacro и STEP.
ОбразцыГалерея готовых механизмов
11 образцов, которые можно взять и посмотреть, как выглядит
правильно описанный узел. Часть — наши черновики, часть — доноры ROS. Учебные: паспортом оборудования они не являются, числа из них цитировать
как замер нельзя.
Образец Что показывает Файлы каталога Мешей Рука ALLEX семиосевой манипулятор, вырезанный из чужого гуманоида механизм · паспорт · программа · спека 8 Конвейер (транспортёр) ЧЕРНОВИК, напечатанный нами механизм · паспорт · программа · спека — Конвейер с рамой ГИБРИД: чужой меш + наше подвижное звено механизм · паспорт · программа · спека 1 Ewellix TLT ЛИНЕЙНАЯ ОСЬ (телескопическая подъёмная колонна), 2 ступени механизм · карта имён · паспорт 51 FLIR PTU-D46 ПОВОРОТНАЯ ГОЛОВА (pan-tilt), 2 оси механизм · карта имён · паспорт 5 Портал 3 оси + захват ЧЕРНОВИК, напечатанный нами механизм · паспорт · программа · спека — KUKA KR16 РУКА как узел автоматики, 6 поворотных осей механизм · карта имён · паспорт · программа · спека 6 MotoPos D500 ПОЗИЦИОНЕР (поворотно-наклонный стол), 2 оси механизм · карта имён · паспорт 6 Robotiq 2F-85 ЗАХВАТ (двухпальцевый параллельный), ОДИН привод механизм · карта имён · паспорт 13 Поворотный делительный стол ЧЕРНОВИК, напечатанный нами механизм · паспорт · программа · спека — Кран-штабелёр (склад) ЧЕРНОВИК, напечатанный нами механизм · паспорт · программа · спека —
Доноры взяты из открытых репозиториев ROS с зафиксированным коммитом и датой загрузки;
лицензия и источник указаны рядом с каждым. Все образцы проходят тот же интерфейс приёма, что и
ваш файл: образец, не проходящий её, означает ошибку либо в образце, либо в правиле.
Дальше — типы станков
и кинематики: какая порода что умеет и почему гексапод программируется движениями,
но не режет по G-code.