# ============================================================================
# Generic / Bimanual YAM + 3 RealSense (overhead + per-arm wrist)
# ============================================================================
# Two independent YAM arms with three RealSense cameras (overhead environment
# view + per-arm wrist). No neck. Fill in the <PLACEHOLDER> fields below
# before launch:
#   - system.license_key
#   - cameras[*].adapter.config.serial_number      (3 RealSense serials)
#   - systems[arm].adapters[arm].connection.port   (CAN interface per arm)
#
# Topic structure:
#   Global:    /sentinel/xr/*, /sentinel/events, /sentinel/telemetry
#   Cameras:   /sentinel/vision/output/{overhead,left_wrist,right_wrist}/encoded
#   Left arm:  /yam_left/sentinel/*
#   Right arm: /yam_right/sentinel/*

# ============================================================================
# System Configuration
# ============================================================================
system:
  license_key: "<LICENSE_KEY>"
  enable_dataset_recording: true

# ============================================================================
# Global Button Listener Configuration
# ============================================================================
button_listener:
  debounce_duration: 0.5

# ============================================================================
# XR Configuration (GLOBAL - shared across all robots)
# ============================================================================
xr:
  coordinate_system: "webxr"

  video:
    enabled: true
    mode: "pre_encoded"
    cameras:
      - {id: "overhead"}
      - {id: "right_wrist"}
      - {id: "left_wrist"}
    max_latency_ms: 100

# ============================================================================
# Analog Input Mapping (GLOBAL)
# ============================================================================
# Joystick Y axes drive per-arm velocity scaling so the operator can throttle
# motion live during teleop.
analog_inputs:
  left_joystick_y: left_velocity_scaling
  right_joystick_y: right_velocity_scaling
  left_grip:       left_grip_control
  right_grip:      right_grip_control
  left_trigger:    left_gripper_control
  right_trigger:   right_gripper_control

# ============================================================================
# Button Configuration (GLOBAL)
# ============================================================================
buttons:
  left_grip_control:
    source: left_grip_control
    threshold: 0.5
    rising_edge:
      service: "/yam_left/sentinel/system/service/start_teleop"
    falling_edge:
      service: "/yam_left/sentinel/system/service/stop_teleop"

  right_grip_control:
    source: right_grip_control
    threshold: 0.5
    rising_edge:
      service: "/yam_right/sentinel/system/service/start_teleop"
    falling_edge:
      service: "/yam_right/sentinel/system/service/stop_teleop"

  a_button:
    single_press:
      handler: "arm_and_start_all"
      params:
        arm_timeout_sec: 30.0
    long_press:
      handler: "go_home_all"

  b_button:
    single_press:
      handler: "disarm_all"

  x_button:
    single_press:
      service: "/sentinel/dataset/service/toggle_episode"

  y_button:
    single_press:
      service: "/sentinel/dataset/service/fail_episode"

# ============================================================================
# Cameras Configuration (GLOBAL - 3 x RealSense: overhead + 2 wrist)
# ============================================================================
cameras:
  - name: "overhead"
    adapter:
      plugin: "sentinel_vision_adapter_realsense::RealSenseCamera"
      config:
        serial_number: "<OVERHEAD_REALSENSE_SERIAL>"
        width: 640
        height: 480
        fps: 30
        enable_depth: false
        enable_color: true
        align_to_color: false
    encoders:
      - name: "streaming"
        plugin: "sentinel_vision_encoder_gstreamer::GStreamerEncoder"
        topic: "encoded"
        qos: "streaming"
        config:
          encoding: "h264"
          width: 640
          height: 480
          framerate: 30
          bitrate: 4000
          hw_accel: "none"
          preset: "veryfast"
          tune: "zerolatency"
          rate_control: "cbr"
          profile: "main"
          gop_size: 2
          bframes: 0

  - name: "left_wrist"
    adapter:
      plugin: "sentinel_vision_adapter_realsense::RealSenseCamera"
      config:
        serial_number: "<LEFT_WRIST_REALSENSE_SERIAL>"
        width: 640
        height: 480
        fps: 30
        enable_depth: false
        enable_color: true
        align_to_color: false
    encoders:
      - name: "streaming"
        plugin: "sentinel_vision_encoder_gstreamer::GStreamerEncoder"
        topic: "encoded"
        qos: "streaming"
        config:
          encoding: "h264"
          width: 640
          height: 480
          framerate: 30
          bitrate: 4000
          hw_accel: "none"
          preset: "veryfast"
          tune: "zerolatency"
          rate_control: "cbr"
          profile: "main"
          gop_size: 2
          bframes: 0

  - name: "right_wrist"
    adapter:
      plugin: "sentinel_vision_adapter_realsense::RealSenseCamera"
      config:
        serial_number: "<RIGHT_WRIST_REALSENSE_SERIAL>"
        width: 640
        height: 480
        fps: 30
        enable_depth: false
        enable_color: true
        align_to_color: false
    encoders:
      - name: "streaming"
        plugin: "sentinel_vision_encoder_gstreamer::GStreamerEncoder"
        topic: "encoded"
        qos: "streaming"
        config:
          encoding: "h264"
          width: 640
          height: 480
          framerate: 30
          bitrate: 4000
          hw_accel: "none"
          preset: "veryfast"
          tune: "zerolatency"
          rate_control: "cbr"
          profile: "main"
          gop_size: 2
          bframes: 0

