High-fidelity MuJoCo model for the SAKE Robotics EZGripper robotic gripper with realistic tendon-driven physics.
This repository contains a physics-accurate MuJoCo model of the SAKE Robotics EZGripper Dual (Gen1/Gen2), featuring:
- ✅ Tendon-driven mechanism - Realistic cable actuation matching real hardware
- ✅ Under-actuated fingers - Single servo controls 2 opposing fingers
- ✅ Adaptive grasping - Fingers wrap around objects independently
- ✅ Accurate meshes - Real STL geometry from SAKE Robotics
- ✅ MuJoCo 3.0+ compatible - Works with latest MuJoCo versions
# Install MuJoCo (if not already installed)
pip3 install mujoco
# Clone this repository
git clone https://github.com/SAKErobotics/ezgripper_sim.git
cd ezgripper_sim
# Test the model
python3 test_gripper.pypython3 test_gripper.pyUse the MuJoCo viewer sliders to control the gripper actuator.
Architecture: Under-actuated, tendon-driven
- Fingers: 2 opposing fingers
- Links per finger: 2 (proximal + distal)
- Joints per finger: 2 (~110° range each)
- Actuation: Single Dynamixel MX-64AR servo
Range of Motion:
- Full range: 2500 servo units (0 = closed, 2500 = open)
- Scaled range: 0-100% (used in control interface)
- Joint angles: ~110° per joint
The EZGripper uses two primary commands:
calibrate(servo)- Moves gripper to closed position
- Resets zero position
- Should be run at startup
goto_position(effort, position)Position Parameter (0-100):
0: Fully closed (continuous close mode)1-100: Specific position (% open)100: Fully open
Effort Parameter (0-100):
0: Torque off (fingers can be back-driven)1-100: Torque level (% of max)
Control Modes:
- Position = 0: Torque control mode (best for grasping)
- Position > 0: Position control mode (best for positioning)
Automatic Back-off Algorithm:
- Closes until fingers stop moving
- Drops to 10% torque to maintain grasp
- Minimizes power and heat
Tendon System:
- Spatial tendon routing through pulleys
- Realistic cable mechanics
- Spring-loaded opening (tendon closes, springs open)
Contact Dynamics:
- Mesh-based collision: All finger/palm meshes provide collision surfaces
- L1-L2 hard stop: Physical mesh collision defines preload position
- Intra-finger collision: L1 and L2 links collide to create spring preload
- Grasping surfaces: Palm, L1, L2, and finger tips all participate in grasping
- Adaptive wrapping: Fingers conform to object shape via under-actuation
Spring Configuration (Preload Mechanism):
The gripper uses collision-based preload to simulate the real hardware behavior:
-
Palm-L1 Joint:
stiffness="0.05114105365"(STRONG spring)springref="-3.14"(-180°, outside joint range)- Range:
-1.57075 to 0.27(-90° to 15°) - Effect: Constant force pulling joint toward open position
-
L1-L2 Joint:
stiffness="0.02459949416"(WEAK spring)springref="-1.57"(-90°, outside joint range)- Range:
0.5236 to 1.7(30° to 97°) - Effect: Constant force pulling joint toward open position
- Hard stop: L1-L2 mesh collision stops opening at ~30°
- Preload: Spring compressed against collision creates resting force
Why This Works:
- MuJoCo doesn't have explicit preload parameters
- Setting
springrefoutside joint range creates constant force - Physical collision between L1 and L2 meshes acts as hard stop
- Spring force compressed against hard stop = mechanical preload
- This matches real hardware where springs are pre-compressed at assembly
Under-Actuation Sequence:
- Open state: Springs pull joints open until L1-L2 collision stops them
- Tendon pull: Overcomes spring preload to close gripper
- Contact: L1 contacts object first, stops moving
- Wrap: L2 continues closing around object (progressive grasp)
Joint Properties:
- Damping: 0.005
- Spring references outside ranges for constant preload force
- Limited ranges matching real hardware
- Collision filtering:
contype=3 conaffinity=3for all grasping surfaces
ezgripper.xml # Main MuJoCo model
├── mount # Gripper base/mount
├── F1_L1 # Finger 1, Link 1 (proximal)
│ └── F1_L2 # Finger 1, Link 2 (distal)
├── F2_L1 # Finger 2, Link 1 (proximal)
│ └── F2_L2 # Finger 2, Link 2 (distal)
└── flex_tendon # Tendon connecting all links
meshes/
├── SAKE_Single_Mount.stl
├── SAKE_Palm_IM.stl
├── SAKE_Finger_L1_IM.stl
├── SAKE_Finger_L2_IM.stl
└── SAKE_Finger_Pad_IM.stl
To integrate the EZGripper into your robot model:
- Include the gripper body (without worldbody):
<include file="ezgripper_body.xml"/>- Attach to your end-effector:
<body name="your_end_effector">
<body name="ezgripper" pos="0 0 -0.05" quat="...">
<!-- Include gripper here -->
</body>
</body>- Orient the gripper:
- Default: Gripper X-axis points forward
- Rotate as needed for your application
See examples/minilift_integration.xml for a complete example of integrating the EZGripper with a SCARA arm.
- ✅ MuJoCo 3.0+: Fully tested and supported
- ✅ MuJoCo 2.x: Should work (not actively tested)
Tested with:
- MuJoCo 3.3.7 on Ubuntu 24.04
- Python 3.12
ezgripper.xml- Complete standalone model with floortest_gripper.py- Interactive test scriptmeshes/- STL mesh filesezgripper.png- Preview image
Original Model: Vikash Kumar (2021) Hardware: SAKE Robotics Maintained by: SAKE Robotics
Apache License 2.0 - See LICENSE file
- SAKE Robotics: https://sakerobotics.com/
- EZGripper Hardware: https://sakerobotics.com/products
- Python Drivers: https://github.com/SAKErobotics/libezgripper
- ROS 2 Drivers: https://github.com/SAKErobotics/EZGripper_ros2
- MuJoCo Documentation: https://mujoco.readthedocs.io/
For questions or issues:
- GitHub Issues: https://github.com/SAKErobotics/ezgripper_sim/issues
- Email: support@sakerobotics.com
