framework/docs/scene_generator.md

435 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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

## Мета-модель фреймворка
## Соответствие Digital Twin Definition Language и мета-модели Robossembler
Слои абстракции
1. DTDL - BASETYPES, COMPLEXTYPES (Array, Map, ...), DT_TYPES
2. ROBOSSEMBLER_CONTEXT (Represents)
3. USE_CASE_CONTEXT (Entities)
4. USE_CASE_INSTANCE (Product)
## Сравнение мета-моделей Digital Twin Definition Language и ROS 2
| Сущность | DTDL | ROS | Robonomics |
| - | - | - | - |
| Описывает всё содержимое двойника, включая ниже приведённые сущности | **Interface** | **Interface Spec** | - |
| Передаваемые данные и их тип | **Telemetry** | **Topic** | **Datalog Hash** |
| Свойство, описывающее какое-то состояние двойника, может быть read-only или read/write; также описывает синхронизацию состояния между компонентами (например, показание датчика записано в облако) | **Property** | **Parameters** | **Launch Param** |
| Функция или операция, которая может быть осуществлена над двойником (например, `reboot`) | **Command** | **Service** / **Action** | **Launch** |
| Структура из примитивных типов (Array, Enum, Map, Object) данных для сериализации (в JSON, Avro, Protobuf) | **Schema** | **IDL** | - |
| Часть интерфейса (отношение part-of с каким-то другим двойником) | **Component** | - | - |
| Связь с другим цифровым двойником. Связи могут представлять различные семантические значения. Например, `contains` ("этаж содержит комнату"), `cools` ("hvac cools room"), `isBilledTo` ("счёт выставляется пользователю") | **Relationship** | - | - |
```json
# базовые типы значений (из JSON Schema)
"string","number", "boolean", "array", "object";
{
"type": "object",
"properties": {
"REPRESENT": {
"type": {
"enum": [ "OBJECT_LINK", "KEY", "FILEPATH", "VALUE", "TREE", "ARRAY", "SEQUENCE" ]
}
}
}
}
# представления
ENUM REPRESENT = "OBJECT_LINK", # строка-ссылка на объект (ENTITY)
"KEY", # уникальный ключ в виде строки (используется как идентификатор записи)
"FILEPATH", # строка - путь к файлу
"VALUE", # непосредственное значение
"TREE", # представление в виде дерева
"ARRAY", # массив значений
"SEQUENCE"; # массив ссылок на объект определённого типа
# сущности
ENUM ENTITY = "MESH", "PART", "ASSET", "BTREE", "BTACTION", "SKILL", "DATASET", "INTERFACE", "WEIGHTS", "DEVICE";
ENUM DEVICE = "ROBOT", "SENSOR";
type SCENE = {
"objects": [ { ref: "1", type: "PART" }; { ref: "2", type: "PART" }; ]
};
type PARAM = {
"sid": \${KEY:string:""},
"name": \${NAME:string:""},
"represent": \${REPRESENT:Enum<REPRESENT>:"VALUE"},
"link": \${LINK:Enum<LINK>:"topic"}
};
### тип поверхность детали
type MESH/SURFACE = {
"sid": \${KEY:string:""};
"path": { "stl": "PATH/*.stl", "brep": "PATH/*.brep", "fbx": "PATH/*.fbx", }
};
type PART = {
"sid": \${NAME:string:""},
"name": \${NAME:string:""},
"pose6d": { "loc_xyz": \${XYZ:Array<number>3:[0.0,0.0,0.0] }, "rot_xyzw": \${XYZW:Array<number>4:[0.0,0.0,0.0,1.0]} },
"attributes": [
"Robossembler_NonSolid": True
],
"surface": { "stl": "PATH/*.stl", "brep": "PATH/*.brep", },
"material": "/path/to/robossembler/materials/mmm.FCMat",
"unit_scale": \${UNIT_SCALE:number:1.0},
"dimensions": \${Array<number>3:[0.0,0.0,0.0]},
"assets": { "fbx": "PATH/*.fbx", "blend": "PATH/*.blend", }
};
type DATASET = {
"sid": \${NAME:string:""},
"name": \${NAME:string:""},
"objects": \${SEQUENCE:PART},
"environment": \${SEQUENCE:PART},
"randomisation": \${FILE}
};
type WEIGHTS = {
"sid": \${NAME:string:""},
"name": \${NAME:string:""},
"file": \${FILE:string:"*.pth"},
"epoch": \${EPOCH:number:""},
"dataset": \${OBJECT_LINK:DATASET}
};
type TOPIC = {
"sid": ...,
"name": "topic_name",
"msg": "sensor_msgs/Image",
};
DEVICE = {
"sid": 1235,
"name": "dev",
"topics": \${SEQUENCE:TOPIC},
}
// DEVICE -> TOPIC LIST -> {DEVICE: {TOPIC LIST}}
type POSE_ESTIMATION = {
"object_name": \${OBJECT_LINK:PART},
"weights": \${OBJECT_LINK:WEIGHTS},
"topic_name": \${OBJECT_LINK:TOPIC}
};
type SKILL = {
"sid": \${NAME:string:""},
"name": \${NAME:string:""},
"interface": \${INTERFACE}
};
command_LifeCycle = "run", "stop"
type ASSEMBLY_SEQUENCE = \{SEQUENCE:TASK};
# task1 = { source_state = []; target_state = [ p1 ] }
# task2 = { source_state = [ p1 ]; target_state = [ p1 p2 ] }
# task3 = { source_state = [ p1 p2 ]; target_state = [ p1 p2 p3 ] }
task = { source_state = \${TREE:PART}; target_state = \${TREE:PART} }
type TASK = {
"sid": ...
"action": \${BT_TREE}
"source_state": \${TREE:PART} // PART
"target_state": \${TREE:PART} // PRODUCT
};
type DOMAIN = {
"objects": \{SEQUENCE:PART}
"predicates": \{OBJECT_LINK:CONDITION}
"actions": \${OBJECT_LINK:BT_ACTION}
};
type BTREE = {
"sid": \${NAME:string:""},
"name": \${NAME:string:""},
};
```
## Device Package
### Camera
```json
{
"DevicePackage": { "name": "Robossembler", "version": "1.0", "format": "1" },
"Module": { "name": "RealSense Dxx", "description": "ROS Wrapper for Intel(R) RealSense(TM) Cameras" },
"Launch": { "package": "realsense2_camera", "executable": "rs_launch.py" },
"DTwin": [
{ "interface": {
"input": [
{ "name": "camera_namespace", "type": "STRING" }, // -- /robot_drawer/455_1/camera_info
{ "name": "camera_name", "type": "STRING" },
{ "name": "serial_port", "type": "STRING" },
],
"output": [
{ "name": "camera_info", "type": "TOPIC", "topic_name": "/${camera_namespace}/${camera_name}/camera_info" },
{ "name": "pose", "type": "TOPIC", "msg": "Pose" }
]
},
}
],
"Settings": [
{ "name": "camera_config", "description": "Camera Config", "type":"file", "defaultValue": "{ rgb_camera.profile: 1280x720x15 }" }
]
}
```
### Robot RBS
```json
{
"DevicePackage": { "name": "Robossembler", "version": "1.0", "format": "1" },
"Module": { "name": "RBS", "description": "Main Robot" },
"Launch": { "package": "rbs_bringup", "executable": "single_robot.launch.py" },
"DTwin": [
{ "interface": {
"input": [
{ "name": "robot_namespace", "type": "STRING", "defaultValue": "rbs_arm" },
{ "name": "dof", "type": "INT", "defaultValue": 6 }
]
}
}
],
"Settings": [
{ "name": "robot_type", "description": "Type of robot by name", "defaultValue": "rbs_arm" }
]
}
```
### Robot UR5
```json
{
"DevicePackage": { "name": "Robossembler", "version": "1.0", "format": "1" },
"Module": { "name": "UR", "description": "..." },
"Launch": { "package": "ur_package", "executable": "ur5_single_arm.py" },
"DTwin": [
{ "interface": {
"input": [
{ "robot_namespace": "robot1" },
],
},
}
],
"Settings": [
{ "name": "", "description": "Config", "type":"file", "defaultValue": "{}" }
]
}
```
```json
{
"SkillPackage": { "name": "Robossembler", "version": "1.0", "format": "1" },
"Module": { "name": "PoseEstimation", "description": "Pose Estimation skill with DOPE" },
"Launch": { "package": "rbs_perception", "executable": "pe_dope_lc.py", "name": "lc_dope" },
"BTAction": [
{ "name": "peConfigure",
"type": "run",
"interface": {
"input": [
{ "name": "image_raw", "type": "TOPIC", "msg": "Image" },
{ "name": "camera_info", "type": "TOPIC", "msg": "CameraInfo" },
{ "name": "object_name", "type": "PART", "msgs": "Part" }, // string
{ "name": "weights", "type": "WEIGHTS", "msgs": "" },
],
"output": [
{ "name": "pose_estimation", "type": "TOPIC" },
]
},
},
{ "name": "peStop", "type": "stop", "interface": { "input": [], "output": [] } }
],
"Settings": [
{ "name": "publishDelay", "description": "Publish Delay", "type":"float", "defaultValue": 0.5 },
{ "name": "tf2_send_pose", "description": "Transform Pose", "type":"int", "defaultValue": 1 },
{ "name": "mesh_scale", "description": "Part Mesh Scale", "type":"float", "defaultValue": 0.001 }
]
}
```
## Атомарные навыки
```xml
<TreeNodesModel>
<SubTree ID="GraspObject">
<input_port default="false" name="__shared_blackboard"></input_port>
<input_port name="pose_vec"/>
<input_port name="robot_name"/>
</SubTree>
<Action ID="GripperAction">
<input_port name="action">Open or close</input_port>
<input_port name="gripper_name"/>
</Action>
<SubTree ID="InspectWorkspace">
<input_port default="true" name="__shared_blackboard">
<input_port name="pose_vec"/>
<input_port name="robot_name"/>
</SubTree>
<Condition ID="IsObjectInWorkspace">
<input_port name="topic_name"/>
</Condition>
<Condition ID="IsObjectVisible"/>
<Action ID="MoveToPose">
<input_port name="cancel_timeout"/>
<input_port name="pose"/>
<input_port name="robot_name"/>
<input_port name="server_name"/>
<input_port name="server_timeout"/>
</Action>
<Action ID="MoveToPoseArray">
<input_port name="cancel_timeout"/>
<input_port name="pose_vec_in"/>
<output_port name="pose_vec_out"/>
<input_port name="robot_name"/>
<input_port name="server_name"/>
<input_port name="server_timeout"/>
</Action>
<SubTree ID="PlaceObject">
<input_port default="true" name="__shared_blackboard"></input_port>
<input_port name="pose_vec"/>
<input_port name="robot_name"/>
</SubTree>
<Action ID="PoseEstimationCleanup"/>
<Action ID="PoseEstimationConfigure">
<input_port name="object_name"/>
<output_port name="topic_name"/>
<input_port name="weight_file"/>
</Action>
<Action ID="RbsBtAction">
<input_port name="command"/>
<input_port name="do"/>
<input_port name="server_name"/>
<input_port name="server_timeout"/>
</Action>
</TreeNodesModel>
```
## Пример интерфейса в DTDL
```json
{
"@context": "...;3",
"@id": "robossember_assembly;1",
"@type": "Interface",
"displayName": "Bolt",
"contents": [
{
"@type": "Property",
"name": "Label",
"schema": "string"
},
{
"@type": "Property",
"name": "mesh",
"writable": true,
"schema": "string"
},
{
"@type": "Telemetry",
"name": "Pose6D",
"writable": true,
"schema": {
"@type": "Object",
"fields": [
{
"name": "x",
"schema": "double"
},
{
"name": "y",
"schema": "double"
},
{
"name": "z",
"schema": "double"
}
]
}
},
{
"@type": "Relationship",
"name": "contains",
"target": "dtmi:com:robossember_assembly:Bolt;1"
},
{
"@type": "Component",
"name": "frontCamera",
"schema": "dtmi:com:example:Camera;3"
},
]
}
```
## Пример файла описания сцены из Blender
TODO: рассписать потребность в основных элементах, что и для чего
```json
{
"assets": [
{
"name": "robo-arm",
"id": "629b29d7-fe15-428b-9014-6c3dde045af8",
"model_path": "../model.urdf"
}
],
"instances": [
// измненная URDF модель
{
"id": "0e29084f-1190-45d0-bd59-8f4ce2591gb1",
"name": "robo-arm-1",
//assetId указывает на родительский ассет
"assetId": "629b29d7-fe15-428b-9014-6c3dde045af8",
"pose": {
"x": 12.0,
"y": 1.0,
"z": 4.0,
"roll": 1.0,
"pitch": 4.0,
"yaw": 5.0
},
//если изменено внутренее состояние URDF модели
"tags": [
"<joint name=\"robotiq_85_right_finger_joint\" type=\"fixed\"><parent link=\"robotiq_85_right_knuckle_link\"/><child link=\"robotiq_85_right_finger_link\"/><origin rpy=\"0 0 0\" xyz=\"-0.03152616 0.0 -0.00376347\"/></joint>"
]
},
{
"id": "0e27984f-8890-4d90-bd59-8f4ce29920f9",
"name": "robo-arm-2",
//assetId указывает на родительский ассет
"assetId": "629b29d7-fe15-428b-9014-6c3dde045af8",
//если дефолтные позиции модели
"pose": null,
//если не изменено внутренее состояние URDF модели
"tags": null
},
{
"type": "LIGHT",
"light_type": "SPOT",
"power": 10.0,
"spot_angle": 45.0,
"name": null,
"pose": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"roll": 0.0,
"pitch": 0.0,
"yaw": 0.0
}
}
]
}
```