mirror of
https://github.com/deepmodeling/Uni-Lab-OS
synced 2026-05-23 20:32:39 +00:00
feat(layout_optimizer): default cardinal snap and alignment to off
align_weight defaults to 0 (was DEFAULT_WEIGHT_ANGLE=60). snap_theta_safe is opt-in via snap_cardinal=True (was always-on). Both remain available when explicitly requested. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -368,6 +368,7 @@ class OptimizeRequest(BaseModel):
|
||||
workflow_edges: list[list[str]] = []
|
||||
maxiter: int = 200
|
||||
seed: int | None = None
|
||||
snap_cardinal: bool = False
|
||||
|
||||
|
||||
class PositionXYZ(BaseModel):
|
||||
@@ -459,8 +460,8 @@ async def run_optimize(request: OptimizeRequest):
|
||||
params={"mode": orientation_mode},
|
||||
weight=request.seeder_overrides.get("orientation_weight", DEFAULT_WEIGHT_ANGLE),
|
||||
))
|
||||
# prefer_aligned: penalize non-cardinal angles
|
||||
align_weight = request.seeder_overrides.get("align_weight", DEFAULT_WEIGHT_ANGLE)
|
||||
# prefer_aligned: penalize non-cardinal angles(默认关闭,用户可通过 align_cardinal intent 或 seeder_overrides 开启)
|
||||
align_weight = request.seeder_overrides.get("align_weight", 0)
|
||||
if align_weight > 0:
|
||||
constraints.append(Constraint(
|
||||
type="soft",
|
||||
@@ -486,8 +487,9 @@ async def run_optimize(request: OptimizeRequest):
|
||||
else:
|
||||
result_placements = seed_placements
|
||||
|
||||
# 5. θ snap post-processing(碰撞安全:snap 后验证,失败则回退)
|
||||
result_placements = snap_theta_safe(result_placements, devices, lab, checker)
|
||||
# 5. θ snap post-processing(opt-in,默认关闭)
|
||||
if request.snap_cardinal:
|
||||
result_placements = snap_theta_safe(result_placements, devices, lab, checker)
|
||||
|
||||
# 6. Evaluate final cost (binary mode for pass/fail reporting)
|
||||
final_cost = evaluate_default_hard_constraints(
|
||||
|
||||
@@ -376,3 +376,58 @@ class TestScenarios:
|
||||
assert not _has_collision(devices, result)
|
||||
for i, p in enumerate(result):
|
||||
assert _facing_dot(p, devices[i], lab) > 0
|
||||
|
||||
|
||||
# ── V2 Stage 1: 默认关闭 cardinal snap/alignment ────────
|
||||
|
||||
class TestV2Stage1Bugfixes:
|
||||
"""align_weight 默认为 0,snap_cardinal 默认关闭。"""
|
||||
|
||||
def test_default_align_weight_is_zero(self):
|
||||
"""Default request (no seeder_overrides) should NOT inject prefer_aligned."""
|
||||
from fastapi.testclient import TestClient
|
||||
from ..server import app
|
||||
|
||||
client = TestClient(app)
|
||||
resp = client.post("/optimize", json={
|
||||
"devices": [{"id": "opentrons_liquid_handler", "uuid": "u1"}],
|
||||
"lab": {"width": 3, "depth": 3},
|
||||
"seeder": "compact_outward",
|
||||
"run_de": True,
|
||||
"maxiter": 50,
|
||||
"seed": 42,
|
||||
})
|
||||
assert resp.status_code == 200
|
||||
|
||||
def test_snap_cardinal_off_by_default(self):
|
||||
"""Default request should NOT snap theta to cardinal."""
|
||||
from fastapi.testclient import TestClient
|
||||
from ..server import app
|
||||
|
||||
client = TestClient(app)
|
||||
resp = client.post("/optimize", json={
|
||||
"devices": [{"id": "opentrons_liquid_handler", "uuid": "u1"}],
|
||||
"lab": {"width": 3, "depth": 3},
|
||||
"seeder": "compact_outward",
|
||||
"run_de": True,
|
||||
"maxiter": 10,
|
||||
"seed": 42,
|
||||
})
|
||||
assert resp.status_code == 200
|
||||
|
||||
def test_snap_cardinal_opt_in(self):
|
||||
"""snap_cardinal=True should be accepted and snap angles."""
|
||||
from fastapi.testclient import TestClient
|
||||
from ..server import app
|
||||
|
||||
client = TestClient(app)
|
||||
resp = client.post("/optimize", json={
|
||||
"devices": [{"id": "opentrons_liquid_handler", "uuid": "u1"}],
|
||||
"lab": {"width": 3, "depth": 3},
|
||||
"seeder": "compact_outward",
|
||||
"snap_cardinal": True,
|
||||
"run_de": True,
|
||||
"maxiter": 10,
|
||||
"seed": 42,
|
||||
})
|
||||
assert resp.status_code == 200
|
||||
|
||||
@@ -199,6 +199,8 @@ class TestStage3VerifyPlacements:
|
||||
"run_de": True,
|
||||
"maxiter": 100,
|
||||
"seed": 42,
|
||||
"snap_cardinal": True,
|
||||
"seeder_overrides": {"align_weight": 60},
|
||||
})
|
||||
data = optimize_resp.json()
|
||||
assert data["success"] is True
|
||||
|
||||
Reference in New Issue
Block a user