docs(sparse-sfm): freeze Gate F parameter fingerprint
This commit is contained in:
parent
fa58c8a225
commit
a67d903a8c
1 changed files with 183 additions and 5 deletions
|
|
@ -597,7 +597,182 @@ The candidate reconstruction identity is:
|
|||
Runtime task IDs, worker count, Governor state, pause timing and resource
|
||||
observations are excluded. Any output-changing threshold, camera model,
|
||||
initialization policy, triangulation policy, PnP policy, BA policy, precision or
|
||||
loss parameter belongs in the future fingerprint.
|
||||
loss parameter belongs in the parameter fingerprint materialized by the Gate F
|
||||
persistent-identity seam. Gate D and Gate E neither receive, compute, serialize
|
||||
nor transport it. Project DB stores it but does not own its meaning; Task Runtime
|
||||
and the Resource System are also excluded. This seam is a Gate F orchestration
|
||||
responsibility, not a new subsystem or scientific solver gate.
|
||||
|
||||
### Sparse SfM parameter fingerprint v1
|
||||
|
||||
The parameter fingerprint is `SHA-256(record_v1)`, with one hash operation over
|
||||
the exact fixed record below. Its output is the complete 32-byte digest. The
|
||||
record begins with the eight ASCII bytes `L3DSFMFP` (`4c 33 44 53 46 4d 46 50`),
|
||||
without a NUL byte, followed by `fingerprint_encoding_version=1`. Every
|
||||
multi-byte scalar is little-endian. `f64` means the exact finite IEEE-754
|
||||
binary64 bit pattern, with both signed zeros encoded as positive zero; NaN and
|
||||
infinity are invalid. Categorical values are the explicit `u32` policy IDs
|
||||
defined here, never native enum ordinals. No native struct, padding, pointer,
|
||||
`size_t`, host-endian value, JSON or locale-dependent text is hashed. A boolean,
|
||||
if a future encoding uses one, is `u8`, with false `0` and true `1`; v1 has no
|
||||
boolean field and no padding or reserved bytes.
|
||||
|
||||
| Offset | Width | Field | Canonical type | Source/value |
|
||||
|---:|---:|---|---|---|
|
||||
| 0 | 8 | `domain` | ASCII bytes | `L3DSFMFP` |
|
||||
| 8 | 4 | `fingerprint_encoding_version` | `u32` | `1` |
|
||||
| 12 | 4 | `minimum_seed_tracks` | `u32` | effective Gate D parameter |
|
||||
| 16 | 4 | `minimum_seed_landmarks` | `u32` | effective Gate D parameter |
|
||||
| 20 | 4 | `minimum_pnp_correspondences` | `u32` | effective Gate D parameter |
|
||||
| 24 | 4 | `maximum_seed_candidates` | `u32` | effective Gate D parameter |
|
||||
| 28 | 4 | `maximum_registration_rounds` | `u32` | effective Gate D parameter |
|
||||
| 32 | 4 | `maximum_landmarks_per_round` | `u32` | effective Gate D parameter |
|
||||
| 36 | 4 | `maximum_images` | `u32` | effective Gate D parameter |
|
||||
| 40 | 8 | `maximum_observations` | `u64` | effective Gate D parameter |
|
||||
| 48 | 8 | `maximum_tracks` | `u64` | effective Gate D parameter |
|
||||
| 56 | 8 | `reprojection_threshold_px` | `f64` | effective Gate D parameter |
|
||||
| 64 | 8 | `minimum_track_parallax_rad` | `f64` | effective Gate D parameter |
|
||||
| 72 | 8 | `relative_pose.robust_threshold_px` | `f64` | effective Gate D parameter |
|
||||
| 80 | 8 | `relative_pose.confidence` | `f64` | effective Gate D parameter |
|
||||
| 88 | 4 | `relative_pose.max_iterations` | `u32` | effective Gate D parameter |
|
||||
| 92 | 4 | `relative_pose.minimum_inliers` | `u32` | effective Gate D parameter |
|
||||
| 96 | 8 | `relative_pose.minimum_inlier_ratio` | `f64` | effective Gate D parameter |
|
||||
| 104 | 8 | `relative_pose.minimum_parallax_rad` | `f64` | effective Gate D parameter |
|
||||
| 112 | 8 | `relative_pose.minimum_cheirality_ratio` | `f64` | effective Gate D parameter |
|
||||
| 120 | 8 | `relative_pose.deterministic_seed` | `u64` | effective Gate D parameter |
|
||||
| 128 | 8 | `pnp.reprojection_threshold_px` | `f64` | effective Gate D parameter |
|
||||
| 136 | 8 | `pnp.confidence` | `f64` | effective Gate D parameter |
|
||||
| 144 | 4 | `pnp.max_iterations` | `u32` | effective Gate D parameter |
|
||||
| 148 | 4 | `pnp.minimum_inliers` | `u32` | effective Gate D parameter |
|
||||
| 152 | 8 | `pnp.minimum_inlier_ratio` | `f64` | effective Gate D parameter |
|
||||
| 160 | 8 | `pnp.deterministic_seed` | `u64` | effective Gate D parameter |
|
||||
| 168 | 4 | `refinement.max_iterations` | `u32` | effective Gate D parameter |
|
||||
| 172 | 8 | `refinement.convergence_tolerance` | `f64` | effective Gate D parameter |
|
||||
| 180 | 4 | `camera_model_policy` | `u32` | `PINHOLE_K1_K2_P1_P2_V1=1` |
|
||||
| 184 | 4 | `calibration_policy` | `u32` | `KNOWN_FIXED_CALIBRATION_V1=1` |
|
||||
| 188 | 4 | `source_pixel_policy` | `u32` | `SOURCE_PIXEL_TOP_LEFT_X_RIGHT_Y_DOWN_V1=1` |
|
||||
| 192 | 4 | `pose_policy` | `u32` | `WORLD_TO_CAMERA_R_CW_CW_V1=1` |
|
||||
| 196 | 4 | `seed_ranking_policy` | `u32` | `SHARED_PARALLAX_IMAGE_ID_V1=1` |
|
||||
| 200 | 4 | `robust_seed_policy` | `u32` | `LOCAL_DETERMINISTIC_SEED_V1=1` |
|
||||
| 204 | 4 | `next_image_policy` | `u32` | `VISIBLE_SUPPORT_THEN_IMAGE_ID_V1=1` |
|
||||
| 208 | 4 | `track_order_policy` | `u32` | `CANONICAL_TRACK_OBSERVATION_V1=1` |
|
||||
| 212 | 4 | `component_policy` | `u32` | `DISCONNECTED_INDEPENDENT_COMPONENTS_V1=1` |
|
||||
| 216 | 4 | `triangulation_policy` | `u32` | `NORMALIZED_DLT_POINT_REFINE_V1=1` |
|
||||
| 220 | 4 | `landmark_rejection_policy` | `u32` | `WHOLE_LANDMARK_ACCEPT_OR_REJECT_V1=1` |
|
||||
| 224 | 4 | `cheirality_policy` | `u32` | `POSITIVE_DEPTH_THRESHOLD_V1=1` |
|
||||
| 228 | 4 | `gate_d_numeric_policy` | `u32` | `BINARY64_DETERMINISTIC_V1=1` |
|
||||
| 232 | 4 | `ba_mode` | `u32` | `FINAL_PER_COMPONENT_POSTPROCESS_V1=1` |
|
||||
| 236 | 4 | `local_ba_policy` | `u32` | `LOCAL_BA_DISABLED_V1=1` |
|
||||
| 240 | 4 | `ba_optimized_variables` | `u32` | `ROTATION_CENTER_LANDMARK_XYZ_V1=1` |
|
||||
| 244 | 4 | `ba_fixed_inputs` | `u32` | `INTRINSICS_DISTORTION_OBSERVATIONS_IDENTITIES_V1=1` |
|
||||
| 248 | 4 | `ba_pose_representation` | `u32` | `UNIT_QUATERNION_R_CW_PLUS_CW_V1=1` |
|
||||
| 252 | 4 | `ba_gauge_policy` | `u32` | `MIN_IMAGE_FARTHEST_CENTER_ONE_AXIS_V1=1` |
|
||||
| 256 | 8 | `ba_degenerate_scale_threshold` | `f64` | `1e-9` |
|
||||
| 264 | 4 | `ba_residual_policy` | `u32` | `ONE_FULL_2D_BLOCK_PER_OBSERVATION_V1=1` |
|
||||
| 268 | 4 | `ba_projection_policy` | `u32` | `SOURCE_PIXEL_PINHOLE_K1_K2_P1_P2_V1=1` |
|
||||
| 272 | 8 | `ba_minimum_camera_depth` | `f64` | `1e-9` |
|
||||
| 280 | 4 | `ba_robust_loss` | `u32` | `HUBER_FULL_2D_NORM_V1=1` |
|
||||
| 284 | 8 | `ba_huber_delta_px` | `f64` | `2.0` |
|
||||
| 292 | 4 | `ba_robust_cost_policy` | `u32` | `HALF_SUM_RHO_SQUARED_NORM_V1=1` |
|
||||
| 296 | 4 | `ba_solver_contract` | `u32` | `CERES_2_2_CONTRACT_V1=1` |
|
||||
| 300 | 4 | `ba_minimizer` | `u32` | `TRUST_REGION_V1=1` |
|
||||
| 304 | 4 | `ba_trust_region_strategy` | `u32` | `LEVENBERG_MARQUARDT_V1=1` |
|
||||
| 308 | 4 | `ba_linear_solver` | `u32` | `ITERATIVE_SCHUR_V1=1` |
|
||||
| 312 | 4 | `ba_preconditioner` | `u32` | `SCHUR_JACOBI_V1=1` |
|
||||
| 316 | 4 | `ba_num_threads` | `u32` | `1` |
|
||||
| 320 | 4 | `ba_max_num_iterations` | `u32` | `50` |
|
||||
| 324 | 8 | `ba_function_tolerance` | `f64` | `1e-6` |
|
||||
| 332 | 8 | `ba_gradient_tolerance` | `f64` | `1e-10` |
|
||||
| 340 | 8 | `ba_parameter_tolerance` | `f64` | `1e-8` |
|
||||
| 348 | 4 | `ba_retry_count` | `u32` | `0` |
|
||||
| 352 | 4 | `ba_convergence_acceptance` | `u32` | `CONVERGENCE_ONLY_V1=1` |
|
||||
| 356 | 8 | `ba_cost_non_regression_factor` | `f64` | `1e-12` |
|
||||
| 364 | 4 | `ba_underconstraint_policy` | `u32` | `MANIFEST_UC1_UC2_UC3_UC4_V1=1` |
|
||||
| 368 | 4 | `ba_numeric_policy` | `u32` | `BINARY64_SINGLE_THREAD_V1=1` |
|
||||
|
||||
The exact v1 record length is 372 bytes. Gate D field semantics and source
|
||||
translations are exhaustive:
|
||||
|
||||
| Field | Source type | Encoding/normalization | Scientific meaning |
|
||||
|---|---|---|---|
|
||||
| `minimum_seed_tracks` | `uint32_t` | `u32` | minimum shared Tracks for a seed |
|
||||
| `minimum_seed_landmarks` | `uint32_t` | `u32` | minimum accepted seed landmarks |
|
||||
| `minimum_pnp_correspondences` | `uint32_t` | `u32` | minimum correspondences for registration |
|
||||
| `maximum_seed_candidates` | `uint32_t` | `u32` | bound on seed attempts |
|
||||
| `maximum_registration_rounds` | `uint32_t` | `u32` | bound on growth rounds |
|
||||
| `maximum_landmarks_per_round` | `uint32_t` | `u32` | bound on new landmarks per round |
|
||||
| `maximum_images` | `uint32_t` | `u32` | accepted input image bound |
|
||||
| `maximum_observations` | `uint64_t` | `u64` | accepted observation bound |
|
||||
| `maximum_tracks` | `uint64_t` | `u64` | accepted Track bound |
|
||||
| `reprojection_threshold_px` | `double` | finite canonical `f64` | landmark reprojection acceptance |
|
||||
| `minimum_track_parallax_rad` | `double` | finite canonical `f64` | landmark parallax acceptance |
|
||||
| `relative_pose.robust_threshold_px` | `double` | finite canonical `f64` | essential robust residual threshold |
|
||||
| `relative_pose.confidence` | `double` | finite canonical `f64` | essential robust confidence |
|
||||
| `relative_pose.max_iterations` | `uint32_t` | `u32` | essential robust iteration bound |
|
||||
| `relative_pose.minimum_inliers` | `uint32_t` | `u32` | essential minimum inlier count |
|
||||
| `relative_pose.minimum_inlier_ratio` | `double` | finite canonical `f64` | essential minimum inlier fraction |
|
||||
| `relative_pose.minimum_parallax_rad` | `double` | finite canonical `f64` | relative-pose minimum parallax |
|
||||
| `relative_pose.minimum_cheirality_ratio` | `double` | finite canonical `f64` | relative-pose positive-depth fraction |
|
||||
| `relative_pose.deterministic_seed` | `uint64_t` | `u64` | local essential robust-estimator seed |
|
||||
| `pnp.reprojection_threshold_px` | `double` | finite canonical `f64` | PnP robust residual threshold |
|
||||
| `pnp.confidence` | `double` | finite canonical `f64` | PnP robust confidence |
|
||||
| `pnp.max_iterations` | `uint32_t` | `u32` | PnP robust iteration bound |
|
||||
| `pnp.minimum_inliers` | `uint32_t` | `u32` | PnP minimum inlier count |
|
||||
| `pnp.minimum_inlier_ratio` | `double` | finite canonical `f64` | PnP minimum inlier fraction |
|
||||
| `pnp.deterministic_seed` | `uint64_t` | `u64` | local PnP robust-estimator seed |
|
||||
| `refinement.max_iterations` | `uint32_t` | `u32` | point-refinement iteration bound |
|
||||
| `refinement.convergence_tolerance` | `double` | finite canonical `f64` | point-refinement stopping tolerance |
|
||||
|
||||
Every row is fingerprinted. Integer fields require no normalization beyond
|
||||
their fixed-width little-endian translation; every floating field uses the
|
||||
canonical-zero rule above.
|
||||
|
||||
The policy IDs above freeze the full named Gate D and Gate E v1 semantics,
|
||||
including canonical order and tie breaks,
|
||||
whole-landmark rejection, positive-depth cheirality, the pose anchor chosen by
|
||||
smallest image ID, the farthest-center scale anchor with exact image-ID tie,
|
||||
X/Y/Z axis tie order and exactly one fixed center coordinate. The Gate E
|
||||
projection is `R_cw + Cw`; intrinsics and `k1/k2/p1/p2` distortion are fixed.
|
||||
The robust cost policy is exactly `0.5 * sum rho(dx^2+dy^2)` with one Huber loss
|
||||
on each full two-dimensional residual. `CERES_2_2_CONTRACT_V1` denotes the
|
||||
accepted Lardon3D Ceres contract `>=2.2.0,<2.3.0`, not package, build, linker or
|
||||
transitive SuiteSparse metadata.
|
||||
|
||||
For Gate D, `WORLD_TO_CAMERA_R_CW_CW_V1` includes the frozen SO(3) residual
|
||||
limit `1e-6`;
|
||||
`POSITIVE_DEPTH_THRESHOLD_V1` means strict camera depth greater than `1e-9`;
|
||||
and `NORMALIZED_DLT_POINT_REFINE_V1` includes the frozen homogeneous-scale
|
||||
epsilon `1e-12` and collinearity covariance-determinant limit `1e-10`. These
|
||||
constants are not runtime members, so their stable policy IDs, rather than
|
||||
duplicate floating fields or implementation enum ordinals, own their exact
|
||||
v1 semantics.
|
||||
|
||||
All 27 effective scalar members, including nested members, of
|
||||
`Lardon3DSparseIncrementalParameters` occur exactly once. Serialization uses
|
||||
the validated effective values actually passed to Gate D, so an omitted default
|
||||
and the same explicitly supplied value produce identical bytes. Actual Track
|
||||
Set identity, Track/Feature IDs, calibration-scope identity and individual
|
||||
calibration IDs or numeric values, `sfm_kind`, `sfm_version`, project/task/
|
||||
transaction/reconstruction IDs, timestamps, resource state, result values and
|
||||
metrics are excluded. The separate calibration scope hash binds sorted image
|
||||
IDs to calibration hashes, and each calibration hash binds dimensions,
|
||||
`fx/fy/cx/cy/k1/k2/p1/p2`, model/version and provenance; the parameter record
|
||||
therefore records calibration semantics without duplicating calibration
|
||||
instances.
|
||||
|
||||
Changing only a parameter value retains encoding version 1 and naturally
|
||||
changes the digest. Adding a fingerprint-owned field or changing byte layout
|
||||
requires a new encoding version; changing the Sparse SfM algorithmic contract
|
||||
may separately require a new `sfm_version`. Neither version substitutes for the
|
||||
other. Equal complete candidate tuples therefore identify the same scientific
|
||||
candidate regardless of runtime metadata.
|
||||
|
||||
Gate F implementation must prefer an internal, solver-independent helper unless
|
||||
a separate public C17 API decision is made. It must reuse the project's SHA-256
|
||||
implementation, use bounded constant-size storage without cache, scheduling,
|
||||
Governor interaction or reservation, and add a golden 372-byte default record,
|
||||
its expected SHA-256 digest, and mutations proving every fingerprint-owned
|
||||
category changes the digest. This contract authorizes no public symbol.
|
||||
|
||||
Exact byte identity is not promised for a future multi-threaded floating-point
|
||||
solver until measured. The v1 target is deterministic ordering and numerical
|
||||
|
|
@ -812,7 +987,8 @@ Gate D consumes exactly one immutable Track Set, one immutable calibration
|
|||
scope, finite calibration values for participating images, bounded keypoint
|
||||
coordinates addressed by `(feature_set_id, feature_index)`, and explicit
|
||||
parameters immutable during execution. Gate D neither computes nor carries the
|
||||
future parameter fingerprint. The Track Set is never mutated.
|
||||
parameter fingerprint materialized later at the Gate F persistent-identity
|
||||
seam. The Track Set is never mutated.
|
||||
|
||||
### Algorithm
|
||||
|
||||
|
|
@ -1025,9 +1201,11 @@ The immutable reconstruction identity is:
|
|||
|
||||
`track_set_id` and `calibration_scope_id` are project-local immutable database
|
||||
references, consistent with the existing Track Model identity convention. The
|
||||
parameter fingerprint is required to be a 32-byte SHA-256 value but its final
|
||||
byte encoding remains a later geometry-gate decision. Runtime IDs, timestamps,
|
||||
worker count, resource state and metrics are excluded.
|
||||
parameter fingerprint is the raw 32-byte SHA-256 digest of the 372-byte Sparse
|
||||
SfM parameter record v1 defined above. Gate F materializes it at its
|
||||
persistent-identity seam; Project DB stores it without owning or recomputing
|
||||
it. Runtime IDs, timestamps, worker count, resource state and metrics are
|
||||
excluded.
|
||||
|
||||
Component identity is the minimum registered `image_id` in that component. It
|
||||
is deterministic, project-local, unique because an image belongs to at most one
|
||||
|
|
|
|||
Loading…
Reference in a new issue