Complete guide for calibrating your OpenFT sensor to achieve high-accuracy measurements using a learned calibration matrix.
Geometric approach assumes ideal sensors and perfect tolerances. Reality includes non-linearities, manufacturing variations, cross-coupling, and thermal effects. Calibration provides 5-10x accuracy improvement.
Need: Reference F/T sensor (ATI, Robotiq, OptoForce) OR calibrated weights + lever arms | Rigid mounting | Data logging
Mount: Reference Sensor → Rigid Coupling → OpenFT → Loading Fixture (no compliance!)
Test: Run ft_min_driver.py --port /dev/ttyACM0 --zmq-port 5555 and verify both sensors output data
Collect 150-200 samples covering:
- All 6 axes: ±X, ±Y, ±Z forces and ±Mx, ±My, ±Mz torques
- Load levels: 20%, 40%, 60%, 80%, 100% of expected range
- Some combined loads (diagonal forces, force+torque)
Manual method:
- Zero both sensors (no load)
- Apply known load and wait 2-3 seconds for stability
- Record data from both sensors simultaneously
- Remove load, wait for zero
- Repeat with different loads/directions
Automated script: Subscribe to ZMQ (port 5555) for OpenFT data, read reference sensor, average 10 samples per recording, combine to CSV row with columns: sensor_1..16, force_local_x,y,z, torque_local_x,y,z
Do: Cover full range, include ±loads on each axis, wait for stability, record zeros periodically Don't: Exceed rated capacity, rush readings, collect only one direction, skip torque if needed
Verify data:
head -n 5 your_calibration_data.csv # Check 22 columns, reasonable valuesRun calibration:
cd software/calibration
python calc_calibration_matrix.py --csv your_data.csv --output my_calibration.jsonInterpreting output:
Loaded 180 valid data points
Matrix rank: 17 (expected: 17)
Condition number: 2.45e+03 ← Should be < 1e4
Calibration quality:
Force RMSE: 0.0234 N ← Should be < 1% of full scale
Torque RMSE: 0.000156 N⋅m ← Should be < 1% of full scale
Good calibration: RMSE < 1% range, similar error across axes, condition number < 1e4 Poor calibration: RMSE > 5% (collect more diverse data), one axis much worse (check loading), condition number > 1e5 (check sensors)
Test: Run ft_min_driver.py (terminal 1), then calc_calibration_matrix.py --live --calibration my_calibration.json (terminal 2). Apply known loads to verify.
Integration: Subscribe to ZMQ port 5556, receive JSON with forces and torques keys
Recalibrate: When accuracy degrades, after mechanical changes, temperature range changes, or repairs
High RMSE (>5%): Collect more diverse data, check rigid coupling, verify reference sensor, check synchronization, reduce vibration
High condition number (>1e5): Check for damaged sensors, collect data in missing directions, reduce load if sensors saturating
One axis high error: Collect more data in that direction, check reference calibration for that axis, verify no compliance
Drift over time: Allow thermal stabilization, tighten fasteners, avoid external magnetic fields
- Mount both sensors rigidly (no compliance)
- Test sensors independently
- Zero with no load
- Plan loading matrix (all axes, multiple levels)
- Collect 150-200 diverse samples
- Save CSV with correct format
- Run calc_calibration_matrix.py
- Verify RMSE < 1% of range
- Test with known loads
- Document calibration date/conditions
- Save with sensor serial number
The calibration matrix learns optimal sensor fusion:
- Each F/T axis uses weighted combination of all 16 sensors (not just geometric assumptions)
- Compensates non-linearities in Hall sensor response curves
- Handles cross-coupling (forces affecting other axes' sensors)
- Corrects per-sensor variations from manufacturing tolerances
This is why it achieves 5-10x better accuracy than geometric calculations.