mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2026-02-06 06:25:06 +00:00
Compare commits
8 Commits
a1e9332b51
...
dfc635189c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfc635189c | ||
|
|
d8f3ebac15 | ||
|
|
4a1e703a3a | ||
|
|
55d22a7c29 | ||
|
|
03a4e4ecba | ||
|
|
2316c34cb5 | ||
|
|
a8887161d3 | ||
|
|
25834f5ba0 |
8
.github/workflows/conda-pack-build.yml
vendored
8
.github/workflows/conda-pack-build.yml
vendored
@@ -242,6 +242,10 @@ jobs:
|
||||
echo Adding: verify_installation.py
|
||||
copy scripts\verify_installation.py dist-package\
|
||||
|
||||
rem Copy source code repository (including .git)
|
||||
echo Adding: Uni-Lab-OS source repository
|
||||
robocopy . dist-package\Uni-Lab-OS /E /XD dist-package /NFL /NDL /NJH /NJS /NC /NS || if %ERRORLEVEL% LSS 8 exit /b 0
|
||||
|
||||
rem Create README using Python script
|
||||
echo Creating: README.txt
|
||||
python scripts\create_readme.py ${{ matrix.platform }} ${{ github.event.inputs.branch }} dist-package\README.txt
|
||||
@@ -274,6 +278,10 @@ jobs:
|
||||
echo "Adding: verify_installation.py"
|
||||
cp scripts/verify_installation.py dist-package/
|
||||
|
||||
# Copy source code repository (including .git)
|
||||
echo "Adding: Uni-Lab-OS source repository"
|
||||
rsync -a --exclude='dist-package' . dist-package/Uni-Lab-OS
|
||||
|
||||
# Create README using Python script
|
||||
echo "Creating: README.txt"
|
||||
python scripts/create_readme.py ${{ matrix.platform }} ${{ github.event.inputs.branch }} dist-package/README.txt
|
||||
|
||||
@@ -170,7 +170,12 @@
|
||||
"z": 0
|
||||
},
|
||||
"config": {
|
||||
"max_volume": 1000.0
|
||||
"max_volume": 1000.0,
|
||||
"type": "RegularContainer",
|
||||
"category": "container",
|
||||
"size_x": 200,
|
||||
"size_y": 150,
|
||||
"size_z": 0
|
||||
},
|
||||
"data": {
|
||||
"liquids": [
|
||||
@@ -194,7 +199,12 @@
|
||||
"z": 0
|
||||
},
|
||||
"config": {
|
||||
"max_volume": 1000.0
|
||||
"max_volume": 1000.0,
|
||||
"type": "RegularContainer",
|
||||
"category": "container",
|
||||
"size_x": 200,
|
||||
"size_y": 150,
|
||||
"size_z": 0
|
||||
},
|
||||
"data": {
|
||||
"liquids": [
|
||||
@@ -218,7 +228,12 @@
|
||||
"z": 0
|
||||
},
|
||||
"config": {
|
||||
"max_volume": 1000.0
|
||||
"max_volume": 1000.0,
|
||||
"type": "RegularContainer",
|
||||
"category": "container",
|
||||
"size_x": 300,
|
||||
"size_y": 150,
|
||||
"size_z": 0
|
||||
},
|
||||
"data": {
|
||||
"liquids": [
|
||||
@@ -242,7 +257,12 @@
|
||||
"z": 0
|
||||
},
|
||||
"config": {
|
||||
"max_volume": 1000.0
|
||||
"max_volume": 1000.0,
|
||||
"type": "RegularContainer",
|
||||
"category": "container",
|
||||
"size_x": 900,
|
||||
"size_y": 150,
|
||||
"size_z": 0
|
||||
},
|
||||
"data": {
|
||||
"liquids": [
|
||||
@@ -266,7 +286,12 @@
|
||||
"z": 0
|
||||
},
|
||||
"config": {
|
||||
"max_volume": 1000.0
|
||||
"max_volume": 1000.0,
|
||||
"type": "RegularContainer",
|
||||
"category": "container",
|
||||
"size_x": 950,
|
||||
"size_y": 150,
|
||||
"size_z": 0
|
||||
},
|
||||
"data": {
|
||||
"liquids": [
|
||||
@@ -335,6 +360,8 @@
|
||||
},
|
||||
"config": {
|
||||
"max_volume": 500.0,
|
||||
"type": "RegularContainer",
|
||||
"category": "container",
|
||||
"max_temp": 200.0,
|
||||
"min_temp": -20.0,
|
||||
"has_stirrer": true,
|
||||
@@ -419,7 +446,12 @@
|
||||
"z": 0
|
||||
},
|
||||
"config": {
|
||||
"max_volume": 2000.0
|
||||
"max_volume": 2000.0,
|
||||
"type": "RegularContainer",
|
||||
"category": "container",
|
||||
"size_x": 500,
|
||||
"size_y": 400,
|
||||
"size_z": 0
|
||||
},
|
||||
"data": {
|
||||
"liquids": [
|
||||
@@ -439,7 +471,12 @@
|
||||
"z": 0
|
||||
},
|
||||
"config": {
|
||||
"max_volume": 2000.0
|
||||
"max_volume": 2000.0,
|
||||
"type": "RegularContainer",
|
||||
"category": "container",
|
||||
"size_x": 1100,
|
||||
"size_y": 500,
|
||||
"size_z": 0
|
||||
},
|
||||
"data": {
|
||||
"liquids": [
|
||||
@@ -649,7 +686,12 @@
|
||||
"z": 0
|
||||
},
|
||||
"config": {
|
||||
"max_volume": 250.0
|
||||
"max_volume": 250.0,
|
||||
"type": "RegularContainer",
|
||||
"category": "container",
|
||||
"size_x": 900,
|
||||
"size_y": 500,
|
||||
"size_z": 0
|
||||
},
|
||||
"data": {
|
||||
"liquids": [
|
||||
@@ -669,7 +711,12 @@
|
||||
"z": 0
|
||||
},
|
||||
"config": {
|
||||
"max_volume": 250.0
|
||||
"max_volume": 250.0,
|
||||
"type": "RegularContainer",
|
||||
"category": "container",
|
||||
"size_x": 950,
|
||||
"size_y": 500,
|
||||
"size_z": 0
|
||||
},
|
||||
"data": {
|
||||
"liquids": [
|
||||
@@ -689,7 +736,12 @@
|
||||
"z": 0
|
||||
},
|
||||
"config": {
|
||||
"max_volume": 250.0
|
||||
"max_volume": 250.0,
|
||||
"type": "RegularContainer",
|
||||
"category": "container",
|
||||
"size_x": 1050,
|
||||
"size_y": 500,
|
||||
"size_z": 0
|
||||
},
|
||||
"data": {
|
||||
"liquids": [
|
||||
@@ -733,6 +785,11 @@
|
||||
},
|
||||
"config": {
|
||||
"max_volume": 500.0,
|
||||
"size_x": 550,
|
||||
"size_y": 250,
|
||||
"size_z": 0,
|
||||
"type": "RegularContainer",
|
||||
"category": "container",
|
||||
"reagent": "sodium_chloride",
|
||||
"physical_state": "solid"
|
||||
},
|
||||
@@ -756,6 +813,11 @@
|
||||
},
|
||||
"config": {
|
||||
"volume": 500.0,
|
||||
"size_x": 600,
|
||||
"size_y": 250,
|
||||
"size_z": 0,
|
||||
"type": "RegularContainer",
|
||||
"category": "container",
|
||||
"reagent": "sodium_carbonate",
|
||||
"physical_state": "solid"
|
||||
},
|
||||
@@ -779,6 +841,11 @@
|
||||
},
|
||||
"config": {
|
||||
"volume": 500.0,
|
||||
"size_x": 650,
|
||||
"size_y": 250,
|
||||
"size_z": 0,
|
||||
"type": "RegularContainer",
|
||||
"category": "container",
|
||||
"reagent": "magnesium_chloride",
|
||||
"physical_state": "solid"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@ container:
|
||||
- container
|
||||
class:
|
||||
module: unilabos.resources.container:RegularContainer
|
||||
type: unilabos
|
||||
type: pylabrobot
|
||||
description: regular organic container
|
||||
handles:
|
||||
- data_key: fluid_in
|
||||
|
||||
@@ -1,67 +1,81 @@
|
||||
import json
|
||||
|
||||
from pylabrobot.resources import Container
|
||||
from unilabos_msgs.msg import Resource
|
||||
|
||||
from unilabos.ros.msgs.message_converter import convert_from_ros_msg
|
||||
|
||||
|
||||
class RegularContainer(object):
|
||||
# 第一个参数必须是id传入
|
||||
# noinspection PyShadowingBuiltins
|
||||
def __init__(self, id: str):
|
||||
self.id = id
|
||||
self.ulr_resource = Resource()
|
||||
self._data = None
|
||||
class RegularContainer(Container):
|
||||
def __init__(self, *args, **kwargs):
|
||||
if "size_x" not in kwargs:
|
||||
kwargs["size_x"] = 0
|
||||
if "size_y" not in kwargs:
|
||||
kwargs["size_y"] = 0
|
||||
if "size_z" not in kwargs:
|
||||
kwargs["size_z"] = 0
|
||||
self.kwargs = kwargs
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@property
|
||||
def ulr_resource_data(self):
|
||||
if self._data is None:
|
||||
self._data = json.loads(self.ulr_resource.data) if self.ulr_resource.data else {}
|
||||
return self._data
|
||||
|
||||
@ulr_resource_data.setter
|
||||
def ulr_resource_data(self, value: dict):
|
||||
self._data = value
|
||||
self.ulr_resource.data = json.dumps(self._data)
|
||||
|
||||
@property
|
||||
def liquid_type(self):
|
||||
return self.ulr_resource_data.get("liquid_type", None)
|
||||
|
||||
@liquid_type.setter
|
||||
def liquid_type(self, value: str):
|
||||
if value is not None:
|
||||
self.ulr_resource_data["liquid_type"] = value
|
||||
else:
|
||||
self.ulr_resource_data.pop("liquid_type", None)
|
||||
|
||||
@property
|
||||
def liquid_volume(self):
|
||||
return self.ulr_resource_data.get("liquid_volume", None)
|
||||
|
||||
@liquid_volume.setter
|
||||
def liquid_volume(self, value: float):
|
||||
if value is not None:
|
||||
self.ulr_resource_data["liquid_volume"] = value
|
||||
else:
|
||||
self.ulr_resource_data.pop("liquid_volume", None)
|
||||
|
||||
def get_ulr_resource(self) -> Resource:
|
||||
"""
|
||||
获取UlrResource对象
|
||||
:return: UlrResource对象
|
||||
"""
|
||||
self.ulr_resource_data = self.ulr_resource_data # 确保数据被更新
|
||||
return self.ulr_resource
|
||||
|
||||
def get_ulr_resource_as_dict(self) -> Resource:
|
||||
"""
|
||||
获取UlrResource对象
|
||||
:return: UlrResource对象
|
||||
"""
|
||||
to_dict = convert_from_ros_msg(self.get_ulr_resource())
|
||||
to_dict["type"] = "container"
|
||||
return to_dict
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.id}"
|
||||
#
|
||||
# class RegularContainer(object):
|
||||
# # 第一个参数必须是id传入
|
||||
# # noinspection PyShadowingBuiltins
|
||||
# def __init__(self, id: str):
|
||||
# self.id = id
|
||||
# self.ulr_resource = Resource()
|
||||
# self._data = None
|
||||
#
|
||||
# @property
|
||||
# def ulr_resource_data(self):
|
||||
# if self._data is None:
|
||||
# self._data = json.loads(self.ulr_resource.data) if self.ulr_resource.data else {}
|
||||
# return self._data
|
||||
#
|
||||
# @ulr_resource_data.setter
|
||||
# def ulr_resource_data(self, value: dict):
|
||||
# self._data = value
|
||||
# self.ulr_resource.data = json.dumps(self._data)
|
||||
#
|
||||
# @property
|
||||
# def liquid_type(self):
|
||||
# return self.ulr_resource_data.get("liquid_type", None)
|
||||
#
|
||||
# @liquid_type.setter
|
||||
# def liquid_type(self, value: str):
|
||||
# if value is not None:
|
||||
# self.ulr_resource_data["liquid_type"] = value
|
||||
# else:
|
||||
# self.ulr_resource_data.pop("liquid_type", None)
|
||||
#
|
||||
# @property
|
||||
# def liquid_volume(self):
|
||||
# return self.ulr_resource_data.get("liquid_volume", None)
|
||||
#
|
||||
# @liquid_volume.setter
|
||||
# def liquid_volume(self, value: float):
|
||||
# if value is not None:
|
||||
# self.ulr_resource_data["liquid_volume"] = value
|
||||
# else:
|
||||
# self.ulr_resource_data.pop("liquid_volume", None)
|
||||
#
|
||||
# def get_ulr_resource(self) -> Resource:
|
||||
# """
|
||||
# 获取UlrResource对象
|
||||
# :return: UlrResource对象
|
||||
# """
|
||||
# self.ulr_resource_data = self.ulr_resource_data # 确保数据被更新
|
||||
# return self.ulr_resource
|
||||
#
|
||||
# def get_ulr_resource_as_dict(self) -> Resource:
|
||||
# """
|
||||
# 获取UlrResource对象
|
||||
# :return: UlrResource对象
|
||||
# """
|
||||
# to_dict = convert_from_ros_msg(self.get_ulr_resource())
|
||||
# to_dict["type"] = "container"
|
||||
# return to_dict
|
||||
#
|
||||
# def __str__(self):
|
||||
# return f"{self.id}"
|
||||
@@ -781,6 +781,7 @@ def initialize_resource(resource_config: dict, resource_type: Any = None) -> Uni
|
||||
else:
|
||||
r = resource_plr
|
||||
elif resource_class_config["type"] == "unilabos":
|
||||
raise ValueError(f"No more support for unilabos Resource class {resource_class_config}")
|
||||
res_instance: RegularContainer = RESOURCE(id=resource_config["name"])
|
||||
res_instance.ulr_resource = convert_to_ros_msg(
|
||||
Resource, {k: v for k, v in resource_config.items() if k != "class"}
|
||||
|
||||
@@ -306,10 +306,7 @@ class ResourceTreeSet(object):
|
||||
replace_info = {
|
||||
"plate": "plate",
|
||||
"well": "well",
|
||||
"tip_spot": "container",
|
||||
"trash": "container",
|
||||
"deck": "deck",
|
||||
"tip_rack": "container",
|
||||
}
|
||||
if source in replace_info:
|
||||
return replace_info[source]
|
||||
@@ -388,7 +385,7 @@ class ResourceTreeSet(object):
|
||||
import inspect
|
||||
|
||||
# 类型映射
|
||||
TYPE_MAP = {"plate": "plate", "well": "well", "container": "tip_spot", "deck": "deck", "tip_rack": "tip_rack"}
|
||||
TYPE_MAP = {"plate": "Plate", "well": "Well", "deck": "Deck"}
|
||||
|
||||
def collect_node_data(node: ResourceDictInstance, name_to_uuid: dict, all_states: dict):
|
||||
"""一次遍历收集 name_to_uuid 和 all_states"""
|
||||
@@ -400,13 +397,13 @@ class ResourceTreeSet(object):
|
||||
def node_to_plr_dict(node: ResourceDictInstance, has_model: bool):
|
||||
"""转换节点为 PLR 字典格式"""
|
||||
res = node.res_content
|
||||
plr_type = TYPE_MAP.get(res.type, "tip_spot")
|
||||
plr_type = TYPE_MAP.get(res.type, res.type)
|
||||
if res.type not in TYPE_MAP:
|
||||
logger.warning(f"未知类型 {res.type},使用默认类型 tip_spot")
|
||||
|
||||
d = {
|
||||
"name": res.name,
|
||||
"type": plr_type,
|
||||
"type": res.type,
|
||||
"size_x": res.config.get("size_x", 0),
|
||||
"size_y": res.config.get("size_y", 0),
|
||||
"size_z": res.config.get("size_z", 0),
|
||||
@@ -417,7 +414,7 @@ class ResourceTreeSet(object):
|
||||
"type": "Coordinate",
|
||||
},
|
||||
"rotation": {"x": 0, "y": 0, "z": 0, "type": "Rotation"},
|
||||
"category": plr_type,
|
||||
"category": res.config.get("category", plr_type),
|
||||
"children": [node_to_plr_dict(child, has_model) for child in node.children],
|
||||
"parent_name": res.parent_instance_name,
|
||||
**res.config,
|
||||
@@ -439,7 +436,7 @@ class ResourceTreeSet(object):
|
||||
try:
|
||||
sub_cls = find_subclass(plr_dict["type"], PLRResource)
|
||||
if sub_cls is None:
|
||||
raise ValueError(f"无法找到类型 {plr_dict['type']} 对应的 PLR 资源类")
|
||||
raise ValueError(f"无法找到类型 {plr_dict['type']} 对应的 PLR 资源类。原始信息:{tree.root_node.res_content}")
|
||||
spec = inspect.signature(sub_cls)
|
||||
if "category" not in spec.parameters:
|
||||
plr_dict.pop("category", None)
|
||||
|
||||
Reference in New Issue
Block a user