tro_flow: Weichen-Separator nach Laufrichtung, Weichen-Slots mit Bauteil
Steuernder Separator einer ILS Weiche (_find_weiche_separators) ist der letzte freie Separator in Laufrichtung VOR der Weiche, gemessen auf dem Kreisel-Umlauf aus Lage und Drehrichtung (kreisel_junctions.separators_before) - nicht mehr der CSV-Nachbar. Ein Nachbar hinter der Weiche steuert sie nie; Hoechstabstand weiche_vorlauf_max in cfg/parameter.ini [tro_flow]. Mubea (Export 2026-10-16): 2Sep2Swi = 0005 (Ausschleus 0061) + 0036 (Weiche 0130) statt 0005 + 0012; 0012 bleibt 1Sep, Kreisel1 wieder angebunden. Dematic, HundM05, showroom, test_system unveraendert. TRO-JSON: DerivedTro.switches (optional) nennt die Weichen-Bauteile in Slot-Reihenfolge (switch<i> gehoert bei 2Sep-Typen zu separator<i>); derive_slots traegt sie in die switch<n>-Slots, merge_hw_layout bindet das Ventil dort. e_planning.ini: Rollen ventil -> valve (Slot-Rolle der SCL), neue Regel Ausschleus_Weiche.valve fuer Ausschleusventile an Kreisel-Weichen. Mubea: MB0715, MB0724, MB0627, MB0671 statt TODO(E-Planung). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@ import math
|
||||
|
||||
import pytest
|
||||
|
||||
from kreisel_junctions import find_contacts, find_junctions, kreisel_loop
|
||||
from kreisel_junctions import find_contacts, find_junctions, kreisel_loop, separators_before
|
||||
from material_flow import Element
|
||||
|
||||
|
||||
@@ -149,3 +149,50 @@ def test_co_rotating_end_contact_is_weiche() -> None:
|
||||
_loops, contacts = find_contacts([a, b], [])
|
||||
assert len(contacts) == 1
|
||||
assert math.hypot(contacts[0].x - 1500.0, contacts[0].y) < 5.0
|
||||
|
||||
|
||||
# Mubea-Export 2026-10-16: Kreisel2 (UZS, senkrecht) und Kreisel1 (GUZ,
|
||||
# waagerecht) beruehren sich an der ILS Weiche 0130. Auf Kreisel2 liegt 0005
|
||||
# davor (steuert schon Ausschleuselement 0061), 0012 dahinter; auf Kreisel1
|
||||
# liegt 0036 davor, 0040 dahinter. Die CSV-Nachbarn der Weiche sind 0061/0012.
|
||||
def _mubea_weiche(kreisel1: str = "GUZ") -> list[Element]:
|
||||
weiche = _el("0130", "Weiche", (400.0, -5478.0))
|
||||
weiche.neighbours = [("0061", None), ("0012", None)]
|
||||
return [
|
||||
_kreisel("0054", (0.0, 4529.5), (800.0, 20815.0), "UZS", 90),
|
||||
_kreisel("0129", (3300.0, -5478.0), (5800.0, 800.0), kreisel1, 0),
|
||||
_el("0005", "Separator", (400.0, -3978.05)),
|
||||
_el("0012", "Separator", (-400.0, -3554.95)),
|
||||
_el("0036", "Separator", (1474.95, -5078.0)),
|
||||
_el("0040", "Separator", (5355.05, -5878.0)),
|
||||
weiche,
|
||||
]
|
||||
|
||||
|
||||
def test_separators_before_uses_geometry_not_trackids() -> None:
|
||||
vorher, nachher = separators_before(_mubea_weiche(), 400.0, -5478.0)
|
||||
assert {u.kreisel: u.separator for u in vorher} == {"0054": "0005", "0129": "0036"}
|
||||
assert all(u.distance < 2000.0 for u in vorher)
|
||||
assert nachher == ["0012", "0040"]
|
||||
|
||||
|
||||
def test_weiche_controlled_by_free_separator_before_it() -> None:
|
||||
from tro_flow import _find_weiche_separators
|
||||
|
||||
elements = _mubea_weiche()
|
||||
frei = [e for e in elements if e.teile_id in ("0012", "0036", "0040")] # 0005: Ausschleus
|
||||
findings: list[str] = []
|
||||
result = _find_weiche_separators(frei, elements, findings)
|
||||
assert {s: w.teile_id for s, w in result.items()} == {"0036": "0130"}
|
||||
assert any("CSV-Nachbar 0012 liegt in Laufrichtung hinter" in f for f in findings)
|
||||
|
||||
|
||||
def test_weiche_far_behind_separator_is_not_assigned() -> None:
|
||||
# Kreisel1 falsch als UZS: davor laege nur 0040, ~5 m weit weg - kein Raten
|
||||
from tro_flow import _find_weiche_separators
|
||||
|
||||
elements = _mubea_weiche(kreisel1="UZS")
|
||||
frei = [e for e in elements if e.teile_id in ("0012", "0036", "0040")]
|
||||
findings: list[str] = []
|
||||
assert _find_weiche_separators(frei, elements, findings) == {}
|
||||
assert any("kein freier Separator in Laufrichtung davor" in f for f in findings)
|
||||
|
||||
@@ -127,10 +127,24 @@ def test_pflichtrollen_ohne_bmk_sind_offen_optionale_nicht():
|
||||
anlage = run()
|
||||
roles = {(b.slot, b.role): b.status for b in anlage.bindings if b.tro == "TRO06"}
|
||||
assert roles == {("separator1", "sensor"): "offen", ("separator1", "stopper"): "offen"}
|
||||
# die Weiche hat noch keine Layout-ID -> Ventil offen
|
||||
# ohne switches (TRO-JSON vor 2026-10-16) keine Layout-ID -> Ventil offen
|
||||
assert anlage.binding("TRO02", "switch1", "valve").status == "offen"
|
||||
|
||||
|
||||
def test_weichen_slot_bekommt_ventil_des_ausschleuselements():
|
||||
# TRO02 steuert Ausschleuselement 0030 (tro_flow: switches) -> switch1 traegt
|
||||
# 0030, das Ausschleusventil (Nummer = Stausensor + 1) landet im Slot.
|
||||
doc = layout()
|
||||
tro = doc.by_id("TRO02")
|
||||
tro.switches = ["0030"]
|
||||
tro.slots = derive_slots(tro)
|
||||
hw = hardware()
|
||||
hw.devices.append(_dev("MB0602", "AE ABZW", (0.0, 2000.0 + 1414.0), direction="out"))
|
||||
valve = run(doc=doc, hw=hw).binding("TRO02", "switch1", "valve")
|
||||
assert (valve.bmk, valve.layout_id, valve.rule, valve.status) == (
|
||||
"MB0602", "0030", "nummer", "zugeordnet")
|
||||
|
||||
|
||||
def test_bauteil_ohne_slot_bleibt_sichtbar():
|
||||
loose = [b for b in run().bindings if not b.tro]
|
||||
assert [(b.role, b.layout_id, b.bmk, b.status) for b in loose] == [
|
||||
|
||||
Reference in New Issue
Block a user