# Calibration Evidence Solver v1 Outil C++ externe de génération d'évidence pour `CALIBRATION_SCIENCE_V1`. Il n'est pas une cible Meson, ne lie pas Lardon3D, ne lit ni n'écrit le Project DB et ne produit pas `L3DCALB1`. ## Build local isolé ```sh make ./calibration_evidence_solver --self-test ``` Le binaire attend OpenCV 5.x et OpenSSL. Le seul mode de production prévu est CPU1; il force `cv::setNumThreads(1)` et une graine OpenCV fixe. ## Session v1 bornée et évidence pré-solve Un fichier texte ASCII, sans commentaire ni espace dans les chemins, contient : ```text L3DCAL_SESSION_V1 target DICT_5X5_100 9 7 30 21 measurement <10-real-square-mm-values> white_border planarity PASS decoder optical_state image <64-hex-source> pre_solve <64-hex-source> clipping <64-hex-source> coordinate <64-hex-source> =20..48 coordinate_point <64-hex-source> distance <64-hex-source> ``` Il y a entre 1 et 4096 lignes `image`, chaque source SHA est unique, et chaque image a exactement une preuve pré-solve, clipping et coordinate. Les dix mesures réelles doivent être à 0.30 mm de 30.000 mm et leur étendue ne doit pas dépasser 0.20 mm; l'instrument doit annoncer une résolution de 0.1 mm ou meilleure. `white_border` archive la bordure blanche physique libre mesurée et doit être d'au moins 30 mm; aucune valeur par défaut n'est inventée. `planarity` est une attestation PASS hachée : Science v1 impose une planche rigide plane mais ne fixe pas de seuil numérique que l'outil pourrait inventer. `optical_state` est un jeton atomique complet du manifeste d'état optique; aucune valeur inconnue n'est acceptée par convention. Les `coordinate_point` consomment exactement les `N` comparaisons annoncées. Chaque point porte aussi, entre le SHA et les coordonnées, l'un des labels `center`, `top`, `right`, `bottom`, `left`, `top_left`, `top_right`, `bottom_left` ou `bottom_right`; les neuf catégories sont obligatoires. Chaque vue porte une `distance` physique mesurée et l'une des trois bandes déclarées; les poses estimées ne constituent jamais une preuve de distance d'acquisition. Le solveur rejette une orientation différente de l'image, une dimension orientée différente, moins de 20 points, ou une composante `dx`/`dy` supérieure à 0.01 px. La déclaration lie donc SHA, décodeur/version, transformée d'orientation, dimensions et mesures de coordonnées plutôt que d'émettre le bit `0x08` par défaut. Sur réussite, le solveur crée de manière atomique `.bundle/`, qui est immuable si déjà présent : `detection.json`, `solve.json`, `evidence.json` et `producer.json`. Ce dernier lie le SHA-256 du binaire solveur en cours, le SHA-256 de sa configuration canonique, le SHA-256 exact du manifeste de session, la version/build OpenCV, la politique CPU1 et le SHA de l’état optique. Les documents ont un ordre déterministe et encodent les valeurs faisant autorité comme chaînes `hexfloat` binary64. `solve.json` archive les trois sorties complètes (paramètres et poses); `evidence.json` archive les vecteurs de résidu, RMSE par vue/global, maximum, fraction élevée, split fit/hold-out, delta cinq directions et les quatre prédicats de `validation_flags`. ## Frontière numérique qualifiée Le seul transport `float` est celui imposé par l'API OpenCV 5.0.x : `CharucoDetector` fournit les pixels en `Point2f` et `calibrateCamera` reçoit les points objet `Point3f`. Chaque valeur de validation est la promotion exacte en `double` de ce transport ; les paramètres, poses, projections et résidus publiés dans le rapport restent `binary64`. Le rapport archive le chemin de conversion et ses bornes maximale image (pixels) et objet (mètres). ## Exécution ```sh ./calibration_evidence_solver --self-test ./calibration_evidence_solver --session session.l3dcal make asan ``` `--self-test` est exclusivement synthétique : il crée 60 vues d'une caméra connue, quantifie une seule fois les observations `binary64` vers le transport OpenCV `binary32`, puis vérifie récupération, résidus indépendants, split fit/hold-out et répétabilité CPU1. Il ne représente jamais une calibration physique.