Skip to content

novaphy.solvers.SolverSemiImplicit

Free-body Sequential Impulse (PGS) solver with semi-implicit Euler integration. Default rigid-body backend in NovaPhy. Suitable for real-time simulation of free-floating bodies under contacts and friction; for articulated systems use SolverFeatherstone instead.

Pipeline

graph LR
    A[CollisionPipeline<br/>explicit / SAP / NXN] --> B[Narrowphase<br/>analytic / contact core]
    B --> C[Sequential Impulse<br/>PGS iterations]
    C --> D[Semi-implicit Euler<br/>integrate]

Features:

  • Explicit, SAP, or NXN broadphase through CollisionPipeline.
  • Specialized narrowphase pairs (sphere-sphere / sphere-plane / sphere-box / box-plane / box-box, cylinders, convex hulls, and triangle meshes where supported by the collision pipeline).
  • Warm-started accumulated impulses across frames.
  • Coulomb friction with |tangent_impulse| ≤ μ * normal_impulse.
  • Baumgarte stabilization for penetration correction.
  • Optional body sleeping for static islands (toggle via settings.sleep_enabled).

Constructor

novaphy.solvers.SolverSemiImplicit(model, config=None)
Parameter Description
model Required. Immutable Model from ModelBuilder.finalize().
config Optional SolverSettings, also exposed as SolverSemiImplicit.Config.

Post-Construction Tuning

Pass a configuration object at construction or mutate solver.settings:

solver.settings.<field> Type Description
velocity_iterations int PGS velocity-iteration count (default 30). Higher = stiffer contacts, slower step.
warm_starting bool Reuse previous-frame accumulated impulses for stability.
sleep_enabled bool Allow bodies in static islands to sleep.
sleep_energy_threshold float Kinetic-energy threshold for sleeping.
sleep_time_required float Time below threshold before sleeping.
sleep_ema_alpha float Energy EMA smoothing factor.
baumgarte float Penetration error reduction parameter.
slop float Penetration tolerance below which corrections are skipped.
config = novaphy.solvers.SolverSemiImplicit.Config()
config.velocity_iterations = 40
config.sleep_enabled = True
solver = novaphy.solvers.SolverSemiImplicit(model, config)

Example

import numpy as np
import novaphy

builder = novaphy.ModelBuilder()
builder.add_ground_plane(y=0.0)

body = builder.add_body(
    novaphy.Transform.from_translation(
        np.array([0.0, 5.0, 0.0], dtype=np.float32)
    )
)
builder.add_shape_box(
    body,
    xform=novaphy.Transform.identity(),
    hx=0.5,
    hy=0.5,
    hz=0.5,
    cfg=novaphy.ShapeConfig(density=1.0, mu=0.5),
)

model = builder.finalize()
solver = novaphy.solvers.SolverSemiImplicit(model)

state    = model.state()
control  = model.control()
pipeline = novaphy.CollisionPipeline(model)
contacts = pipeline.contacts()

for _ in range(600):
    state.clear_forces()
    pipeline.collide(state, contacts)
    solver.step(state, state, control, contacts, 1.0 / 120.0)

When To Use

Scenario Recommendation
Free-floating rigid body piles, stacks, projectiles Default choice.
Articulated robots / multibody systems Use SolverFeatherstone.
Position-level constraints with compliance Use SolverXPBD.
Guaranteed no penetration (tight tolerances) Use SolverIPC when CUDA available.

Demos

Demo What it shows
python/demos/demo_pyramid_ball.py 4-3-2-1 pyramid with sphere projectile.
python/demos/demo_friction_ramp.py Boxes on a 30° ramp with varied friction coefficients.
python/demos/demo_dominoes.py 20-domino chain reaction (warm-starting helpful here).
python/demos/demo_wall_break.py 5×5 wall hit by sphere.

See Also