# ============================================================================
# Dataset Recording Configuration (GLOBAL)
# ============================================================================
dataset_recording:
  enabled: true
  output_dir: "/datasets"
  storage_format: "mcap"
  max_bag_size_bytes: 1073741824  # 1GB per MCAP file
  min_free_disk_bytes: 5368709120  # 5GB minimum free space
  fps: 30.0

  topics:
    # Peripheral
    - /tf
    - /tf_static
    - /sentinel/events
    - /sentinel/xr/input/xr_input
    - /yam_left/sentinel/system/state/current
    - /yam_right/sentinel/system/state/current

    # State measurements
    - /yam_left/sentinel/robot/state/joint_states/measured
    - /yam_right/sentinel/robot/state/joint_states/measured
    - /yam_left/sentinel/robot/state/gripper_states/measured
    - /yam_right/sentinel/robot/state/gripper_states/measured

    # Commands
    - /yam_left/sentinel/control/commands/joint_safe
    - /yam_right/sentinel/control/commands/joint_safe
    - /yam_left/sentinel/control/commands/gripper
    - /yam_right/sentinel/control/commands/gripper

    # Video (encoded H.264)
    - /sentinel/vision/output/overhead/encoded
    - /sentinel/vision/output/left_wrist/encoded
    - /sentinel/vision/output/right_wrist/encoded

