Skip to content

novaphy.solvers.SolverVBD

Vertex Block Descent (VBD) and Augmented VBD (AVBD) primal-dual rigid-body solver, aligned with the Augmented Vertex Block Descent SIGGRAPH 2025 paper. Suitable for stiff stacks, joints under tight constraints, and compliant springs where Sequential Impulse drift becomes visible. For real-time free-body piles use SolverSemiImplicit; for articulated robots in reduced coordinates use SolverFeatherstone.

Supports:

  • Rigid contacts with Coulomb friction (shared SAP + SAT collision pipeline).
  • Augmented-Lagrangian joints between bodies.
  • Particle cloth / soft-body constraints on the CPU SolverBase path.

SolverBase API

SolverVBD is exposed as novaphy.solvers.SolverVBD and is driven through solver.step(state_in, state_out, control, contacts, dt). There is no top-level novaphy.VBDWorld container.

Pipeline

graph LR
    A[Broadphase<br/>SAP] --> B[Narrowphase<br/>SAT]
    B --> C[AVBD primal-dual<br/>iterations]
    C --> D[Block-coordinate<br/>descent]
    D --> E[Integrate]

SolverVBD shares the rigid collision pipeline with SolverSemiImplicit: SAP broadphase to generate candidate pairs, SAT narrowphase for exact contacts, then the contact / joint / spring constraints are fed into the AVBD primal-dual iterations and integrated.

Backends

Backend Build flag Notes
CPU always built Default.
CUDA NOVAPHY_WITH_VBD_CUDA=ON GPU-accelerated; experimental. Selected via VbdBackend.

Constructor

Construct SolverVBD from an immutable model and a VBD configuration:

novaphy.solvers.SolverVBD(model: Model, config: VBDConfig)
Parameter Description
model Immutable simulation model from ModelBuilder.finalize().
config VBDConfig with dt, iterations, backend, and AVBD penalty / relaxation parameters.

Example

import novaphy

builder = novaphy.ModelBuilder()
builder.add_ground_plane(y=0.0)
# ... add bodies and shapes ...

cfg = novaphy.solvers.VBDConfig()
cfg.dt = 1.0 / 60.0
cfg.iterations = 4
# cfg.backend = novaphy.solvers.VbdBackend.CUDA   # optional GPU backend

model = builder.finalize()
solver = novaphy.solvers.SolverVBD(model, cfg)
state = model.state()
control = model.control()
pipeline = novaphy.CollisionPipeline(model)
contacts = pipeline.contacts()

for _ in range(120):
    pipeline.collide(state, contacts)
    solver.step(state, state, control, contacts, cfg.dt)

Demos

Demo Description
python/demos/vbd/demo_vbd_rigid.py CPU rigid contact and supported-joint scenes.
python/demos/vbd/demo_vbd_soft.py CPU cloth and soft-rigid contact scenes.

See Also