Animatica Autoposer (SOMA-30)
A neural autoposer for full-body character rigs. Give it a handful of handles β where a hand should be, where the feet are planted, which way the head looks β and it returns a complete, natural pose for a 30-joint skeleton. It is what makes posing in the Animatica Blender add-on feel like moving a character rather than rotating thirty bones.
It is a poser, not an animator: one pose per call, a few milliseconds each, no motion model and no temporal state. Ask it once per frame and you have an editable animation; ask it once and you have a pose.
What you give it
Any number of effectors, in any combination. Each carries a tolerance β metres of slack β so a handle can be an exact pin or a loose suggestion the model may overrule to keep the body plausible.
| Effector | Type id | Value | Meaning |
|---|---|---|---|
| Position | 0 |
xyz | put this joint here |
| Rotation | 1 |
6D rotation | orient this joint like this |
| Look-at | 2 |
xyz + direction | aim this joint at this point |
Plus a body descriptor: 29 bone lengths, z-scored. The same effectors solve correctly on a child, a heavyset adult, or a giant, because proportion is an input rather than an assumption.
Three position effectors is the sparsest input it was trained to answer well; one or two will return something, but the body below them is mostly prior.
What you get back
- draft joint positions β
[B, 90], the 30 joints as xyz, root first - 6D rotations β
[B, 180], per joint, for FK on your own skeleton
Run the rotations through SOMA-30 forward kinematics with your body's neutral joints to get world positions. The bundled IK pass (below) then pins the effectors exactly and keeps the feet out of the floor.
Use it in Blender
The Animatica add-on downloads this repository on first use and needs no token or manual setup β handles appear on your rig and you drag them. That is the shortest path to using this model, and the one it is tuned for.
Use it directly (ONNX)
onnx/ is the runtime bundle: two graphs and the metadata that describes them.
import json, numpy as np, onnxruntime as ort
from huggingface_hub import snapshot_download
d = snapshot_download("Animatica-ai/autoposer", allow_patterns=["onnx/*"])
meta = json.load(open(f"{d}/onnx/meta.json"))
poser = ort.InferenceSession(f"{d}/onnx/poser.onnx")
E = 3 # three handles: hips and both hands
val = np.zeros((1, E, 7), np.float32) # 6 value channels + 1 tolerance
val[0, 0, :3], val[0, 0, 6] = (0.0, 0.95, 0.0), 0.005
val[0, 1, :3], val[0, 1, 6] = (0.35, 1.20, 0.20), 0.005
val[0, 2, :3], val[0, 2, 6] = (-0.35, 1.20, 0.20), 0.005
draft, rot6d = poser.run(None, {
"val": val,
"weights": np.ones((1, E), np.float32), # encoder blending weights
"joint_id": np.array([[0, 13, 19]], np.int64), # Hips, LeftHand, RightHand
"eff_type": np.zeros((1, E), np.int64), # all positions
"cond": np.zeros((1, 29), np.float32), # z-scored bone lengths
})
Two details the graph will not tell you, and which decide whether the output is a pose or a heap:
- Reference frame. Position and look-at values are expressed relative to the centroid of the
position targets. This checkpoint is floor-referenced (
floor_ref: true), so y stays absolute β the ground is a real height, not something relative β and the centroid is zeroed on y before subtracting. - Conditioning.
condis the 29 bone lengths, z-scored withblen_mean/blen_stdfrommeta.jsonand clamped to Β±4.5. Zeros mean "the average body the statistics describe", which is why the snippet above works at all.
The IK pass
onnx/ik.onnx is a damped least-squares refinement that runs after the network: it pins
effectors to the tolerance you asked for, holds a floor plane, and rolls the toes rather than
sinking the feet. Twelve iterations over a damping ladder, accepting per step. The network gets
the pose right; this makes the handles exact.
meta.json carries a selftest β recorded inputs and expected outputs β so a miscompiled
graph is detectable. It matters more than it sounds: a bad kernel fusion does not raise, it
quietly returns a wrong pose. Run the IK graph on selftest.inputs and compare against
selftest.expect; agreement should be well under half a centimetre.
Use it directly (PyTorch)
model.safetensors + config.json are the training weights, for research use and for anyone who
wants to fine-tune. config.json records the skeleton (njoints, ux/ux_names), the
conditioning width (cond_dim: 29), floor referencing, and the training step.
The skeleton
30 joints, root first:
Hips Spine1 Spine2 Chest Neck1 Neck2 Head Jaw LeftEye RightEye
LeftShoulder LeftArm LeftForeArm LeftHand LeftHandThumbEnd LeftHandMiddleEnd
RightShoulder RightArm RightForeArm RightHand RightHandThumbEnd RightHandMiddleEnd
LeftLeg LeftShin LeftFoot LeftToeBase
RightLeg RightShin RightFoot RightToeBase
meta.json has the parent list, the neutral (rest) joint positions, the four foot joints used by
the floor term, and the effector joint ids.
How it works
Each effector is embedded from its value, tolerance, joint id and type, and the set is blended by weight into a single pose code β so the model takes any number of handles in any order, rather than a fixed rig of them. Two-stage decoding follows: draft joint positions first, then per-joint 6D rotations, which is what keeps limbs attached to a body of the right proportions instead of merely near the handles. The body descriptor is injected twice, at the encoder alongside each effector and again at the decoder embedding (zero-initialised, so it starts as a no-op and is learned into).
Files
| File | Size | What |
|---|---|---|
onnx/poser.onnx |
142 MB | the network |
onnx/ik.onnx |
1.9 MB | the IK refinement pass |
onnx/meta.json |
19 KB | skeleton, normalisation stats, checksums, selftest |
model.safetensors |
β | PyTorch weights |
config.json |
β | training configuration |
Limitations
- One pose at a time. There is no temporal model: consecutive frames are consistent because consecutive effectors are, not because the model remembers anything.
- SOMA-30 only. Other skeletons need retargeting onto these 30 joints first.
- Hands and face are along for the ride. Fingers are a thumb and middle tip per hand; jaw and eyes are in the skeleton but are not meaningfully posed.
- Fewer than three position effectors leaves most of the body to the prior. It will answer; it just has little to answer from.
- Floor-referenced. Feed it absolute heights. A pose built in a different vertical frame will come back crouching or floating.
Made by Animatica. Found something odd? Tell us β the model and the add-on move together, and a pose that comes out wrong is usually interesting.
- Downloads last month
- 560