mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-17 21:11:12 +00:00
add electrode_sheets definition, and fix magazines
This commit is contained in:
@@ -18,70 +18,11 @@ from pylabrobot.resources.tip_rack import TipRack, TipSpot
|
|||||||
from pylabrobot.resources.trash import Trash
|
from pylabrobot.resources.trash import Trash
|
||||||
from pylabrobot.resources.utils import create_ordered_items_2d
|
from pylabrobot.resources.utils import create_ordered_items_2d
|
||||||
|
|
||||||
from unilabos.resources.battery.magazine import MagazineHolder_1, MagazineHolder_2, MagazineHolder_4, MagazineHolder_6
|
from unilabos.resources.battery.magazine import MagazineHolder_4_Cathode, MagazineHolder_6_Cathode, MagazineHolder_6_Anode, MagazineHolder_6_Battery
|
||||||
from unilabos.resources.battery.bottle_carriers import YIHUA_Electrolyte_12VialCarrier
|
from unilabos.resources.battery.bottle_carriers import YIHUA_Electrolyte_12VialCarrier
|
||||||
|
|
||||||
|
|
||||||
class ElectrodeSheetState(TypedDict):
|
|
||||||
diameter: float # 直径 (mm)
|
|
||||||
thickness: float # 厚度 (mm)
|
|
||||||
mass: float # 质量 (g)
|
|
||||||
material_type: str # 材料类型(正极、负极、隔膜、弹片、垫片、铝箔等)
|
|
||||||
height: float
|
|
||||||
electrolyte_name: str
|
|
||||||
data_electrolyte_code: str
|
|
||||||
open_circuit_voltage: float
|
|
||||||
assembly_pressure: float
|
|
||||||
electrolyte_volume: float
|
|
||||||
|
|
||||||
info: Optional[str] # 附加信息
|
|
||||||
|
|
||||||
class ElectrodeSheet(Resource):
|
|
||||||
"""极片类 - 包含正负极片、隔膜、弹片、垫片、铝箔等所有片状材料"""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
name: str = "极片",
|
|
||||||
size_x=10,
|
|
||||||
size_y=10,
|
|
||||||
size_z=10,
|
|
||||||
category: str = "electrode_sheet",
|
|
||||||
model: Optional[str] = None,
|
|
||||||
):
|
|
||||||
"""初始化极片
|
|
||||||
|
|
||||||
Args:
|
|
||||||
name: 极片名称
|
|
||||||
category: 类别
|
|
||||||
model: 型号
|
|
||||||
"""
|
|
||||||
super().__init__(
|
|
||||||
name=name,
|
|
||||||
size_x=size_x,
|
|
||||||
size_y=size_y,
|
|
||||||
size_z=size_z,
|
|
||||||
category=category,
|
|
||||||
model=model,
|
|
||||||
)
|
|
||||||
self._unilabos_state: ElectrodeSheetState = ElectrodeSheetState(
|
|
||||||
diameter=14,
|
|
||||||
thickness=0.1,
|
|
||||||
mass=0.5,
|
|
||||||
material_type="copper",
|
|
||||||
info=None
|
|
||||||
)
|
|
||||||
|
|
||||||
# TODO: 这个还要不要?给self._unilabos_state赋值的?
|
|
||||||
def load_state(self, state: Dict[str, Any]) -> None:
|
|
||||||
"""格式不变"""
|
|
||||||
super().load_state(state)
|
|
||||||
self._unilabos_state = state
|
|
||||||
#序列化
|
|
||||||
def serialize_state(self) -> Dict[str, Dict[str, Any]]:
|
|
||||||
"""格式不变"""
|
|
||||||
data = super().serialize_state()
|
|
||||||
data.update(self._unilabos_state) # Container自身的信息,云端物料将保存这一data,本地也通过这里的data进行读写,当前类用来表示这个物料的长宽高大小的属性,而data(state用来表示物料的内容,细节等)
|
|
||||||
return data
|
|
||||||
|
|
||||||
# TODO: 这个应该只能放一个极片
|
# TODO: 这个应该只能放一个极片
|
||||||
class MaterialHoleState(TypedDict):
|
class MaterialHoleState(TypedDict):
|
||||||
@@ -477,13 +418,13 @@ def TipBox64(
|
|||||||
size_x: float = 127.8,
|
size_x: float = 127.8,
|
||||||
size_y: float = 85.5,
|
size_y: float = 85.5,
|
||||||
size_z: float = 60.0,
|
size_z: float = 60.0,
|
||||||
category: str = "tip_box_64",
|
category: str = "tip_rack",
|
||||||
model: Optional[str] = None,
|
model: Optional[str] = None,
|
||||||
):
|
):
|
||||||
"""64孔枪头盒类"""
|
"""64孔枪头盒类"""
|
||||||
from pylabrobot.resources.tip import Tip
|
from pylabrobot.resources.tip import Tip
|
||||||
|
|
||||||
# 创建8x8=64个枪头位
|
# 创建12x8=96个枪头位
|
||||||
def make_tip():
|
def make_tip():
|
||||||
return Tip(
|
return Tip(
|
||||||
has_filter=False,
|
has_filter=False,
|
||||||
@@ -508,17 +449,19 @@ def TipBox64(
|
|||||||
)
|
)
|
||||||
idx_available = list(range(0, 32)) + list(range(64, 96))
|
idx_available = list(range(0, 32)) + list(range(64, 96))
|
||||||
tip_spots_available = {k: v for i, (k, v) in enumerate(tip_spots.items()) if i in idx_available}
|
tip_spots_available = {k: v for i, (k, v) in enumerate(tip_spots.items()) if i in idx_available}
|
||||||
return TipRack(
|
tip_rack = TipRack(
|
||||||
name=name,
|
name=name,
|
||||||
size_x=size_x,
|
size_x=size_x,
|
||||||
size_y=size_y,
|
size_y=size_y,
|
||||||
size_z=size_z,
|
size_z=size_z,
|
||||||
ordered_items=tip_spots_available,
|
# ordered_items=tip_spots_available,
|
||||||
|
ordered_items=tip_spots,
|
||||||
category=category,
|
category=category,
|
||||||
model=model,
|
model=model,
|
||||||
with_tips=True,
|
with_tips=False,
|
||||||
)
|
)
|
||||||
|
tip_rack.set_tip_state([True]*32 + [False]*32 + [True]*32) # 前32和后32个有枪头,中间32个无枪头
|
||||||
|
return tip_rack
|
||||||
|
|
||||||
|
|
||||||
class WasteTipBoxstate(TypedDict):
|
class WasteTipBoxstate(TypedDict):
|
||||||
@@ -629,58 +572,23 @@ class CoincellDeck(Deck):
|
|||||||
def setup(self) -> None:
|
def setup(self) -> None:
|
||||||
"""设置工作站的标准布局 - 包含子弹夹、料盘、瓶架等完整配置"""
|
"""设置工作站的标准布局 - 包含子弹夹、料盘、瓶架等完整配置"""
|
||||||
# ====================================== 子弹夹 ============================================
|
# ====================================== 子弹夹 ============================================
|
||||||
# 铝箔(1个洞位)
|
|
||||||
lvbo_zip = MagazineHolder_1("铝箔弹夹", 80, 80, 10)
|
|
||||||
self.assign_child_resource(lvbo_zip, Coordinate(x=2737.0, y=301.0, z=0))
|
|
||||||
|
|
||||||
# 正极片(4个洞位,2x2布局)
|
# 正极片(4个洞位,2x2布局)
|
||||||
zhengji_zip = MagazineHolder_4("正极弹夹", 80, 80, 10)
|
zhengji_zip = MagazineHolder_4_Cathode("正极&铝箔弹夹")
|
||||||
self.assign_child_resource(zhengji_zip, Coordinate(x=2799.0, y=356.0, z=0))
|
self.assign_child_resource(zhengji_zip, Coordinate(x=2799.0, y=356.0, z=0))
|
||||||
|
|
||||||
# 正极壳(4个洞位,2x2布局)
|
# 正极壳、平垫片(6个洞位,2x2+2布局)
|
||||||
zhengjike_zip = MagazineHolder_4("正极壳弹夹", 80, 80, 10)
|
zhengjike_zip = MagazineHolder_6_Cathode("正极壳&平垫片弹夹")
|
||||||
self.assign_child_resource(zhengjike_zip, Coordinate(x=2586.0, y=1143.0, z=0))
|
self.assign_child_resource(zhengjike_zip, Coordinate(x=2586.0, y=1143.0, z=0))
|
||||||
|
|
||||||
# 垫片(2个洞位,1x2布局)
|
# 负极壳、弹垫片(6个洞位,2x2+2布局)
|
||||||
danpian_zip = MagazineHolder_2("垫片弹夹", 80, 80, 10)
|
fujike_zip = MagazineHolder_6_Anode("负极壳&弹垫片弹夹")
|
||||||
self.assign_child_resource(danpian_zip, Coordinate(x=2690.0, y=1141.0, z=0))
|
|
||||||
|
|
||||||
# 负极壳(4个洞位,2x2布局)
|
|
||||||
fujike_zip = MagazineHolder_4("负极壳弹夹", 80, 80, 10)
|
|
||||||
self.assign_child_resource(fujike_zip, Coordinate(x=2492.0, y=1144.0, z=0))
|
self.assign_child_resource(fujike_zip, Coordinate(x=2492.0, y=1144.0, z=0))
|
||||||
|
|
||||||
# 弹片(2个洞位,1x2布局)
|
|
||||||
tanpian_zip = MagazineHolder_2("弹片弹夹", 80, 80, 10)
|
|
||||||
self.assign_child_resource(tanpian_zip, Coordinate(x=2492.0, y=1139.0, z=0))
|
|
||||||
|
|
||||||
# 成品弹夹(6个洞位,3x2布局)
|
# 成品弹夹(6个洞位,3x2布局)
|
||||||
chengpindanjia_zip = MagazineHolder_6("成品弹夹", 80, 80, 10)
|
chengpindanjia_zip = MagazineHolder_6_Battery("成品弹夹")
|
||||||
self.assign_child_resource(chengpindanjia_zip, Coordinate(x=3112.0, y=1295.0, z=0))
|
self.assign_child_resource(chengpindanjia_zip, Coordinate(x=3112.0, y=1295.0, z=0))
|
||||||
|
|
||||||
# 为子弹夹添加极片
|
|
||||||
for i in range(1): # MagazineHolder_1 有1个洞位
|
|
||||||
lvbo = ElectrodeSheet(name=f"铝箔_{i}", size_x=12, size_y=12, size_z=0.1)
|
|
||||||
lvbo_zip.children[i].assign_child_resource(lvbo, location=None)
|
|
||||||
for i in range(4): # MagazineHolder_4 有4个洞位
|
|
||||||
zhengji = ElectrodeSheet(name=f"正极_{i}", size_x=12, size_y=12, size_z=0.1)
|
|
||||||
zhengji_zip.children[i].assign_child_resource(zhengji, location=None)
|
|
||||||
for i in range(4): # MagazineHolder_4 有4个洞位
|
|
||||||
zhengjike = ElectrodeSheet(name=f"正极壳_{i}", size_x=12, size_y=12, size_z=0.1)
|
|
||||||
zhengjike_zip.children[i].assign_child_resource(zhengjike, location=None)
|
|
||||||
for i in range(2): # MagazineHolder_2 有2个洞位
|
|
||||||
danpian = ElectrodeSheet(name=f"垫片_{i}", size_x=12, size_y=12, size_z=0.1)
|
|
||||||
danpian_zip.children[i].assign_child_resource(danpian, location=None)
|
|
||||||
for i in range(4): # MagazineHolder_4 有4个洞位
|
|
||||||
fujike = ElectrodeSheet(name=f"负极壳_{i}", size_x=12, size_y=12, size_z=0.1)
|
|
||||||
fujike_zip.children[i].assign_child_resource(fujike, location=None)
|
|
||||||
for i in range(2): # MagazineHolder_2 有2个洞位
|
|
||||||
tanpian = ElectrodeSheet(name=f"弹片_{i}", size_x=12, size_y=12, size_z=0.1)
|
|
||||||
tanpian_zip.children[i].assign_child_resource(tanpian, location=None)
|
|
||||||
# for i in range(6): # MagazineHolder_6 有6个洞位
|
|
||||||
# chengpindanjia = ElectrodeSheet(name=f"成品弹夹_{i}", size_x=12, size_y=12, size_z=0.1)
|
|
||||||
# chengpindanjia_zip.children[i].assign_child_resource(chengpindanjia, location=None)
|
|
||||||
|
|
||||||
|
|
||||||
# ====================================== 物料板 ============================================
|
# ====================================== 物料板 ============================================
|
||||||
# 创建物料板(料盘carrier)- 4x4布局
|
# 创建物料板(料盘carrier)- 4x4布局
|
||||||
# 负极料盘
|
# 负极料盘
|
||||||
@@ -699,7 +607,7 @@ class CoincellDeck(Deck):
|
|||||||
|
|
||||||
# ====================================== 瓶架、移液枪 ============================================
|
# ====================================== 瓶架、移液枪 ============================================
|
||||||
# 在台面上放置 3x4 瓶架、6x2 瓶架 与 64孔移液枪头盒
|
# 在台面上放置 3x4 瓶架、6x2 瓶架 与 64孔移液枪头盒
|
||||||
# 奔耀上料5ml分液瓶小板 - 由奔曜跨站转运而来,不单独写
|
# 奔耀上料5ml分液瓶小板 - 由奔曜跨站转运而来,不单独写,但是这里应该有一个堆栈用于摆放分液瓶小板
|
||||||
|
|
||||||
# bottle_rack_3x4 = BottleRack(
|
# bottle_rack_3x4 = BottleRack(
|
||||||
# name="bottle_rack_3x4",
|
# name="bottle_rack_3x4",
|
||||||
|
|||||||
179
unilabos/resources/battery/electrode_sheet.py
Normal file
179
unilabos/resources/battery/electrode_sheet.py
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
from typing import Any, Dict, Optional, TypedDict
|
||||||
|
|
||||||
|
from pylabrobot.resources import Resource as ResourcePLR
|
||||||
|
from pylabrobot.resources import Container
|
||||||
|
|
||||||
|
|
||||||
|
electrode_colors = {
|
||||||
|
"PositiveCan": "#ff0000",
|
||||||
|
"PositiveElectrode": "#cc3333",
|
||||||
|
"NegativeCan": "#000000",
|
||||||
|
"NegativeElectrode": "#666666",
|
||||||
|
"SpringWasher": "#8b7355",
|
||||||
|
"FlatWasher": "a9a9a9",
|
||||||
|
"AluminumFoil": "#ffcccc",
|
||||||
|
"Battery": "#00ff00",
|
||||||
|
}
|
||||||
|
|
||||||
|
class ElectrodeSheetState(TypedDict):
|
||||||
|
mass: float # 质量 (g)
|
||||||
|
material_type: str # 材料类型(铜、铝、不锈钢、弹簧钢等)
|
||||||
|
color: str # 材料类型对应的颜色
|
||||||
|
|
||||||
|
|
||||||
|
class ElectrodeSheet(ResourcePLR):
|
||||||
|
"""极片类 - 包含正负极片、隔膜、弹片、垫片、铝箔等所有片状材料"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: str = "极片",
|
||||||
|
size_x=10,
|
||||||
|
size_y=10,
|
||||||
|
size_z=10,
|
||||||
|
category: str = "electrode_sheet",
|
||||||
|
model: Optional[str] = None,
|
||||||
|
):
|
||||||
|
"""初始化极片
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: 极片名称
|
||||||
|
category: 类别
|
||||||
|
model: 型号
|
||||||
|
"""
|
||||||
|
super().__init__(
|
||||||
|
name=name,
|
||||||
|
size_x=size_x,
|
||||||
|
size_y=size_y,
|
||||||
|
size_z=size_z,
|
||||||
|
category=category,
|
||||||
|
model=model,
|
||||||
|
)
|
||||||
|
self._unilabos_state: ElectrodeSheetState = ElectrodeSheetState(
|
||||||
|
diameter=14,
|
||||||
|
thickness=0.1,
|
||||||
|
mass=0.5,
|
||||||
|
material_type="copper",
|
||||||
|
info=None
|
||||||
|
)
|
||||||
|
|
||||||
|
# TODO: 这个还要不要?给self._unilabos_state赋值的?
|
||||||
|
def load_state(self, state: Dict[str, Any]) -> None:
|
||||||
|
"""格式不变"""
|
||||||
|
super().load_state(state)
|
||||||
|
self._unilabos_state = state
|
||||||
|
#序列化
|
||||||
|
def serialize_state(self) -> Dict[str, Dict[str, Any]]:
|
||||||
|
"""格式不变"""
|
||||||
|
data = super().serialize_state()
|
||||||
|
data.update(self._unilabos_state) # Container自身的信息,云端物料将保存这一data,本地也通过这里的data进行读写,当前类用来表示这个物料的长宽高大小的属性,而data(state用来表示物料的内容,细节等)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def PositiveCan(name: str) -> ElectrodeSheet:
|
||||||
|
"""创建正极壳"""
|
||||||
|
sheet = ElectrodeSheet(name=name, size_x=12, size_y=12, size_z=3.0, model="PositiveCan")
|
||||||
|
sheet.load_state({"material_type": "aluminum", "color": electrode_colors["PositiveCan"]})
|
||||||
|
return sheet
|
||||||
|
|
||||||
|
|
||||||
|
def PositiveElectrode(name: str) -> ElectrodeSheet:
|
||||||
|
"""创建正极片"""
|
||||||
|
sheet = ElectrodeSheet(name=name, size_x=10, size_y=10, size_z=0.1, model="PositiveElectrode")
|
||||||
|
sheet.load_state({"material_type": "positive_electrode", "color": electrode_colors["PositiveElectrode"]})
|
||||||
|
return sheet
|
||||||
|
|
||||||
|
|
||||||
|
def NegativeCan(name: str) -> ElectrodeSheet:
|
||||||
|
"""创建负极壳"""
|
||||||
|
sheet = ElectrodeSheet(name=name, size_x=12, size_y=12, size_z=2.0, model="NegativeCan")
|
||||||
|
sheet.load_state({"material_type": "steel", "color": electrode_colors["NegativeCan"]})
|
||||||
|
return sheet
|
||||||
|
|
||||||
|
|
||||||
|
def NegativeElectrode(name: str) -> ElectrodeSheet:
|
||||||
|
"""创建负极片"""
|
||||||
|
sheet = ElectrodeSheet(name=name, size_x=10, size_y=10, size_z=0.1, model="NegativeElectrode")
|
||||||
|
sheet.load_state({"material_type": "negative_electrode", "color": electrode_colors["NegativeElectrode"]})
|
||||||
|
return sheet
|
||||||
|
|
||||||
|
|
||||||
|
def SpringWasher(name: str) -> ElectrodeSheet:
|
||||||
|
"""创建弹片"""
|
||||||
|
sheet = ElectrodeSheet(name=name, size_x=10, size_y=10, size_z=0.5, model="SpringWasher")
|
||||||
|
sheet.load_state({"material_type": "spring_steel", "color": electrode_colors["SpringWasher"]})
|
||||||
|
return sheet
|
||||||
|
|
||||||
|
|
||||||
|
def FlatWasher(name: str) -> ElectrodeSheet:
|
||||||
|
"""创建垫片"""
|
||||||
|
sheet = ElectrodeSheet(name=name, size_x=10, size_y=10, size_z=0.2, model="FlatWasher")
|
||||||
|
sheet.load_state({"material_type": "steel", "color": electrode_colors["FlatWasher"]})
|
||||||
|
return sheet
|
||||||
|
|
||||||
|
|
||||||
|
def AluminumFoil(name: str) -> ElectrodeSheet:
|
||||||
|
"""创建铝箔"""
|
||||||
|
sheet = ElectrodeSheet(name=name, size_x=10, size_y=10, size_z=0.05, model="AluminumFoil")
|
||||||
|
sheet.load_state({"material_type": "aluminum", "color": electrode_colors["AluminumFoil"]})
|
||||||
|
return sheet
|
||||||
|
|
||||||
|
|
||||||
|
class BatteryState(TypedDict):
|
||||||
|
color: str # 材料类型对应的颜色
|
||||||
|
electrolyte_name: str
|
||||||
|
data_electrolyte_code: str
|
||||||
|
open_circuit_voltage: float
|
||||||
|
assembly_pressure: float
|
||||||
|
electrolyte_volume: float
|
||||||
|
|
||||||
|
info: Optional[str] # 附加信息
|
||||||
|
|
||||||
|
|
||||||
|
class Battery(Container):
|
||||||
|
"""电池类 - 包含组装好的电池"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name: str = "电池",
|
||||||
|
size_x=12,
|
||||||
|
size_y=12,
|
||||||
|
size_z=6,
|
||||||
|
category: str = "battery",
|
||||||
|
model: Optional[str] = None,
|
||||||
|
):
|
||||||
|
"""初始化电池
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: 电池名称
|
||||||
|
category: 类别
|
||||||
|
model: 型号
|
||||||
|
"""
|
||||||
|
super().__init__(
|
||||||
|
name=name,
|
||||||
|
size_x=size_x,
|
||||||
|
size_y=size_y,
|
||||||
|
size_z=size_z,
|
||||||
|
category=category,
|
||||||
|
model=model,
|
||||||
|
)
|
||||||
|
self._unilabos_state: BatteryState = BatteryState(
|
||||||
|
color=electrode_colors["Battery"],
|
||||||
|
electrolyte_name="无",
|
||||||
|
data_electrolyte_code="",
|
||||||
|
open_circuit_voltage=0.0,
|
||||||
|
assembly_pressure=0.0,
|
||||||
|
electrolyte_volume=0.0,
|
||||||
|
info=None
|
||||||
|
)
|
||||||
|
|
||||||
|
def load_state(self, state: Dict[str, Any]) -> None:
|
||||||
|
"""格式不变"""
|
||||||
|
super().load_state(state)
|
||||||
|
self._unilabos_state = state
|
||||||
|
|
||||||
|
#序列化
|
||||||
|
def serialize_state(self) -> Dict[str, Dict[str, Any]]:
|
||||||
|
"""格式不变"""
|
||||||
|
data = super().serialize_state()
|
||||||
|
data.update(self._unilabos_state) # Container自身的信息,云端物料将保存这一data,本地也通过这里的data进行读写,当前类用来表示这个物料的长宽高大小的属性,而data(state用来表示物料的内容,细节等)
|
||||||
|
return data
|
||||||
@@ -1,10 +1,18 @@
|
|||||||
from typing import Dict, List, Optional, OrderedDict, Union
|
from typing import Dict, List, Optional, OrderedDict, Union, Callable
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from pylabrobot.resources.coordinate import Coordinate
|
from pylabrobot.resources.coordinate import Coordinate
|
||||||
from pylabrobot.resources import Resource, ResourceStack, ItemizedResource
|
from pylabrobot.resources import Resource, ResourceStack, ItemizedResource
|
||||||
from pylabrobot.resources.carrier import create_homogeneous_resources
|
from pylabrobot.resources.carrier import create_homogeneous_resources
|
||||||
|
|
||||||
|
from unilabos.resources.battery.electrode_sheet import (
|
||||||
|
PositiveCan, PositiveElectrode,
|
||||||
|
NegativeCan, NegativeElectrode,
|
||||||
|
SpringWasher, FlatWasher,
|
||||||
|
AluminumFoil,
|
||||||
|
Battery
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Magazine(ResourceStack):
|
class Magazine(ResourceStack):
|
||||||
"""子弹夹洞位类"""
|
"""子弹夹洞位类"""
|
||||||
@@ -32,6 +40,18 @@ class Magazine(ResourceStack):
|
|||||||
)
|
)
|
||||||
self.max_sheets = max_sheets
|
self.max_sheets = max_sheets
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size_x(self) -> float:
|
||||||
|
return self.get_size_x()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size_y(self) -> float:
|
||||||
|
return self.get_size_y()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size_z(self) -> float:
|
||||||
|
return self.get_size_z()
|
||||||
|
|
||||||
|
|
||||||
class MagazineHolder(ItemizedResource):
|
class MagazineHolder(ItemizedResource):
|
||||||
"""子弹夹类 - 有多个洞位,每个洞位放多个极片"""
|
"""子弹夹类 - 有多个洞位,每个洞位放多个极片"""
|
||||||
@@ -98,6 +118,7 @@ def magazine_factory(
|
|||||||
size_y: float,
|
size_y: float,
|
||||||
size_z: float,
|
size_z: float,
|
||||||
locations: List[Coordinate],
|
locations: List[Coordinate],
|
||||||
|
klasses: Optional[List[Callable[[str], str]]] = None,
|
||||||
hole_diameter: float = 14.0,
|
hole_diameter: float = 14.0,
|
||||||
hole_depth: float = 10.0,
|
hole_depth: float = 10.0,
|
||||||
max_sheets_per_hole: int = 100,
|
max_sheets_per_hole: int = 100,
|
||||||
@@ -112,12 +133,17 @@ def magazine_factory(
|
|||||||
size_y: 宽度 (mm)
|
size_y: 宽度 (mm)
|
||||||
size_z: 高度 (mm)
|
size_z: 高度 (mm)
|
||||||
locations: 洞位坐标列表
|
locations: 洞位坐标列表
|
||||||
|
klasses: 每个洞位中极片的类列表
|
||||||
hole_diameter: 洞直径 (mm)
|
hole_diameter: 洞直径 (mm)
|
||||||
hole_depth: 洞深度 (mm)
|
hole_depth: 洞深度 (mm)
|
||||||
max_sheets_per_hole: 每个洞位最大极片数量
|
max_sheets_per_hole: 每个洞位最大极片数量
|
||||||
category: 类别
|
category: 类别
|
||||||
model: 型号
|
model: 型号
|
||||||
"""
|
"""
|
||||||
|
for loc in locations:
|
||||||
|
loc.x -= hole_diameter / 2
|
||||||
|
loc.y -= hole_diameter / 2
|
||||||
|
|
||||||
# 创建洞位
|
# 创建洞位
|
||||||
_sites = create_homogeneous_resources(
|
_sites = create_homogeneous_resources(
|
||||||
klass=Magazine,
|
klass=Magazine,
|
||||||
@@ -132,7 +158,7 @@ def magazine_factory(
|
|||||||
keys = [f"A{i+1}" for i in range(len(locations))]
|
keys = [f"A{i+1}" for i in range(len(locations))]
|
||||||
sites = dict(zip(keys, _sites.values()))
|
sites = dict(zip(keys, _sites.values()))
|
||||||
|
|
||||||
return MagazineHolder(
|
holder = MagazineHolder(
|
||||||
name=name,
|
name=name,
|
||||||
size_x=size_x,
|
size_x=size_x,
|
||||||
size_y=size_y,
|
size_y=size_y,
|
||||||
@@ -145,18 +171,143 @@ def magazine_factory(
|
|||||||
model=model,
|
model=model,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if klasses is not None:
|
||||||
|
for i, klass in enumerate(klasses):
|
||||||
|
hole_key = keys[i]
|
||||||
|
hole = holder.children[i]
|
||||||
|
for j in reversed(range(max_sheets_per_hole)):
|
||||||
|
item_name = f"{hole_key}_sheet{j+1}"
|
||||||
|
item = klass(name=item_name)
|
||||||
|
hole.assign_child_resource(item)
|
||||||
|
return holder
|
||||||
|
|
||||||
def MagazineHolder_4(
|
|
||||||
|
def MagazineHolder_6_Cathode(
|
||||||
name: str,
|
name: str,
|
||||||
size_x: float = 80.0,
|
size_x: float = 80.0,
|
||||||
size_y: float = 80.0,
|
size_y: float = 80.0,
|
||||||
size_z: float = 10.0,
|
size_z: float = 40.0,
|
||||||
hole_diameter: float = 14.0,
|
hole_diameter: float = 14.0,
|
||||||
hole_depth: float = 10.0,
|
hole_depth: float = 10.0,
|
||||||
hole_spacing: float = 25.0,
|
hole_spacing: float = 20.0,
|
||||||
max_sheets_per_hole: int = 100,
|
max_sheets_per_hole: int = 100,
|
||||||
|
) -> MagazineHolder:
|
||||||
|
"""创建6孔子弹夹 - 六边形排布"""
|
||||||
|
center_x = size_x / 2
|
||||||
|
center_y = size_y / 2
|
||||||
|
|
||||||
|
locations = []
|
||||||
|
|
||||||
|
# 周围6个孔,按六边形排布
|
||||||
|
for i in range(6):
|
||||||
|
angle = i * 60 * math.pi / 180 # 每60度一个孔
|
||||||
|
x = center_x + hole_spacing * math.cos(angle)
|
||||||
|
y = center_y + hole_spacing * math.sin(angle)
|
||||||
|
locations.append(Coordinate(x, y, size_z - hole_depth))
|
||||||
|
|
||||||
|
return magazine_factory(
|
||||||
|
name=name,
|
||||||
|
size_x=size_x,
|
||||||
|
size_y=size_y,
|
||||||
|
size_z=size_z,
|
||||||
|
locations=locations,
|
||||||
|
klasses=[FlatWasher, PositiveCan, PositiveCan, FlatWasher, PositiveCan, PositiveCan],
|
||||||
|
hole_diameter=hole_diameter,
|
||||||
|
hole_depth=hole_depth,
|
||||||
|
max_sheets_per_hole=max_sheets_per_hole,
|
||||||
|
category="magazine_holder",
|
||||||
|
model="MagazineHolder_6_Cathode",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def MagazineHolder_6_Anode(
|
||||||
|
name: str,
|
||||||
|
size_x: float = 80.0,
|
||||||
|
size_y: float = 80.0,
|
||||||
|
size_z: float = 40.0,
|
||||||
|
hole_diameter: float = 14.0,
|
||||||
|
hole_depth: float = 10.0,
|
||||||
|
hole_spacing: float = 20.0,
|
||||||
|
max_sheets_per_hole: int = 100,
|
||||||
|
) -> MagazineHolder:
|
||||||
|
"""创建6孔子弹夹 - 六边形排布"""
|
||||||
|
center_x = size_x / 2
|
||||||
|
center_y = size_y / 2
|
||||||
|
|
||||||
|
locations = []
|
||||||
|
|
||||||
|
# 周围6个孔,按六边形排布
|
||||||
|
for i in range(6):
|
||||||
|
angle = i * 60 * math.pi / 180 # 每60度一个孔
|
||||||
|
x = center_x + hole_spacing * math.cos(angle)
|
||||||
|
y = center_y + hole_spacing * math.sin(angle)
|
||||||
|
locations.append(Coordinate(x, y, size_z - hole_depth))
|
||||||
|
|
||||||
|
return magazine_factory(
|
||||||
|
name=name,
|
||||||
|
size_x=size_x,
|
||||||
|
size_y=size_y,
|
||||||
|
size_z=size_z,
|
||||||
|
locations=locations,
|
||||||
|
klasses=[SpringWasher, NegativeCan, NegativeCan, SpringWasher, NegativeCan, NegativeCan],
|
||||||
|
hole_diameter=hole_diameter,
|
||||||
|
hole_depth=hole_depth,
|
||||||
|
max_sheets_per_hole=max_sheets_per_hole,
|
||||||
|
category="magazine_holder",
|
||||||
|
model="MagazineHolder_6_Anode",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def MagazineHolder_6_Battery(
|
||||||
|
name: str,
|
||||||
|
size_x: float = 80.0,
|
||||||
|
size_y: float = 80.0,
|
||||||
|
size_z: float = 40.0,
|
||||||
|
hole_diameter: float = 14.0,
|
||||||
|
hole_depth: float = 10.0,
|
||||||
|
hole_spacing: float = 20.0,
|
||||||
|
max_sheets_per_hole: int = 100,
|
||||||
|
) -> MagazineHolder:
|
||||||
|
"""创建6孔子弹夹 - 六边形排布"""
|
||||||
|
center_x = size_x / 2
|
||||||
|
center_y = size_y / 2
|
||||||
|
|
||||||
|
locations = []
|
||||||
|
|
||||||
|
# 周围6个孔,按六边形排布
|
||||||
|
for i in range(6):
|
||||||
|
angle = i * 60 * math.pi / 180 # 每60度一个孔
|
||||||
|
x = center_x + hole_spacing * math.cos(angle)
|
||||||
|
y = center_y + hole_spacing * math.sin(angle)
|
||||||
|
locations.append(Coordinate(x, y, size_z - hole_depth))
|
||||||
|
|
||||||
|
return magazine_factory(
|
||||||
|
name=name,
|
||||||
|
size_x=size_x,
|
||||||
|
size_y=size_y,
|
||||||
|
size_z=size_z,
|
||||||
|
locations=locations,
|
||||||
|
klasses=None, # 初始化时,不放入装好的电池
|
||||||
|
hole_diameter=hole_diameter,
|
||||||
|
hole_depth=hole_depth,
|
||||||
|
max_sheets_per_hole=max_sheets_per_hole,
|
||||||
|
category="magazine_holder",
|
||||||
|
model="MagazineHolder_6_Battery",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def MagazineHolder_4_Cathode(
|
||||||
|
name: str,
|
||||||
) -> MagazineHolder:
|
) -> MagazineHolder:
|
||||||
"""创建4孔子弹夹 - 正方形四角排布"""
|
"""创建4孔子弹夹 - 正方形四角排布"""
|
||||||
|
size_x: float = 80.0
|
||||||
|
size_y: float = 80.0
|
||||||
|
size_z: float = 10.0
|
||||||
|
hole_diameter: float = 14.0
|
||||||
|
hole_depth: float = 10.0
|
||||||
|
hole_spacing: float = 25.0
|
||||||
|
max_sheets_per_hole: int = 100
|
||||||
|
|
||||||
# 计算4个洞位的坐标(正方形四角排布)
|
# 计算4个洞位的坐标(正方形四角排布)
|
||||||
center_x = size_x / 2
|
center_x = size_x / 2
|
||||||
center_y = size_y / 2
|
center_y = size_y / 2
|
||||||
@@ -175,110 +326,10 @@ def MagazineHolder_4(
|
|||||||
size_y=size_y,
|
size_y=size_y,
|
||||||
size_z=size_z,
|
size_z=size_z,
|
||||||
locations=locations,
|
locations=locations,
|
||||||
|
klasses=[AluminumFoil, PositiveElectrode, PositiveElectrode, PositiveElectrode],
|
||||||
hole_diameter=hole_diameter,
|
hole_diameter=hole_diameter,
|
||||||
hole_depth=hole_depth,
|
hole_depth=hole_depth,
|
||||||
max_sheets_per_hole=max_sheets_per_hole,
|
max_sheets_per_hole=max_sheets_per_hole,
|
||||||
category="clip_magazine_four",
|
category="magazine_holder",
|
||||||
|
model="MagazineHolder_4_Cathode",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def MagazineHolder_2(
|
|
||||||
name: str,
|
|
||||||
size_x: float = 80.0,
|
|
||||||
size_y: float = 80.0,
|
|
||||||
size_z: float = 10.0,
|
|
||||||
hole_diameter: float = 14.0,
|
|
||||||
hole_depth: float = 10.0,
|
|
||||||
hole_spacing: float = 25.0,
|
|
||||||
max_sheets_per_hole: int = 100,
|
|
||||||
) -> MagazineHolder:
|
|
||||||
"""创建2孔子弹夹 - 竖向排布"""
|
|
||||||
# 计算2个洞位的坐标(竖向排布)
|
|
||||||
center_x = size_x / 2
|
|
||||||
center_y = size_y / 2
|
|
||||||
offset = hole_spacing / 2
|
|
||||||
|
|
||||||
locations = [
|
|
||||||
Coordinate(center_x, center_y - offset, size_z - hole_depth), # 下方
|
|
||||||
Coordinate(center_x, center_y + offset, size_z - hole_depth), # 上方
|
|
||||||
]
|
|
||||||
|
|
||||||
return magazine_factory(
|
|
||||||
name=name,
|
|
||||||
size_x=size_x,
|
|
||||||
size_y=size_y,
|
|
||||||
size_z=size_z,
|
|
||||||
locations=locations,
|
|
||||||
hole_diameter=hole_diameter,
|
|
||||||
hole_depth=hole_depth,
|
|
||||||
max_sheets_per_hole=max_sheets_per_hole,
|
|
||||||
category="clip_magazine_two",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def MagazineHolder_1(
|
|
||||||
name: str,
|
|
||||||
size_x: float = 80.0,
|
|
||||||
size_y: float = 80.0,
|
|
||||||
size_z: float = 10.0,
|
|
||||||
hole_diameter: float = 14.0,
|
|
||||||
hole_depth: float = 10.0,
|
|
||||||
max_sheets_per_hole: int = 100,
|
|
||||||
) -> MagazineHolder:
|
|
||||||
"""创建1孔子弹夹 - 中心单孔"""
|
|
||||||
# 计算1个洞位的坐标(中心位置)
|
|
||||||
center_x = size_x / 2
|
|
||||||
center_y = size_y / 2
|
|
||||||
|
|
||||||
locations = [
|
|
||||||
Coordinate(center_x, center_y, size_z - hole_depth), # 中心
|
|
||||||
]
|
|
||||||
|
|
||||||
return magazine_factory(
|
|
||||||
name=name,
|
|
||||||
size_x=size_x,
|
|
||||||
size_y=size_y,
|
|
||||||
size_z=size_z,
|
|
||||||
locations=locations,
|
|
||||||
hole_diameter=hole_diameter,
|
|
||||||
hole_depth=hole_depth,
|
|
||||||
max_sheets_per_hole=max_sheets_per_hole,
|
|
||||||
category="clip_magazine_one",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def MagazineHolder_6(
|
|
||||||
name: str,
|
|
||||||
size_x: float = 80.0,
|
|
||||||
size_y: float = 80.0,
|
|
||||||
size_z: float = 40.0,
|
|
||||||
hole_diameter: float = 14.0,
|
|
||||||
hole_depth: float = 10.0,
|
|
||||||
hole_spacing: float = 20.0,
|
|
||||||
max_sheets_per_hole: int = 100,
|
|
||||||
) -> MagazineHolder:
|
|
||||||
"""创建6孔子弹夹 - 六边形排布"""
|
|
||||||
# 计算6个洞位的坐标(六边形排布:中心1个,周围5个)
|
|
||||||
center_x = size_x / 2
|
|
||||||
center_y = size_y / 2
|
|
||||||
|
|
||||||
locations = []
|
|
||||||
|
|
||||||
# 周围6个孔,按六边形排布
|
|
||||||
for i in range(6):
|
|
||||||
angle = i * 60 * math.pi / 180 # 每60度一个孔
|
|
||||||
x = center_x + hole_spacing * math.cos(angle)
|
|
||||||
y = center_y + hole_spacing * math.sin(angle)
|
|
||||||
locations.append(Coordinate(x, y, size_z - hole_depth))
|
|
||||||
|
|
||||||
return magazine_factory(
|
|
||||||
name=name,
|
|
||||||
size_x=size_x,
|
|
||||||
size_y=size_y,
|
|
||||||
size_z=size_z,
|
|
||||||
locations=locations,
|
|
||||||
hole_diameter=hole_diameter,
|
|
||||||
hole_depth=hole_depth,
|
|
||||||
max_sheets_per_hole=max_sheets_per_hole,
|
|
||||||
category="clip_magazine_six",
|
|
||||||
)
|
|
||||||
Reference in New Issue
Block a user