| name | real-hardware-safety |
| description | CRITICAL safety skill for the WATonomous humanoid robot arm project. Use this skill ANY time code is being written, reviewed, debugged, or modified that will run on or could run on real robot hardware โ including motor control code, CAN bus commands, ROS2 launch files, trajectory planners, teleop scripts, sim-to-real transfer, zero-position calibration, or any script that sends commands to CubeMars AK10-9, AK80-9, or GL40 motors. Also trigger when the user mentions "real arm", "real hardware", "deploy", "on the robot", "test on hardware", "run on the arm", "sim to real", "sim2real", "zero position", "homing", "calibration", "motor test", or any indication that code will command physical actuators. Even if the user just asks for a "quick script to move the arm", trigger this skill. AI-generated code for robot arms has caused physical damage before (stripped screws, broken mounts, violent jerking) โ this skill exists to prevent that from happening again.
|
Real Hardware Safety Checker
Why This Skill Exists
This team has experienced real hardware damage from deploying AI-generated code without sufficient
safety checks. In one incident, mismatched zero positions between simulation and the real arm
caused the arm to jerk violently at full speed, ripping threads off motor mounting screws. This
skill ensures that every piece of code destined for real hardware goes through a rigorous safety
review before it touches an actuator.
MANDATORY: The Safety Checklist
Before generating, reviewing, or approving ANY code that will run on real hardware, Claude MUST
walk through every item in this checklist. Do not skip items. Do not assume things are fine. If
any item cannot be verified from the code/context, flag it explicitly and tell the user they must
verify it manually before running.
1. VELOCITY LIMITS โ Is everything slow?
THIS IS THE #1 KILLER. Check it first.
What to look for in code:
motor.velocity = target_velocity
MAX_VEL = 2.0
motor.velocity = np.clip(target_velocity, -MAX_VEL, MAX_VEL)
velocity_cmd = msg->velocity;
constexpr double MAX_VEL = 2.0;
velocity_cmd = std::clamp(msg->velocity, -MAX_VEL, MAX_VEL);
If velocity limiting is missing, DO NOT just mention it โ inject it into the code and explain
why. This is non-negotiable.
2. ZERO POSITION / HOMING โ Are sim and real aligned?
This is what caused the screw-ripping incident.
What to look for:
motor.position = 0.0
current_pos = motor.get_position()
target_pos = current_pos + 0.1
motor.position = target_pos
Critical questions to surface to the user:
- "Have you verified that the motor zero positions match your URDF/sim zero positions?"
- "Is the arm currently in the position your code thinks it's in?"
- "Have you done a manual check by reading encoder values before sending commands?"
3. JOINT POSITION LIMITS โ Can the arm reach impossible configurations?
Recommended limits structure (adapt to actual arm geometry):
JOINT_LIMITS = {
'shoulder_1': {'min': -1.57, 'max': 1.57},
'shoulder_2': {'min': -1.57, 'max': 1.57},
'elbow_1': {'min': -2.09, 'max': 2.09},
'elbow_2': {'min': -1.57, 'max': 1.57},
'elbow_3': {'min': -1.57, 'max': 1.57},
'wrist': {'min': -3.14, 'max': 3.14},
'gripper': {'min': 0.0, 'max': 1.0},
}
4. TORQUE LIMITS โ Can the motors overpower the structure?
What to look for:
Kp = 50.0
Kd = 5.0
Kp = 3.0
Kd = 0.3
5. EMERGENCY STOP โ Can you kill it instantly?
Remind the user every time:
โ ๏ธ HARDWARE E-STOP REMINDER: Before running this on the real arm, confirm you have a
physical emergency stop button wired in series with the 48V motor power supply. Software
E-stops are a complement, not a replacement. If your control PC freezes, only a hardware
E-stop can save the arm.
Software E-stop pattern:
import signal
import sys
def emergency_stop(signum, frame):
print("E-STOP TRIGGERED โ killing all motors")
for motor in motors:
motor.torque = 0.0
motor.velocity = 0.0
motor.update()
for motor in motors:
motor.disable()
sys.exit(1)
signal.signal(signal.SIGINT, emergency_stop)
signal.signal(signal.SIGTERM, emergency_stop)
6. CAN BUS WATCHDOG โ What happens if communication drops?
7. STARTUP SEQUENCE โ Does the code ramp up safely?
Safe startup pattern:
for motor in motors:
motor.enable()
time.sleep(0.5)
current_pos = motor.get_position()
print(f"Motor {motor.id} at position {current_pos:.3f} rad")
for motor in motors:
pos = motor.get_position()
if abs(pos) > EXPECTED_RANGE:
print(f"WARNING: Motor {motor.id} position {pos:.3f} outside expected range!")
print("Aborting โ check zero positions")
emergency_stop()
for motor in motors:
motor.set_impedance_gains(Kp=2.0, Kd=0.2)
motor.position = motor.get_position()
motor.update()
time.sleep(2.0)
8. SIM-TO-REAL TRANSFER โ Has the code been verified in simulation first?
Ask the user:
- "Have you run this in simulation first? What did the joint trajectories look like?"
- "Are the URDF joint limits identical between your sim config and your real config?"
9. THERMAL MONITORING โ Will the motors overheat?
10. STRUCTURAL INTEGRITY โ Has the physical arm been inspected?
Remind the user to physically check:
- All motor mounting screws are tight and use threadlocker where appropriate
- 3D-printed brackets are not cracked or deformed
- Cables and wires have strain relief and won't snag during motion
- The arm is securely clamped to a stable surface
- Nothing is in the arm's workspace that could be damaged
How To Present This Review
When reviewing code for real hardware deployment, Claude should:
- Lead with the safety review โ before discussing the code's functionality, logic, or
elegance, go through the checklist above
- Use a clear pass/fail format for each checklist item
- Inject fixes directly โ don't just say "you should add velocity limiting"; actually
modify the code to include it
- Print the hardware E-stop reminder every single time
- End with a "Ready to Run?" summary like this:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
REAL HARDWARE SAFETY REVIEW
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
Velocity limits: Clamped to 2.0 rad/s
โ
Zero position: Reads current pos before moving
โ
Joint limits: Defined and enforced
โ ๏ธ Torque limits: Using Kp=10 โ consider lowering to 3-5 for first test
โ
Software E-stop: SIGINT handler present
โ CAN watchdog: No timeout monitoring โ ADD THIS
โ
Startup sequence: Gradual ramp-up
โ
Sim verification: User confirmed sim test passed
โ
Thermal monitoring: Temperature read in feedback loop
โ ๏ธ Physical inspection: REMIND USER TO CHECK SCREWS AND MOUNTS
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
STATUS: NOT READY โ fix CAN watchdog before running
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Motor-Specific Reference
CubeMars AK10-9 V3.0 (Shoulder joints)
- Rated torque: 18 Nm / Peak: 53 Nm
- Gear ratio: 9:1
- MIT mode position range: ยฑ12.5 rad (output shaft)
- MIT mode velocity range: ยฑ50 rad/s (output shaft)
- Safe testing torque: โค10 Nm
- Safe testing velocity: โค2 rad/s
CubeMars AK80-9 V3.0 (Elbow joints)
- Rated torque: 9 Nm / Peak: 22 Nm
- Gear ratio: 9:1
- MIT mode position range: ยฑ12.5 rad (output shaft)
- MIT mode velocity range: ยฑ50 rad/s (output shaft)
- Safe testing torque: โค5 Nm
- Safe testing velocity: โค2 rad/s
CubeMars GL40 KV70 (Wrist + Gripper)
- Rated torque: 0.25 Nm / Peak: 0.73 Nm
- Safe testing torque: โค0.3 Nm
- Safe testing velocity: โค3 rad/s
CAN Bus Configuration
- Bus type: CAN 2.0 Classic, 500 kbps
- Interface: CANable (SLCAN) via /dev/ttyACM0
- Termination: 120ฮฉ at both ends required
- Communication timeout: set to 100-200ms via R-Link
Common AI-Generated Code Mistakes That Break Hardware
These are patterns that AI code generators (including Claude) frequently produce that are
dangerous on real hardware:
-
Assuming zero is zero โ AI writes go_to_position(0, 0, 0, 0, 0, 0) as a "home"
command without realizing the motor's zero is wherever it was when powered on
-
No velocity limiting โ AI generates position trajectories with no max velocity, so
the motor tries to get there as fast as possible
-
Full-stiffness impedance โ AI uses Kp=100 from a sim example where motors are
idealized; on real hardware this means the arm becomes a battering ram
-
Missing error handling โ AI writes the happy path but if a CAN message is dropped
or a motor faults, the code hangs or crashes without disabling motors
-
Copy-pasting sim parameters โ Sim gravity is often slightly off, friction models
don't match, and encoder zeros are different. AI copies the sim config verbatim.
-
Absolute position commands at startup โ The very first command is "go to position X"
without reading where the arm currently is. If the arm is at position Y far from X, it
moves at maximum speed to get there.
-
No ramp-up โ Trajectory starts at full speed from t=0 instead of gradually
accelerating from rest
When generating code, Claude must actively avoid all seven of these patterns.
Final Note
This skill is deliberately conservative. It is better to be annoyingly cautious and have a
working robot than to be permissive and have a pile of broken 3D prints and stripped screws.
Every time you think "this check is overkill," remember the arm that ripped its own mounting
screws out because sim-zero โ real-zero.