Grotti 2.10.0: Orca-Senden, Slice-Ordner, ED-Strom, Hygiene.
Slice-Watch mit Ordnern/Filtern, Orca-Nachbearbeitung, Cockpit-Verlauf mit ED, Zeitzone im Browser. Tasten-Grenze und README-API angeglichen, toter Code entfernt, Requirements gepinnt.
This commit is contained in:
1 parent
efd0801cd1
commit
9e22cebb81
48 files changed
+2259
-422
No files matched your search
+2
-101
@@ -55,8 +55,8 @@ DEFAULT_SWEEP = {
|
||||
# Ein Punkt in der Bettmitte — kein LeviQ, kein 3×3, kein Heizen.
|
||||
DEFAULT_CHECK = {
|
||||
"type": "check",
|
||||
# Result is z= gegen Grenze. Temporär 3 mm — kalter Kunststoff an der Düse
|
||||
# tastet sonst oft 1–2 mm und meldet Restteil. Später wieder straffen.
|
||||
# Result is z= gegen Grenze. 3 mm: kalter Kunststoff an der Düse
|
||||
# tastet sonst oft 1–2 mm und meldet Restteil.
|
||||
"max_delta_mm": 3.0,
|
||||
"timeout_min": 2,
|
||||
"x": 125.0,
|
||||
@@ -454,11 +454,6 @@ def sweep_lower_to_push_script(sweep):
|
||||
])
|
||||
|
||||
|
||||
def sweep_probe_height_script(sweep):
|
||||
"""Kompatibel: hoch, hinten, langsam auf z_push."""
|
||||
return sweep_go_back_high_script(sweep) + "\n" + sweep_lower_to_push_script(sweep)
|
||||
|
||||
|
||||
def assert_clear_before_lower(live, sweep, min_z_mm=15.0):
|
||||
"""Vor dem Senken: Toolhead muss noch klar über dem Bett stehen."""
|
||||
pos = (live or {}).get("position") or []
|
||||
@@ -562,100 +557,6 @@ def check_lift_script(check):
|
||||
])
|
||||
|
||||
|
||||
def _axis_coords(lo, hi, count):
|
||||
if count <= 1:
|
||||
return [(lo + hi) / 2.0]
|
||||
return [lo + (hi - lo) * i / (count - 1) for i in range(count)]
|
||||
|
||||
|
||||
def _matrix_ok(matrix):
|
||||
if not isinstance(matrix, list) or not matrix:
|
||||
return False
|
||||
width = None
|
||||
for row in matrix:
|
||||
if not isinstance(row, list) or not row:
|
||||
return False
|
||||
if width is None:
|
||||
width = len(row)
|
||||
if len(row) != width:
|
||||
return False
|
||||
for value in row:
|
||||
if not isinstance(value, (int, float)):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def interpolate_mesh_z(mesh, x, y):
|
||||
"""Bilinear aus Roh-probed_matrix. Klipper: Zeile 0 = mesh_min Y."""
|
||||
matrix = mesh.get("matrix") if isinstance(mesh, dict) else None
|
||||
if not _matrix_ok(matrix):
|
||||
return None
|
||||
mesh_min = mesh.get("mesh_min") or [0, 0]
|
||||
mesh_max = mesh.get("mesh_max") or [0, 0]
|
||||
try:
|
||||
x0, y0 = float(mesh_min[0]), float(mesh_min[1])
|
||||
x1, y1 = float(mesh_max[0]), float(mesh_max[1])
|
||||
except (TypeError, ValueError, IndexError):
|
||||
return None
|
||||
rows = len(matrix)
|
||||
cols = len(matrix[0])
|
||||
if cols < 1 or rows < 1:
|
||||
return None
|
||||
if abs(x1 - x0) < 1e-9 or abs(y1 - y0) < 1e-9:
|
||||
return float(matrix[0][0])
|
||||
tx = 0.0 if cols == 1 else (float(x) - x0) / (x1 - x0) * (cols - 1)
|
||||
ty = 0.0 if rows == 1 else (float(y) - y0) / (y1 - y0) * (rows - 1)
|
||||
tx = max(0.0, min(float(cols - 1), tx))
|
||||
ty = max(0.0, min(float(rows - 1), ty))
|
||||
c0 = int(tx)
|
||||
r0 = int(ty)
|
||||
c1 = min(cols - 1, c0 + 1)
|
||||
r1 = min(rows - 1, r0 + 1)
|
||||
fx = tx - c0
|
||||
fy = ty - r0
|
||||
z00 = float(matrix[r0][c0])
|
||||
z10 = float(matrix[r0][c1])
|
||||
z01 = float(matrix[r1][c0])
|
||||
z11 = float(matrix[r1][c1])
|
||||
z0 = z00 * (1 - fx) + z10 * fx
|
||||
z1 = z01 * (1 - fx) + z11 * fx
|
||||
return z0 * (1 - fy) + z1 * fy
|
||||
|
||||
|
||||
def mesh_delta_mm(baseline, measured):
|
||||
"""Max |Δ| und Mittel |Δ|: Messpunkte gegen interpoliertes Baseline-Netz."""
|
||||
if not isinstance(baseline, dict) or not _matrix_ok(baseline.get("matrix")):
|
||||
raise GrottiError("Kein Bettnetz zum Vergleich — vorher nivellieren.", "mesh")
|
||||
if not isinstance(measured, dict) or not _matrix_ok(measured.get("matrix")):
|
||||
raise GrottiError("Neues Bettnetz fehlt nach dem Antasten.", "mesh")
|
||||
matrix = measured["matrix"]
|
||||
mesh_min = measured.get("mesh_min") or [0, 0]
|
||||
mesh_max = measured.get("mesh_max") or [0, 0]
|
||||
try:
|
||||
x0, y0 = float(mesh_min[0]), float(mesh_min[1])
|
||||
x1, y1 = float(mesh_max[0]), float(mesh_max[1])
|
||||
except (TypeError, ValueError, IndexError) as exc:
|
||||
raise GrottiError("Messnetz ohne gültigen Bereich.", "mesh") from exc
|
||||
rows = len(matrix)
|
||||
cols = len(matrix[0])
|
||||
xs = _axis_coords(x0, x1, cols)
|
||||
ys = _axis_coords(y0, y1, rows)
|
||||
deltas = []
|
||||
for ri, y in enumerate(ys):
|
||||
for ci, x in enumerate(xs):
|
||||
expected = interpolate_mesh_z(baseline, x, y)
|
||||
if expected is None:
|
||||
raise GrottiError("Baseline-Netz lässt sich nicht interpolieren.", "mesh")
|
||||
deltas.append(abs(float(matrix[ri][ci]) - expected))
|
||||
if not deltas:
|
||||
raise GrottiError("Keine Messpunkte zum Vergleich.", "mesh")
|
||||
return {
|
||||
"max_delta_mm": max(deltas),
|
||||
"mean_delta_mm": sum(deltas) / len(deltas),
|
||||
"points": len(deltas),
|
||||
}
|
||||
|
||||
|
||||
def step_label(step):
|
||||
if not isinstance(step, dict):
|
||||
return ""
|
||||
|
||||
Reference in new issue
Block a user