# Hand kinematics

The dependency-free hand solver: five digits in one frame, a thumb on a two-angle saddle joint with the coupled axial roll opposition really is, and the pad gap that falls out of it.

> For the complete index, see [llms.txt](https://robocn.dev/llms.txt). A Markdown version of any page is available by appending `.md` to its URL or by sending an `Accept: text/markdown` header.

## Install

```bash
bunx --bun shadcn@latest add https://robocn.dev/r/hand-kinematics.json
```

Registry item: `hand-kinematics` · [`https://robocn.dev/r/hand-kinematics.json`](https://robocn.dev/r/hand-kinematics.json)

## Notes

- Phalanx lengths are preserved at every closure, spread and wrist angle, because each digit is posed forward in a plane whose two basis vectors are unit and perpendicular.
- A tip pinch sits at the very edge of the thumb's workspace, which is why the grasp table closes the thumb so little for it: in a real pinch the thumb is nearly straight and the finger comes to meet it.
- No contact, no forces, no collision between digits. Nothing stops a hand closing through itself if you pose it that way.

## Usage

```tsx
import { solveHand, graspProfile } from "@/lib/robocn/hand"

const pose = solveHand({ grasp: "pinch", curl: 1, side: "left" })
pose.digits   // thumb first: joints, radii, closure, tip, pad
pose.pinch    // { thumb, finger, gap } in world units
graspProfile("tripod") // { digits, opposition, spread }
```

## API

| name | type | default | description |
| --- | --- | --- | --- |
| `solveHand` | `(options?: HandOptions) => HandPose` | — | Five digits in hand-local 3D: x across the palm toward the thumb, y up the hand, z out of the palm. The wrist is the origin. |
| `HandOptions` | `{ grasp?, curl?, digits?, spread?, opposition?, side?, wristPitch?, wristYaw? }` | — | Same axes as RobotHand. Every field is finite-checked; nonsense degrades to a neutral open hand. |
| `HandDigit` | `{ name, joints: Vec3[], radii, closure, tip, pad }` | — | Knuckle then one point per joint out to the tip, with the contact pad on the flexion side of the last phalanx. |
| `graspProfile` | `(grasp: HandGrasp) => HandGraspProfile` | — | The per-digit closure, thumb opposition and finger fan a named grip asks for. |
| `handGoal / handWave` | `(behavior, clock) => number` | — | The grip loop and the digit ripple, as pure functions of the clock. |

## Source

- `src/lib/robocn/hand.ts`
