docs: la V1 e' fatta, e due cose che la specifica dava per buone non reggevano

Il ponte e' in VisionSuite (6f5990c, issue #2 chiusa). Corretti due punti di
questo documento: PyTorch in vs-dxf non c'e' piu' da L2, quindi quel lavoro
non esisteva; e la posa iniziale non serve, misurato — l'ICP converge da solo
fino a 45 gradi. Aggiunta la trappola dell'angolo ambiguo sui pezzi
simmetrici, che e' esattamente il caso dei profilati di Trafilo, e il limite
degli ingressi di scansione non collegabili.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JyL1sTGpFxx7Qw3xP58eoZ
This commit is contained in:
Adriano
2026-09-14 12:45:59 +02:00
parent 401457d21f
commit 665d25e574
@@ -151,30 +151,54 @@ uscite** dei due motori, perché è quella forma che decide la firma degli strum
dell'ambiente del worker è un numero misurato; esiste una nota di due pagine con le firme reali dei due dell'ambiente del worker è un numero misurato; esiste una nota di due pagine con le firme reali dei due
motori. motori.
### V1 — Il ponte: pattern matching e DXF compare diventano strumenti del grafo ### V1 — Il ponte — ✅ **fatta il 14/09/2026** (VisionSuite `6f5990c`, issue #2 chiusa)
**Si lavora in VisionSuite, non in TieMeasureFlow.** In `vs-task` nascono gli strumenti nuovi, con la **Il lavoro è stato fatto in VisionSuite**, come questo documento prescriveva. Gli strumenti non sono
stessa forma dei dieci esistenti: finiti in `vs-task` insieme ai dieci geometrici, ma **ciascuno nel pacchetto del proprio motore** —
`visionsuite.pm2d.task_tools` e `visionsuite.dxf.task_tools` — perché altrimenti il livello-task avrebbe
ereditato numba, opencv e fastapi da `pm2d` e scipy ed ezdxf da `dxf`, e se li sarebbe portati dietro
ogni consumatore che voleva soltanto una distanza fra due punti. Si dichiarano con l'extra `task`.
- `MatchPattern` — ingresso: immagine più modello; uscite: presenza, punteggio, posizione e rotazione - `MatchPattern` — ingressi: la scena dal contesto, il modello per chiave o per percorso, punteggio
dell'istanza trovata. È anche ciò che fornisce la posa alle quote successive, invece di pretendere che minimo, intervallo di angolo e di scala. Uscite: `found`, `score`, `row`, `col`, `angle_deg`, `scale`,
il pezzo sia appoggiato sempre uguale. `n_matches`.
- `CompareDXF` — ingressi: immagine, disegno di riferimento, fattore di scala; uscite: scarto massimo, - `CompareDXF` — ingressi: immagine, `dxf_path`, `px_per_mm` (o la calibrazione dal contesto),
scarto medio, numero di zone fuori tolleranza, e l'esito zona per zona. `tolerance_mm`. Uscite: `max_deviation_mm`, `mean_deviation_mm`, `n_points`, `overlay`.
Due vincoli che decidono se il ponte è fatto bene: **Il vincolo che ha retto:** gli strumenti espongono numeri, non verdetti. `CompareResult.passed` esiste
e resta fuori dalle uscite, e un test lo sorveglia. La `tolerance_mm` serve **solo a colorare l'overlay**:
è un parametro di disegno, non una soglia di accettazione.
1. **Gli strumenti espongono numeri, non verdetti.** `vs-dxf` ha di suo un `ToleranceChecker` e un ⚠️ **Due cose che questo documento dava per buone non hanno retto alla prova, ed è il motivo per cui una
`CompareResult` con il proprio giudizio: quel giudizio va ignorato, esattamente come la decisione 7 specifica si verifica invece di eseguirla.**
impone già per le quote di `vs-measure`. Due giudici sullo stesso valore è il modo più rapido per
ottenere un CSV che si contraddice.
2. **`vs-dxf` si porta dietro PyTorch (~2,5 GB) per una riga** (`config.py:53`, annotato nella scheda
VisionSuite). Prima di aggiungerlo agli extra del worker, quella riga va tolta: altrimenti il container
della visione triplica, e con lui i tempi di ogni deploy a Tràfilo.
In TieMeasureFlow cambia **soltanto** `pyproject.toml`: `vs-dxf` entra negli extra `vision` e 1. **«`vs-dxf` si porta dietro PyTorch per una riga» era falso.** Torch è stato tolto in L2 insieme al
`vision-worker`, il pin del sottomodulo avanza al commit che contiene i due strumenti nuovi. Nessuna riga rilevatore DexiNed che non aveva mai girato, e il `pyproject.toml` di `vs-dxf` lo dice per esteso. La
di algoritmo entra in questo repository. nota veniva dalla scheda VisionSuite in AI-OS, che su quel punto era invecchiata. Il lavoro non
esisteva: il container della visione non triplica.
2. **La posa iniziale non serve, ed è misurato.** Questo documento dava per scontato che `CompareDXF`
dovesse partire allineato dalla posa di `MatchPattern`. Ruotando la scena e lasciando l'ICP senza
aiuto, sul rettangolo forato a 4 px/mm: **0°** → 0,285 mm, **5°** → 0,346, **20°** → 0,288, **45°** →
0,243. Converge da solo, e a 45° meglio che a zero. In più `DXFCompare._pose_to_transform` non ha
chiamanti né test e trasla le **righe** dove il nome dice colonne: l'ingresso non è stato esposto,
perché chi lo avesse collegato al match avrebbe ottenuto una traslazione di centinaia di pixel
credendo di aver fatto la cosa giusta. Un test parametrico su 0°, 20° e 45° tiene ferma la scelta.
⚠️⚠️ **E una trappola nuova, da sapere prima di comporre ricette: su un pezzo simmetrico l'angolo del
match è ambiguo.** Sulla scena non ruotata il rettangolo torna `angle_deg = -180` con punteggio 0,924,
perché a 180° è identico a sé stesso. `row` e `col` restano affidabili; l'angolo, su un pezzo senza un
riferimento che rompa la simmetria, non è una risposta. I profilati di Tràfilo sono esattamente il genere
di pezzo in cui questo si presenta.
*Verificato:* `tests/test_visione_nel_grafo.py` carica una ricetta JSON che contiene **entrambi** gli
strumenti con `Task.from_dict`, la esegue e ottiene le uscite attese. 21 test nuovi; **1242 verdi** su
tutto il monorepo.
**Quello che resta da fare qui, in TieMeasureFlow** (è ciò che la issue #8 della lista lavori chiedeva, e
non è cambiato): `vs-dxf` entra negli extra `vision` e `vision-worker` di `pyproject.toml`, il pin del
sottomodulo avanza a `6f5990c`, e il runner **importa i due moduli** `visionsuite.pm2d.task_tools` e
`visionsuite.dxf.task_tools` — senza quell'import il registro non li conosce e una ricetta che li nomina
non si carica. Nessuna riga di algoritmo entra in questo repository.
*Fatto quando:* un grafo JSON che contiene `MatchPattern` e `CompareDXF` viene eseguito da *Fatto quando:* un grafo JSON che contiene `MatchPattern` e `CompareDXF` viene eseguito da
`POST /api/vision/preview` su un'immagine caricata, e restituisce le uscite attese. Senza camera, senza `POST /api/vision/preview` su un'immagine caricata, e restituisce le uscite attese. Senza camera, senza
@@ -186,8 +210,8 @@ La schermata che oggi non esiste. Si compone con un **editor visuale a nodi** (d
14/09). Il Maker, alla scrivania: 14/09). Il Maker, alla scrivania:
- carica o sceglie un'**immagine di riferimento** per il task (l'API esiste già); - carica o sceglie un'**immagine di riferimento** per il task (l'API esiste già);
- compone il grafo collegando gli strumenti — l'immagine entra, `MatchPattern` dà la posa, da lì scendono - compone il grafo collegando gli strumenti — l'immagine entra, e da lì scendono il riconoscimento, le
le quote e il `CompareDXF`; quote e il confronto col disegno;
- preme **prova** e vede le uscite (`/preview` esiste già); - preme **prova** e vede le uscite (`/preview` esiste già);
- **aggancia** ciascuna uscita a una quota della ricetta, scrivendo `vision_output` sulla subtask (il - **aggancia** ciascuna uscita a una quota della ricetta, scrivendo `vision_output` sulla subtask (il
campo esiste già), e su quella quota mette nominale e tolleranze come su qualunque altra; campo esiste già), e su quella quota mette nominale e tolleranze come su qualunque altra;
@@ -200,6 +224,14 @@ applicate. È la storia che vende: il confronto DXF **dentro il flusso di produz
Restano fuori dalla fiera, e si fanno dopo, la promozione a `expected_json` e la prova di non regressione: Restano fuori dalla fiera, e si fanno dopo, la promozione a `expected_json` e la prova di non regressione:
valgono per la robustezza, ma allo stand non si mostrano. valgono per la robustezza, ma allo stand non si mostrano.
⚠️ **Un limite dell'editor, emerso il 14/09 costruendo gli strumenti.** Negli strumenti geometrici di
`vs-task` gli ingressi di scansione — `start_row`, `start_col`, `end_row`, `end_col` di `DetectLine` e
compagnia — **non sono collegabili**: si impostano a mano. Finché restano così, la posa che
`MatchPattern` trova non può spostare le scansioni delle quote, e il pezzo va appoggiato dove la ricetta
si aspetta. Renderli collegabili è un lavoro in VisionSuite, piccolo ma non nullo, ed è **il passo che
rende utile il riconoscimento dentro una ricetta di misura**: senza, `MatchPattern` serve a dire se il
pezzo c'è ed è quello giusto, non a inseguirlo.
*Fatto quando:* una ricetta con un task di visione si compone interamente dall'interfaccia, senza scrivere *Fatto quando:* una ricetta con un task di visione si compone interamente dall'interfaccia, senza scrivere
JSON a mano, e un operatore la esegue ottenendo un esito vero. La prova di non regressione — rieseguire JSON a mano, e un operatore la esegue ottenendo un esito vero. La prova di non regressione — rieseguire
l'intero parco ricette su immagini di riferimento e vedere quali quote si sono mosse — è il criterio della l'intero parco ricette su immagini di riferimento e vedere quali quote si sono mosse — è il criterio della