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 # Expected sensing surface topology for r01 (from shipped 30fps-0703 runtime). # First exports from geometry.blend may differ until topology is locked. expected: sensing_vertices: 2595 sensing_triangles: 5005 frames: sensor: origin_sensor objects: sensing_surface: sensing_surface cam_sensor: cam_sensor origin_sensor: origin_sensor # Headless colored-patch texture generation (`orisys-design texture`). # UV unwrapping is still done in the Blender GUI: the headless run consumes the # UV maps already stored in source_blend and never creates or unwraps one. # One PNG/SVG/PDF set is written per UV map below. All maps and formats share # the settings and patch colours, so they differ only by UV layout. # These are the revision defaults; CLI flags override every value. texture_patch: mesh: sensing_surface camera: cam_sensor uv_outputs: produce: patch_texture_produce.png # hardware production layout compute: patch_texture_compute.png # compute/runtime layout width: 3700 # 1850*2 height: 3280 # 1640*2 # Camera frame is square (1000x1000), so equal counts make camera-space # elements square. The original 80x45 grid was copied from a 16:9 camera. nx: 80 ny: 80 color_r: 0.05 edge_sample_grid: 5 seed: 7 # fixed so PNG/SVG/PDF share one reproducible colour set vector: width_mm: 18.5 # editable SVG/PDF production page width height_mm: 16.4 # editable SVG/PDF production page height cross: enabled: true length_px: 40 thickness_px: 3 color: [1.0, 0.0, 0.0, 1.0] # red reference cross # Post-generation printability inspection (`orisys-design inspect`). Advisory # only: it reports a verdict but 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 from the camera inward. # The markers sit on the sensing surface underneath these layers, so their image # is displaced relative to the straight-line pinhole model. # # ior values are LITERATURE ASSUMPTIONS, not measurements - that is what # ior_source records, so an assumed index can never pass for a measured one. # Replace them with measured values when available; nothing else needs to change. 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. # Stack: camera > shell > rubber-1 > sensing_surface > rubber-2. # 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`). # Deforms the vertices of `group` through known x/y/z displacements expressed in a # local probe-average basis (normal force along z, shear along x/y), renders what # `camera` sees, and measures DIS optical flow against the zero-displacement frame. # # 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 # Proportional falloff radius for the outer rubber. Note this mesh has a median # edge of 0.63 mm, so 0.5 mm reaches only the probe's 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] # Frames are rendered at the revision's real camera resolution. Keep this in step with # the camera in source/geometry.blend: the pipeline overrides the scene resolution from # here, so a blend edited to a different size is silently ignored otherwise. # # Single scale on purpose. The ROI radius is radius_mm x the probe-local px/mm, so at # 125x125 it would be 1.66 px against an 8 px DIS window: the estimator measures its own # regulariser, not the displacement. See docs/probe-findings.md section 2. resolution: [250, 250] process_resolution: [250, 250] # Mirrors the SDK sensor tracker keys (orisys-sdk config/finger.json), EXCEPT # dis_mode. The estimator window is 8 * 2**dis_mode input px (16 at dis_mode=1, 8 at 0) # and the moving region is ~6.6 px across at 250x250, so the shipped dis_mode=1 gives # window/moving = 2.42: DIS's smoothness pulls the estimate toward zero and the measured # response drops ~3x (1.42 -> 4.30 px/mm at the matched cell). dis_mode=0 gives 1.21, # the same ratio as 500x500 with dis_mode=1, which recovers to ~73%. # See docs/probe-findings.md section 2. # If the deployed tracker is fixed at dis_mode=1, run the bench at 500x500 instead. 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 # Noise calibration and the injected noise model. # # The estimator's `floor_px` is measured as reference vs a re-render at seed+1, which # is Cycles antialiasing jitter, NOT sensor noise: on this data it differs by ~5 grey # levels RMS on half the pixels and scales with edge contrast. Ranking patterns by # gain/that-floor is unsound - the ordering reverses under additive noise, and it # understates the real idle floor measured from the footage below, coarse patterns # most. So the render-seed floor is kept only as a reproducibility diagnostic and the # score is anchored to the injected model plus this measured calibration. noise: # Real idle (no-contact) footage, relative to the repo root. Measured: floor # ~0.23 px at 1280x720 (short baseline == long baseline, so it is white noise and # the clip is genuinely idle), dominant marker period ~25 px, i.e. ~0.0093 floor # per period. That is 2-6x the simulated render-seed floor per cell. idle_footage: ../data/dd02-0703/190.mp4 roi_fraction: 0.18 max_frames: 120 # Additive white Gaussian in grey levels. Defaults are deliberately small: each # sigma costs a full DIS pass, and the process scale is a resample of the render # one, so only the render scale is evaluated unless asked. sigmas: [4.0, 16.0] draws: 1 seed: 0 models: [render_seed, injected] scales: [render] collections: frames: FRAMES export_compute: EXPORT_COMPUTE assembly: ASSEMBLY design_sim: DESIGN_SIM exclude: EXCLUDE 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.