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.

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,
)#

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.

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.

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,
)#

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.

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,
)#

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.

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.