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, *,
    angular_damping: float = 0.05,
    friction_smoothing: float = 1.0,
    joint_attach_ke: float = 1.0e4,
    joint_attach_kd: float = 1.0e2,
    enable_tri_contact: bool = True,
)
Parameter Description
model Required. Immutable Model from ModelBuilder.finalize().
angular_damping Multiplicative angular velocity damping per step.
friction_smoothing Smooths friction direction transitions to reduce jitter.
joint_attach_ke Stiffness for soft attach constraints (Newton parity field).
joint_attach_kd Damping for soft attach constraints (Newton parity field).
enable_tri_contact Enable triangle-mesh contact generation.

The Newton-parity kwargs (friction_smoothing, joint_attach_*, enable_tri_contact) are stored on the instance for API parity but are not yet wired into the C++ free-body integrator.

Post-Construction Tuning

Mutate solver.settings for NovaPhy-specific PGS knobs:

solver.settings.<field> Type Description
velocity_iterations int PGS velocity-iteration count (default ~10). 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.
solver = novaphy.solvers.SolverSemiImplicit(model)
solver.settings.velocity_iterations = 30
solver.settings.warm_starting = True
solver.settings.sleep_enabled = True

Example

import numpy as np
import novaphy

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

body = novaphy.RigidBody.from_box(1.0, np.array([0.5, 0.5, 0.5], dtype=np.float32))
idx = builder.add_body(body, novaphy.Transform.from_translation(np.array([0, 5, 0])))
builder.add_shape(novaphy.CollisionShape.make_box(np.array([0.5, 0.5, 0.5]), idx))

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):
    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_pyramids_numerous.py Stress test with many pyramids.
python/demos/demo_wall_break.py 5×5 wall hit by sphere.

See Also