SMPL

SMPLBody and SmplPoseDeformation in witwin.radar.smpl, for posing an SMPL human mesh and moving it through a Radar scene.

witwin.radar.smpl wraps the SMPL body model. It needs the smpl extra (smplpytorch and OpenCV), imported at first use, and the SMPL model files, which you download from the SMPL authors. See Simulate SMPL humans.

from witwin.radar.smpl import SMPLBody, SmplPoseDeformation

SMPLBody#

class SMPLBody(pose, shape, *, position=(0.0, 0.0, 0.0), gender='male', model_root=None, rotation=None, device=None)

An SMPL body as a witwin.core geometry (kind == "smpl") with a position and rotation. A requires_grad pose or shape reaches the vertices it publishes.

posetensor (72,)required

Axis-angle rotation of 24 joints, 3 values each, rad.

shapetensor (10,)required

Shape coefficients.

position(x, y, z)default (0.0, 0.0, 0.0)

World position, m.

genderstrdefault 'male'

Which model file to load from model_root, for example "male", "female" or "neutral".

model_rootstr | Nonedefault None

Folder that holds the SMPL model files. None points to a models/smpl_models folder next to the installed witwin package, which a pip install does not have, so pass it explicitly.

rotationtensor | Nonedefault None

Body rotation. None is no rotation.

devicestr | torch.device | Nonedefault None

Device for the posing function.

Raises ImportError naming smplpytorch or OpenCV at first use if the smpl extra is missing.

SMPLBody.to_mesh#

SMPLBody.to_mesh(segments=16, *, device=None) -> tuple[torch.Tensor, torch.Tensor]

The posed mesh as (vertices, faces), with position and rotation applied. SMPL has 6890 vertices. segments is part of the Core geometry interface.

SMPLBody.updated#

SMPLBody.updated(**changes) -> SMPLBody

A new body with some fields changed. Accepts pose, shape, position, gender, model_root, rotation and device.

Raises TypeError for any other keyword.

import torch
 
body = SMPLBody(pose=torch.zeros(72), shape=torch.zeros(10), gender="neutral",
                model_root="path/to/smpl_models", position=(0.0, 0.0, -4.0), device="cuda")
vertices, faces = body.updated(pose=new_pose).to_mesh()

SmplPoseDeformation#

class SmplPoseDeformation(body, *, pose_rate, reference_time_s=0.0, device=None)

A posed SMPL body as a witwin.core.dynamics deformation over a fixed rest mesh. Face indexing and material assignment stay fixed and only the vertices move, so Radar can replay a frozen path topology against the moving body. The pose changes linearly in time: pose(t) = body.pose + pose_rate · (t - reference_time_s).

bodySMPLBodyrequired

The body at reference_time_s.

pose_ratetensor (72,)required

Pose derivative, rad/s, in the same joint layout as the pose. It is a direction, not a leaf, so it must not carry a gradient.

reference_time_sfloatdefault 0.0

Time at which the pose equals body.pose, s.

devicestr | torch.device | Nonedefault None

Device. None uses the body's device.

Raises

  • TypeError if body is not an SMPLBody.
  • ValueError if pose_rate has a different number of entries than the pose.
  • RuntimeError if the body's pose or shape, or pose_rate, carries a gradient or a forward tangent. Derivatives do not cross the Core/Channel compile boundary through this route.
MemberReturns
pose_rateThe pose rate tensor.
pose_at(time_s)Pose at time_s.
vertices_at(time_s)Posed vertices at time_s.
velocity_at(time_s)Exact vertex velocity d(vertices)/dt, from forward-mode differentiation of the skinning, one row per vertex.
at(time_s)The witwin.core deformation state at time_s.
rest_mesh(**mesh_kwargs)The rest Mesh for a Structure, built with recenter=False and with the body's position and rotation applied. Raises RuntimeError if the position or rotation carries a gradient.
from witwin.core.dynamics import DynamicScene
 
deformation = SmplPoseDeformation(body, pose_rate=pose_rate)
scene = Scene(structures=(Structure(geometry=deformation.rest_mesh(), material=skin, structure_id=7,
                                    material_id=1, assignment_id=1, surface_id=1),), endpoints=[])
world = DynamicScene(scene, structure_deformations={7: deformation})

The mesh reflects and occludes but adds no scatterers. To make the body return energy, place PointTargets on its surface as in Simulate SMPL humans.