Kamino#
SolverKamino simulates constrained rigid multi-body
systems in maximal coordinates. It is designed for mechanical assemblies with
kinematic loops, under- or overactuation, joint limits, hard frictional
contacts, and restitutive impacts.
Unlike the other maximal-coordinate solvers, Kamino focuses on constrained rigid mechanical assemblies rather than particle or deformable simulation. Kamino is currently in BETA 1, and Newton users are discouraged from depending on it. Evaluate it only when kinematic loops and hard contact constraints are primary requirements and an experimental solver is acceptable.
Experimental
SolverKamino is experimental. Its public API,
behavior, feature support, performance, and implementation may change
without prior notice.
See the SolverKamino API reference for construction
and configuration details. Runnable workflows are available in the
Kamino examples.
Choosing a dynamics solver#
Kamino provides two forward-dynamics backends:
"padmm"(default): proximal ADMM, dense Jacobians/dynamics, and the Euler integrator. It is the slower, more robust option because it solves equality and inequality constraints together."dvi"(opt-in): projected dual iterations, sparse Jacobians, dense dynamics with the RCM-reordered blocked LLT solver, and the Euler integrator. It is generally faster, but approximates the coupled problem by alternating between a direct solve for equality constraints and projected iterations for inequality constraints. As a rule of thumb, DVI solves inequality constraints less accurately than PADMM, particularly as the number of active inequalities grows. Dual preconditioning is not supported.
Select the backend when constructing the configuration so dependent defaults initialize consistently:
config = newton.solvers.SolverKamino.Config(dynamics_solver="dvi")
solver = newton.solvers.SolverKamino(model, config=config)
DVI is best suited to performance-sensitive rigid mechanisms with relatively
few active contacts; PADMM remains the safer and more broadly validated choice.
Set sparse_jacobian=False for fully dense DVI, or set
sparse_dynamics=True to use sparse dynamics with the Conjugate Residual
solver.
For large bilateral systems, opt into RCM-reordered factorization explicitly:
config.dvi.bilateral_solver_type = "LLTBRCM"
config.dvi.bilateral_solver_kwargs = {
"block_size": 32,
"reuse_permutation": True,
"parallel_factorization": True,
}
The cached permutation remains mathematically valid when matrix values or
sparsity change and is recomputed automatically if the active dimension
changes. Keep the default "LLTB" solver for small systems.
Inspecting terminal status#
After each step, status provides one
device-resident terminal status record per world. PADMM and DVI both provide
converged, iterations, r_p, r_d, and r_c fields. Their
residual definitions are backend-specific:
PADMM: Let
xandybe the current preconditioned impulse iterates,x_prevandy_prevtheir previous values,Pthe diagonal dual preconditioner, andetaandrhothe proximal and penalty parameters.r_p = ||P (x - y)||_infis the primal consensus residual [N·s or N·m·s].r_d = ||P^-1 (eta (x - x_prev) + rho (y - y_prev))||_infis the ADMM dual residual [m/s or rad/s].r_cis the maximum absolute impulse-velocity inner product over inequality blocks [J]. ThePfactors convert the first two residuals from solver scaling to physical constraint units.DVI: With physical impulse
lambdaand augmented constraint velocityv,r_pis the maximum infinity-norm projection distance of unilateral impulses from the nonnegative limit cone or Coulomb contact cone [N·s or N·m·s].r_dis the maximum of the corresponding velocity distance from the dual cone and the bilateral velocity violation [m/s or rad/s].r_c = max |lambda_k dot v_k|is the maximum inequality complementarity violation [J].
These are absolute maxima: neither backend divides them by a reference norm, constraint count, or tolerance. Additional fields are not portable between backends.
status = solver.status
assert status.device == model.device
assert status.shape == (model.world_count,)
# Host inspection is explicit and synchronizes the device-to-host copy.
status_host = status.numpy()
unconverged_worlds = (~status_host["converged"].astype(bool)).nonzero()[0]
Terminal status is always maintained. collect_solver_info=True enables
additional solver diagnostics and adds runtime and memory overhead; it is not
required to access status.
Actuation and forward kinematics#
Kamino dynamics routes actuation independently for each joint DoF. A DoF can use explicit effort, unbounded implicit PD, or effort-limited implicit PD; passive armature, damping, and Coulomb friction are likewise configured per DoF. Implicit-PD target modes require a non-zero applicable gain: velocity mode requires derivative gain, while position-based modes require proportional or derivative gain. Coulomb friction supports all non-free joint types, while joint dynamics and implicit PD currently support revolute, prismatic, and gimbal joint types only.
The forward-kinematics solver still partitions each joint as entirely passive
or entirely actuated. Different non-passive target modes are allowed within a
joint, but mixing passive and actuated DoFs within one joint is not yet
supported. The fk_actuation_flag model attribute provides an explicit
joint-level override for this FK partition.