# Duck kinematics

The pose solver behind the duck. Two planar legs, a footfall cycle that never lifts both feet, and a neck chain swung on a constant radius.

> 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/duck-kinematics.json
```

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

## Notes

- No React and no three.js: the solver is plain functions over `{x, y}` objects and does not mutate its input.
- Walk holds 0.62 of the cycle in stance and strut 0.52, so at most one foot is ever off the ground. These are illustrative trajectories, not a balance model.

## Usage

```tsx
import { solveDuck } from "@/lib/robocn/duck"

const pose = solveDuck({ gait: "walk", phase: 0.3, gaze: 0.5 })
pose.legs // id, hip, knee, ankle, contact
pose.neck // four joints from shoulder to skull base
pose.head // pivot, angle, beak opening in degrees
```

## API

| name | type | default | description |
| --- | --- | --- | --- |
| `solveDuck` | `(options?: DuckOptions) => DuckPose` | — | Solves both legs, the neck chain, and the head from the gait and stance controls. |
| `DuckOptions` | `{ gait?, phase?, height?, stride?, lift?, gaze?, beak? }` | — | Same controls as MicroDuck. Every value is clamped, and non-finite input falls back to the default. |
| `DuckLeg` | `{ id, hip: Vec2, knee: Vec2, ankle: Vec2, contact }` | — | Sagittal coordinates: x forward, y up, ground at zero. Thigh 26 units, shank 28, ankle 9 above the ground when the foot is down. |
| `duckLinks` | `{ thigh, shank, neck }` | — | The link lengths the solver uses, exported so a renderer can size parts from them. |

## Source

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