SOMAHandLayer#

SOMAHandLayer is the hand-only counterpart to SOMALayer. It provides a 25-joint parametric hand in wrist-local space for left and right hands at mid, low, and extra-low LODs.

It combines:

  • the native SOMA hand identity PCA, or a user-supplied MANO/MHR backend

  • identity-dependent skeleton fitting

  • Warp-accelerated or dense linear blend skinning

  • an optional bind-relative articulation-pose PCA

Use prepare_identity(...) when identity changes and pose(...) for each new pose. forward(...) is the one-call convenience wrapper.

The pose tensor has shape (B, 25, 3) in axis-angle form, or (B, 25, 3, 3) when pose2rot=False. Joint zero is the wrist; the remaining 24 joints articulate the fingers. Outputs contain wrist-local vertices, joints, and transforms in the requested output unit.

Use constructor reference_pose= for a reusable default, or pass it to pose() / forward() for a one-call override. See Data Assets for the shared body/hand lookup API and frames.

See SOMA Hand data assets for the checked-in identity and pose-PCA asset contract and the MANO setup requirements.

Hand-only SOMA-X layers and MANO interoperability.

class soma.hand.SOMAHandLayer(
data_root=None,
hand_type='left',
device='cuda',
identity_model_type='soma',
mode='warp',
output_unit=Unit.METERS,
identity_model_kwargs=None,
lod=None,
low_lod=False,
load_correctives_model=None,
correctives_model_path=_DEFAULT_CORRECTIVES_MODEL_PATH,
*,
reference_pose=None,
)#

Bases: Module

Hand-only parametric model operating in wrist-local coordinate space.

Two-phase API (matching SOMALayer):

  1. prepare_identity(identity_coeffs, scale_params=None) – cache rest shape + fitted skeleton for an identity.

  2. pose(poses, global_translation=None) – apply articulation to the cached identity.

forward() is a convenience wrapper that calls both.

See the soma.hand module docstring for the SOMAHand joint layout (25 joints, strict subset of the full-body SOMA skeleton), pose tensor conventions, per-backend identity dimensions, and scale_params semantics.

Build a SOMAHandLayer with the selected identity backend.

Parameters:
  • data_root (str | Path | None) – Directory containing SOMAHand.npz, SOMA_neutral.npz, and the per-backend model folders. If None or missing, assets are downloaded from HuggingFace automatically.

  • hand_type (str) – "left" or "right".

  • device (str | device) – Torch device for all buffers and intermediate tensors (e.g. "cuda", "cpu").

  • identity_model_type (str) – Identity backend. One of "soma" (default, hand PCA from SOMAHand.npz), "mano", or "mhr". See soma.hand for per-backend identity dimensions and scale_params semantics.

  • mode (str) – Skinning backend. "warp" uses the NVIDIA Warp accelerated LBS kernel; other values fall back to the dense PyTorch implementation.

  • output_unit (Unit) – Unit for all translational outputs of pose() / forward() (vertices, joints, transforms). Default Unit.METERS.

  • identity_model_kwargs (Mapping[str, Any] | None) – Extra keyword arguments forwarded to the identity-model constructor. Used e.g. by MANO to pass model_path.

  • lod (str | None) – Hand mesh level of detail: "mid" (2,859 vertices per hand), "low" (718 vertices per hand), or "xlo" (134 vertices per hand). Defaults to "mid", or "low" when low_lod=True.

  • low_lod (bool) – Legacy alias for lod="low".

  • load_correctives_model (bool | None) – Deprecated compatibility alias. Use correctives_model_path=None instead of False.

  • correctives_model_path (str | Path | None) – Path to a pose-corrective checkpoint. Defaults to data_root/correctives_model.pt. Pass None to skip loading correctives.

  • reference_pose (Tensor | dict[str, str] | None) – Default reference tensor or lookup dictionary for pose() and forward(). Dictionaries resolve once. None uses the current T-pose. See pose() for tensor shapes.

property default_skin_mesh_name: str#

Default USD skin-mesh prim name for this hand’s topology.

Consumed by export_soma_usd when the caller does not pass an explicit skin_mesh_name. Encodes handedness so left/right exports don’t collide when written into the same stage.

property num_shape_components: int#

Number of identity coefficients.

list_reference_poses()#

List reference keys and metadata in the current core NPZ.

get_reference_pose(
reference_id=None,
*,
version=None,
data_key='t_pose_world',
asset_revision=None,
alias=None,
)#

Return saved orientations for this hand, including the wrist.

Select one of version, asset_revision, alias, or reference_id. Version lookup uses the newest stored revision at or before that version; full keys and asset revisions match exactly. No downloads are used.

The fresh (25, 3, 3) tensor uses this layer’s joint order, device, dtype, and current wrist bind frame. Translations are not included.

convert_reference(rotations, from_ref, to_ref)#

Re-express (B, 25, 3, 3) rotations in another reference.

Both references accept a tensor or get_reference_pose() dictionary: orientations in this layer’s wrist bind frame, including the wrist. The result preserves absolute local rotations, input device/dtype and gradients. No identity preparation or layer state changes are needed. References are explicit; the constructor default is not used. Pass the result to pose(..., pose2rot=False, reference_pose=to_ref).

