STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_layerx_vehicle.py
Go to the documentation of this file.
1"""Layer X burns the vehicle, not the GSE drawn beside it (engine/layerx/vehicle.py).
2
3LE4 (6) drew the rocket on one page and the GSE on another, joined only by quick-disconnects paired
4across the pages. Layer X then found two ethanol tanks (the vehicle's and the GSE transfer tank),
5swapped the GSE K-bottles to helium along with the COPV, and -- with the GSE dome regulator mated
6to the vehicle's dome line -- tripped the LOX tank before T-0. These pin the cut on a small drawing
7of the same shape, and that a one-piece drawing is untouched.
8"""
9
10from __future__ import annotations
11
12import copy
13
14import pytest
15
16pytest.importorskip("feedtwin", reason="lib/feedtwin is not installed")
17
18
19def _node(nid, typ, label, page, fluid=None, **params):
20 data = {"componentType": typ, "label": label, "page": page, "options": {}, "params": {
21 k: {"value": v[0], "unit": v[1], "source": "estimated"} for k, v in params.items()}}
22 if fluid:
23 data["fluid"] = fluid
24 return {"id": nid, "type": typ, "position": {"x": 0, "y": 0}, "data": data}
25
26
27def _edge(a, b):
28 return {"id": f"{a}-{b}", "source": a, "target": b, "data": {}}
29
30
32 nodes = [
33 _node("eng", "ENGINE", "ENG-1", "Rocket"),
34 _node("copv", "KBOTTLE", "COPV", "Rocket", "nitrogen", pressure=(4000, "psi"), volume=(4.69, "L")),
35 _node("reg", "PR", "DPR", "Rocket"),
36 _node("fut", "TANK", "Eth-Tank", "Rocket", "ethanol", volume=(8.19, "L")),
37 _node("oxt", "TANK", "LOX-Tank", "Rocket", "oxygen", volume=(8.19, "L")),
38 _node("fm", "ROT", "FM", "Rocket"),
39 _node("om", "ROT", "OM", "Rocket"),
40 _node("qv", "QD", "QD-FF-B", "Rocket"),
41 _node("rtd", "RTD", "OX-RTD", "Rocket"),
42 # GSE page: a transfer tank and a cart bottle, behind the disconnect's other half.
43 _node("qg", "QD", "QD-FF-A", "GSE"),
44 _node("xfer", "TANK", "Fuel Transfer Tank", "GSE", "ethanol", volume=(20, "L")),
45 _node("k6", "KBOTTLE", "6K-GN2", "GSE", "nitrogen", pressure=(6000, "psi"), volume=(49, "L")),
46 ]
47 by = {n["id"]: n for n in nodes}
48 by["qv"]["data"]["options"]["pairedWith"] = "qg"
49 by["rtd"]["data"]["attachedTo"] = "oxt"
50 edges = [_edge("copv", "reg"), _edge("reg", "fut"), _edge("reg", "oxt"), _edge("fut", "fm"), _edge("fm", "eng"),
51 _edge("oxt", "om"), _edge("om", "eng"), _edge("fut", "qv"), _edge("qg", "xfer"), _edge("k6", "xfer")]
52 return {"nodes": nodes, "edges": edges}
53
54
56 from feedtwin.pid import read_diagram
57
58 from engine.layerx.vehicle import vehicle_ids
59
60 v = vehicle_ids(read_diagram(stand_with_gse(), name="t"))
61 assert {"eng", "copv", "reg", "fut", "oxt", "fm", "om", "qv", "rtd"} <= v
62 assert not v & {"qg", "xfer", "k6"}
63
64
66 from engine.layerx.vehicle import vehicle_payload
67
68 payload = stand_with_gse()
69 cut, ground = vehicle_payload(payload)
70 ids = {n["id"] for n in cut["nodes"]}
71 assert "xfer" not in ids and "k6" not in ids and "qg" not in ids
72 assert sorted(ground) == ["6K-GN2", "Fuel Transfer Tank"]
73 assert next(n for n in cut["nodes"] if n["id"] == "qv")["data"]["options"]["pairedWith"] == ""
74 assert all(e["source"] in ids and e["target"] in ids for e in cut["edges"])
75 # The caller's drawing is not mutated.
76 assert next(n for n in payload["nodes"] if n["id"] == "qv")["data"]["options"]["pairedWith"] == "qg"
77
78
80 from engine.layerx.vehicle import vehicle_payload
81
82 payload = stand_with_gse()
83 payload["edges"].append(_edge("qv", "qg")) # GSE drawn with a line into the vehicle: one piece
84 same, ground = vehicle_payload(payload)
85 assert same is payload and ground == []
86
87
89 from engine.layerx.prepare import swap_pressurant
90
91 out, n, was = swap_pressurant(stand_with_gse(), "helium")
92 fluid = {nd["id"]: nd["data"].get("fluid") for nd in out["nodes"]}
93 assert was == "nitrogen" and n == 1
94 assert fluid["copv"] == "helium" and fluid["k6"] == "nitrogen"
95
96
98 from engine.layerx.sources import summarize
99
100 s = summarize(copy.deepcopy(stand_with_gse()), "t")
101 assert [t["label"] for t in s["tanks"]] == ["Eth-Tank", "LOX-Tank"]
102 assert [b["label"] for b in s["bottles"]] == ["COPV"]
103 assert {g["label"] for g in s["ground_support"]} == {"Fuel Transfer Tank", "6K-GN2"}
_node(nid, typ, label, page, fluid=None, **params)
test_the_summary_lists_the_vehicle_and_the_gse_apart()
test_the_cut_drops_the_gse_and_caps_the_vehicle_half()