Keyboard-Controlled Sign Language Hand Model
By Minwen ChenDescription
This project extends the skeletal animation and inverse kinematics system from Assignment 7 to support American Sign Language (ASL) fingerspelling. The 3D human hand model (developed based on the champanzee hand model) can now display all 26 letters of the ASL alphabet through keyboard input, with smooth transitions between poses.
Features Added
1. Sign Language Pose Data Structure
A new data structure to hold pose information for each ASL letter, mapping bone IDs to XZX Euler angles.
Code Location: main.cpp, Lines 22-26
struct SLPose {
std::string description;
std::map<int, Eigen::Vector3d> angles; // holds bone_id & xzx angles
};
2. ASL Alphabet Pose Definitions (26 Letters)
Complete definitions for all 26 ASL alphabet letters (A-Z), each specifying the exact joint angles for the hand skeleton to form the correct hand shape.
Code Location: main.cpp, Lines 28-513
// Initialize all sign language poses
std::map<char, SLPose> init_sl_poses() {
std::map<char, SLPose> poses;
// Lambda to create a pose
auto make_pose = [](const std::string& desc,
std::initializer_list<std::pair<int, Eigen::Vector3d>> angle_list) {
SLPose pose;
pose.description = desc;
for (const auto& p : angle_list) {
pose.angles[p.first] = p.second;
}
return pose;
};
// 26 letter definitions (A-Z) start here
return poses;
}
Each pose uses XZX Euler angles where:
- First X component: Controls lateral spread (fingers spread apart or squeeze back in)
- Z component: Controls extension (curling)
- Second X component: Additional twist
Example pose definition (Letter A):
poses['A'] = make_pose("Fist with thumb alongside", {
{3, Eigen::Vector3d(0, 20, 0)}, // Thumb proximal
{4, Eigen::Vector3d(0, 10, 0)}, // Thumb distal
{6, Eigen::Vector3d(0, 70, 0)}, // Index proximal - curled
{7, Eigen::Vector3d(0, 70, 0)}, // Index middle - curled
// Remaining bones
});
3. Pose Application Function
A function that applies ASL poses to the skeleton by setting joint angles for each bone.
Code Location: main.cpp, Lines 515-528
void apply_sl_pose(Skeleton& skeleton, const SLPose& pose) {
// Reset all bones to rest pose
for (auto& bone : skeleton) {
bone.xzx.setZero();
}
// Apply the pose angles
for (const auto& [bone_id, angles] : pose.angles) {
if (bone_id >= 0 && bone_id < static_cast<int>(skeleton.size())) {
skeleton[bone_id].xzx = angles;
}
}
}
4. Smooth Pose Transition with Interpolation
When switching between ASL letters, the hand linearly interpolates from the current pose to the target pose over 0.5 seconds.
Code Location: main.cpp, Lines 530-546
void interpolate_to_pose(Skeleton& skeleton, const SLPose& target_pose,
double t, const std::vector<Eigen::Vector3d>& start_angles) {
t = std::min(1.0, std::max(0.0, t)); // Clamp t to [0, 1]
for (size_t i = 0; i < skeleton.size(); i++) {
Eigen::Vector3d target_ang = Eigen::Vector3d::Zero();
auto it = target_pose.angles.find(static_cast<int>(i));
if (it != target_pose.angles.end()) {
target_ang = it->second;
}
// Linear interpolation
skeleton[i].xzx = (1.0 - t) * start_angles[i] + t * target_ang;
}
}
The smooth ease-in-out is applied in the pre-draw callback:
Code Location: main.cpp, Lines 740-741
t = t * t * (3.0 - 2.0 * t);
interpolate_to_pose(skeleton, target_pose, t, start_angles);
5. Multi-Mode System
The application supports three distinct modes of operation, allowing users to switch between the new Sign Language mode and the original A7 functionality.
Code Location: main.cpp, Lines 635-636
// Mode: 0 = IK, 1 = FK animation, 2 = sign language pose mode
int mode = 2; // Default to sign language mode
Mode handling in pre-draw callback:
Code Location: main.cpp, Lines 704-746
v.callback_pre_draw = [&](igl::opengl::glfw::Viewer &)->bool
{
if(mode == 0) // IK mode
{
ik();
}
else if(mode == 1) // FK animation mode
{
// Original FK animation code
}
else if(mode == 2) // sign language pose mode
{
if(transitioning_to_pose && v.core().is_animating)
{
// Smooth transition handling
}
}
update();
return false;
};
6. Keyboard Input Handling for Letter Keys
The system captures A-Z key presses and triggers the corresponding ASL pose transition with visual feedback in the console.
Code Location: main.cpp, Lines 807-838
v.callback_key_pressed = [&](
igl::opengl::glfw::Viewer & viewer,
unsigned char key,
int
)->bool
{
// Check if it's a letter key
char upper_key = std::toupper(key);
if(upper_key >= 'A' && upper_key <= 'Z' && mode == 2)
{
auto it = sl_poses.find(upper_key);
if(it != sl_poses.end())
{
// Start transition to new pose - save current angles
start_angles.clear();
for(size_t i = 0; i < skeleton.size(); i++) {
start_angles.push_back(skeleton[i].xzx);
}
target_pose = it->second;
transition_start_time = igl::get_seconds();
transitioning_to_pose = true;
current_letter = upper_key;
std::cout << "sign language Letter: " << upper_key;
if(!target_pose.description.empty())
{
std::cout << " - " << target_pose.description;
}
std::cout << std::endl;
return true;
}
}
// Mode switching code starts here
};
7. Transition State Variables
Variables to manage the smooth animated transitions between poses.
Code Location: main.cpp, Lines 627-633
// sign language pose transition variables
bool transitioning_to_pose = false;
double transition_start_time = 0;
double transition_duration = 0.5; // seconds
SLPose target_pose;
std::vector<Eigen::Vector3d> start_angles; // Store angles instead of Skeleton
char current_letter = ' ';
8. Console User Interface
Console output showing available controls and current state.
Code Location: main.cpp, Lines 890-902
std::cout << std::endl;
std::cout << "=== Keyboard-controlled sign language hand model ===" << std::endl;
std::cout << std::endl;
std::cout << "Controls:" << std::endl;
std::cout << " A-Z Show sign language letter pose (in sign language mode)" << std::endl;
std::cout << " 0 Reset to rest pose" << std::endl;
std::cout << " 1 Switch to IK mode (drag fingertips)" << std::endl;
std::cout << " 2 Switch to FK animation mode - content from assignment#7" << std::endl;
std::cout << " 3 Switch to sign language alphabet mode (need to set to this mode before using letters)" << std::endl;
std::cout << std::endl;
std::cout << "Current mode (default): sign language Alphabet" << std::endl;
std::cout << "Press any letter A-Z to see the sign language sign!" << std::endl;
std::cout << std::endl;
ASL Pose Summary Table
| Letter | Description | Key Bone Configurations |
|---|---|---|
| A | Fist with thumb alongside | All fingers curled (70°), thumb slight curl (20°) |
| B | Flat hand, thumb across palm | All fingers straight (0°), thumb curled across (50°) |
| C | Curved hand (holding ball) | All fingers ~35° curl |
| D | Index pointing, others curled | Index straight, others 65° curl |
| E | All fingers curled, thumb across | Progressive curl (60°, 50°, 40°) |
| F | OK sign (index-thumb circle) | Index curled to thumb, others straight |
| G | Index pointing sideways | Index ~10°, others curled |
| H | Index and middle sideways | Index & middle ~10°, others curled |
| I | Pinky up, fist | Pinky straight, others curled (70°) |
| J | Same as I (movement letter) | Same as I |
| K | Index up, middle spread, thumb between | Index straight, middle spread (-5°), thumb toward middle |
| L | L-shape (thumb and index) | Thumb extended (-10°), index straight |
| M | Thumb under three fingers | Index/middle/ring curled over thumb |
| N | Thumb under two fingers | Index/middle curled over thumb |
| O | All fingertips touch thumb | All fingers ~45° curl forming O |
| P | Like K (index up, middle angled) | Index straight, middle angled (15°), thumb out |
| Q | Thumb and index pinching | Thumb (10°, 15°), index slight curl, tips close |
| R | Index and middle crossed | Index (-10° lateral), middle (+5° lateral) crossing |
| S | Fist with thumb over fingers | All curled (70°), thumb over (50°) |
| T | Thumb between index and middle | Index curled (65°), thumb tucked (40°) |
| U | Index and middle up together | Index & middle straight (0°), close together |
| V | Peace sign (V shape) | Index & middle spread (±10° lateral) |
| W | Three fingers up | Index/middle/ring straight and spread |
| X | Index bent like hook | Index hooked (35°, 55°, 45°) |
| Y | Hang loose (thumb and pinky) | Thumb out (-15°), pinky straight, others curled |
| Z | Index pointing (draws Z) | Index straight, others curled |
Bone Structure Reference
The skeleton consists of 21 bones organized hierarchically:
| Bone ID | Name | Parent | Function |
|---|---|---|---|
| 0 | Root | -1 | Wrist anchor point |
| 1 | Palm | 0 | Palm/hand base |
| 2-4 | Thumb | 1→2→3 | Metacarpal → Proximal → Distal |
| 5-8 | Index | 1→5→6→7 | Metacarpal → Proximal → Middle → Distal |
| 9-12 | Middle | 1→9→10→11 | Metacarpal → Proximal → Middle → Distal |
| 13-16 | Ring | 1→13→14→15 | Metacarpal → Proximal → Middle → Distal |
| 17-20 | Pinky | 1→17→18→19 | Metacarpal → Proximal → Middle → Distal |
JSON File Changes: Expanded Joint Limits
The chimpanzee-hand.json file was modified to expand joint angle limits (xzx_min and xzx_max) to allow more expressive finger movements required for ASL poses.
Key Changes
| Bone Type | Original Lateral Spread | Modified Lateral Spread | Original Curl Max | Modified Curl Max |
|---|---|---|---|---|
| Metacarpals (5,9,13,17) | ±5° | ±10° | 0° | ±10° |
| Finger Joints | 0° | ±10° | 70° | 90° |
| Thumb Bones | Limited | Expanded | 60-70° | 70° |
Why These Changes Were Necessary
- Finger Spreading (V, W, K): Required expanded lateral rotation (first X component) on metacarpals and proximal joints to spread fingers apart
- Finger Crossing (R): Required lateral rotation on finger joints (originally locked at 0°) to allow index and middle fingers to cross
- Tighter Curling: Some poses needed curl beyond the original 70° limit for proper fist formation
- Thumb Mobility: Expanded range needed for various pinching and gripping poses (Q, F, O)
Acknowledgements
Libraries Used
libigl (Geometry Processing Library)
- Website: https://libigl.github.io/
- Files:
igl/opengl/glfw/Viewer.h,igl/project.h,igl/unproject.h,igl/get_seconds.h
Eigen (C++ Linear Algebra Library)
- Website: https://eigen.tuxfamily.org/
- Core dependency for all skeletal animation computations
GLFW (Graphics Library Framework)
- Website: https://www.glfw.org/
- Used for: Window management and OpenGL context creation
nlohmann/json (JSON for Modern C++)
- Website: https://github.com/nlohmann/json
- File:
json.hpp
References
- American Sign Language (ASL) Alphabet
- https://www.startasl.com/american-sign-language-alphabet/
- Reference charts used to design accurate hand poses for fingerspelling
- ASL is a complete natural language used by the Deaf and hard-of-hearing community in the United States and Canada