f85dc047e8369985e2e617e78309325b4e1f36fd
The _enforce_quat_continuity function previously skipped dragged parts, assuming the GUI directly controls their placement. However, Newton re-solves all free params (including the dragged part's) to satisfy constraints, and can converge to an equivalent but distinct quaternion branch. The C++ validateNewPlacements() then sees a >91 degree rotation and rejects the step. Two-level fix: 1. Remove the dragged_ids skip — apply continuity to ALL non-grounded bodies, including the dragged part. 2. Add rotation angle check beyond simple hemisphere negation: compute the relative quaternion angle using the same formula as the C++ validator (2*acos(w)). If it exceeds 91 degrees, reset to the previous step's quaternion. This catches branch jumps where the solver finds a geometrically different but constraint-satisfying orientation (e.g. Cylindrical + Planar with 180-degree ambiguity). Verified: all 291 solver tests pass.
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)
Languages
C++
66.2%
Python
32.5%
CMake
1.1%