pyondsel
Python bindings for OndselSolver, the multibody kinematics engine behind FreeCAD's Assembly workbench. Define a mechanism (parts, joints, a motor), solve it, and read back where every part is at each instant.
- Author in Python or in native ASMT. Build a model from
Part/Marker/Joint/Motionobjects, or hand it OndselSolver's own.asmttext (portable to and from FreeCAD). - All 26 joint kinds. Lower pairs (revolute, cylindrical, translational, spherical, screw, ...), higher pairs (point/line/plane incidence), and coupling joints (gear, rack-and-pinion, constant velocity, ...), so the full OndselSolver constraint set is reachable from Python.
- Fault-isolated. The solver runs in a worker subprocess, so an ill-posed model raises
SolveErrorinstead of crashing your program. - Structured results. Get a
Trajectory: the time samples plus each part's position and orientation at every frame.
Getting started
Install
pip install -e . # or: uv pip install -e .
This compiles the vendored OndselSolver C++ into a single extension module (scikit-build-core + pybind11). You need a C++17 compiler and CMake >= 3.18. No other system libraries are required.
Your first mechanism
A crank on a pivot, driven one full turn per second:
The authoring classes are imported from their modules (pyondsel's top-level package is
intentionally empty; import each class from its submodule):
from pyondsel.model.asmt_model import AsmtModel
from pyondsel.model.joint import Joint
from pyondsel.model.marker import Marker
from pyondsel.model.motion import Motion
from pyondsel.model.part import Part
from pyondsel.model.simulation import Simulation
model = AsmtModel(name="Rig")
model.add_ground_marker(Marker("pivot")) # a fixed point to pin the crank to
crank = model.add_part(Part("crank", mass=1.0,
moments_of_inertia=(0.001, 0.02, 0.02),
mass_center=(0.5, 0.0, 0.0)))
crank.add_marker(Marker("hub")) # where the crank meets the pivot
model.add_joint(Joint("j1", "revolute",
model.ground_path("pivot"),
model.part_path("crank", "hub"))) # 1 rotational DoF about the hub Z
model.add_motion(Motion.constant_speed("spin", "j1", turns_per_time=1.0))
model.simulation = Simulation(t_start=0.0, t_end=1.0, frames=36)
trajectory = model.solve()
crank = trajectory.parts["/Rig/crank"]
for t, angle in zip(trajectory.times, (b[2] for b in crank.bryant_angles)):
print(f"t={t:.2f}s crank angle={angle:.3f} rad")
The later snippets assume these imports (and the model above).
How-to
Read a part's pose at each frame
Trajectory.parts maps each part's full path (/<assembly>/<part>) to a PartTrajectory with
positions (x, y, z) and bryant_angles (Bryant / Tait X-Y-Z angles) per frame. For a full 3x3
rotation, use rotation_matrix:
from pyondsel.asmt_solver import rotation_matrix
part = trajectory.parts["/Rig/crank"]
for pos, ang in zip(part.positions, part.bryant_angles):
R = rotation_matrix(ang) # R = Rx(bx) . Ry(by) . Rz(bz)
...
Choose the joint and motion
A Joint couples two markers under a kind that maps to an OndselSolver ASMT joint block. All 26
kinds the solver recognizes are exposed, in four groups:
- Lower pairs:
fixed(lock / ground),revolute,cylindrical,translational,spherical,universal,screw,planar. - Compound lower pairs:
cylspherical,revcylindrical,sphspherical,revrevolute. - Higher pairs (point / line / plane incidence):
point_in_line,point_in_plane,in_line,line_in_plane,in_plane. These keep a point or line on another marker's line or plane, e.g. a crank pin riding a yoke slot. - Coupling / relational:
gear,rack_pinion,constant_velocity,no_rotation,parallel_axes,perpendicular,angle,at_point,compound.
Motion kinds are rotational (drives the angle about Z) and translational (drives the slide along
Z); the expression is a function of time, e.g. "2.0*pi*time", "0.5*time", "sin(time)".
model.add_joint(Joint("slide", "translational", a_path, b_path))
model.add_motion(Motion("push", joint="slide", expression="0.05*time", kind="translational"))
Joints that carry extra parameters (gears, screws, and friends)
Some kinds need extra scalars beyond the two markers; they are optional Joint fields the writer
emits only for the kinds that declare them, and a missing required one raises ValueError:
| Kind | Field(s) | Meaning |
|---|---|---|
screw |
pitch |
translation per radian about Z |
gear |
radius_i, radius_j |
the two pitch radii (their ratio is the gear ratio) |
rack_pinion |
pitch_radius |
the pinion pitch radius |
angle |
angle |
the constrained angle between the marker Z axes |
in_plane |
offset |
offset of the point from marker J's plane |
compound |
distance_ij |
the fixed distance between the two markers |
# a meshing gear pair: a coupling joint whose two pitch radii set the ratio
model.add_joint(Joint("mesh", "gear",
model.part_path("pinion", "axis"), model.part_path("gear", "axis"),
radius_i=0.024, radius_j=0.036))
Ground a part
Fix a part to the world by joining one of its markers to a ground marker with a fixed joint:
model.add_joint(Joint("anchor", "fixed", model.ground_path("origin"),
model.part_path("base", "seat")))
Control the number of frames
Simulation(t_start, t_end, frames) records frames evenly spaced samples over the span, so the
trajectory length is predictable regardless of the solver's internal step size.
Handle failures
from pyondsel.errors import AsmtInputError, SolveError
try:
trajectory = model.solve()
except AsmtInputError: # malformed model / ASMT text
...
except SolveError as exc: # solver could not solve, or crashed on an ill-posed model
print(exc.returncode, exc.detail)
Work with native ASMT directly
model.to_asmt() returns OndselSolver's text format; solve_asmt(text) (from
pyondsel.solve import solve_asmt) solves raw ASMT and returns the solved ASMT (carrying the
trajectory). Pre-solved files (with a stored trajectory) are accepted: pyondsel strips the old
series and re-solves. This is the interchange with FreeCAD and the upstream solver.
Format
pyondsel does not invent a format; it speaks OndselSolver's ASMT. See extern/OndselSolver for the
upstream project and tests/data/*.asmt for reference models (crank-slider, four-bar, and others).
License
LGPL-2.1-only. pyondsel statically links OndselSolver (LGPL-2.1), so it adopts the same license;
see NOTICE.md for what that means for use and redistribution (and why the label is -only, not
-or-later).
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyondsel-0.0.3.tar.gz.
File metadata
- Download URL: pyondsel-0.0.3.tar.gz
- Upload date:
- Size: 1.8 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8124ffbf586f7361cf22c70fe151f8276f2bb83c31e4df55794c704bc1e3a8fd
|
|
| MD5 |
7aba89d0a1137ed6dd00473020dd6881
|
|
| BLAKE2b-256 |
a5ab75034871075dab62fcc55d03a786ac3808fa430a74ed9d71d86564dc8d31
|
Provenance
The following attestation bundles were made for pyondsel-0.0.3.tar.gz:
Publisher:
publish.yml on deepsaia/pyondsel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyondsel-0.0.3.tar.gz -
Subject digest:
8124ffbf586f7361cf22c70fe151f8276f2bb83c31e4df55794c704bc1e3a8fd - Sigstore transparency entry: 2231844894
- Sigstore integration time:
-
Permalink:
deepsaia/pyondsel@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Branch / Tag:
refs/tags/0.0.3 - Owner: https://github.com/deepsaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyondsel-0.0.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: pyondsel-0.0.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 907.6 kB
- Tags: CPython 3.13, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6e7674bdbee5d64a613cc7735dce98a60252ab44fecfc87a45af1d5b00601dfb
|
|
| MD5 |
4cc728b481714cb3b58a369c198392b9
|
|
| BLAKE2b-256 |
e9cabc0b5315eceff1074ec0ba436a0187264cd59ab079388bf8c18b35080f28
|
Provenance
The following attestation bundles were made for pyondsel-0.0.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
publish.yml on deepsaia/pyondsel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyondsel-0.0.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
6e7674bdbee5d64a613cc7735dce98a60252ab44fecfc87a45af1d5b00601dfb - Sigstore transparency entry: 2231847200
- Sigstore integration time:
-
Permalink:
deepsaia/pyondsel@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Branch / Tag:
refs/tags/0.0.3 - Owner: https://github.com/deepsaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyondsel-0.0.3-cp313-cp313-macosx_11_0_arm64.whl.
File metadata
- Download URL: pyondsel-0.0.3-cp313-cp313-macosx_11_0_arm64.whl
- Upload date:
- Size: 542.9 kB
- Tags: CPython 3.13, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c9ec96f039395b82344284c42e824ab027e0395a9385441cb0e1403f16ae842
|
|
| MD5 |
457f0cab6d38a2d846657e2c8eaf9e89
|
|
| BLAKE2b-256 |
0b834e347791c24dbf0d4ad1953b2a256b6f5372d263eea5fc91e90e43b7bb19
|
Provenance
The following attestation bundles were made for pyondsel-0.0.3-cp313-cp313-macosx_11_0_arm64.whl:
Publisher:
publish.yml on deepsaia/pyondsel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyondsel-0.0.3-cp313-cp313-macosx_11_0_arm64.whl -
Subject digest:
5c9ec96f039395b82344284c42e824ab027e0395a9385441cb0e1403f16ae842 - Sigstore transparency entry: 2231846735
- Sigstore integration time:
-
Permalink:
deepsaia/pyondsel@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Branch / Tag:
refs/tags/0.0.3 - Owner: https://github.com/deepsaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyondsel-0.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: pyondsel-0.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 907.2 kB
- Tags: CPython 3.12, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ec36a523d31b27e6327f7139deca87ca4173e56c881f75027174d602b4cb1ce
|
|
| MD5 |
d741e95ede3024728158b30b728b47cb
|
|
| BLAKE2b-256 |
6cd4e69e9d34fb57a102298c7c345b4616f5b6236caba188c4629babeb342f71
|
Provenance
The following attestation bundles were made for pyondsel-0.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
publish.yml on deepsaia/pyondsel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyondsel-0.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
3ec36a523d31b27e6327f7139deca87ca4173e56c881f75027174d602b4cb1ce - Sigstore transparency entry: 2231845507
- Sigstore integration time:
-
Permalink:
deepsaia/pyondsel@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Branch / Tag:
refs/tags/0.0.3 - Owner: https://github.com/deepsaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyondsel-0.0.3-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: pyondsel-0.0.3-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 542.8 kB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
54487523e1b0416f0a317e2c7333375cdc39543b792f285d50484841535cf5a2
|
|
| MD5 |
10ac43341563e719d409a9c12ba5b5d8
|
|
| BLAKE2b-256 |
49392b10bed0977ed6a986a0de24e007b58f4809b19f6930822fa78bd8586303
|
Provenance
The following attestation bundles were made for pyondsel-0.0.3-cp312-cp312-macosx_11_0_arm64.whl:
Publisher:
publish.yml on deepsaia/pyondsel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyondsel-0.0.3-cp312-cp312-macosx_11_0_arm64.whl -
Subject digest:
54487523e1b0416f0a317e2c7333375cdc39543b792f285d50484841535cf5a2 - Sigstore transparency entry: 2231849114
- Sigstore integration time:
-
Permalink:
deepsaia/pyondsel@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Branch / Tag:
refs/tags/0.0.3 - Owner: https://github.com/deepsaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyondsel-0.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: pyondsel-0.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 907.2 kB
- Tags: CPython 3.11, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
762f153e87ad6872dd6df0967a1f8c67f62b83d8317f6a164847ad27b92d24a4
|
|
| MD5 |
8f9d27d429b8b5eee92942ef93ceacdb
|
|
| BLAKE2b-256 |
42751a19ab8c7d005d254b856c168d8eec97bd1bd3f1344aabefaeff4a6da181
|
Provenance
The following attestation bundles were made for pyondsel-0.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
publish.yml on deepsaia/pyondsel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyondsel-0.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
762f153e87ad6872dd6df0967a1f8c67f62b83d8317f6a164847ad27b92d24a4 - Sigstore transparency entry: 2231847900
- Sigstore integration time:
-
Permalink:
deepsaia/pyondsel@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Branch / Tag:
refs/tags/0.0.3 - Owner: https://github.com/deepsaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyondsel-0.0.3-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: pyondsel-0.0.3-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 542.2 kB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2fc8bb63d1ead1e9c90066c86357994d87d2224aacc6508af246bbc9bf4248b3
|
|
| MD5 |
d8f4fbdb0aafc7dfae4c08396fce9d64
|
|
| BLAKE2b-256 |
9c6ca4f8f6907899a0f7e9c1f2b460436d21d6b6336fc312b20c69c5cf4914c9
|
Provenance
The following attestation bundles were made for pyondsel-0.0.3-cp311-cp311-macosx_11_0_arm64.whl:
Publisher:
publish.yml on deepsaia/pyondsel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyondsel-0.0.3-cp311-cp311-macosx_11_0_arm64.whl -
Subject digest:
2fc8bb63d1ead1e9c90066c86357994d87d2224aacc6508af246bbc9bf4248b3 - Sigstore transparency entry: 2231849757
- Sigstore integration time:
-
Permalink:
deepsaia/pyondsel@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Branch / Tag:
refs/tags/0.0.3 - Owner: https://github.com/deepsaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyondsel-0.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: pyondsel-0.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 903.4 kB
- Tags: CPython 3.10, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4783b000a462f204b57c35716fbfcf6e926918715437fe4d021a8eeff9a34057
|
|
| MD5 |
4ccabc2ff9959456412005ea3b258398
|
|
| BLAKE2b-256 |
dec5430c998bbb71669756b82249195c00a31805ea41e6b6a38a95dc5534b412
|
Provenance
The following attestation bundles were made for pyondsel-0.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
publish.yml on deepsaia/pyondsel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyondsel-0.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
4783b000a462f204b57c35716fbfcf6e926918715437fe4d021a8eeff9a34057 - Sigstore transparency entry: 2231846265
- Sigstore integration time:
-
Permalink:
deepsaia/pyondsel@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Branch / Tag:
refs/tags/0.0.3 - Owner: https://github.com/deepsaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyondsel-0.0.3-cp310-cp310-macosx_11_0_arm64.whl.
File metadata
- Download URL: pyondsel-0.0.3-cp310-cp310-macosx_11_0_arm64.whl
- Upload date:
- Size: 541.3 kB
- Tags: CPython 3.10, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea28350d007abc7e7c039981f5bdf6f35831a82e191dc17a0a35c0e1c3d2c2ea
|
|
| MD5 |
d60efbdf6ff65848b558935bf473e550
|
|
| BLAKE2b-256 |
611a5173367a6be6fc80df285c5ac7da9dade262bc1c0e5d12f756c05ce7c2f2
|
Provenance
The following attestation bundles were made for pyondsel-0.0.3-cp310-cp310-macosx_11_0_arm64.whl:
Publisher:
publish.yml on deepsaia/pyondsel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyondsel-0.0.3-cp310-cp310-macosx_11_0_arm64.whl -
Subject digest:
ea28350d007abc7e7c039981f5bdf6f35831a82e191dc17a0a35c0e1c3d2c2ea - Sigstore transparency entry: 2231848305
- Sigstore integration time:
-
Permalink:
deepsaia/pyondsel@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Branch / Tag:
refs/tags/0.0.3 - Owner: https://github.com/deepsaia
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cee96d1c2e387c9060ab1e59294c085b6a4004c2 -
Trigger Event:
release
-
Statement type: