Files
syncro_multi_agente/BRIDGE_NOTES.md

146 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Note operative — produttore GLB (Fusion → Blender)
Questo file è la sponda **produttore** del [FUSION_GLB_CONTRACT.md](FUSION_GLB_CONTRACT.md).
Tutte le risposte ai problemi `[OPEN]` del contratto vivono qui finché non vengono spostate nello stato `[RESOLVED]` del contratto stesso.
---
## Risposte ai problemi aperti del contratto §8
### 1) Motion link con `joint1: null`
**Stato:** è un limite dell'API Fusion. Quando l'utente crea il motion link tramite la finestra "Collegamento movimento", Fusion lo memorizza con un riferimento interno (entity-token) ma il proxy `motionLink.entityOne` può ritornare `None` se il joint è stato creato/rinominato dopo il link. L'add-in **non** può inventarsi il nome.
**Workaround consigliato a chi consuma:**
- I 5 driver (`A`, `X`, `Y`, `PEN`, `Z`) NON sono mai `null` su `joint2`: i link con `joint2 == driver` sono usabili anche senza `joint1` (basta non propagare nulla).
- Per i link con `joint2: null` AND `joint1: null` (es. `"Collegamento movimento 32"`, `"Collegamento movimento 4"`): sono rumore, ignorabili.
- Per i link con `joint1: null` ma `joint2` valorizzato (es. `"Collegamento movimento 14"``Motore asse X`, `"Collegamento movimento 28"``Rivoluzione 26`, `"Collegamento movimento 38"``Asse Penna `):
- **`Motore asse X`** è il driver, non ha bisogno di slave esterni — la traslazione del carrello X è già descritta dal rigid group `Gruppo rigido 6` (`end stop X PIastrina:1 | binario SX:1 | Cinghia T5:1`).
- **`Asse Penna `** idem: lo slider muove direttamente `guida lineare:1`, gli altri pezzi seguono via rigid groups.
**TL;DR per il viewer:** ignora tranquillamente i link con `joint1: null`. Tutta la propagazione necessaria passa dai rigid groups + i 5 driver diretti.
### 2) `Motore A` esiste in `asBuiltJoints`?
**Confermato.** Verificato sul file corrente: presente con nome esatto `"Motore A"`, tipo `revolute`, `child = "6627T331_Stepper Motor (1) (1):1"`, `axis ≈ [0, 0, 1]`.
L'eventuale mismatch lato viewer dipende dal `child` name: nel JSON è esattamente `"6627T331_Stepper Motor (1) (1):1"` (due " (1)" di seguito), che nasce dal fatto che in Fusion il componente è stato copiato/incollato due volte. Se il viewer non lo trova, il bug è nel matching, non nell'export.
### 3) Convenzione multi-macchina
Da concordare quando servirà. Proposta minimale:
```
exports/
plotter/
plotter.glb
plotter.joints.json
<altra_macchina>/
<altra_macchina>.glb
<altra_macchina>.joints.json
```
Lato viewer un file `machines.json` indicizza nome → coppia (glb, json, DRIVERS map).
---
## Stato attuale dell'export (rispetto alla checklist §6 del contratto)
| Voce checklist | Stato | Note |
|---|---|---|
| GLB in metri | ✅ | `build_glb_from_fusion_export.py` applica `scaleFactor=0.01` al root, mesh OBJ importate in cm sono rimpicciolite di 100× → metri |
| Gerarchia Empty 1:1 | ✅ | Pass 1 crea un Empty per ogni `node` del `hierarchy.json` |
| `fusion_name` e `fusion_path` per ogni Empty | ✅ (dal 2026-06-09) | Aggiunti come custom properties; coincidono byte-per-byte con `Joint.child` / `Joint.childFullPath` |
| Mesh figlie degli Empty, non joinate | ✅ | OBJ importati e re-parentati all'Empty corrispondente |
| Stato salvato = posa "tutti i driver a 0" | ⚠️ | Posa "as built" di Fusion al momento dell'export. Se l'utente esporta con `slideValue ≠ 0` o `rotationValue ≠ 0` la posa neutra slitta. **Convenzione:** in Fusion riportare i 5 driver a zero prima di lanciare lo script. |
| Manifest embedded `scene["fusion"]` | ✅ | Il GLB contiene già il JSON completo in `scene.extras.fusion` |
---
## Comandi operativi
Rigenera GLB dopo modifica codice:
```powershell
.\build_glb.bat "C:\Users\croce\OneDrive\Desktop\export"
```
Riallinea script Fusion (da fare dopo ogni `edit` di `ExportKinematicGraph.py`):
```powershell
python -c "import py_compile; py_compile.compile(r'C:\Users\croce\OneDrive\Desktop\export grafo fusion\ExportKinematicGraph.py', doraise=True); print('OK')"; if($LASTEXITCODE -eq 0){ Copy-Item -Force 'C:\Users\croce\OneDrive\Desktop\export grafo fusion\ExportKinematicGraph.py' (Join-Path $env:APPDATA 'Autodesk\Autodesk Fusion 360\API\Scripts\ExportKinematicGraph'); Write-Host "Sync OK" }
```
Sanity-check sui driver nel JSON:
```powershell
$j = Get-Content 'C:\Users\croce\OneDrive\Desktop\export\joints.json' -Raw | ConvertFrom-Json
$names = @('Motore asse X','Motore asse Y','Asse Penna ','asse Z pneumatico M5?')
foreach($n in $names){ $j.joints | Where-Object name -eq $n | Select-Object name,type,child,axis,@{n='limits';e={ if($_.slideLimits){'slide '+$_.slideLimits.minimumValue+'..'+$_.slideLimits.maximumValue}elseif($_.rotationLimits){'rot '+$_.rotationLimits.minimumValue+'..'+$_.rotationLimits.maximumValue} }} | Format-List }
$j.asBuiltJoints | Where-Object name -eq 'Motore A' | Select-Object name,type,child,axis | Format-List
```
---
## Findings dal viewer (2026-06-09)
Lato consumer (`automation_kriz`) ho aggiunto una pagina di ispezione live a `/lab/graph` che carica `hierarchy.json` + `joints.json` direttamente dal server e ne mostra: l'albero completo con conteggi joint/rigid per nodo, i 5 driver con stato OK/rotto, la lista di tutti i 329 joint + 28 asBuilt con filtro per tipo, i 9 motion link (validi vs rotti) e i 20 rigid group. Serve per fare debug del JSON senza dover aprire Fusion. Dato che è una pagina autenticata e legge `/api/fusion/{joints,hierarchy}/` lato Django, basta sostituire i file in `/home/marco/automation_kriz/joints.json` + `hierarchy.json` e ricaricare.
Ispezionando l'export attuale (`329 joints, 28 asBuiltJoints, 9 motionLinks, 20 rigidGroups`) ho trovato tre problemi che impediscono al viewer di propagare il movimento sull'asse X (e probabilmente anche Y e PEN dipendono dagli stessi pattern). Servono fix lato `ExportKinematicGraph.py`.
### BUG 1 — `rigidGroups[].occurrences` è SEMPRE vuoto
Tutti i 20 gruppi rigidi esportati hanno `occurrences: []`. Esempio dal file corrente:
```json
[
{"name": "Gruppo rigido 6", "occurrences": []},
{"name": "Gruppo rigido 17", "occurrences": []},
...
]
```
Nel `BRIDGE_NOTES` precedente è scritto che `Gruppo rigido 6` doveva contenere `end stop X PIastrina:1 | binario SX:1 | Cinghia T5:1`. Nell'export reale quelle occorrenze NON ci sono. Senza occurrences, il viewer non sa quali parti tenere "incollate" al carrello / motore / cinghia → il driver X non muove nulla.
Possibili cause da verificare nell'add-in:
- Si itera `rigidGroup.occurrences` ma con un proxy stale (collection invalidata dopo `activate`/`returnToParent`)?
- Si guarda `nativeObject.occurrences` invece di farla risolvere via `assemblyContext`?
- Si filtra accidentalmente per `occ.isLightBulbOn` o `isSuppressed`?
Verifica veloce: in console Fusion durante export stampare `len(list(rg.occurrences))` per ogni `rg` in `rootComp.allRigidGroups` e confrontare con quello che finisce nel JSON.
### BUG 2 — `Collegamento movimento 14` (driver X) ha `joint1: null`
```json
{"name": "Collegamento movimento 14", "joint1": null, "joint2": "Motore asse X", "ratio": null}
```
`Motore asse X` è un giunto `revolute` (il motore stepper gira), `joint2 = Motore asse X` significa "questo è il driver". Senza `joint1` (lo slider del carrello che dovrebbe seguire) il viewer non può propagare la rotazione del motore in traslazione del carrello.
Stessa cosa per `Collegamento movimento 38` (`joint2 = "Asse Penna "`) e `Collegamento movimento 28` (`joint2 = "Rivoluzione 26"`).
Nel BRIDGE_NOTES precedente è scritto "ignorabili, propagazione passa dai rigid groups" → ma siccome i rigid groups sono vuoti (BUG 1), questi motion link diventano cruciali. Bisogna almeno provare a recuperare `joint1` quando è `None`: il pattern API è `motionLink.entityOne` (proxy) vs `motionLink.entityOneNative` o usare `motionLink.bRepEdge.assemblyContext`. Se proprio l'API ritorna `None`, scrivere nel JSON il `componentToken` o l'`entityToken` come stringa hex così almeno il consumer può fare matching manuale.
### BUG 3 — `Motore asse X` ha parent/child invertiti (convenzione)
```json
{
"name": "Motore asse X",
"type": "revolute",
"parent": "Puleggia_HTD5M_z15:1",
"child": "6627T281_Stepper Motor:1",
"axis": [-1, 0, 0]
}
```
Fisicamente è il motore stepper che è fissato al telaio e fa girare la puleggia. Nel JSON è il contrario. Il viewer applica sempre la rotazione al `child` mantenendo fermo il `parent`, quindi vede il motore ruotare nel vuoto e la puleggia (che dovrebbe seguire) sta ferma.
Fix in Fusion: aprire il joint, cliccare **Switch** per invertire `Component 1`/`Component 2`. Sospetto valga anche per gli altri driver — andrebbero controllati tutti e cinque con questo criterio:
- `parent` = pezzo che resta solidale al telaio (o al precedente livello cinematico)
- `child` = pezzo che si muove rispetto al parent
### Patch temporanea lato viewer (in valutazione, non ancora applicata)
Se i fix 1-3 lato Fusion richiedono tempo, lato viewer posso aggiungere:
- una mappa `viewerOverrides.json` con `{ jointName: { swapParentChild: true } }` per simulare il fix BUG 3 senza modificare l'export
- una mappa `viewerRigidGroups.json` con i contenuti che `Gruppo rigido N` dovrebbe avere, in attesa del fix BUG 1
- una mappa `viewerMotionLinks.json` per ricostruire i `joint1` mancanti del BUG 2
Sono workaround sporchi: preferisco fixare l'export quando possibile e tenere il viewer privo di patch ad-hoc. Fammi sapere se preferisci che proceda comunque con gli override per sbloccare le demo nel frattempo.
### Per gli altri driver
Stessa analisi va fatta per `Motore asse Y`, `Asse Penna ` e `asse Z pneumatico M5?`. Possibili problemi simmetrici: rigid groups vuoti, motion link `joint1=null`, parent/child invertiti. Quando rilancerai un export pulito segnalalo qui e rifaccio il giro su `/lab/graph`.