forbes-0023 5802d45a7f fix(solver): skip single_equation_pass during drag to prevent stale constraints
single_equation_pass analytically solves variables and bakes their values
as Const() nodes into downstream residual expressions. During drag, the
cached residuals use these stale constants even though part positions have
changed, causing constraints like Planar distance=0 to silently stop
being enforced.

Skip single_equation_pass in the pre_drag() path. Only substitution_pass
(which replaces genuinely grounded parameters) is safe to cache across
drag steps. Newton-Raphson converges in 1-2 iterations from a nearby
initial guess anyway, so the prepass optimization is unnecessary for drag.

Add regression tests covering the bug scenario and the fix.
2026-02-25 12:57:43 -06:00
2023-10-17 09:56:26 -05:00

Kindred Solver

Assembly constraint solver addon for Kindred Create. Implements the IKCSolver interface via kcsolve.register_solver().

Components

Kindred Solver (Phase 1)

Expression-based Newton-Raphson constraint solver. Pure Python, registered as a Create addon.

  • Expression DAG with eval, symbolic differentiation, simplification: kindred_solver/expr.py
  • Parameter table with fixed/free tracking: kindred_solver/params.py
  • Quaternion rotation as polynomial Expr trees: kindred_solver/quat.py
  • RigidBody entity (7 params: position + unit quaternion): kindred_solver/entities.py
  • Constraint residual generators (Coincident, DistancePointPoint, Fixed): kindred_solver/constraints.py
  • Newton-Raphson solver with symbolic Jacobian: kindred_solver/newton.py
  • Pre-solve passes (substitution, single-equation): kindred_solver/prepass.py
  • DOF counting via Jacobian rank: kindred_solver/dof.py
  • KCSolve IKCSolver bridge: kindred_solver/solver.py

GNN (future phases)

Graph neural network constraint prediction layer. OndselSolver C++ engine and ML training infrastructure. Moved to GNN/ — will be integrated in later phases.

Create Addon Integration

This repo is a git submodule at mods/solver/ in the Create repository. The addon loader discovers package.xml and executes Init.py, which registers the solver:

import kcsolve
from kindred_solver import KindredSolver
kcsolve.register_solver("kindred", KindredSolver)

Testing

python3 -m venv .venv && . .venv/bin/activate
pip install pytest numpy
PYTHONPATH=. pytest tests/ -v

Repository Structure

├── package.xml            # Create addon manifest
├── Init.py                # Solver registration entry point
├── kindred_solver/        # Phase 1: expression-based Newton solver
│   ├── expr.py            # Expression DAG
│   ├── params.py          # Parameter table
│   ├── quat.py            # Quaternion math as Expr trees
│   ├── entities.py        # RigidBody entity
│   ├── constraints.py     # Constraint residual generators
│   ├── newton.py          # Newton-Raphson solver
│   ├── prepass.py         # Pre-solve passes
│   ├── dof.py             # DOF counting
│   └── solver.py          # IKCSolver bridge
├── tests/                 # Unit tests (82 tests)
└── GNN/                   # GNN solver layer (future phases)

License

LGPL-2.1-or-later (see LICENSE)

Description
An assembly solving stack for Kindred Create based on a trained GNN layer between placement actions in the UI and actual constraints applied.
Readme LGPL-2.1 17 MiB
Languages
C++ 66.2%
Python 32.5%
CMake 1.1%