# ============================================================================
# Robots Configuration
# ============================================================================
systems:
  # --------------------------------------------------------------------------
  # Robot 1: Left YAM Arm
  # --------------------------------------------------------------------------
  - name: "YAM Left"
    namespace: "yam_left"
    serial: "YAM_LEFT"

    adapters:
      - id: "arm"
        plugin: "sentinel_adapter_yam::YamAdapter"
        urdf: "package://yam_description/urdf/yam.urdf"

        publish_rate_hz: 120.0
        command_timeout_s: 0.5

        connection:
          port: "<LEFT_ARM_CAN_PORT>"  # e.g. "can0" / "can1"
        zero_gravity: false
        arm_kp: [80, 80, 80, 40, 10, 10]
        arm_kd: [5, 5, 5, 1.5, 1.5, 1.5]

    capabilities:
      - type: manipulator
        id: left_arm
        adapter_id: "arm"
        enabled: true

        posturing:
          enabled: false
          mode: "simple"
          weight: 0.0

        chains:
          - id: arm
            base_link: "base_link"
            ee_link: "link_6"
            joints:
              - joint1
              - joint2
              - joint3
              - joint4
              - joint5
              - joint6
            q_min: [-2.61799, -0.01, -0.01, -1.5708, -1.5708, -2.0944]
            q_max: [3.13, 3.65, 3.13, 1.5708, 1.5708, 2.0944]
            q_nominal: [-0.003242542153047978, 0.015068284122987663, 0.007438773174639479, -0.06466010528725441, 0.003242542153047978, 0.022697795071335847]
            segments:
              upper_arm: 0.25
              forearm: 0.25

        retargeting:
          mode: "simple"
          enable_posture: false
          scale: 1.3
          workspace_limits:
            min: [-0.4, -0.5, 0.1]
            max: [0.6, 0.5, 0.8]
          tracking_frames:
            primary: "controller_left"
          laterality: "left"
          control_button: "trigger"
          coordinate_transform: [0, 0, 1, -1, 0, 0, 0, 1, 0]
          grip_threshold: 0.5
          reanchor_on_grip: true

          motion_pipeline:
            filter:
              notch_hz: 7.3
              notch_q: 8.0
              lowpass_hz: 9.0
            speed_gate:
              v_low: 0.015
              v_high: 0.050

        haptics:
          enabled: true
          min_event_m: 0.033
          max_event_m: 0.07
          time_constant_s: 0.2
          event_rate_hz: 30.0
          direction_axis_sign: [1, 1, -1]

        ik:
          solver_mode: "simple"
          solver: "casadi"
          max_iterations: 50
          tolerance: 0.001
          timeout_ms: 100.0
          enable_posture: false
          weight_translational: 100.0
          weight_rotational: 50.0
          weight_regularization: 0.1
          weight_smooth: 0.1
          weight_manipulability: 0.0

        trajectory:
          control_mode: "open_loop"
          max_velocity:     [6.0, 6.0, 6.0, 8.0, 8.0, 10.0]
          max_acceleration: [8.0, 8.0, 8.0, 10.0, 10.0, 12.0]
          max_jerk:         [20.0, 20.0, 20.0, 25.0, 25.0, 30.0]

        planning:
          interpolation_points: 100
          execution_rate_hz: 60.0
          planning_time_limit: 10.0
          enable_viz: true
          joints_to_lock: []

      - type: gripper
        id: gripper
        adapter_id: "arm"
        enabled: true
        parent_chain: arm

        retargeting:
          mode: "toggle"
          laterality: "left"
          trigger_threshold: 0.5
          close_threshold: 0.7
          open_threshold: 0.3
          toggle_debounce_s: 0.3
          invert: true

        hardware:
          type: "linear_4310"
          speed: 50.0
          force: 40.0
          max_force: 50.0
          kp: 0.5
          kd: 0.3

    safety:
      joint_limit_margin: 0.05
      velocity_limit_scale: 0.9
      emergency_stop_enabled: true
      max_torque: [50.0, 50.0, 50.0, 20.0, 20.0, 20.0]

    state_machine:
      initial_state: "DISARMED"
      joint_names: ["joint1", "joint2", "joint3", "joint4", "joint5", "joint6"]
      home_positions: [-0.003242542153047978, 0.015068284122987663, 0.007438773174639479, -0.06466010528725441, 0.003242542153047978, 0.022697795071335847]
      start_positions: [-0.003242542153047978, 0.5556191348134583, 0.6071183337148085, -0.09899290455481768, 0.0005722133211261138, 0.02193484397650103]
      motion:
        action_server_wait_timeout: 5.0
        goal_acceptance_timeout: 2.0
        motion_duration: 3.0
      calibration_timeout_s: 10.0
      skeleton_validation:
        enabled: true
        min_confidence: 0.5
        require_full_body: false
        min_bone_length_m: 0.05

    orchestration:
      on_arm:
        - node: "robot_adapter_"
          transition: "configure"
          timeout: 10.0
        - node: "trajectory_smoother_"
          transition: "configure"
          timeout: 10.0
        - node: "safety_"
          transition: "configure"
          timeout: 10.0
        - node: "arm_retargeter_"
          transition: "configure"
          timeout: 10.0
        - node: "gripper_retargeter_"
          transition: "configure"
          timeout: 10.0
        - node: "ik_solver_"
          transition: "configure"
          timeout: 10.0
        - node: "ompl_joint_planner_"
          transition: "configure"
          timeout: 10.0
        - node: "haptic_feedback_"
          transition: "configure"
          timeout: 10.0
        - node: "robot_adapter_"
          transition: "activate"
          timeout: 5.0
        - node: "safety_"
          transition: "activate"
          timeout: 5.0
        - node: "trajectory_smoother_"
          transition: "activate"
          timeout: 5.0
        - node: "haptic_feedback_"
          transition: "activate"
          timeout: 5.0
        - node: "gripper_retargeter_"
          transition: "activate"
          timeout: 5.0

      on_start_teleop:
        - node: "ik_solver_"
          transition: "activate"
          timeout: 5.0
        - node: "arm_retargeter_"
          transition: "activate"
          timeout: 5.0

      on_stop_teleop:
        - node: "arm_retargeter_"
          transition: "deactivate"
          timeout: 5.0
        - node: "ik_solver_"
          transition: "deactivate"
          timeout: 5.0

      on_go_home:
        - node: "ompl_joint_planner_"
          transition: "activate"
          timeout: 5.0

      on_go_home_complete:
        - node: "ompl_joint_planner_"
          transition: "deactivate"
          timeout: 5.0

      on_go_to_start:
        - node: "ompl_joint_planner_"
          transition: "activate"
          timeout: 5.0

      on_go_to_start_complete:
        - node: "ompl_joint_planner_"
          transition: "deactivate"
          timeout: 5.0

    visualization:
      enable_markers: true
      publish_xr_to_tf: true
      rviz_config: "package://yam_teleop_bringup/config/yam_dual_viz.rviz"
      base_frame_offset:
        x: 0.0
        y: 0.2286
        z: 0.0
        roll: 0.0
        pitch: 0.0
        yaw: 0.0

  # --------------------------------------------------------------------------
  # Robot 2: Right YAM Arm
  # --------------------------------------------------------------------------
  - name: "YAM Right"
    namespace: "yam_right"
    serial: "YAM_RIGHT"

    adapters:
      - id: "arm"
        plugin: "sentinel_adapter_yam::YamAdapter"
        urdf: "package://yam_description/urdf/yam.urdf"

        publish_rate_hz: 120.0
        command_timeout_s: 0.5

        connection:
          port: "<RIGHT_ARM_CAN_PORT>"  # e.g. "can0" / "can1"
        zero_gravity: false
        arm_kp: [80, 80, 80, 40, 10, 10]
        arm_kd: [5, 5, 5, 1.5, 1.5, 1.5]

    capabilities:
      - type: manipulator
        id: right_arm
        adapter_id: "arm"
        enabled: true

        posturing:
          enabled: false
          mode: "simple"
          weight: 0.0

        chains:
          - id: arm
            base_link: "base_link"
            ee_link: "link_6"
            joints:
              - joint1
              - joint2
              - joint3
              - joint4
              - joint5
              - joint6
            q_min: [-2.61799, -0.01, -0.01, -1.5708, -1.5708, -2.0944]
            q_max: [3.13, 3.65, 3.13, 1.5708, 1.5708, 2.0944]
            q_nominal: [-0.003242542153047978, 0.015068284122987663, 0.007438773174639479, -0.06466010528725441, 0.003242542153047978, 0.022697795071335847]
            segments:
              upper_arm: 0.25
              forearm: 0.25

        retargeting:
          mode: "simple"
          enable_posture: false
          scale: 1.3
          workspace_limits:
            min: [-0.4, -0.5, 0.1]
            max: [0.6, 0.5, 0.8]
          tracking_frames:
            primary: "controller_right"
          laterality: "right"
          control_button: "trigger"
          coordinate_transform: [0, 0, 1, -1, 0, 0, 0, 1, 0]
          grip_threshold: 0.5
          reanchor_on_grip: true

          motion_pipeline:
            filter:
              notch_hz: 7.3
              notch_q: 8.0
              lowpass_hz: 9.0
            speed_gate:
              v_low: 0.015
              v_high: 0.050

        haptics:
          enabled: true
          min_event_m: 0.033
          max_event_m: 0.07
          time_constant_s: 0.2
          event_rate_hz: 30.0
          direction_axis_sign: [1, 1, -1]

        ik:
          solver_mode: "simple"
          solver: "casadi"
          max_iterations: 50
          tolerance: 0.001
          timeout_ms: 100.0
          enable_posture: false
          weight_translational: 100.0
          weight_rotational: 50.0
          weight_regularization: 0.1
          weight_smooth: 0.1
          weight_manipulability: 0.0

        trajectory:
          control_mode: "open_loop"
          max_velocity:     [6.0, 6.0, 6.0, 8.0, 8.0, 10.0]
          max_acceleration: [8.0, 8.0, 8.0, 10.0, 10.0, 12.0]
          max_jerk:         [20.0, 20.0, 20.0, 25.0, 25.0, 30.0]

        planning:
          interpolation_points: 100
          execution_rate_hz: 60.0
          planning_time_limit: 10.0
          enable_viz: true
          joints_to_lock: []

      - type: gripper
        id: gripper
        adapter_id: "arm"
        enabled: true
        parent_chain: arm

        retargeting:
          mode: "toggle"
          laterality: "right"
          trigger_threshold: 0.5
          close_threshold: 0.7
          open_threshold: 0.3
          toggle_debounce_s: 0.3
          invert: true

        hardware:
          type: "linear_4310"
          speed: 50.0
          force: 40.0
          max_force: 50.0
          kp: 0.5
          kd: 0.3

    safety:
      joint_limit_margin: 0.05
      velocity_limit_scale: 0.9
      emergency_stop_enabled: true
      max_torque: [50.0, 50.0, 50.0, 20.0, 20.0, 20.0]

    state_machine:
      initial_state: "DISARMED"
      joint_names: ["joint1", "joint2", "joint3", "joint4", "joint5", "joint6"]
      home_positions: [-0.003242542153047978, 0.015068284122987663, 0.007438773174639479, -0.06466010528725441, 0.003242542153047978, 0.022697795071335847]
      start_positions: [-0.003242542153047978, 0.5556191348134583, 0.6071183337148085, -0.09899290455481768, 0.0005722133211261138, 0.02193484397650103]
      motion:
        action_server_wait_timeout: 5.0
        goal_acceptance_timeout: 2.0
        motion_duration: 3.0
      calibration_timeout_s: 10.0
      skeleton_validation:
        enabled: true
        min_confidence: 0.5
        require_full_body: false
        min_bone_length_m: 0.05

    orchestration:
      on_arm:
        - node: "robot_adapter_"
          transition: "configure"
          timeout: 10.0
        - node: "trajectory_smoother_"
          transition: "configure"
          timeout: 10.0
        - node: "safety_"
          transition: "configure"
          timeout: 10.0
        - node: "arm_retargeter_"
          transition: "configure"
          timeout: 10.0
        - node: "gripper_retargeter_"
          transition: "configure"
          timeout: 10.0
        - node: "ik_solver_"
          transition: "configure"
          timeout: 10.0
        - node: "ompl_joint_planner_"
          transition: "configure"
          timeout: 10.0
        - node: "haptic_feedback_"
          transition: "configure"
          timeout: 10.0
        - node: "robot_adapter_"
          transition: "activate"
          timeout: 5.0
        - node: "safety_"
          transition: "activate"
          timeout: 5.0
        - node: "trajectory_smoother_"
          transition: "activate"
          timeout: 5.0
        - node: "haptic_feedback_"
          transition: "activate"
          timeout: 5.0
        - node: "gripper_retargeter_"
          transition: "activate"
          timeout: 5.0

      on_start_teleop:
        - node: "ik_solver_"
          transition: "activate"
          timeout: 5.0
        - node: "arm_retargeter_"
          transition: "activate"
          timeout: 5.0

      on_stop_teleop:
        - node: "arm_retargeter_"
          transition: "deactivate"
          timeout: 5.0
        - node: "ik_solver_"
          transition: "deactivate"
          timeout: 5.0

      on_go_home:
        - node: "ompl_joint_planner_"
          transition: "activate"
          timeout: 5.0

      on_go_home_complete:
        - node: "ompl_joint_planner_"
          transition: "deactivate"
          timeout: 5.0

      on_go_to_start:
        - node: "ompl_joint_planner_"
          transition: "activate"
          timeout: 5.0

      on_go_to_start_complete:
        - node: "ompl_joint_planner_"
          transition: "deactivate"
          timeout: 5.0

    visualization:
      enable_markers: true
      publish_xr_to_tf: true
      rviz_config: "package://yam_teleop_bringup/config/yam_dual_viz.rviz"
      base_frame_offset:
        x: 0.0
        y: -0.2286
        z: 0.0
        roll: 0.0
        pitch: 0.0
        yaw: 0.0
