py-ikgeo-kinematics
Forward and inverse kinematics for six-axis robot arms, including arms with
non-spherical wrists such as the Comau NJ4. The solver uses IK-Geo subproblem
decomposition in Rust, with a Python API based on NumPy and SciPy
RigidTransform.
The main tested models are the Comau NJ4-220-3.0 and OPW-compatible arms. Other geometries use the detected IK-Geo family; search-based solvers can miss valid solutions.
Install
pip install py-ikgeo-kinematics
Build from source
Install Rust and uv, then run from this checkout:
uv sync --extra test
uv run --with maturin maturin develop --release
Python 3.11–3.14 is covered by the CI configuration. The extension uses PyO3
0.27, which does not support Python 3.15. To choose an interpreter explicitly,
use uv sync --python 3.14 --extra test.
Solve a pose
This example uses the OPW conversion helper. For a non-spherical wrist, pass
axis directions and offsets directly to KinematicModel(h, p), as in the
Comau NJ4 example.
import numpy as np
from py_ikgeo_kinematics import KinematicModel, Robot
model = KinematicModel.from_opw(
a1=0.1, c1=0.2, c2=0.3, c3=0.25, c4=0.05,
)
robot = Robot(model, degrees=True)
joints = (20.0, 30.0, -40.0, 10.0, 50.0, -20.0)
pose = robot.forward(joints)
solutions = robot.inverse(pose, current_joints=joints)
assert solutions
np.testing.assert_allclose(
robot.forward(solutions[0]).as_matrix(), pose.as_matrix(), atol=1e-9,
)
poses = robot.batch_forward(np.array([joints, joints]))
path = robot.batch_inverse(poses, current_joints=joints) # Shape (2, 6).
reach = robot.reach(poses)
print(robot.family, reach.n_solutions)
Model and units
h has shape (3, 6). Each column is a joint axis direction in the zero pose;
nonzero directions are normalized. p has shape (3, 7), with columns for the
base-to-J1 offset, the five offsets between joints, and the J6-to-flange offset.
Both use a common coordinate frame at the zero pose.
All lengths use the model's unit. The example above uses metres; the NJ4
example uses millimetres. Joint angles and model offsets use degrees by
default, or radians with Robot(model, degrees=False). Internally,
q = sign * joint - offset, where flip_axes=True selects a negative sign.
Model values must be finite, and axis directions must be nonzero. The model's
h and p getters return read-only NumPy copies. Build a new model to change
geometry.
axis_tolerance defaults to 1e-9: radians for parallelism and a fraction of
the longest offset for intersections. robot.axis_report() shows the measured
deviations. Raising the tolerance lets the solver treat nearly parallel or
intersecting axes as exact relations; returned roots are checked against the
original model. A general family emits a warning because its 2D search is
slow and can miss roots.
API
Public pose inputs and outputs are SciPy RigidTransform objects. Use
.as_matrix() for (4, 4) or (n, 4, 4) NumPy matrices. Flattened (n, 16)
arrays belong to the internal extension API.
| Method | Result |
|---|---|
forward(joints) |
One flange or TCP pose. |
batch_forward(joints) |
A stack of poses for (n, 6) joints. |
inverse(pose, current_joints=None) |
Up to 16 solutions as six-element tuples. An empty list means no root was found. |
batch_inverse(poses, current_joints=None) |
A tracked joint path, shape (n, 6). Failed poses produce NaN rows. |
joint_poses(joints) |
Six joint frames, plus TCP when a tool is supplied. |
batch_joint_poses(joints) |
The joint frames stacked in pose order. |
forward_frames(joints) |
Base, six joint frames, and TCP. |
jacobian(joints) |
A (6, 6) geometric Jacobian, translation rows first, per radian. |
reach(poses, joint_limits=None, threads=1) |
Solutions and margins described below. |
These methods accept an optional ee_transform as a RigidTransform. For
compatibility with py-opw-kinematics, a tool with rotation R and translation
t uses R @ t as its flange-frame offset. This differs from ordinary
homogeneous-transform composition when both rotation and translation are set.
inverse unwraps joints near current_joints and sorts by summed absolute
joint distance. Without a seed it uses zero. batch_inverse follows the
previous solution by Newton continuation and falls back to the nearest cold
root when tracking fails. It can therefore choose a different valid branch
from a loop over inverse. Failed rows leave the last valid seed intact.
Neither method filters joint limits.
Batch joint inputs also accept pandas or Polars DataFrames with columns
J1 through J6. A DataFrame seed for batch_inverse produces the same type
of DataFrame. interpolate_poses(x, poses, xn) combines linear translation
interpolation with rotation SLERP.
Reach results
reach returns a frozen ReachResult; its NumPy arrays remain mutable.
threads=1 runs serially, and threads=0 uses the available cores. The GIL is
released during the solve.
| Field | Shape | Meaning |
|---|---|---|
joints |
(n, 16, 6) |
Found solutions, with NaN rows in unused slots. |
n_solutions |
(n,) |
Number of populated slots. |
limit_margin |
(n, 16) |
Minimum distance to a joint bound; negative outside, +inf without limits. |
sigma_min |
(n, 16) |
Smallest Jacobian singular value; NaN for empty or out-of-limit branches. |
wrist |
(n, 16) |
Angular distance to the nearest wrist fold, in the robot's angle unit. |
extension |
(n,) |
Signed distance to the shoulder annulus, in model length units; NaN when axes 2 and 3 are not parallel. |
joint_limits has shape (6, 2) and uses the robot's angle unit. Margins use
joints normalized to (-180, 180], or (-pi, pi] in radians. Limits report
usability; they do not remove solutions. Branch columns are deterministic
within a pose but do not promise continuity between poses. Consumers must
track branches themselves.
The wrist margin differs from py-opw's dimensionless margin: for an
orthogonal wrist, the sine of this angle in radians equals py-opw's value.
At an NJ4 wrist fold, wrist can be zero while the full arm Jacobian still
has rank six. sigma_min also depends on the model's length unit.
Limits of the solver
Returned roots are checked against forward kinematics. This checks their accuracy, not whether every root was found. NJ4 and OPW models have dedicated regression and completeness tests. Some other 1D search families miss roots, and the general 2D search has lower coverage. An empty result alone does not prove that a pose is unreachable.
The NJ4 example checks geometry against the working-area drawing. Wrist joint signs and the controller's J3 convention still need confirmation on the machine. Controller validation and downstream integration are outside this repository.
Development
uv run --with maturin maturin develop --release
cargo test -p ikgeo --release
uv run pytest
uv run mypy python
uvx ruff check .
cargo fmt --check
PYO3_PYTHON="$PWD/.venv/bin/python" cargo clippy --workspace --all-targets -- -D warnings
CI builds and tests wheels for Linux x86_64, Linux ARM64, Windows x64 and
macOS ARM64 on Python 3.11–3.14. These checks run on pull requests, pushes to
main, and manual dispatch. Version tags stamp Cargo.toml, create a GitHub
release and upload to PyPI after all checks pass; the upload runs while the
PUBLISH_TO_PYPI repository variable is true. Local PEP 517 builds take a
git describe version, while a bare maturin develop reports 0.0.0; in a
consumer checkout, use uv run --no-sync to avoid replacing a locally
installed build with the locked wheel.
PLAN.md records design decisions and remaining integration work. The bindings use the MIT license; the vendored solver uses BSD-3-Clause, with provenance in ikgeo/NOTICE.
Metadata
Release files for py-ikgeo-kinematics 0.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| py_ikgeo_kinematics-0.0.2.tar.gz | 382.4 kB | Details |
Built distributions (wheels)
Total release size: 8.7 MB
Release files / py_ikgeo_kinematics-0.0.2.tar.gz
| Download URL | py_ikgeo_kinematics-0.0.2.tar.gz |
|---|---|
| Size | 382.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5456728928e0f271cffa6848d17b25247626925e0563f2c0f25dbf680f72d0e1
|
|
BLAKE2b-256 checksum How to use checksums |
30d96c5aac434f885b1bb3e3ab7eacf6cb05139efa30e220fe033408d123f8d4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp314-cp314-win_amd64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp314-cp314-win_amd64.whl |
|---|---|
| Size | 412.6 kB |
| Tags | CPython 3.14 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
c2017aed105823a49403e07a3ac36878757bd18022a29ad6fd9f0b99194fae06
|
|
BLAKE2b-256 checksum How to use checksums |
d8d1162147bf8f3e7304e16d76baac46f76492a20ba915f3bf1e0c6d613109b1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 587.8 kB |
| Tags | CPython 3.14 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
6ff7608419a7aac6100af701ea6ba3ecdd56964589a8fef57f2e4c20fe5a4ae4
|
|
BLAKE2b-256 checksum How to use checksums |
ca7ee66fcf3269f8fa703caeec69d49fab7448c8d2dc095cbbf4cd4b95847767
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 563.9 kB |
| Tags | CPython 3.14 Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
083783bd7bbf55c372d736eac0b868f4d903d5ae0ff994fff6f67f55e27b4c04
|
|
BLAKE2b-256 checksum How to use checksums |
43cf0ba19e352cd7d21a4437514332a796805e3a2ce3ad80310b6d58771b79b9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp314-cp314-macosx_11_0_arm64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp314-cp314-macosx_11_0_arm64.whl |
|---|---|
| Size | 508.4 kB |
| Tags | CPython 3.14 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
585840c704c1d2ebd2178872f0e6ea0ba07529de75cc968c5a29ee92542735ab
|
|
BLAKE2b-256 checksum How to use checksums |
a190c4424a8c6bc38c8e168cc80ed8ecb5824b2baa596dde54b19c0ec6cf71dd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp313-cp313-win_amd64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 405.8 kB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
441f71875b9a6fe03f728f1594c475f472df9451f39696dc602aa38f7fcb8586
|
|
BLAKE2b-256 checksum How to use checksums |
1299f165c193cdac314eed4588d288e4e6886e0aa82251858f67c6b5724fa042
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 588.6 kB |
| Tags | CPython 3.13 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
908045bd475f20446732b63b37b1831d4f12c6cd87fcff065c041547a6fc5956
|
|
BLAKE2b-256 checksum How to use checksums |
c17fb4ef57552ab66768065af6855a5104ca56aa2ebbb262c2c25c37f2ad5cc7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 563.6 kB |
| Tags | CPython 3.13 Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
0d1c83efca526960779dcc3cbe994177c7fc57aeb1c63b05542739d00dde3a97
|
|
BLAKE2b-256 checksum How to use checksums |
d13f7ce34fff4f01d8025f0a9476f7b556295953338eb36192c4089151eb87b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp313-cp313-macosx_11_0_arm64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp313-cp313-macosx_11_0_arm64.whl |
|---|---|
| Size | 508.9 kB |
| Tags | CPython 3.13 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
7327b7de9c6085e012341bc3cf769c8ffde09433d9e7afb486a64e0d9b6dac40
|
|
BLAKE2b-256 checksum How to use checksums |
484303f8d9a8e27d97199d4580ecf46eba79fecea178f91e8431dbd22d91c114
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp312-cp312-win_amd64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 412.7 kB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
70ca39371c5bb280b6bd3fa975cdecb2fdff46f46905658cc7e1f90113ad5b55
|
|
BLAKE2b-256 checksum How to use checksums |
a37cd2e180822089fa823057a5de0a2d781b682ab83d866a41a1316dfeafaad1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 589.0 kB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
50dfcf54a129d1c763802c72e1619a9f8cddcb851547b9cfdcf35367eea4cfd8
|
|
BLAKE2b-256 checksum How to use checksums |
cc4e840d48034a0c70b2914ce8c920b441e0fef3b1e1a3000de88e5cb92d9bd3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 564.1 kB |
| Tags | CPython 3.12 Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
6460c25d356d2a0d7eda16ded8d9af8b7ddeaf22c7c18678cdc9e18027fc71f5
|
|
BLAKE2b-256 checksum How to use checksums |
a81e1356251133ed5b9ab9ec7011fa773419fe984be7eb49dfb97db4d3cbb65b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 508.8 kB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
456ccc3e2aa871a4b16e9c729f21296f1da83f743a16c837b6e924732a089d39
|
|
BLAKE2b-256 checksum How to use checksums |
cc96563de2420d28caa66e0d35b0111d568944796f0ac822e5af177915e8e1a1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp311-cp311-win_amd64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 413.9 kB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
023a0ab99f58eeffc5bb7abdda488cd0c7593d43db25ce26356704f3f0d7b4a7
|
|
BLAKE2b-256 checksum How to use checksums |
bc45f6beb5fc96c7eb793b605dde1c1821bd35c8cae9b68551e021afca38e68a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 591.4 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
ba43c2cec5e1c73bda147be0d70e50d727e32ad63f21b94f8709fcf8cfdc9c17
|
|
BLAKE2b-256 checksum How to use checksums |
bf2f455f1913e74a29946859a213a5b0b3b03fbdc8008fb1547fc2d8a92f76c0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 566.8 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
c3b83f8904d8cc3ecdb937cc45ca89edfea1298962dc4404123986b9efd5ad5b
|
|
BLAKE2b-256 checksum How to use checksums |
096af0f75fd26f7cf3db04131fb8107aa6745f7ec6a162ef1247eac7dc18c412
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|
Release files / py_ikgeo_kinematics-0.0.2-cp311-cp311-macosx_11_0_arm64.whl
| Download URL | py_ikgeo_kinematics-0.0.2-cp311-cp311-macosx_11_0_arm64.whl |
|---|---|
| Size | 511.6 kB |
| Tags | CPython 3.11 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
324c43e1034e98013efd880ef84091ba2bb1ff140cd3b4cf709386db82b2fb63
|
|
BLAKE2b-256 checksum How to use checksums |
05b2fc48184299cbb459a3b5e64e3e7427e8a9d9a1b959275f40fef4ec9faa65
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.15.0
|