A homebrew Multi-Body solver.
What is it?
kSolver is a multi-body, kinematics and dynamic equilibrium solver, written in Python and in C++. It can be used to find the kinematic equilibrium of a complex mechanical system by forcing motion, or to find its dynamic equilibrium by imposing both motions and external forces. It is particularly suited for Kinematics and Compliance studies of vehicle suspensions.
How is it built?
The Multi-Body solver logic is based on the algebraic formulation of 3D motions of rigid bodies described in Federico Cheli's "Dinamica dei sistemi meccanici", with Euler (3-1-2) angle representations.
The MB assembly is represented hierarchically by a series of Parts, each supporting an unlimited set of Markers. Joints, bushings and force elements are represented as entities acting between two markers, plus a third one acting as a reference for positioning and orientation.
The Python library provides constructor functions to instantiate Parts, Markers and bushings following their most common definition (i.e., place a marker between these two existing markers, build a part whose center of mass is located in the mean of a series of markers' coordinates, etc). This way, building any complex mechanical system becomes like building a Python script; custom functions and routines can be created to represent deformable tires, anti-roll bars, struts, arms, up to the definition of functions building an entire suspension according to a given topology.
Once the Assembly has been built, it is either directly passed to the Python solver, or transformed in a custom-defined "deck file", which is then passed to the C++ solver.
Control is then passed to C++, which can either go through the (potentially) multi-step simulation silently, or provide step-by-step feedback (through stdout) to a guest application, such as, for example, the GUI you see in the above picture, so that the user can just monitor the loadcase simulation as it is being solved.
The solver in itself is based on assigning to each constraint a penalty value, which the arithmetical solver is attempting to minimize by acting on the system's degrees of freedom. For the kinematic solver, these penalties are summed into a scalar value, and kSolver relies on the OptimLib implementation of the BFGS solver (C++) or onto Scipy's implementation of the same logic when running in Python. In dynamic mode, the solution is an array of penalties, each corresponding to a constraint. kSolver handles this through a custom implementation of a Gauss-Newton like solver (with Levenberg-Marquardt regularization), made in Numpy in Python, and with Armadillo in C++.
In both cases, a Jacobian array/matrix (analytically calculated) is provided to the solver for increased speed.
What can it do?
It can simulate a full K&C use-case for a car suspension, including deformable (linear) bushings and deformable wheel-tire assembiles.
Executed in C++, it can run a circa 200 step, full K&C loadcase simulation in circa 1 minute on one modern CPU. On my current set-up, this allows me to run around 5-10 simulations per minute, when parallelization is possible (for example, with heuristic optimization algorithms).
It supports the following suspension topologies:
- MacPherson (solid/decomposed lower control arm)
- Double Wishbone (solid/decomposed upper and lower control arms)
- Double Wishbone with push-rod and I/T bars
- Jaguar Independent Rear Suspension
- Swing Axle
- 5-link (optional integral link)
Research example: Genetic Optimization of suspension geometry
One of the main reasons I created kSolver for was to be able to do research in heuristic suspension optimization without paying for an Adams license. What you see below is the representation of a genetic algorithm optimization run on a K&C simulation for a double wishbone suspension, set to match some simplified targets. The algorithm started from random hardpoints, and was let free to change each of their coordinates by a relatively large amount.
You can see how the initially "cloudy" suspension geometry progressively becomes more defined, as individuals converge towards the same hardpoints; the genetic code, rasterized in the "barcode" you see below, shows progressive loss of variety and again, convergence over a unique solution.
In this case, the algorithm was able to withstand the imposed targets after some tens of generations, showcasing the soundness of this technique. These initial successes eventually led to me leading a team into research in the field at my company, IDIADA Spain. There, the concept evolved into a tool, algorithms were reinvented and refined by a colleague of mine, and, as of 2026, we are perhaps the only VD consulting company trained to use these techniques daily, and to offer this kind of optimization to customers choosing us for chassis platform development.
Where is it going?
In Python, the MB engine has been extended to also provide dynamic equations in ODE form, supporting full, dynamic simulations with custom-built variable step integration. An obvious development direction, considering the would be to port this functionality to C++ too, something I am planning for the upcoming months.