fix: Laengenbilanz des gefalteten Modus-2-Laufs (U-Form)
Gefaltete VF-Laeufe wurden zu kurz gebaut, weil der Solver Posten dem falschen Schenkel zurechnete. Vier Aenderungen, alle nach demselben Leitsatz: die letzten freien Groessen folgen der GEMESSENEN Ist-Lage, nicht einer vorab verteilten Gesamtplanung. 1. vfl-zsolve-schluss-ziel (neu): endet der Lauf auf einem flachen Fueller, werden RICHTUNG und LAENGE gemeinsam gegen den Zielpunkt geloest statt nur die Laenge. Geschlossene Loesung ueber A = sqrt(|D|^2 - P^2), hz = Winkel(D) - atan2(P, A); C und P sind von hz unabhaengig, daher ohne Iteration. Bisher uebernahm der Solve die Richtung aus dem gezeichneten Pfad - ein Querversatz der realen Eck-Bauteile war damit prinzipiell unerreichbar, weil eine Laenge die Kette nur entlang ihrer Achse verschiebt. 2. Eingangs-Hardware bei gefaltetem Lauf: Umlenkstation + Separator stehen auf dem Eingangs-Schenkel und verbrauchen die Kletterspanne nicht; ihr Laengenanteil wird der Spanne wieder zugeschlagen. feste-vf bleibt unveraendert - sein sin3-Hoehenanteil ist real. 3. kletter-ende-fp: endet der Lauf auf einem KLETTERER, gibt es keinen Schluss-Fueller, der Motorstation + Separator + ES abzieht - sie standen in keinem Budget. Nur bei flacher Zone, Pfadende und vorhandenem ES, sonst sind sie bereits anderweitig verbucht. 4. Nachrechner wieder aktiv (8 statt 4 Runden): GF1 steht im Budget, aber im Eingangs-Schenkel. Die Kollision mit filler-A-len, wegen der er abgeschaltet war, ist entfallen. 3 und 4 wirken NUR gemeinsam - die Betraege heben sich teilweise auf, eine einzeln eingebaute Korrektur verschiebt den Fehler bloss in die andere Richtung (GF1 1636.9 - (Motor+Sep+ES) 1235.1 = 401.8 mm). Gemessen am selben Pfad: 9 Grad 0.56 mm, 12 Grad 0.7 mm quer (vorher 1424 bzw. 934 mm), dZ 0.1 mm. Beide Modus-2-Regressionsketten weiter OK; TEST_UNIT 904/904 mit 7 neuen file-freien Tests. doc/todo.md: Punkt "Modus-2-Solver: achsenweise Laengen-Bilanz" ist damit erledigt. Die Detaildatei bleibt liegen, weil vier Kommentare in vf_linienzug.lsp auf ihren Pfad verweisen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,21 @@
|
||||
# TODO: Modus-2-Solver auf achsenweise Laengen-Bilanz umstellen
|
||||
# Modus-2-Solver: achsenweise Laengen-Bilanz
|
||||
|
||||
Status: **Vorschlag / noch nicht umgesetzt** (2026-09-18). Mit dem Entwickler zu
|
||||
besprechen, bevor der Solver angefasst wird. Reiner Plan - kein Code geaendert.
|
||||
Status: **ERLEDIGT 2026-10-29.** Gefaltete Laeufe (U-Form) werden gebaut; am
|
||||
selben Pfad gemessen 0.56 mm (9 Grad) und 0.7 mm (12 Grad) quer, beide
|
||||
Regressionsketten weiter OK. Der Abschnitt "Stand 2026-10-29" und der "Nachtrag
|
||||
2026-10-29" am Ende beschreiben Loesung und Herleitung.
|
||||
|
||||
**Pruefung 2026-10-26:** weiterhin OFFEN - der Solver bilanziert noch skalar
|
||||
(`climber-span`, `hor-pairs` 0/1), auch die Zwischenloesung (gefaltete Laeufe
|
||||
abweisen) ist nicht eingebaut. Die Zeilennummern unten sind veraltet: Phase B
|
||||
von `vf-linienzug-modus2` liegt inzwischen bei ca. `vf_linienzug.lsp:11880-12100`
|
||||
(per Suche nach `climber-span` finden).
|
||||
Die Datei bleibt BEWUSST liegen, obwohl der Auftrag abgeschlossen ist: vier
|
||||
Kommentare in `Lisp/vf_linienzug.lsp` verweisen auf diesen Pfad (Suche nach
|
||||
`modus2-achsenweise-bilanz`). Sie dokumentiert damit nicht mehr einen Plan,
|
||||
sondern WARUM der Solver so bilanziert, wie er es tut - einschliesslich der
|
||||
fehlgeschlagenen Versuche, damit sie niemand ein zweites Mal unternimmt.
|
||||
|
||||
Alles unterhalb dieser Zeile ist der urspruengliche Plan von 2026-09-18 und
|
||||
seine Zwischenstaende. Die dort genannten Zeilennummern sind veraltet; Phase B
|
||||
von `vf-linienzug-modus2` findet man per Suche nach `climber-span`. Die damals
|
||||
vorgeschlagene Zwischenloesung (gefaltete Laeufe mit Meldung abweisen) wurde
|
||||
NICHT umgesetzt und ist gegenstandslos - solche Laeufe funktionieren jetzt.
|
||||
|
||||
## Kurzfassung
|
||||
|
||||
@@ -166,3 +174,220 @@ namentlich (`AS-Fussabdruck ... von Segment N abgezogen`,
|
||||
`Abschluss-Fussabdruck ...`, `Eck-Korrektur ... auf Segment N`). Eine
|
||||
FEHLENDE Zeile ist das Warnsignal - so wurde ein 2,4-mm-Rest gefunden. Fuer
|
||||
die U-Form-Diagnose sind diese Zeilen der schnellste Einstieg.
|
||||
|
||||
---
|
||||
|
||||
## Stand 2026-10-28: Fueller-Seite geloest, Solver-Seite offen
|
||||
|
||||
### Geloest und gemessen
|
||||
|
||||
`vfl-m2-eingang-fp`: GF1 + Separator + Umlenkstation + Uebergangsbogen stehen
|
||||
auf dem Segment `vf-start`. Ist dieses Segment ein FUELLER (der Kletterer
|
||||
liegt hinter einer Kurve), bekam der Fueller bisher die volle Restlaenge, als
|
||||
staende dort nichts. Jetzt werden sie abgezogen.
|
||||
|
||||
Ist das Eingangs-Segment selbst der Kletterer - der gerade Normalfall -, gibt
|
||||
die Funktion hart 0.0 zurueck; der funktionierende Fall kann sich also nicht
|
||||
aendern. Gemessen am U-Form-Testfall: **Querabweichung 8005 -> 1424 mm**,
|
||||
Segment 1 danach auf 0,2 mm genau belegt.
|
||||
|
||||
### Noch offen: der Solver rechnet GF und Stationen gegen die falsche Achse
|
||||
|
||||
Rest 1424 mm. Segment 5 (Kletterer) legt 6475,5 mm zurueck, verfuegbar waeren
|
||||
7899,8 - der Solver reserviert dort Platz fuer Umlenkstation, Separator und
|
||||
den GF1-Anteil, die auf Segment 1 stehen.
|
||||
|
||||
### Fehlgeschlagene Versuche (nicht wiederholen)
|
||||
|
||||
Drei Anlaeufe am 2026-10-27/28, jeder an einer anderen Kopplung gescheitert:
|
||||
|
||||
1. **`feste-vf` kleiner uebergeben.** Geht nicht: `feste-hz` fliesst in
|
||||
`vf-winkel-AB` (vf_standard.lsp:241/245) sowohl als `feste*cos3` in die
|
||||
LAENGE als auch als `feste*sin3` in die HOEHE. Die Hoehe ist real - die
|
||||
Teile senken die Kette ab, egal auf welchem Schenkel sie stehen. Nur der
|
||||
Laengenanteil darf verschoben werden.
|
||||
2. **Spanne vorab korrigieren und iterieren.** Geht nicht direkt:
|
||||
`vfl-zsolve-winkel-waehlen` enthaelt die WINKELFRAGE an den Nutzer - eine
|
||||
Iteration wuerde mehrfach fragen. Und die Korrektur ist pro Winkel
|
||||
verschieden, weil jeder Winkel ein anderes `L_GF` ergibt.
|
||||
3. **Stiller Nachrechner nach der GF-Verteilungsfrage** (Code vorhanden, per
|
||||
`(setq nachrechnen-k 4)` deaktiviert). Technisch sauber: kein Dialog,
|
||||
Fragenfolge und Journal unveraendert, Konvergenz in 4 Runden
|
||||
(3278 -> 4372 -> 4737 -> 4859 -> 4899 mm). ABER er kollidiert mit
|
||||
**`filler-A-len`**: dieser Fueller belegt im Kletter-Segment genau den
|
||||
Platz, den das halbe GF1 dort frei laesst. Nimmt man GF1 aus der
|
||||
Kletterer-Spanne heraus, wird Fueller-A trotzdem gebaut - zusaetzlich zum
|
||||
echten GF1 auf demselben Segment. Gemessen: Fueller nach der
|
||||
Umlenkstation -369 mm (auf 100 geklemmt), Kette 746 mm daneben.
|
||||
Kleinerer Endfehler, aber entartete Geometrie - deshalb zurueckgenommen.
|
||||
|
||||
### Daraus fuer den naechsten Anlauf
|
||||
|
||||
Der Nachrechner ist vermutlich der richtige Weg, aber **`filler-A-len` muss
|
||||
mitbehandelt werden**: er gehoert zur Annahme "GF1 liegt im Kletter-Segment"
|
||||
und darf bei gefaltetem Lauf nicht mehr entstehen. Wer das angeht, sollte
|
||||
beide Mechanismen zusammen betrachten, nicht nacheinander.
|
||||
|
||||
Testfall vorhanden: U-Form 5855 / 270 / 7806 mm (Kletterer hinter zwei
|
||||
90-Grad-Kurven), Soll-Querabweichung ~0, Stand heute 1424 mm. Die beiden
|
||||
geraden Referenzketten in `c:TEST_LINIENZUG_MODUS2` schuetzen den Normalfall.
|
||||
|
||||
---
|
||||
|
||||
## Stand 2026-10-29: Eingangs-Segment exakt, Kletterer-Segment offen
|
||||
|
||||
### Zusaetzlich geloest (gegenueber dem Stand vom 2026-10-28)
|
||||
|
||||
**Fueller-A entfaellt bei gefaltetem Lauf**, und `vfl-m2-eingang-fp` zieht
|
||||
seitdem `br-gf1` ab statt `gf-total`. Beides gehoert zusammen:
|
||||
|
||||
`filler-A-len` fuellt den Platz, den ein halbiertes GF1 auf DERSELBEN Achse
|
||||
frei laesst - er gehoert zur Annahme "GF1 und GF2 liegen auf einer Geraden".
|
||||
Bei gefaltetem Lauf wurde er auf dem Eingangs-Segment ZUSAETZLICH zu GF1
|
||||
gebaut; zusammen mit GF2 im Kletterer-Schenkel entstanden damit 1.5 x
|
||||
gf-total Gefaellestrecke bei einem Budget von gf-total.
|
||||
|
||||
Ergebnis, am U-Form-Testfall nachgerechnet (9 Grad, Verteilung 1/2+1/2):
|
||||
|
||||
```
|
||||
Segment 1: AS 425,8 + GF1 1370,3 + Sep 299,6 + Umlenk 499,3
|
||||
+ Bogen 199,9 + Fueller 3153,7 = 5948,6 mm
|
||||
Budget: 5855 + 93,8 (Eck-Korrektur) = 5948,8 mm
|
||||
```
|
||||
|
||||
Das Eingangs-Segment ist damit **auf 0,2 mm exakt belegt**, und im Protokoll
|
||||
steht nur noch EIN Fueller statt zwei.
|
||||
|
||||
### Was offen bleibt
|
||||
|
||||
Das KLETTERER-Segment. Gemessen im selben Lauf: Segment 5 belegt 6965,8 mm,
|
||||
verfuegbar waeren 7899,8 - es fehlen **934 mm**, exakt die Endabweichung.
|
||||
|
||||
Der Solver bekommt als Spanne 7704,16 mm und verplant darin u.a. GF1
|
||||
(1370,3) sowie Umlenkstation + Separator (798,9) - Teile, die auf Segment 1
|
||||
stehen. Umgekehrt enthaelt seine Spanne NICHT den Abschluss-Fussabdruck
|
||||
(ab_3 + Motorstation, 695 mm), weil dieser nur von FUELLER-Segmenten
|
||||
abgezogen wird (`fill-len`) und das Kletterer-Segment keines ist.
|
||||
|
||||
**Der Restfehler skaliert mit `L_GF`** und damit mit dem gewaehlten Winkel -
|
||||
unabhaengig bestaetigt durch zwei Laeufe auf demselben Pfad:
|
||||
|
||||
| Winkel | L_GF | Querabweichung |
|
||||
|---|---|---|
|
||||
| 6 Grad | 1093 | 90 mm |
|
||||
| 9 Grad | 2744 | 934 mm |
|
||||
|
||||
Praktische Folge: Mit flachem Winkel ist der gefaltete Lauf heute brauchbar,
|
||||
mit steilem nicht.
|
||||
|
||||
### Hinweis zur Methodik fuer den naechsten Anlauf
|
||||
|
||||
Zwei Laeufe sind nur vergleichbar, wenn **Winkel UND GF-Verteilung gleich**
|
||||
sind. Mehrere Messreihen dieser Sitzung waren nicht deutbar, weil sich
|
||||
zwischendurch der Winkel geaendert hatte und der Restfehler mit `L_GF`
|
||||
skaliert. Vor einer Aenderung also eine feste Kombination festlegen
|
||||
(Vorschlag: 12 Grad, Verteilung 1/2+1/2) und nur die vergleichen.
|
||||
|
||||
---
|
||||
|
||||
## Nachtrag 2026-10-29: Loesungsansatz vom Nutzer
|
||||
|
||||
Der Abschnitt darueber beschreibt den Stand VOR dem folgenden Umbau; er bleibt
|
||||
als Herleitung stehen.
|
||||
|
||||
Nutzer-Vorgabe: *"nach der zweiten VF-Kurve den passenden Winkel neu aus dem
|
||||
KS_AUS der Kurve und dem Zielpunkt rechnen"* und *"da GF2 feststeht, steht auch
|
||||
die fuer Auf/Ab verbleibende Laenge fest - passender Winkel plus eine
|
||||
ausgleichende GF"*.
|
||||
|
||||
Das ist die Umkehrung der bisherigen Logik und trifft den Kern: bisher wurde
|
||||
ALLES vorab global verplant und der aufgelaufene Fehler landete am Kettenende.
|
||||
Richtig ist, die letzten freien Groessen aus der GEMESSENEN Ist-Lage zu
|
||||
bestimmen. Je nachdem, was das letzte Segment ist, sind das verschiedene
|
||||
Groessen:
|
||||
|
||||
| Letztes Segment | feste Groesse | freie Groessen |
|
||||
|---|---|---|
|
||||
| flacher Fueller | - | Richtung + Fuellerlaenge |
|
||||
| Auf/Ab-Koerper (U-Form) | Laenge (aus dem Pfad) | Winkel (diskret) + GF-Ausgleich |
|
||||
|
||||
### Umgesetzt
|
||||
|
||||
**1. Flacher Fueller als Schlussstueck** - neue Funktion
|
||||
`vfl-zsolve-schluss-ziel`. Bisher loeste `vfl-zsolve-es-fueller` nur die LAENGE
|
||||
und uebernahm die Richtung aus dem gezeichneten Pfad. Eine Laenge verschiebt die
|
||||
Kette aber nur ENTLANG ihrer Achse - steht der reale Kurvenausgang seitlich
|
||||
NEBEN der gezeichneten Geraden, laeuft die gebaute Achse parallel zur Zielachse
|
||||
und der Querversatz ist unerreichbar. Gibt man die Richtung mit frei, stehen
|
||||
zwei Unbekannte zwei Gleichungen (X und Y) gegenueber, geschlossen loesbar:
|
||||
|
||||
```
|
||||
D = Ziel - KS_AUS(letzte Kurve)
|
||||
A = sqrt(|D|^2 - P^2) ; P = Querversatz des ES-Fussabdrucks
|
||||
fill = A - C
|
||||
hz = Winkel(D) - atan2(P, A)
|
||||
```
|
||||
|
||||
`C` und `P` sind von `hz` unabhaengig, weil `vfl-zsolve-es-vektor` Vektor und
|
||||
Bezugsrahmen um denselben Winkel dreht - deshalb ist keine Iteration noetig.
|
||||
Scheitert der Solve (Ziel naeher als `P`), bleibt der bisherige Weg. Unit-Tests:
|
||||
`tu-tests-vfl-schluss` (file-frei ueber `es-block = nil`).
|
||||
|
||||
**2. Eingangs-Hardware bei gefaltetem Lauf** - der am 2026-10-28 zurueck-
|
||||
genommene Spannen-Zuschlag ist wieder da. Begruendung fuer die Ruecknahme war
|
||||
die Kollision mit `filler-A-len`; dieser Blocker ist entfallen, seit Fueller-A
|
||||
bei gefaltetem Lauf gar nicht mehr entsteht. Zugeschlagen wird weiterhin NUR
|
||||
der Laengenanteil (`entry-fixed * cos3`), nie `feste-vf` selbst - dessen
|
||||
`sin3`-Hoehenanteil ist real.
|
||||
|
||||
**3. Abschluss-Hardware auf dem Kletterer** (`kletter-ende-fp`) - endet der Lauf
|
||||
auf einem FUELLER, zieht `vfl-zsolve-es-fueller` Motorstation + Separator + ES
|
||||
beim Loesen der Fuellerlaenge selbst ab. Endet er auf einem KLETTERER, gibt es
|
||||
diesen Fueller nicht: die drei Teile werden dort gebaut, standen aber in keinem
|
||||
Budget. Abgezogen wird dasselbe wie in dessen Konstante `cc`, OHNE den
|
||||
ab_3-Bogen (der steckt in diesem Fall schon in `uebergang-fp`).
|
||||
|
||||
**4. GF1-Fremdanteil** (Nachrechner wieder aktiv, 8 statt 4 Runden) - `gf-total`
|
||||
ist ein ERGEBNIS des Winkel-Solves, sein auf dem Eingangs-Schenkel stehender
|
||||
Teil laesst sich dort noch nicht abziehen (Henne-Ei). Der Nachrechner loest bei
|
||||
UNVERAENDERTEM Winkel neu und konvergiert mit Faktor ~1/3.
|
||||
|
||||
### Der entscheidende Punkt: 3 und 4 wirken nur GEMEINSAM
|
||||
|
||||
| Posten | im Budget des Solvers | steht real auf dem Kletterer |
|
||||
|---|---|---|
|
||||
| GF1 | ja | nein - liegt im Eingangs-Schenkel |
|
||||
| Motor + Separator + ES | nein | ja |
|
||||
|
||||
Die beiden Betraege heben sich TEILWEISE auf. Wer nur einen davon korrigiert,
|
||||
verschiebt den Fehler bloss in die andere Richtung - genau das war der
|
||||
746-mm-Befund vom 2026-10-28, der damals wie eine Verschlechterung aussah.
|
||||
Gemessen am 9-Grad-Lauf: GF1 1636.9 - (Motor+Sep+ES) 1235.1 = 401.8 mm, exakt
|
||||
die damalige Restabweichung von 401.7 mm.
|
||||
|
||||
### Messergebnis
|
||||
|
||||
| Lauf | vorher | nachher |
|
||||
|---|---|---|
|
||||
| U-Form 9 Grad | 1424 -> 934 mm | **0.56 mm** |
|
||||
| U-Form 12 Grad | - | **0.7 mm** |
|
||||
| Variante A (Vario-Kurve) | OK | OK |
|
||||
| Variante B (GF-Bogen) | OK | OK |
|
||||
|
||||
Zwei verschiedene Winkel auf demselben Pfad - der Restfehler skaliert also
|
||||
nicht mehr mit `L_GF`, die Bilanz selbst stimmt.
|
||||
|
||||
### Regression auf dem Weg dorthin (Lehrstueck)
|
||||
|
||||
`kletter-ende-fp` schlug zunaechst auch in Variante B zu und verkuerzte deren
|
||||
Segment 1 um 798.9 mm. Dort ist `vf-start = vf-ende = 0`: der VF-Lauf besteht
|
||||
aus EINEM Segment, die Segmente 2..5 sind Back-Lauf. Damit ist der Kletterer
|
||||
zugleich Laufende, der Abzug griff - obwohl ohne flache Zone die Motorstation
|
||||
bereits in `feste-vf` steckt und Separator + ES vom Back-Lauf reserviert werden.
|
||||
Die drei Bedingungen am `if` (`hor-pairs > 0`, `vf-ende = n-1`, `es-vorhanden`)
|
||||
sind deshalb keine Vorsichtsmassnahme, sondern benennen genau die Faelle, in
|
||||
denen sonst doppelt gebucht wird.
|
||||
|
||||
Auffindbar war die Ursache nur, weil Segment 1 von Variante B bei `hz=0` liegt:
|
||||
eine Verkuerzung dieses Segments uebersetzt sich 1:1 in `dX`, und `IST - SOLL =
|
||||
(-799.11 | -104.68)` aus `logs/vfl_modus2.dbg` zeigte die reine X-Verschiebung.
|
||||
|
||||
Reference in New Issue
Block a user