sensor: finger-xynova revision: r01 status: draft # Authoring unit in Blender (mm). Export converts using meters_per_source_unit. authoring_unit: mm meters_per_source_unit: 0.001 source_blend: source/geometry.blend frames: sensor: origin_sensor objects: sensing_surface: sensing_surface cam_sensor: cam_sensor origin_sensor: origin_sensor # Read on every export; changing `assembly` silently changes what ships. collections: frames: FRAMES export_compute: EXPORT_COMPUTE assembly: ASSEMBLY design_sim: DESIGN_SIM exclude: EXCLUDE # Topology guard. NOT YET WIRED - no code reads these, and the measured topology is # 2584/5007. Unverified until connected to the export manifest; see # docs/design-parameters.md part 5. expected: sensing_vertices: 2595 sensing_triangles: 5005 # Camera-space artwork on UV unwraps (`orisys-design texture`). # See docs/design-parameters.md part 1. texture_patch: mesh: sensing_surface camera: cam_sensor uv_outputs: # ORDER IS OBSERVABLE: becomes the job's outputs[] array produce: patch_texture_produce.png compute: patch_texture_compute.png width: 3700 # raster px; keep == px_per_mm * vector below height: 3280 nx: 80 # square camera frame, so nx == ny ny: 80 color_r: 0.05 edge_sample_grid: 5 seed: 7 # pinned: one reproducible colour set across PNG/SVG/PDF vector: # physical page; the `page: fixed` fallback for texture_patch_views width_mm: 18.5 height_mm: 16.4 cross: enabled: true length_px: 40 thickness_px: 3 color: [1.0, 0.0, 0.0, 1.0] # Projected views with per-triangle ownership (`orisys-design texture-views`). # See docs/design-parameters.md part 2. texture_patch_views: enabled: true pattern_camera: cam_sensor # the ink source; a pair's `camera` only decides ownership page: mode: auto # auto = derived per view (projections only); fixed = use vector above px_per_mm: 200 pairs: - id: uv_1 camera: cam_uv_1 # REGION camera, not the pattern source uv_map: uv_1 - id: uv_2 camera: cam_uv_2 uv_map: uv_2 merge: mode: authored # honour the seam marked on the mesh incidence_limit_deg: 70.0 # DO NOT DELETE: built-in default 62.0 FAILS here (4.8% hole) max_hole_fraction: 0.02 # enforced: the run fails above this rather than shipping a gap min_footprint_mm2: 2.0e-3 min_triangle_coverage: 0.60 component_policy: best_coverage seam: boundary: use_seam pins: [] gap: enabled: false # false = hard butt at the seam, no band at all apply: post_process # post_process = straight edge | geometry_trim = sawtooth treatment: no_print alignment_tolerance_mm: 0.1 print: base_fill: owned # white ground, already split by the seam # Random Stroke Pattern (`orisys-design stroke-texture`). # One mode: a capsule of `width` swept `length`, rotated per cell, sized from the camera # cell's print-page footprint so a cell the projection stretches gets a proportionally # larger mark. `--seed` / `--min-cell-pixels` / `--camera-width-fraction` override per run. # Field reference: the inline comments below. These defaults are an image-space experiment, # not a print master: `width_min_mm: 0.11` is below the demonstrated 0.2 mm dot (see # docs/probe-findings.md). The resolved values are written to _stroke_pattern_params.json and # recorded in the stroke-texture manifest, which is what makes a run reproducible. stroke_pattern: seed: 7 # per-cell offset and angle; reproducible min_cell_pixels: 20 # cells smaller than this are skipped jitter_fraction: 0.66 # mark offset range inside its cell; 0 pins to the centre angle_span_deg: 180.0 # rotation range; 0 makes every stroke parallel width_fraction: 0.50 # width = clamp(cell footprint x this, width_min_mm, width_max_mm) width_min_mm: 0.11 width_max_mm: 0.28 length_ratio: 2.4 # length = ratio x width coverage_cap: 0.45 # skip a mark that would exceed this local fill neighbourhood_mm: 0.5 # radius of the local-fill neighbourhood # Advisory only: reports a verdict, never blocks generation or changes exit codes. # Millimetres are measured on the vector page declared above. printability: printer_dpi: 600 # target UV printer resolution min_dots: 2 # printer dots required across the smallest feature min_feature_mm: 0.10 # smallest acceptable feature width min_edge_mm: 0.05 # shortest acceptable polygon edge max_sliver_ratio: 4.0 # longest edge / minimum width min_patch_area_mm2: 1.0e-4 # area above which a polygon is a material feature # Optical stack above the markers, ordered camera-inward. ior values are LITERATURE # ASSUMPTIONS, not measurements - that is what ior_source records. optics: marker_surface: sensing_surface layers: # Solids, not surface pairs: `shell` and `rubber-1` are each one closed mesh, so the # ray enters and leaves the same object. rubber-2 is BEHIND the markers, so it does # not refract camera light and is deliberately not a layer. - name: plastic_shell solid: shell ior: 1.59 ior_source: assumed_pc_literature - name: clear_rubber solid: rubber-1 ior: 1.43 ior_source: assumed_silicone_literature # Probe sensitivity bench (`orisys-design deform|render|track|sensitivity|optimise`). # Contract: docs/probe-pipeline.md. The .blend is never written by the pipeline. probe: mesh: sensing_surface camera: cam_sensor group: probe uv_map: compute texture: patch_texture_compute.png # Median mesh edge here is 0.63 mm, so 0.5 mm reaches only immediate neighbours; the # deform report prints how many vertices actually move rather than hiding it. radius_mm: 0.5 falloff: smooth step_mm: 0.01 max_mm: 0.10 axes: [x, y, z] # The pipeline overrides the scene resolution from here, so a blend edited to a # different size is silently ignored. Keep in step with source/geometry.blend. resolution: [250, 250] process_resolution: [250, 250] # Mirrors the SDK tracker keys EXCEPT dis_mode: the 8*2**dis_mode window against a # ~6.6 px moving region makes the shipped dis_mode=1 collapse the estimate ~3x. # See docs/probe-findings.md section 2. tracker: algorithm: dis dis_preset: medium dis_mode: 0 # Standard (not AgX) and denoise off: a filmic view transform silently distorts the # marker values the tracker is supposed to measure. render: engine: CYCLES samples: 16 denoise: false view_transform: Standard interpolate: Closest seed: 0 # `floor_px` from a re-render at seed+1 is Cycles antialiasing jitter, NOT sensor # noise, so it is kept only as a reproducibility diagnostic; the score is anchored to # the injected model plus the idle-footage calibration below. # See docs/probe-findings.md section 2. noise: idle_footage: ../data/dd02-0703/190.mp4 roi_fraction: 0.18 max_frames: 120 sigmas: [4.0, 16.0] draws: 1 seed: 0 models: [render_seed, injected] scales: [render] notes: | Canonical source is geometry.blend with named collections and objects. Compute export uses sensing_surface + cam_sensor relative to origin_sensor. Studio observation cameras are derived from mesh bounds; no cam_viz required.