Merge dptech/workstation_dev_YB4: resolve conflicts by keeping local changes (ours)

This commit is contained in:
dijkstra402
2025-12-22 11:09:17 +08:00
28 changed files with 19433 additions and 622 deletions

View File

@@ -0,0 +1,653 @@
from pylabrobot.resources import create_homogeneous_resources, Coordinate, ResourceHolder, create_ordered_items_2d
from unilabos.resources.itemized_carrier import Bottle, BottleCarrier
from unilabos.resources.bioyond.YB_bottles import (
YB_jia_yang_tou_da,
YB_ye_Bottle,
YB_ye_100ml_Bottle,
YB_gao_nian_ye_Bottle,
YB_5ml_fenyeping,
YB_20ml_fenyeping,
YB_pei_ye_xiao_Bottle,
YB_pei_ye_da_Bottle,
YB_qiang_tou,
)
# 命名约定:试剂瓶-Bottle烧杯-Beaker烧瓶-Flask小瓶-Vial
def BIOYOND_Electrolyte_6VialCarrier(name: str) -> BottleCarrier:
"""6瓶载架 - 2x3布局"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 50.0
# 瓶位尺寸
bottle_diameter = 30.0
bottle_spacing_x = 42.0 # X方向间距
bottle_spacing_y = 35.0 # Y方向间距
# 计算起始位置 (居中排列)
start_x = (carrier_size_x - (3 - 1) * bottle_spacing_x - bottle_diameter) / 2
start_y = (carrier_size_y - (2 - 1) * bottle_spacing_y - bottle_diameter) / 2
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=3,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="Electrolyte_6VialCarrier",
)
carrier.num_items_x = 3
carrier.num_items_y = 2
carrier.num_items_z = 1
# for i in range(6):
# carrier[i] = YB_Solid_Vial(f"{name}_vial_{i+1}")
return carrier
def BIOYOND_Electrolyte_1BottleCarrier(name: str) -> BottleCarrier:
"""1瓶载架 - 单个中央位置"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 100.0
# 烧杯尺寸
beaker_diameter = 80.0
# 计算中央位置
center_x = (carrier_size_x - beaker_diameter) / 2
center_y = (carrier_size_y - beaker_diameter) / 2
center_z = 5.0
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=create_homogeneous_resources(
klass=ResourceHolder,
locations=[Coordinate(center_x, center_y, center_z)],
resource_size_x=beaker_diameter,
resource_size_y=beaker_diameter,
name_prefix=name,
),
model="Electrolyte_1BottleCarrier",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
# carrier[0] = YB_Solution_Beaker(f"{name}_beaker_1")
return carrier
def YB_6StockCarrier(name: str) -> BottleCarrier:
"""6瓶载架 - 2x3布局"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 50.0
# 瓶位尺寸
bottle_diameter = 20.0
bottle_spacing_x = 42.0 # X方向间距
bottle_spacing_y = 35.0 # Y方向间距
# 计算起始位置 (居中排列)
start_x = (carrier_size_x - (3 - 1) * bottle_spacing_x - bottle_diameter) / 2
start_y = (carrier_size_y - (2 - 1) * bottle_spacing_y - bottle_diameter) / 2
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=3,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="6StockCarrier",
)
carrier.num_items_x = 3
carrier.num_items_y = 2
carrier.num_items_z = 1
ordering = ["A1", "A2", "A3", "B1", "B2", "B3"] # 自定义顺序
# for i in range(6):
# carrier[i] = YB_Solid_Stock(f"{name}_vial_{ordering[i]}")
return carrier
def YB_6VialCarrier(name: str) -> BottleCarrier:
"""6瓶载架 - 2x3布局"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 50.0
# 瓶位尺寸
bottle_diameter = 30.0
bottle_spacing_x = 42.0 # X方向间距
bottle_spacing_y = 35.0 # Y方向间距
# 计算起始位置 (居中排列)
start_x = (carrier_size_x - (3 - 1) * bottle_spacing_x - bottle_diameter) / 2
start_y = (carrier_size_y - (2 - 1) * bottle_spacing_y - bottle_diameter) / 2
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=3,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="6VialCarrier",
)
carrier.num_items_x = 3
carrier.num_items_y = 2
carrier.num_items_z = 1
ordering = ["A1", "A2", "A3", "B1", "B2", "B3"] # 自定义顺序
# for i in range(3):
# carrier[i] = YB_Solid_Vial(f"{name}_solidvial_{ordering[i]}")
# for i in range(3, 6):
# carrier[i] = YB_Liquid_Vial(f"{name}_liquidvial_{ordering[i]}")
return carrier
# 1瓶载架 - 单个中央位置
def YB_ye(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 20.0
# 烧杯尺寸
beaker_diameter = 60.0
# 计算中央位置
center_x = (carrier_size_x - beaker_diameter) / 2
center_y = (carrier_size_y - beaker_diameter) / 2
center_z = 5.0
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=create_homogeneous_resources(
klass=ResourceHolder,
locations=[Coordinate(center_x, center_y, center_z)],
resource_size_x=beaker_diameter,
resource_size_y=beaker_diameter,
name_prefix=name,
),
model="YB_ye",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
carrier[0] = YB_ye_Bottle(f"{name}_flask_1")
return carrier
# 高粘液瓶载架 - 单个中央位置
def YB_gaonianye(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 20.0
# 烧杯尺寸
beaker_diameter = 60.0
# 计算中央位置
center_x = (carrier_size_x - beaker_diameter) / 2
center_y = (carrier_size_y - beaker_diameter) / 2
center_z = 5.0
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=create_homogeneous_resources(
klass=ResourceHolder,
locations=[Coordinate(center_x, center_y, center_z)],
resource_size_x=beaker_diameter,
resource_size_y=beaker_diameter,
name_prefix=name,
),
model="YB_gaonianye",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
carrier[0] = YB_gao_nian_ye_Bottle(f"{name}_flask_1")
return carrier
# 100ml液体瓶载架 - 单个中央位置
def YB_100ml_yeti(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 20.0
# 烧杯尺寸
beaker_diameter = 60.0
# 计算中央位置
center_x = (carrier_size_x - beaker_diameter) / 2
center_y = (carrier_size_y - beaker_diameter) / 2
center_z = 5.0
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=create_homogeneous_resources(
klass=ResourceHolder,
locations=[Coordinate(center_x, center_y, center_z)],
resource_size_x=beaker_diameter,
resource_size_y=beaker_diameter,
name_prefix=name,
),
model="YB_100ml_yeti",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
carrier[0] = YB_ye_100ml_Bottle(f"{name}_flask_1")
return carrier
# 5ml分液瓶板 - 4x2布局8个位置
def YB_5ml_fenyepingban(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 50.0
# 瓶位尺寸
bottle_diameter = 15.0
bottle_spacing_x = 42.0 # X方向间距
bottle_spacing_y = 35.0 # Y方向间距
# 计算起始位置 (居中排列)
start_x = (carrier_size_x - (4 - 1) * bottle_spacing_x - bottle_diameter) / 2
start_y = (carrier_size_y - (2 - 1) * bottle_spacing_y - bottle_diameter) / 2
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=4,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="YB_5ml_fenyepingban",
)
carrier.num_items_x = 4
carrier.num_items_y = 2
carrier.num_items_z = 1
ordering = ["A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4"]
for i in range(8):
carrier[i] = YB_5ml_fenyeping(f"{name}_vial_{ordering[i]}")
return carrier
# 20ml分液瓶板 - 4x2布局8个位置
def YB_20ml_fenyepingban(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 70.0
# 瓶位尺寸
bottle_diameter = 20.0
bottle_spacing_x = 42.0 # X方向间距
bottle_spacing_y = 35.0 # Y方向间距
# 计算起始位置 (居中排列)
start_x = (carrier_size_x - (4 - 1) * bottle_spacing_x - bottle_diameter) / 2
start_y = (carrier_size_y - (2 - 1) * bottle_spacing_y - bottle_diameter) / 2
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=4,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="YB_20ml_fenyepingban",
)
carrier.num_items_x = 4
carrier.num_items_y = 2
carrier.num_items_z = 1
ordering = ["A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4"]
for i in range(8):
carrier[i] = YB_20ml_fenyeping(f"{name}_vial_{ordering[i]}")
return carrier
# 配液瓶(小)板 - 4x2布局8个位置
def YB_peiyepingxiaoban(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 65.0
# 瓶位尺寸
bottle_diameter = 35.0
bottle_spacing_x = 42.0 # X方向间距
bottle_spacing_y = 35.0 # Y方向间距
# 计算起始位置 (居中排列)
start_x = (carrier_size_x - (4 - 1) * bottle_spacing_x - bottle_diameter) / 2
start_y = (carrier_size_y - (2 - 1) * bottle_spacing_y - bottle_diameter) / 2
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=4,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="YB_peiyepingxiaoban",
)
carrier.num_items_x = 4
carrier.num_items_y = 2
carrier.num_items_z = 1
ordering = ["A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4"]
for i in range(8):
carrier[i] = YB_pei_ye_xiao_Bottle(f"{name}_bottle_{ordering[i]}")
return carrier
# 配液瓶(大)板 - 2x2布局4个位置
def YB_peiyepingdaban(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 95.0
# 瓶位尺寸
bottle_diameter = 55.0
bottle_spacing_x = 60.0 # X方向间距
bottle_spacing_y = 60.0 # Y方向间距
# 计算起始位置 (居中排列)
start_x = (carrier_size_x - (2 - 1) * bottle_spacing_x - bottle_diameter) / 2
start_y = (carrier_size_y - (2 - 1) * bottle_spacing_y - bottle_diameter) / 2
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=2,
num_items_y=2,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="YB_peiyepingdaban",
)
carrier.num_items_x = 2
carrier.num_items_y = 2
carrier.num_items_z = 1
ordering = ["A1", "A2", "B1", "B2"]
for i in range(4):
carrier[i] = YB_pei_ye_da_Bottle(f"{name}_bottle_{ordering[i]}")
return carrier
# 加样头(大)板 - 1x1布局1个位置
def YB_jia_yang_tou_da_Carrier(name: str) -> BottleCarrier:
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 95.0
# 瓶位尺寸
bottle_diameter = 35.0
bottle_spacing_x = 42.0 # X方向间距
bottle_spacing_y = 35.0 # Y方向间距
# 计算起始位置 (居中排列)
start_x = (carrier_size_x - (1 - 1) * bottle_spacing_x - bottle_diameter) / 2
start_y = (carrier_size_y - (1 - 1) * bottle_spacing_y - bottle_diameter) / 2
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=1,
num_items_y=1,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=bottle_spacing_x,
item_dy=bottle_spacing_y,
size_x=bottle_diameter,
size_y=bottle_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="YB_jia_yang_tou_da_Carrier",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
carrier[0] = YB_jia_yang_tou_da(f"{name}_head_1")
return carrier
def YB_shi_pei_qi_kuai(name: str) -> BottleCarrier:
"""适配器块 - 单个中央位置"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 30.0
# 适配器尺寸
adapter_diameter = 80.0
# 计算中央位置
center_x = (carrier_size_x - adapter_diameter) / 2
center_y = (carrier_size_y - adapter_diameter) / 2
center_z = 0.0
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=create_homogeneous_resources(
klass=ResourceHolder,
locations=[Coordinate(center_x, center_y, center_z)],
resource_size_x=adapter_diameter,
resource_size_y=adapter_diameter,
name_prefix=name,
),
model="YB_shi_pei_qi_kuai",
)
carrier.num_items_x = 1
carrier.num_items_y = 1
carrier.num_items_z = 1
# 适配器块本身不包含瓶子,只是一个支撑结构
return carrier
def YB_qiang_tou_he(name: str) -> BottleCarrier:
"""枪头盒 - 8x12布局96个位置"""
# 载架尺寸 (mm)
carrier_size_x = 127.8
carrier_size_y = 85.5
carrier_size_z = 55.0
# 枪头尺寸
tip_diameter = 10.0
tip_spacing_x = 9.0 # X方向间距
tip_spacing_y = 9.0 # Y方向间距
# 计算起始位置 (居中排列)
start_x = (carrier_size_x - (12 - 1) * tip_spacing_x - tip_diameter) / 2
start_y = (carrier_size_y - (8 - 1) * tip_spacing_y - tip_diameter) / 2
sites = create_ordered_items_2d(
klass=ResourceHolder,
num_items_x=12,
num_items_y=8,
dx=start_x,
dy=start_y,
dz=5.0,
item_dx=tip_spacing_x,
item_dy=tip_spacing_y,
size_x=tip_diameter,
size_y=tip_diameter,
size_z=carrier_size_z,
)
for k, v in sites.items():
v.name = f"{name}_{v.name}"
carrier = BottleCarrier(
name=name,
size_x=carrier_size_x,
size_y=carrier_size_y,
size_z=carrier_size_z,
sites=sites,
model="YB_qiang_tou_he",
)
carrier.num_items_x = 12
carrier.num_items_y = 8
carrier.num_items_z = 1
# 创建96个枪头
for i in range(96):
row = chr(65 + i // 12) # A-H
col = (i % 12) + 1 # 1-12
carrier[i] = YB_qiang_tou(f"{name}_tip_{row}{col}")
return carrier

View File

@@ -0,0 +1,163 @@
from unilabos.resources.itemized_carrier import Bottle, BottleCarrier
# 工厂函数
"""加样头(大)"""
def YB_jia_yang_tou_da(
name: str,
diameter: float = 20.0,
height: float = 100.0,
max_volume: float = 30000.0, # 30mL
barcode: str = None,
) -> Bottle:
"""创建粉末瓶"""
return Bottle(
name=name,
diameter=diameter,# 未知
height=height,
max_volume=max_volume,
barcode=barcode,
model="YB_jia_yang_tou_da",
)
"""液1x1"""
def YB_ye_Bottle(
name: str,
diameter: float = 40.0,
height: float = 70.0,
max_volume: float = 50000.0, # 50mL
barcode: str = None,
) -> Bottle:
"""创建液体瓶"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="YB_ye_Bottle",
)
"""100ml液体"""
def YB_ye_100ml_Bottle(
name: str,
diameter: float = 50.0,
height: float = 90.0,
max_volume: float = 100000.0, # 100mL
barcode: str = None,
) -> Bottle:
"""创建100ml液体瓶"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="YB_100ml_yeti",
)
"""高粘液"""
def YB_gao_nian_ye_Bottle(
name: str,
diameter: float = 40.0,
height: float = 70.0,
max_volume: float = 50000.0, # 50mL
barcode: str = None,
) -> Bottle:
"""创建高粘液瓶"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="High_Viscosity_Liquid",
)
"""5ml分液瓶"""
def YB_5ml_fenyeping(
name: str,
diameter: float = 20.0,
height: float = 50.0,
max_volume: float = 5000.0, # 5mL
barcode: str = None,
) -> Bottle:
"""创建5ml分液瓶"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="YB_5ml_fenyeping",
)
"""20ml分液瓶"""
def YB_20ml_fenyeping(
name: str,
diameter: float = 30.0,
height: float = 65.0,
max_volume: float = 20000.0, # 20mL
barcode: str = None,
) -> Bottle:
"""创建20ml分液瓶"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="YB_20ml_fenyeping",
)
"""配液瓶(小)"""
def YB_pei_ye_xiao_Bottle(
name: str,
diameter: float = 35.0,
height: float = 60.0,
max_volume: float = 30000.0, # 30mL
barcode: str = None,
) -> Bottle:
"""创建配液瓶(小)"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="YB_pei_ye_xiao_Bottle",
)
"""配液瓶(大)"""
def YB_pei_ye_da_Bottle(
name: str,
diameter: float = 55.0,
height: float = 100.0,
max_volume: float = 150000.0, # 150mL
barcode: str = None,
) -> Bottle:
"""创建配液瓶(大)"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="YB_pei_ye_da_Bottle",
)
"""枪头"""
def YB_qiang_tou(
name: str,
diameter: float = 10.0,
height: float = 50.0,
max_volume: float = 1000.0, # 1mL
barcode: str = None,
) -> Bottle:
"""创建枪头"""
return Bottle(
name=name,
diameter=diameter,
height=height,
max_volume=max_volume,
barcode=barcode,
model="YB_qiang_tou",
)