get_rest_shape(
identity_coeffs,
scale_params=None,
global_scale=1.0,
kwargs=None,
)#

Compute hand rest shape from identity coefficients.

Parameters:
  • identity_coeffs (Tensor) – (B, K) identity coefficients.

  • scale_params (Tensor | None) – backend-dependent per-identity scale vector (SOMA: (B, 24); MHR: (B, 26); MANO: unused). See class docstring.

  • global_scale (float | Tensor) – uniform scale scalar or (B,) tensor. Default 1.0.

  • kwargs (Mapping[str, Any] | None) – optional dict forwarded to the identity model’s get_rest_shape.

Returns:

(B, Vh, 3) wrist-local rest shape in output_unit.

Return type:

Tensor

prepare_identity(
identity_coeffs,
scale_params=None,
repose_to_bind_pose=True,
global_scale=1.0,
kwargs=None,
)#

Cache rest shape and fitted skeleton for the given identity.

Parameters:
  • identity_coeffs (Tensor) – (B, K) identity coefficients.

  • scale_params (Tensor | None) – backend-dependent per-identity scale vector (SOMA: (B, 24); MHR: (B, 26); MANO: unused). See class docstring. MHR consumes this here; SOMA caches it for pose().

  • repose_to_bind_pose (bool) – if True, rebind skinning to the bind pose after fitting. Keep enabled when apply_correctives is used.

  • global_scale (float | Tensor) – uniform scale scalar or (B,) tensor. Default 1.0.

  • kwargs (Mapping[str, Any] | None) – optional dict forwarded to the identity model’s get_rest_shape.

pose(
poses,
pose2rot=True,
apply_correctives=False,
absolute_pose=False,
global_translation=None,
fk_only=False,
*,
reference_pose=None,
)#

Pose the cached identity. Call prepare_identity() first.

For the SOMA backend, scale_params cached by prepare_identity() are applied here as per-joint bone-length scales (override of local_translations). MHR already baked them into the rest shape.

Parameters:
  • poses (Tensor) – (B, 25, 3) axis-angle, or (B, 25, 3, 3) rot matrices. Joint 0 = global wrist rotation; joints 1-24 = fingers.

  • pose2rot (bool) – convert axis-angle to rot matrices if True.

  • apply_correctives (bool) – if True, apply pose-dependent corrective offsets from the shared SOMA body correctives checkpoint.

  • absolute_pose (bool) – if True, rotations are absolute (not relative to T-pose joint orient). Matches SOMALayer convention.

  • global_translation (Tensor | None) – (B, 3) or (3,) wrist translation in output_unit. If None, wrist stays at origin.

  • fk_only (bool) – if True, run forward kinematics only and skip LBS.

  • reference_pose (Tensor | dict[str, str] | None) – None uses the constructor default, or the current T-pose if none was set. Otherwise, a dictionary of get_reference_pose() arguments or a (25, 3, 3) / (25, 4, 4) tensor of orientations in this hand’s joint order and current wrist bind frame. Only rotation blocks are used. absolute_pose=True bypasses the stored default but rejects an explicit reference.

Returns:

SOMAHandPoseOutput (all translations in output_unit) –

  • vertices: (B, Vh, 3). Omitted if fk_only=True.

  • joints: (B, 25, 3).

  • transforms: (B, 25, 4, 4).

Return type:

SOMAHandPoseOutput

forward(
poses,
identity_coeffs,
pose2rot=True,
apply_correctives=False,
absolute_pose=False,
global_translation=None,
global_scale=1.0,
scale_params=None,
kwargs=None,
*,
reference_pose=None,
)#

Combined prepare_identity + pose (convenience).

Parameters:
  • poses (Tensor) – (B, 25, 3) axis-angle, or (B, 25, 3, 3) rot matrices. Joint 0 = global wrist rotation; joints 1-24 = fingers.

  • identity_coeffs (Tensor) – (B, K) identity coefficients.

  • pose2rot (bool) – convert axis-angle to rot matrices if True.

  • apply_correctives (bool) – if True, apply pose-dependent corrective offsets.

  • absolute_pose (bool) – if True, rotations are absolute (not relative to T-pose joint orient). Matches SOMALayer convention.

  • global_translation (Tensor | None) – (B, 3) or (3,) wrist translation in output_unit. If None, wrist stays at origin.

  • global_scale (float | Tensor) – uniform scale scalar or (B,) tensor. Default 1.0.

  • scale_params (Tensor | None) – backend-dependent per-identity scale vector (SOMA: (B, 24); MHR: (B, 26); MANO: unused). See class docstring.

  • kwargs (Mapping[str, Any] | None) – optional dict forwarded to the identity model’s get_rest_shape.

  • reference_pose (Tensor | dict[str, str] | None) – Reference tensor or lookup dictionary, as in pose().

Returns:

SOMAHandPoseOutput (all translations in output_unit) –

  • vertices: (B, Vh, 3).

  • joints: (B, 25, 3).

  • transforms: (B, 25, 4, 4).

Return type:

SOMAHandPoseOutput

class soma.hand.SOMAHandPoseOutput#

Bases: dict[str, Tensor]

Structured output returned by pose and forward.

Behaves like a dict for backwards compatibility (out["vertices"]) while also supporting attribute access (out.vertices). vertices is absent when fk_only=True.