{
  "_comment": "Real --ros-config for the SRM 'MATERIAL_TRANSFER_ROBOT_2026' AMR (github.com/senth-srmist/MATERIAL_TRANSFER_ROBOT_2026), derived by reading that repo's actual ROS 2 workspace (CODE/ros_ws/src/*) rather than from the paper-only integration brief material_transfer_robot_ros.json was written against. Do NOT confuse the two files: material_transfer_robot_ros.json backs the simulated `zelpi transporterdemo` (brief-only, placeholder topic names); this file is for docker/mtr2026-bridge — a real rosbridge_websocket bridge meant to run co-located on the robot's own Jetson, joining its existing ROS_DOMAIN_ID=42 / rmw_cyclonedds_cpp graph over host networking. See docker/mtr2026-bridge/README.md and docs/TRANSPORT_ROBOT_INTEGRATION.md for the full walkthrough.",
  "url": "ws://127.0.0.1:9090",
  "robotId": "transporter1",
  "robotKind": "srm-mtr2026-jetson-nano",
  "drive": "diff",
  "dof": 0,
  "skills": [],
  "units": { "len": "m", "ang": "rad" },
  "frame": "odom",
  "limits": { "vMax": 0.6, "wMax": 1.2 },
  "rateHz": 20,
  "topics": {
    "_cmdVel_comment": "twist_mux (CODE/ros_ws/src/diff_drive_controller/config/twist_mux.yaml) arbitrates 4 inputs by priority: /cmd_vel_estop(30) > /cmd_vel_joy(20) > /cmd_vel_nav2(10) > /cmd_vel_relocalize(5) -> /cmd_vel_out. zelpi publishes on the nav2 lane since that's the 'autonomous command source' slot this robot's own architecture reserves -- do NOT publish to /cmd_vel_estop or /cmd_vel_joy, and do not run this alongside their own Nav2 stack (both would fight for the same lane).",
    "cmdVel": "/cmd_vel_nav2",
    "_odom_comment": "Real odometry is ZED Mini VIO, not wheel-encoder dead-reckoning -- CODE/ros_ws/src/system_supervisor/config/supervisor_config.yaml's 'zed' node heartbeats on this exact topic/type (nav_msgs.msg.Odometry). Wheel encoders only exist as /encoder/ticks + /encoder/velocity (Int32MultiArray/Float32MultiArray, not Odometry) feeding the local PID loop -- do not point odom at those.",
    "odom": "/zed/zed_node/odom",
    "initialPose": "/transporter1/initialpose"
  },
  "skillServices": {},
  "_estop_comment": "IMPORTANT GAP: this robot's real e-stop (CODE/ros_ws/src/system_supervisor/scripts/system_supervisor.py's _send_estop()) is a TOPIC PUBLISH of a zero Twist to /cmd_vel_estop (RELIABLE QoS, twist_mux priority 30) -- not a ROS service. createRosDriver.mjs's estopService field only supports calling a service, so config-level estop wiring is not yet possible against this robot. Until createRosDriver.mjs gains topic-publish estop support (tracked as a Phase 2 follow-up -- see docs/TRANSPORT_ROBOT_INTEGRATION.md), estop is by SILENCE ONLY: stop publishing /cmd_vel_nav2 and twist_mux's 0.5s timeout + motor_driver.py's own 0.3s watchdog will zero the motors within ~0.8s worst case. That is materially slower and less certain than the robot's own real estop path -- do not treat zelpi's estop() call as a safety-rated stop on this robot yet.",
  "estopService": null,
  "_skills_comment": "This robot's real task-level API is far richer than a generic dock/estop pair: job_manager (DeliveryJob/ConfirmJob/CancelJob custom .srv) and mission_controller (NavigateToRoom/CancelMission custom .srv). Bridging these through rosbridge_suite generically requires those packages' interface definitions to be installed in the bridge container's own ROS environment (rosbridge serializes custom types by importing them, same as any ROS2 node) -- docker/mtr2026-bridge's image does not build the robot's full ros_ws, so these are left empty here rather than silently broken. See docs/TRANSPORT_ROBOT_INTEGRATION.md Phase 2 for what's needed to wire them up for real."
}
