The RDS 2025 project is a sophisticated robotic hand control system featuring three integrated subsystems: a 2-DOF wrist, a 4-DOF dexterous finger, and a 1-DOF power finger. The system employs Series Elastic Actuators (SEAs) for compliant control, tendon-driven mechanisms for compact design, and distributed control architecture across multiple microcontrollers.
- Wrist Control: 2-DOF (pitch and yaw)
- Dexterous Finger: 4-DOF (PIP, DIP, MCP, Splay) with coupled tendon actuation between PIP and MCP
- Power Finger: 1-DOF grasp mechanism with high force capability
- Force Control: Series Elastic Actuators with real-time force feedback
- Distributed Architecture: Multi-MCU system with CAN bus communication
High-Level Controller (Teensy 4.1)
├── State Management & Coordination
├── Joint-Level Control (Position/Force)
├── Tendon Kinematics & Coupling
└── CAN Communication Hub
Low-Level Controllers (Teensy 4.1)
├── SEA Force Control
├── Motor Current Control
├── Encoder Feedback
└── Load Cell Integration
Palm Controller (Teensy 4.0)
├── Multi-Encoder Reading (8 channels)
├── SPI Communication
└── Joint Angle Feedback
- User Interface: handling user input (PID gains, reference type, plotter & logger) for control and testing
- High-level MCU: responsible for parsing commands, kinematics calculation, and position PID control; will send joint torque commands to low-level MCU
- Low-level MCU: responsible for inner force control loop with PID and tendon force calculation with SEA modules; will drive the motor with the motor driver board (in this case ODrive Pro) by sending current/torque command
- Palm Board/Sensor Board: gathering joint sensor information to give it to high-level MCU for kinematics calculation
- Communication Library: handling CAN bus communication between all the MCUs, designed for our original architecture with high-level and low-level controllers, but can be used for any other architecture as well. Stored in separate repository: rds25-comms to use across the
High-Level,Low-Level, andPalmcontrollers
The system uses a Jacobian-based approach for tendon-to-joint mapping, with each motor's velocity mapped to its respective actuating joint's velocity through a tendon routing matrix, an example for which is shown in dex finger below:
Dexterous Finger Jacobian:
J_dex = [ 1.0 -2.0 -1.2 -1.2]
[-1.0 0.0 0.0 0.0]
[-1.0 2.0 1.2 1.2]
[ 1.0 2.52 1.2 1.2]
More information on wrist coupling and power finger can be found in the Mechanical documentation linked below.
Motor Torque Calculation:
τ_motor = (1/R_motor) × (J × τ_joint + τ_null)
Where:
R_motor = 5.0 mm(motor pulley radius)τ_nullprovides null-space control for tendon pretension
Force-deflection relationships were experimentally determined for each SEA:
Linear SEAs:
F_SEA2 = 0.206 × θ
Nonlinear SEAs:
F_SEA3 = 0.972 × θ - 0.00432 × θ²
F_SEA4 = 0.829 × θ - 0.00714 × θ²
Where:
- F is the force in Newtons (N)
- θ is the angular deflection in degree (deg)
The spring characterization for all the SEAs can be found in the references below.
- Encoders: AS5047P magnetic encoders (14-bit resolution)
- Force Feedback: SEA measurements taken through encoder ans spring calibrated through NAU7802 load cells
- Motor Control: ODrive motor controllers via CAN bus
The system implements cascaded PD control with anti-windup:
SEA-based force control with PD gains:
The system accepts commands in the format ID:value1 value2 ...:
Command Examples:
10:30.0 15.0 45.0 30.0 15.0 0.0 60.0 // Set all joint positions
20 // Emergency stop
30 // Get system status
The system uses CAN bus for inter-controller communication:
- Baud Rate: 250 kbps
- High-Level: Joint coordination and state management
- Low-Level: Motor control and sensor feedback
- Palm: Multi-encoder data acquisition
To manage this communication, we use a combination of the ODrive library for Teensy and our custom rds25-comms library, which provides a simple interface for sending and receiving commands across the CAN bus.
For speaking to motor controllers, we use the ODrive library, which provides a high-level interface for controlling motors via CAN bus. The library allows us to set motor parameters, read encoder values, and control motor currents.
For communication between the various other controllers, we use our custom rds25-comms library. This library provides a simple interface for sending and receiving commands across the CAN bus, managing heartbeats, and handling errors. It allows us to easily send commands to the high-level controller, low-level controllers, and palm controller, ensuring that all components of the system can communicate effectively.
rds25-comms documentation and reflections can be found in the rds25-comms repository.
A comprehensive Tkinter-based GUI provides:
- Real-time joint position control
- Force/position data recording
- System monitoring and diagnostics
- Preset hand configurations
# Real-time pitch/yaw recording with statistical analysis
def plot_recorded_data(self):
pitch_error = np.array(pitch_desired) - np.array(pitch_actual)
yaw_error = np.array(yaw_desired) - np.array(yaw_actual)
rms_error_pitch = np.sqrt(np.mean(pitch_error**2))
rms_error_yaw = np.sqrt(np.mean(yaw_error**2))Each SEA was individually calibrated to determine force-deflection relationships:
- Linear SEAs: Simple proportional relationship (SEA_2, SEA_5, SEA_6)
- Nonlinear SEAs: Quadratic compensation required (SEA_3, SEA_4, SEA_7, SEA_8)
Indexing of SEAs in comparison to mechanical convention can be found here: SEA Indexing
Load cell feedback demonstrates:
- Force accuracy: ±0.1N at 5N maximum
- Response time: <100ms for force steps
- Stability: No oscillations observed in normal operation
- Modular Architecture: Clean separation of concerns across subsystems
- Real-time Performance: 100Hz control loop with deterministic timing
- Force Feedback: Accurate SEA-based force control enables compliant manipulation
- Comprehensive Monitoring: Extensive logging and visualization capabilities
- Robust Communication: CAN bus provides reliable inter-controller communication
- Tendon Coupling: Complex interdependencies require careful tuning
- Calibration Complexity: Each SEA requires individual characterization
- Range Limitations: Some joints have restricted ROM due to mechanical constraints
- Force Limits: Current SEA design limits maximum force output
- Hardware Configuration: Better architecture design to account for changes in hardware
- Feedforward Control: Using feedforward + PD control to enhance control of large subsystems
- Gravity Compensation: Working with mechanical to get a model of the gravity distribution and integrate it into the control loop to improve system stability
- Zero Impedence Control: Consider adding zero impedance control mode, which makes it easier to set up based on certain configuration
- Motor Drivers with SimpleFOC: Using custom motor drivers with Arduino-SimpleFOC library
- Integration of Control Loops: All control loops working in their layer of abstraction together
- Kinematic Integration: Control of integrated mechanical system with kinematic integration
- Incremental Testing: For each hardware design iteration, there should be some testing done on the software side on a small unit/moddule of the hardware before we build the entire thing
- High-Level Control:
/high-level/src/- State management and coordination - Low-Level Control:
/low-level/src/- Force control and motor interfaces - Palm Interface:
/palm/src/- Multi-encoder sensor reading - GUI Applications:
/GUI/- Python control interfaces - Communication Library: rds25-comms - For CAN bus communication and command parsing
- Mechanical Documentation: Specifications, CAD files, assembly drawings, kinematics
- Electrical Schematics: PCB designs and wiring diagrams (found in Electrical Documentation folder in repo)
- Calibration Data: SEA force curves and sensor offsets
- Demos: all the photos and videos taken during testing
- rds25-comms Documentation: Documentation for the CAN bus communication library, found in the readme.
- PlatformIO for microcontroller development
- Python 3.8+ with matplotlib, numpy, tkinter
- CAN bus hardware (ODrive controllers)
- Hardware Setup: Connect encoders, load cells, and CAN devices according to electrical architecture
- Firmware Upload: Flash appropriate code to each Teensy controller
- Calibration: Run encoder offset and SEA force calibration procedures
- GUI Launch: Execute
python GUI/PhaniGUI.pyfor system control - Testing: Use preset configurations to verify system operation
# Compile and upload high-level controller
cd high-level && pio run -t upload
# Launch monitoring GUI
python GUI/PhaniGUI.py
# Run force control validation
python GUI/SerialGUI.pyFor detailed technical documentation, calibration procedures, and troubleshooting guides, refer to the complete project repository and associated technical reports.







