{
  "schema_version": "machine-capabilities.v1",
  "machine_id": "fullum-alpha",
  "machine_family": "swing-arm",
  "machine_name": "Fullum swing-arm polisher",
  "controller_version": "polisher-control/0.1.0",
  "supported_motion_families": [
    "swing-arm-rosette"
  ],
  "force_range_n": [
    0,
    80
  ],
  "table_rpm_range": [
    0,
    5.0
  ],
  "spindle_rpm_range": [
    0,
    80
  ],
  "cam_amplitude_range_deg": [
    0,
    45
  ],
  "cam_offset_range_deg": [
    -30,
    30
  ],
  "force_modulation": {
    "supported": true,
    "max_harmonics": 3,
    "max_amplitude_n": 20.0,
    "notes": "Angle-synchronized force modulation from live table encoder angle; validate during commissioning."
  },
  "supported_dither_profiles": [
    "none",
    "default"
  ],
  "segment_duration_limits": {
    "min_s": 10,
    "max_s": 7200
  },
  "pause_resume_support": true,
  "telemetry_channels": [
    {
      "name": "timestamp_us",
      "unit": "see docs/05-telemetry-channel-spec-v1.md",
      "sample_rate_hz": 100
    },
    {
      "name": "table_angle_deg",
      "unit": "see docs/05-telemetry-channel-spec-v1.md",
      "sample_rate_hz": 100
    },
    {
      "name": "arm_angle_deg",
      "unit": "see docs/05-telemetry-channel-spec-v1.md",
      "sample_rate_hz": 100
    },
    {
      "name": "fz_n",
      "unit": "see docs/05-telemetry-channel-spec-v1.md",
      "sample_rate_hz": 100
    },
    {
      "name": "mx",
      "unit": "see docs/05-telemetry-channel-spec-v1.md",
      "sample_rate_hz": 100
    },
    {
      "name": "my",
      "unit": "see docs/05-telemetry-channel-spec-v1.md",
      "sample_rate_hz": 100
    },
    {
      "name": "mz",
      "unit": "see docs/05-telemetry-channel-spec-v1.md",
      "sample_rate_hz": 100
    },
    {
      "name": "spindle_rpm_actual",
      "unit": "see docs/05-telemetry-channel-spec-v1.md",
      "sample_rate_hz": 100
    },
    {
      "name": "table_rpm_actual",
      "unit": "see docs/05-telemetry-channel-spec-v1.md",
      "sample_rate_hz": 100
    },
    {
      "name": "arm_amplitude_deg_derived",
      "unit": "see docs/05-telemetry-channel-spec-v1.md",
      "sample_rate_hz": 100
    },
    {
      "name": "arm_center_deg_derived",
      "unit": "see docs/05-telemetry-channel-spec-v1.md",
      "sample_rate_hz": 100
    },
    {
      "name": "machine_state",
      "unit": "see docs/05-telemetry-channel-spec-v1.md",
      "sample_rate_hz": 100
    },
    {
      "name": "force_setpoint_n",
      "unit": "see docs/05-telemetry-channel-spec-v1.md",
      "sample_rate_hz": 100
    },
    {
      "name": "spindle_direction_setpoint",
      "unit": "enum(cw|ccw)",
      "sample_rate_hz": 10
    },
    {
      "name": "spindle_direction_actual",
      "unit": "enum(cw|ccw)",
      "sample_rate_hz": 10
    }
  ],
  "safety_limits": {
    "max_force_n": 80,
    "max_table_rpm": 5.0,
    "max_spindle_rpm": 80,
    "notes": "Initial source-aligned limits; final hardware commissioning must verify."
  },
  "known_constraints": [
    "Manual mode is the first production target.",
    "No powered Zero-G/admittance mode in v1.",
    "Oscillation amplitude/center are operator-entered configuration in v1, not actuated cam commands.",
    "Controller rejects unknown controller-job fields rather than silently ignoring them."
  ],
  "unknowns": [
    "Exact KWR75B-CAN frame map, scaling, status bits, and update rate.",
    "Final ODrive runtime interface and command scaling.",
    "Final SV2A-2150 torque/current command scaling and Iq monitor mapping.",
    "Final safety relay model and wiring details."
  ],
  "supported_spindle_directions": [
    "cw",
    "ccw"
  ]
}
