Skip to main content

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 / Motion objects, or hand it OndselSolver's own .asmt text (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 SolveError instead 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

pyondsel-0.0.3.tar.gz (1.8 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pyondsel-0.0.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (907.6 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

pyondsel-0.0.3-cp313-cp313-macosx_11_0_arm64.whl (542.9 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

pyondsel-0.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (907.2 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

pyondsel-0.0.3-cp312-cp312-macosx_11_0_arm64.whl (542.8 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

pyondsel-0.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (907.2 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

pyondsel-0.0.3-cp311-cp311-macosx_11_0_arm64.whl (542.2 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

pyondsel-0.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (903.4 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

pyondsel-0.0.3-cp310-cp310-macosx_11_0_arm64.whl (541.3 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

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

Hashes for pyondsel-0.0.3.tar.gz
Algorithm Hash digest
SHA256 8124ffbf586f7361cf22c70fe151f8276f2bb83c31e4df55794c704bc1e3a8fd
MD5 7aba89d0a1137ed6dd00473020dd6881
BLAKE2b-256 a5ab75034871075dab62fcc55d03a786ac3808fa430a74ed9d71d86564dc8d31

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyondsel-0.0.3.tar.gz:

Publisher: publish.yml on deepsaia/pyondsel

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyondsel-0.0.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyondsel-0.0.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6e7674bdbee5d64a613cc7735dce98a60252ab44fecfc87a45af1d5b00601dfb
MD5 4cc728b481714cb3b58a369c198392b9
BLAKE2b-256 e9cabc0b5315eceff1074ec0ba436a0187264cd59ab079388bf8c18b35080f28

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyondsel-0.0.3-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyondsel-0.0.3-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5c9ec96f039395b82344284c42e824ab027e0395a9385441cb0e1403f16ae842
MD5 457f0cab6d38a2d846657e2c8eaf9e89
BLAKE2b-256 0b834e347791c24dbf0d4ad1953b2a256b6f5372d263eea5fc91e90e43b7bb19

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyondsel-0.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyondsel-0.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3ec36a523d31b27e6327f7139deca87ca4173e56c881f75027174d602b4cb1ce
MD5 d741e95ede3024728158b30b728b47cb
BLAKE2b-256 6cd4e69e9d34fb57a102298c7c345b4616f5b6236caba188c4629babeb342f71

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyondsel-0.0.3-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyondsel-0.0.3-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 54487523e1b0416f0a317e2c7333375cdc39543b792f285d50484841535cf5a2
MD5 10ac43341563e719d409a9c12ba5b5d8
BLAKE2b-256 49392b10bed0977ed6a986a0de24e007b58f4809b19f6930822fa78bd8586303

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyondsel-0.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyondsel-0.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 762f153e87ad6872dd6df0967a1f8c67f62b83d8317f6a164847ad27b92d24a4
MD5 8f9d27d429b8b5eee92942ef93ceacdb
BLAKE2b-256 42751a19ab8c7d005d254b856c168d8eec97bd1bd3f1344aabefaeff4a6da181

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyondsel-0.0.3-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyondsel-0.0.3-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2fc8bb63d1ead1e9c90066c86357994d87d2224aacc6508af246bbc9bf4248b3
MD5 d8f4fbdb0aafc7dfae4c08396fce9d64
BLAKE2b-256 9c6ca4f8f6907899a0f7e9c1f2b460436d21d6b6336fc312b20c69c5cf4914c9

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyondsel-0.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyondsel-0.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4783b000a462f204b57c35716fbfcf6e926918715437fe4d021a8eeff9a34057
MD5 4ccabc2ff9959456412005ea3b258398
BLAKE2b-256 dec5430c998bbb71669756b82249195c00a31805ea41e6b6a38a95dc5534b412

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyondsel-0.0.3-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyondsel-0.0.3-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ea28350d007abc7e7c039981f5bdf6f35831a82e191dc17a0a35c0e1c3d2c2ea
MD5 d60efbdf6ff65848b558935bf473e550
BLAKE2b-256 611a5173367a6be6fc80df285c5ac7da9dade262bc1c0e5d12f756c05ce7c2f2

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.0.3 This release

9 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page