- Rust 100%
Port TDD de lj_rust (protonphoton) dans laser-opt : - src/sim/galvo.rs : miroir 2nd ordre par axe (f_n 2.5 kHz, zeta 0.7), garde d'intégration MAX_W_DT (substeps auto), laser_delay en substeps, renvoie le 2e tour (régime établi). - src/sim/metrics.rs : 7 familles de métriques sur la trace simulée — déviation mean/p95/max, overshoot/rounding des coins, luminosité cv (bins le long des tracés), leak (faisceau allumé en transit), coverage, fps/lit_fraction, pics accel/vitesse. Tout relatif à FS=2.0. - examples/sim_quality_bench.rs -> bench_sim_quality.json (5 formes x 3 charges x 4 mix, trame jouée à 30 kpps). Fix leak (TDD, 3 tests blank_tests) : le blank d'approche statique (13 pts au départ du saut) est remplacé par transit_blanks() — transit dynamique quintic porté de laser-dac/presentation (Linf -> 0-64 pts + dwells 100/400 µs). asteroids leak 0.176 -> 0.000, cov 1.000. Bench croisé (examples/bench_lj_vs_mix.rs -> bench_compare_lj.json) : pipeline optimize() complet de lj_rust branché en dev-dep (feature helios rendue optionnelle pour éviter le conflit libusb1-sys), mesuré par les mêmes métriques. Verdict : lj_rust cov 1.000 / leak 0.000 mais cv luminosité 0.46-0.56 et nb de points fixé par le temps (526 pts sur un carré demandé à 10000) ; v2+velocity : leak 0.000, cov >= 0.955, cv 0.003-0.16 (3-37x mieux), le plus rapide à charge égale. 119 tests verts, 0 warning. README : état au 2026-10-18, pro/con du bench croisé, quick start à jour. |
||
|---|---|---|
| ConvolutionInterpolations.jl@dc9f9806b2 | ||
| laser-dac-rs@92e632ad8d | ||
| laser-opt | ||
| laser-optimizer | ||
| lasy@a9e79a5ef1 | ||
| lzr@e19b5b3b82 | ||
| OpenIDN-Laser-DAC-Framework@437e7a245c | ||
| .gitignore | ||
| .gitmodules | ||
| COMPARAISON_OPTIMISATION.md | ||
| README.md | ||
optilaz — Laser Optimisation & Interpolation Toolkit.
Lis ce README dans l'ordre : il est écrit pour un nouveau venu (humain ou IA).
- Où en est-on → 2. Résultats clés → 3. Structure & technologies (la stack, Linux et macOS) → 4. Quick start (faire tourner) → 5. Roadmap (ce qui est fait/coché) → 6. Architecture & physique (le fond) → 7. Plateformes & patches (macOS).
Où en est-on ? (2026-10-18)
L'implémentation existe et tourne : laser-opt/ — port Rust du meilleur algo connu (lzr v2, sans FFI) + moteur lasy (papier Abderyim 2008) + velocity planning curvature-aware + sorties DAC (EtherDream/IDN). 119 tests verts, 0 warning, matrice de 4 pipelines benchée sur 5 formes × 3 charges : v2+velocity gagnant (couverture lit complète, leak 0.000, 393 µs @10k asteroids — sous la frame 60 Hz).
Nouveau (2026-10-17→18) — simulation + métriques + bench croisé lj_rust :
crates/laser-opt/src/sim/: simulateur galvo 2nd ordre (f_n 2.5 kHz, ζ 0.7, garde d'intégration MAX_W_DT, laser_delay) + 7 familles de métriques de qualité (déviation mean/p95/max, overshoot/rounding des coins, uniformité de luminosité cv, leak = faisceau allumé en transit, coverage, fps/effort) — portés de lj_rust (protonphoton), TDD.- Fix leak : le blank d'approche statique (13 pts) remplacé par un transit dynamique quintic (L∞ → 0–64 pts + dwells) — asteroids leak 0.176 → 0.000.
- Bench croisé (
examples/bench_lj_vs_mix.rs→bench_compare_lj.json) : le pipelineoptimize()complet de lj_rust branché en dev-dep, mesuré par LES MÊMES métriques. Verdict chiffré ci-dessous.
Ce qui marche : pipeline complet forme → ordre → interpolation → asserts physiques → PNG/JSON → DAC (IDN testé bout-en-bout avec le simulateur, EtherDream attend le matériel).
Ce qui reste (P2) : laser réel EtherDream, GalvoSafety en OutputFilter sur le flux DAC, profils galvo prédéfinis.
La doc pour aller plus loin :
laser-opt/DEVBOOK.md— LE journal de développement (point d'entrée pour reprendre) : tous les bugs corrigés (symptôme → cause → fix), les résultats mesurés de chaque phase, les pièges et leçons TDD. Écrit pour être lisible sans contexte.COMPARAISON_OPTIMISATION.md— la référence physique/architecturale (équations galvos, comparatif des composants, annexes interpolation lazy). Sa bannière d'entête dit ce qui est déjà exécuté.laser-opt/bench_mix_matrix.json— les benchs bruts (régénérables :cargo run -p laser-opt --example mix_full_bench).laser-opt/bench_compare_lj.json— le bench croisé vs lj_rust (régénérable :cargo run -p laser-opt --release --example bench_lj_vs_mix).- PNG de rendu :
laser-opt/out_*.png(5 formes) +laser-opt/bench_*.png(comparatif moteurs).
Pour une IA : donner DEVBOOK.md + COMPARAISON_OPTIMISATION.md + ce README — ça suffit pour connaître l'état exact, les décisions prises et les bugs déjà corrigés (ne pas les re-découvrir).
Bench croisé vs lj_rust (2026-10-18, release, 30 kpps, mêmes formes/charges/métriques)
Le pipeline optimize() complet de lj_rust (stages clean→order→plan→budget→sample) est branché en dev-dependency et mesuré par les mêmes métriques que nos 4 mix (bench_compare_lj.json, 75 lignes).
| lj_rust | laser-opt v2+velocity |
|
|---|---|---|
| leak (transit allumé) | 0.000 partout | 0.000 (depuis le fix quintic) |
| couverture | 1.000 partout | 0.955–1.000 |
| luminosité (cv, ↓ = mieux) | 0.46–0.56 | 0.003–0.16 (3–37× mieux) |
| nb de points | fixé par le temps (377–1000 pts, ignore la charge) | suit la charge demandée (500–10000) |
| vitesse @10k asteroids | 234 µs (1000 pts) | 393 µs (10000 pts) |
| densification des coins | non (sampling temporel uniforme) | oui (κ Menger, ratio 2×) |
Pro lj_rust : blanking propre par construction (un tracé = un run allumé, sauts blank explicites) ; très rapide au point (13–47 ns/pt) ; pipeline en stages purs testables ; le meilleur simulateur/métriques du domaine (portés ici). Con lj_rust : trame sous-échantillonnée à luminosité inégale (cv 0.46–0.56) — pas de densification de coin ; budget en temps ignore la charge ; pas de blanking intra-tracé, pas de GalvoSafety, pas de sorties IDN ; Redis/Valkey en bus (à ne pas prendre). Pro laser-opt : qualité mesurable et supérieure (cv, coverage, budget respecté) ; matrice ordre×interpolation ; GalvoSafety ; sorties IDN réelles ; asserts physiques. Con laser-opt : plus cher au point (146–412 ns/pt) ; V2ApplyPlan reste défaillant (cov 0.92, leak 0.176 — mix écarté) ; LasyNative garde un leak résiduel 0.008–0.015.
Verdict : v2+velocity domine en qualité à budget égal ; de lj_rust on a pris les outils (simulateur, métriques, transition quintic), pas le pipeline.
Résultats clés (détail complet dans laser-opt/DEVBOOK.md)
La découverte qui a débloqué le --mix (2026-10-15)
lasy et lzr v2 font tous les deux ordre et interpolation — les deux étapes sont découplables → 4 pipelines mixtes possibles (2 ordres × 2 interpolations), exposés par --mix :
| Étape | lasy | lzr v2 | laser-dac | Verdict |
|---|---|---|---|---|
| Ordre | ✅ graphe eulérien | ✅ glouton | — | 2 implémentations |
| Interpolation | ✅ distance_per_point | ✅ apply_plan | resample Catmull-Rom (device) | 2+1 |
| Velocity/coins | — | — | — | velocity.rs (maison) |
| Transition/dwell | — | — | ✅ default_transition | unique |
| Sécurité | — | — | — | GalvoSafety unique |
Matrice finale (bench_mix_matrix.json, 5 formes × 4 mix × 3 charges)
Après les fixes du 16 oct (allocation cumulative du budget, blanks réservés), les 4 mix sortent 500 exact. État final (matrice du 16 oct, bench_mix_matrix.json) :
| Mix | Budget @500 | Lit (carré+point) | Coin varied_angles | Temps @500 |
|---|---|---|---|---|
| lasy+native | 500 exact | 4.400 | 32 | 141 µs |
| lasy+velocity | 500 exact | 4.400 | 31 | 140 µs |
| v2+apply_plan | 500 exact | 4.391 (omet le point) | 28 | 103 µs |
| v2+velocity ✅ | 500 exact | 4.400 (complet) | 31 | 76 µs |
Historique (avant les fixes, matrice du 15 oct) : apply_plan explosait en densité coin (74 → 299 → 1498 @500/2000/10000) et le budget dérivait (510-542) — le velocity resampling corrigeait déjà la sur-densification, les fixes budget/blank ont fait le reste.
GAGNANT v2+velocity : budget exact, couverture lit complète, densité coin saine à toute charge, le plus rapide. Sur le scénario asteroids (6 polylignes disjointes + blanking) : 5 jumps au lieu de 6, lit 3.554u complet, 175 µs @500.
Temps de calcul : pas un critère discriminant
lasy 8-936 µs, v2 3-269 µs (budgets 100-10000, 4 formes, release). Tous < 1 ms → marge ×16 minimum sur la frame 60 Hz (16.7 ms). Ratio v2/lasy 1.8-4.1×.
Physique du budget (500 pts/frame)
30 kpps @ 60 Hz = 500 pts/frame (16.67 ms) — compromis de travail, pas une vérité physique (le kpps mesure la galva, pas le DAC ; EtherDream monte à 100 kpps hardware mais la galva downstream reste le goulot). Amplification input → output mesurée : 45× à 125× (4-9 sommets → 500 pts). Formes toutes en zone safe r_max ≤ 0.78 (marge 20 % vs bords DAC ±1).
Les bugs corrigés en chemin (le DEVBOOK les détaille tous)
- lasy : segment blank→lit classé Lit → faisceau ALLUMÉ en transit (ligne parasite à travers l'écran) ; nœuds blank exclus du graphe → points isolés jamais tracés
- port lzr v2 : bug off-by-one C++ (traverse cycle)
- budget : dérive d'arrondi de l'allocation cumulative (velocity + apply_plan), blanks de saut non réservés, clamp sur la mauvaise dernière traversée
- κ des bouts de polyligne = κ du premier virage ;
Shape.closed; fusion lasy à couleur égale ; polylignes dégénérées eulériennes filtrées
Structure du repo
optilaz/
├── README.md # Ce fichier — point d'entrée
├── COMPARAISON_OPTIMISATION.md # Référence physique/architecturale + annexes
├── .gitmodules # 5 submodules
├── OpenIDN-Laser-DAC-Framework/ # Submodule: C++ — Récepteur IDN → DAC (transport pur)
├── laser-dac-rs/ # Submodule: Rust — Backbone DAC + hooks (TransitionFn, OutputFilter)
├── lzr/ # Submodule: C++ — liblzr optimizer v1/v2 + ILDA parser (référence portée)
├── ConvolutionInterpolations.jl/ # Submodule: Julia — Interpolation haute ordre, lazy=true (référence)
├── lasy/ # Submodule: Rust — Papier Abderyim 2008 (eulerian + blanking), patché (bug faisceau allumé en transit)
├── laser-optimizer/ # Placeholder historique de la roadmap → réalisé par laser-opt/
└── laser-opt/ # ✅ L'IMPLÉMENTATION (workspace : lib laser-opt + binaire laser-opt-test)
├── DEVBOOK.md # ← JOURNAL COMPLET : bugs corrigés, résultats, pièges
├── SORTIES-TDD.md # Décisions + tests TDD de la couche DAC
└── crates/ # laser-opt (lib) + laser-opt-test (binaire CLI/webui)
Le papier de référence
Abderyim_2008_Accurate_Efficient_Laser_Projection.pdf(4 MB) est dans.gitignore— pas dans le repo.
Technologies utilisées
La stack de l'implémentation (laser-opt/)
| Technologie | Version | Rôle | Pourquoi elle |
|---|---|---|---|
| Rust (edition 2021) | stable ≥1.96 | Tout le code | Zero-copy, mono-process, sûr ; le port lzr v2 tourne sans FFI |
| lasy 0.4.1 (submodule, patché) | 0.4.1 | Ordre de tracé : graphe eulérien + blanking (papier Abderyim et al. 2008) | Seule implémentation du papier ; patché (2 bugs : faisceau allumé en transit, points isolés) |
| laser-dac-rs 0.14 (submodule) | 0.14.0 | Backbone DAC : abstraction unifiée 7 DACs + hooks TransitionFn/OutputFilter + presentation (quintic + dwells) + resample Catmull-Rom |
MIT, Rust pur, cible d'intégration du plan |
| petgraph | 0.5 | Graphes (eulérien, pairing) | Imposé par lasy — ne pas monter 0.6 (API break) |
| serde / serde_json | 1 | Sorties JSON (métriques, benchs) | Standard |
| clap | 4 | CLI (--shape, --mix, --target, --out-dac, --safety, --web, --png) |
Standard, derive |
| anyhow | 1 | Erreurs du binaire | Standard |
| approx | 0.5 | Comparaisons flottantes dans les tests | Standard |
Zéro dépendance plateforme : pas de FFI, pas de C++ compilé, pas de Python/Julia au runtime. Le PNG est écrit à la main (zlib stored blocks + CRC32, zéro crate), la webui aussi (TcpListener, zéro framework HTTP).
Les références (submodules, pas compilées par laser-opt)
| Technologie | Langage | Usage dans ce repo |
|---|---|---|
| lzr (liblzr) | C++17 | Algo de référence porté en Rust (lzr2*.rs) — pas compilé par laser-opt |
| OpenIDN-Laser-DAC-Framework | C++17 | Récepteur IDN alternatif (transport pur) — optionnel |
| ConvolutionInterpolations.jl | Julia | Référence math interpolation lazy — non intégrée (décision : velocity planning maison, cf. COMPARAISON §verdict) |
Protocoles DAC supportés (via laser-dac-rs)
| DAC | Transport | État dans laser-opt |
|---|---|---|
| IDN (Open IDN) | UDP (wave, scan) | ✅ testé bout-en-bout avec le simulateur idn-simulator |
| EtherDream | UDP broadcast 7654 + TCP | ✅ code prêt (scan, prepare_stream/begin/data) — attend le DAC réel (P2) |
| Helios, lasercube, AVB, oscilloscope | USB/réseau | Disponibles dans laser-dac-rs, non branchés dans le harness |
Plateformes : Linux ET macOS
Le code est Rust pur, sans dépendance plateforme — il compile et passe les tests tel quel sur Linux (X11) et macOS :
- développé sur Linux tl13 (X11) ; recompilation macOS prévue (user
sammm, cf. § Plateformes plus bas) - la seule partie sensible à la plateforme est la GUI
idn-simulator(winit/eframe) : sur Linux sans wayland on forcefeatures = ["x11"](patch documenté), sur macOS leCargo.tomld'origine du fork convient - le mode headless (tests, benchs, asserts, PNG, JSON) ne touche à aucune GUI — CI-able sur les deux OS
- aucun binaire dans le repo : chaque machine recompile ses artefacts (
target/ignoré)
Les 4 composants d'origine (état de l'art, pourquoi ils sont là)
| Composant | Langage | Rôle | Force | Gap critique pour l'objectif |
|---|---|---|---|---|
| OpenIDN | C++17 | Récepteur IDN réseau → DAC | Transport natif IDN, 4 DACs | Pas d'optimisation (points bruts) |
| laser-dac-rs | Rust | Backbone DAC : abstraction unifiée + hooks | 7 DACs, Frame/Stream API, TransitionFn, OutputFilter, reconnect, watchdog |
Pas d'optimizer (par design) — cible d'intégration |
| lzr optimizer v2 | C++17 | Algo référence : Path discovery + TSP angle-aware + cycles natifs | Architecture modulaire, traversal solve temps/énergie | Interpolation manquante (étape 5), LGPL v3, 1 seul DAC |
| convinterp | Julia/Python/Rust | Moteur math : B-spline ≤13e degré, lazy O(1), dérivées exactes 7e ordre | Seul avec lazy + dérivées + degré élevé | Zéro notion laser/DAC/blanking — moteur à brancher |
Architecture cible (Rust pur, DAC-agnostique)
┌────────────────────────────────────────────────────────────────────────────────────┐
│ laser-optimizer (crate Rust autonome) │
│ ┌──────────────────────────────────────────────────────────────────────────────┐ │
│ │ OPTIMIZATION PIPELINE │ │
│ │ │ │
│ │ INPUT (Frame) │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ 1. PATH DISCOVERY ← Port lzr v2: split lit/blank/angle │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ 2. TRAVERSAL SOLVE ← Port lzr v2: TSP angle-aware + cycles natifs │ │
│ │ │ (Path, PathTraversal, TraversalSolve, cache) │ │
│ │ ▼ │ │
│ │ 3. KEYFRAME EXTRACTION ← Points réordonnés + sens parcours par cycle │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ 4. LAZY INTERPOLATION ← convinterp: Spline1D::builder().lazy(true) │ │
│ │ │ B-spline degré 7 (C⁶), dérivées 1 & 2 exactes │ │
│ │ ▼ │ │
│ │ 5. VELOCITY PLANNING ← κ = |d²p/ds²| → v_max = √(a_max/κ) │ │
│ │ │ Resampling adaptatif PPS-driven │ │
│ │ ▼ │ │
│ │ 6. BLANKING (intra-frame)← lasy: blank_delay_points + angle delay (Eq.1) │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ OUTPUT (OptimizedFrame) ← Points denses, PPS-correct, galvo-safe │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────────────────────────┘
│
▼ (via laser-dac-rs hooks)
┌────────────────────────────────────────────────────────────────────────────────────┐
│ laser-dac-rs (BACKBONE — ne pas modifier) │
│ • TransitionFn → inter-frame blanking courbe (C² via même interpolant lazy) │
│ • OutputFilter → safety clamp, color delay, final PPS resample │
│ • 7 DACs → Helios, EtherDream, IDN, LaserCube, AVB, Oscilloscope, DaisyDAC│
│ • Reconnect, watchdog, metrics │
└────────────────────────────────────────────────────────────────────────────────────┘
Séparation des responsabilités
| Couche | Responsabilité | Implémentation |
|---|---|---|
| laser-optimizer | Algo pur : path discovery, TSP, cycles, interpolation lazy, velocity planning, blanking intra-frame | Nouveau crate — DAC-agnostique, galvo-aware |
| laser-dac-rs | Transport : DAC abstraction, inter-frame transition, output filter, reconnect, watchdog | Existant — ne pas modifier |
| lasy | Papier Abderyim : blanking delay, angle delay linéaire, Eulerian graph min blanks | Dépendance (déjà Rust) |
| convinterp | Math : B-spline lazy, dérivées exactes, resampling | Dépendance (wrapper Rust) |
Problème physique → Contraintes d'implémentation
4 modes de failure (points bruts → galvos)
- Segments longs → coins coupés (galvos trop lents)
- Sauts blank longs → flicker, perte luminosité
- Angles brusques → overshoot/ringing
- Vitesse excessive → distorsion, chauffe, usure
Contrainte fondamentale : Velocity planning curvature-aware
v_max_curvature = √(a_max / κ) (κ = courbure = |d²p/ds²|)
v_target = min(v_max, v_max_curvature)
→ Il faut insérer des points où κ est forte (coins serrés). → Résolution : interpolation lazy (convinterp) + dérivée 2 → κ → resampling adaptatif.
Paramètres galvo (configurables par profil matériel)
| Paramètre | Symbole | Unité | Typique | Source |
|---|---|---|---|---|
| Points/sec DAC | PPS |
pts/s | 30 000 | DAC spec |
| Accélération max | a_max |
rad/s² | ~10⁶ | Galvo spec |
| Vitesse max | v_max |
rad/s | ~10⁴ | Galvo spec |
| Délai blanking | blank_delay_points |
pts | 10–50 | Papier Abderyim + calibration |
| Délai angulaire | radians_per_point |
rad/pt | ~0.001 | Papier Abderyim Eq.1 + calibration |
Roadmap d'implémentation (phases)
Phase 0 — Préparation ✅ (2026-10-14)
- Repo git + submodules + doc complète
- Lire
lzr/lzr/optimizer2/optimizer2.cpp+optimizer2.hpp(algo référence) - Lire
lasy/src/lib.rs(implémentation papier Abderyim) - Tester
laser-dac-rsexamples + intégration IDN (idn-simulator GUI, webui) - Expérimenter
convinterp(Python) — remplacé par velocity planning maison (Menger κ, v_target=min(v_max, √(a_max/κ))) danslaser-opt/crates/laser-opt/src/velocity.rs
Phase 1 — Port lzr v2 → Rust ✅ (2026-10-14, dans laser-opt/crates/laser-opt/src/lzr2*.rs)
- Structures :
Point,Path(avecis_cycle),PathTraversal(entry + direction) - Traversal Solve : glouton, coût v1 exacte (0.9/0.1), multi-entry cycles, bug off-by-one C++ corrigé
- Eulerian graph + min blanks via
lasy(submodule patché : bug faisceau allumé en transit corrigé) - Output :
Vec<Path>réordonnés + parcours optimal par cycle - Path discovery par angle threshold (135°) : split par blank toggle uniquement (suffisant sur les formes test)
- Tests : 95 tests verts + 6 asserts physiques (budget exact, pureté, timing couleur, blank delay, densité coin, coins nets)
Phase 2 — Velocity planning curvature-aware ✅ (2026-10-15, laser-opt/.../velocity.rs, sans convinterp)
- Courbure κ par cercle circonscrit de Menger (3 points consécutifs)
v_target = min(v_max, √(a_max/κ))par point (a_max=100, v_max=12 recalibrés)- Resampling adaptatif pondéré len/v_worst — densité coin 125/u vs côté 63/u (ratio 2×)
- Spline lazy degree 7 (convinterp) : conditionné à un spike de port — le cas laser est couvert par le resampling pondéré
- Tests : asserts densité coin + coins nets sur 5 formes (dont asteroids multi-polylignes)
Phase 3 — Blanking intra-frame + papier Abderyim ✅ (via lasy, 2026-10-14→16)
blank_delay_points: 10 pts, run blank min 13 mesuré (≥ 10 OK)radians_per_point: délai angulaire aux coins (κ des bouts de polyligne = κ du premier virage)lasy::blank_segment_points+corner_point_countintégrés (troncature(rad/rpp) as u32confirmée)- Eulerian graph pour min blanks inter-paths (lasy, patché : nœuds blank ancrés au graphe)
- Tests : asserts 4 (blank delay) + 5 (densité coin) + 6 (coins nets) verts sur 5 formes × 4 pipelines
Phase 4 — API unifiée + intégration laser-dac-rs ✅ (2026-10-15→16)
mix::run_mix(shape, Mix, target, params)— 4 pipelines ordre×interp (--mix lasy+native|lasy+velocity|v2+apply_plan|v2+velocity)- Sorties DAC :
--out-dac none|etherdream|idn(scan broadcast 7654, TCP/UDP, webui :0.0.0.0:8900) - Presentation :
present_framequintic + dwells (end 100 µs / start 400 µs), budget réel mesuré - Inter-frame blanking courbe C² (le quintic dac couvre le cas)
- Tests : end-to-end IDN OK (idn-simulator) ; EtherDream attend le DAC réel (P2)
Phase 5 — Polish & production (en cours)
- Benchs : matrice 5 formes × 4 mix × 3 charges (bench_mix_matrix.json) + PNG (11 rendus)
- Simulateur galvo + métriques de qualité (port lj_rust, TDD) + fix leak (transit quintic) + bench croisé vs lj_rust (2026-10-17→18)
- Documentation :
laser-opt/DEVBOOK.md(journal complet),laser-opt/SORTIES-TDD.md - Profils galvo prédéfinis (CT6210, CT6215, DT40, etc.)
- P2 : laser réel EtherDream + GalvoSafety en OutputFilter (--safety non désactivable en prod)
- Publier sur crates.io
Quick start (état réel, testé)
# 0. Récupérer le repo + submodules
git clone --recurse-submodules https://git.interhacker.space/protonphoton/optilaz
cd optilaz
# 1. Lancer la suite complète (95 tests + 6 asserts × formes)
cd laser-opt
cargo test # 119 tests verts, 0 warning
# 2. Le banc : une forme, un pipeline, asserts + PNG
cargo run -p laser-opt-test -- --shape asteroids --mix v2+velocity --png
# 3. Les benchs qualité (simulateur galvo + métriques)
cargo run -p laser-opt --release --example sim_quality_bench # 4 mix × 5 formes × 3 charges
cargo run -p laser-opt --release --example bench_lj_vs_mix # bench croisé vs lj_rust
# formes : colored_square | open_square | square_with_dot | varied_angles | asteroids
# mixes : lasy+native | lasy+velocity | v2+apply_plan | v2+velocity (défaut lasy+native)
# 3. La matrice complète (5 formes × 4 mix × 3 charges + presentation)
cargo run -p laser-opt --example mix_full_bench # → bench_mix_matrix.json
# 4. Envoyer une trame à un DAC
# IDN : lance le simulateur d'abord
cd ../laser-dac-rs && cargo build -p idn-simulator
DISPLAY=:0 ./target/debug/idn-simulator --port 7255 &
cd ../laser-opt
cargo run -p laser-opt-test -- --out-dac idn --shape colored_square --target 500
# EtherDream : scan broadcast 7654 automatique
cargo run -p laser-opt-test -- --out-dac etherdream --shape colored_square --target 500
# 5. Webui (panneau DAC, scan, send) : http://0.0.0.0:8900
cargo run -p laser-opt-test -- --web --out-dac idn
# 6. Doc de dev détaillée (journal T0→P2, pièges, résultats)
cat laser-opt/DEVBOOK.md
État des plateformes (Linux tl13 ↔ macOS)
Tout le développement a été fait sur Linux (tl13, X11). Le repo ne contient aucun binaire (sources + docs + JSON + PNG seulement, target/ ignoré) — pas de mélange Linux/macOS possible. Workflow prévu : pull sur macOS (user sammm) puis recompilation complète — voir ci-dessous. Au pull sur macOS :
cargo testdanslaser-opt/doit passer tel quel (Rust pur, aucune dépendance plateforme ; petgraph 0.5, pas de FFI)- la GUI
idn-simulator(submodule laser-dac-rs) : sur macOS le patch winit x11 ne s'applique pas — garder leCargo.tomld'origine du fork (winit default features, wayland/x11 inutiles sur mac) --out-dac idn/ webui : testables sans matériel (simulateur) ; EtherDream attend un DAC réel- les PNG/JSON du repo sont des résultats de référence (générés sur Linux) — les régénérer sur mac écrira par-dessus, c'est voulu
Recompilation sur macOS après pull (ordre recommandé)
# 1. Submodules d'abord (les 5, dont lasy)
git clone --recurse-submodules https://git.interhacker.space/protonphoton/optilaz
# (ou si déjà cloné : git submodule update --init --recursive)
# 2. Le cœur : laser-opt (lib + binaire + tests + benchs) — aucune dépendance plateforme
cd laser-opt && cargo test # 95 tests attendus verts
cargo run -p laser-opt-test -- --shape asteroids --mix v2+velocity --png
# 3. Les benchs qualité (simulateur galvo + métriques)
cargo run -p laser-opt --release --example sim_quality_bench # 4 mix × 5 formes × 3 charges
cargo run -p laser-opt --release --example bench_lj_vs_mix # bench croisé vs lj_rust
# 3. Le simulateur IDN (submodule laser-dac-rs) — sur macOS NE PAS appliquer
# le patch winit x11 (cf. ci-dessous), compiler le Cargo.toml d'origine
cd ../laser-dac-rs && cargo build -p idn-simulator
# 4. OpenIDN-Laser-DAC-Framework (C++) : optionnel, cmake déjà testé sur Linux
# 5. lzr / ConvolutionInterpolations.jl : références, pas nécessaires pour tourner
À ne PAS recopier depuis Linux : target/ (ignoré de toute façon), les Cargo.lock des submodules modifiés localement (laser-dac-rs), et le patch winit x11 (spécifique X11).
Patch connu sur le submodule laser-dac-rs (non poussé au fork)
tools/idn-simulator/Cargo.toml : ajouter winit = { version = "0.30", default-features = false, features = ["x11"] } pour compiler la GUI sans wayland (testé sur tl13/X11).
Patch connu sur le submodule lasy (non poussé au fork nannou)
src/lib.rs : 2 bugs corrigés dans laser-opt (2026-10-16, voir DEVBOOK § asteroids) :
points_to_segments: segment blank→lit classé Lit → faisceau ALLUMÉ en transit (ligne parasite entre polylignes disjointes). Fix : une extrémité blank ⇒ segment Blank.segments_to_point_graph: nœuds blank exclus du graphe → points isolés jamais tracés. Fix : nœuds blank ajoutés (sans arête) comme ancrage du pairing eulérien.