Skip to main content

screws

Screw-theory robotics in Python, after Lynch and Park, Modern Robotics (MR). screws is the MR code library reorganised: the same mathematics under snake_case names, MR's own names kept as aliases, a Robot class, a URDF loader, robots that ship ready to use, and a bridge to CoppeliaSim.

Install

uv add screws                 # the mathematics: numpy is the only dependency
uv add "screws[coppelia]"     # plus the CoppeliaSim ZMQ remote API client

Four lines

import screws as sc

ur5 = sc.robots.ur5()                              # M, screw axes, inertias from the textbook's URDF
T = ur5.fk([0.3, -1.2, 0.8, -0.4, 1.1, 0.2])         # a reachable, non-singular pose
result = ur5.ik(T, theta0=[0.1, -1.4, 0.1, 0.1, 1.4, 0.1])   # result.theta, result.converged, result.history

The free functions are the reference implementation and read as the book does: sc.exp6(sc.vec_to_se3(S * theta)) is $e^{[\mathcal{S}]\theta}$, sc.fk_space(M, S, theta) is the space form of the product of exponentials, and sc.FKinSpace is the very same function under MR's name.

Screw-axis lists are 6xn, one axis per column, as MR writes them. Nothing guesses the orientation (a 6x6 array is ambiguous for a six-axis arm), so hand entry goes through a sequence of 6-vectors: sc.Robot.from_screw_axes(M, [S1, S2, ...]).

Check your own code against the library

import numpy as np
import screws as sc

def my_exp6(se3mat): ...                          # your implementation

rng = np.random.default_rng(0)
cases = [sc.vec_to_se3(rng.normal(size=6)) for _ in range(20)]
sc.testing.check(my_exp6, sc.exp6, cases)          # raises on the first disagreement

CoppeliaSim

Works with CoppeliaSim 4.9 or later through the ZMQ remote API (0.1 verified on 4.10.0).

from screws.coppelia import Scene

with Scene() as scene:                 # connects to localhost:23000 in stepping mode
    arm = scene.arm("/UR5")            # the joints under that tree, base to tip
    robot = arm.robot()                # a screws.Robot read off the scene at zero
    arm.mode("position")
    log = scene.run(lambda t, theta, dtheta: theta_desired(t), duration=5.0, arm=arm)
log.plot()

Scene owns the connection and the clock (start, step, stop, time, dt, frame, show_frame). Arm reads (theta, dtheta, tau, tip_frame) and commands in one of three modes (position, velocity, torque), or teleports without physics to animate an IK history. Arm.robot() derives M and the screw axes from the scene's joint frames (omega is the joint's z axis, v = -omega x q). Scene inertias arrive in 0.2.

Two UR5s

sc.robots.ur5() is built from the URDF the textbook prints in section 4.2: the manufacturer's lengths and the printed inertias, the closest published match to the simulator's model. sc.robots.ur5(source="textbook") is the rounded table of MR Figure 4.6 with no inertias. They differ in the third decimal of the $v$ entries, and the course notes' problems ask why.

Names

Modern Robotics screws
NearZero near_zero
Normalize normalize
RotInv rot_inv
VecToso3 vec_to_so3
so3ToVec so3_to_vec
AxisAng3 axis_angle3
MatrixExp3 exp3
MatrixLog3 log3
RpToTrans rp_to_transform
TransToRp transform_to_rp
TransInv transform_inv
VecTose3 vec_to_se3
se3ToVec se3_to_vec
Adjoint adjoint
ScrewToAxis screw_axis
AxisAng6 axis_angle6
MatrixExp6 exp6
MatrixLog6 log6
ProjectToSO3 project_so3
ProjectToSE3 project_se3
DistanceToSO3 distance_so3
DistanceToSE3 distance_se3
TestIfSO3 is_so3
TestIfSE3 is_se3
FKinBody fk_body
FKinSpace fk_space
JacobianBody jacobian_body
JacobianSpace jacobian_space
IKinBody ik_body
IKinSpace ik_space

Where a screws function's signature matches MR's, the alias is that function (sc.FKinSpace is sc.fk_space). IKinBody and IKinSpace are thin wrappers that return MR's (thetalist, success) tuple; the primaries return an IKResult with the iteration history. No deprecation warnings, ever.

Licence

MIT. Portions derived from the Modern Robotics code library, copyright 2018 Huan Weng, Bill Hunt, Jarvis Schultz and Mikhail Todes, MIT licence; see LICENSE.

Release files for screws 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for screws 0.1.0
File Size Uploaded
screws-0.1.0.tar.gz 178.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for screws 0.1.0
File Interpreter ABI Platform
screws-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 210.6 kB

Release files / screws-0.1.0.tar.gz

Download URL screws-0.1.0.tar.gz
Size 178.4 kB
Tags Source
SHA-256 checksum
How to use checksums
2ffd5b395588b00f7c17d86c348024ba38fe055b571cacdc8024dd54d7971e12
BLAKE2b-256 checksum
How to use checksums
d85c90bfdb041b7e47434248e69773977b51a5a9a66aefb3b334c27bf08ae634
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.

Transparency log

Release files / screws-0.1.0-py3-none-any.whl

Download URL screws-0.1.0-py3-none-any.whl
Size 32.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
49b3f0da0dd655e5b3b7f2c7a47f4471d359802106667ea130dcfcac23cc5def
BLAKE2b-256 checksum
How to use checksums
84a6f69b053659196504960ff5fd10974203dd2dc459657301873f7d7a3a1ec7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 27, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page