Skip to main content

GitHub  •  LinkedIn  •  X  •  Discord

Telekinesis Axon

Telekinesis Axon is a camera calibration library for the Telekinesis ecosystem, with a C++ core (targets, calibration, geometry, quality) exposed to Python via pybind11. It supports intrinsic calibration, eye-in-hand (hand-eye) extrinsic calibration, multi-camera extrinsic calibration, and benchmarking, built on OpenCV.

The hardware-driving runtime layer (DataCollector, PerturbationSampler) stays pure Python — camera/robot SDKs are inherently async/IO-bound and don't benefit from a native rewrite.

Installation

pip install telekinesis-axon

Ships as a prebuilt wheel (Linux/Windows, Python 3.11/3.12) from Telekinesis's private package registry — no C++ toolchain needed. If you're building from source instead (e.g. contributing to axon itself), see DEVELOPMENT.md.

Targets

Define your calibration board once and pass it to any calibrator:

from telekinesis.axon.targets import ChessboardTarget, CharucoTarget, ArucoTarget

chessboard = ChessboardTarget(size=(9, 6), square_size=0.025)  # meters

charuco = CharucoTarget(
    squares_x=6,
    squares_y=9,
    square_length=0.012,
    marker_length=0.009,
    aruco_dict_id="DICT_4X4_1000",  # or the raw cv2.aruco.DICT_4X4_1000 int
)

aruco = ArucoTarget(
    board_size=(5, 7),
    marker_length=0.025,
    marker_separation=0.005,
)

Intrinsic Calibration

A single IntrinsicCalibrator dispatches on the target type you pass it — no more separate ArucoIntrinsicCalibrator / CharucoIntrinsicCalibrator subclasses or an IntrinsicBackend indirection:

from telekinesis.axon import IntrinsicCalibrator, IntrinsicOptions
from telekinesis.axon.targets import CharucoTarget

target = CharucoTarget(squares_x=6, squares_y=9, square_length=0.012, marker_length=0.009)

options = IntrinsicOptions()
options.per_view_error_threshold = 0.8

calibrator = IntrinsicCalibrator(target, options)
result = calibrator.calibrate(images)

result.ok                     # bool
result.intrinsic_matrix       # (3, 3) np.ndarray
result.distortion_coefficients
result.reprojection_error
result.successful_indices
result.low_view_error_indices

Eye-in-Hand Calibration

Calibrate the transform between the camera and the robot TCP. Requires images of a calibration board alongside the robot's TCP pose (robot_T_tcp as 4×4 homogeneous matrices) for each frame.

from telekinesis.axon import EyeInHandCalibrator
from telekinesis.axon.targets import CharucoTarget

target = CharucoTarget(squares_x=6, squares_y=9, square_length=0.012, marker_length=0.009)

calibrator = EyeInHandCalibrator(target)

result = calibrator.calibrate(
    robot_T_tcp_list=robot_poses,  # list of (4, 4) np.ndarray
    image_list=images,
    method="TSAI",
)

result.ok               # bool
result.tcp_T_camera     # (4, 4) np.ndarray
result.intrinsic_matrix
result.distortion_coefficients
result.reprojection_error
result.consistency       # TargetConsistencyStats, when result.has_consistency

Pass pre-computed per-frame poses

If you have camera_T_target transforms from an external source, pass them via camera_T_target_list to skip EyeInHandCalibrator's internal solvePnP. The caller is responsible for aligning robot_T_tcp_list and image_list to it.

result = calibrator.calibrate(
    robot_T_tcp_list=robot_poses,
    image_list=images,
    camera_T_target_list=external_camera_T_target_list,
    intrinsic_matrix=K,
    distortion_coefficients=d,
)

Multi-Camera Calibration

Calibrate N ≥ 2 synchronized cameras against a reference camera via pairwise cv::stereoCalibrate, with an automatic triangulation validation pass:

from telekinesis.axon import MultiCameraCalibrator
from telekinesis.axon.targets import CharucoTarget

target = CharucoTarget(squares_x=6, squares_y=9, square_length=0.012, marker_length=0.009)

calibrator = MultiCameraCalibrator(target, num_cameras=3, reference_index=1)
result = calibrator.calibrate(image_lists)  # image_lists[cam][frame]

result.ok                          # True iff every non-reference pair solved
result.reference_T_camera_list     # per-camera (4, 4) np.ndarray
result.intrinsic_matrices
result.pair_reprojection_errors

Benchmarking

Cross-validate a target/IntrinsicOptions configuration and, optionally, a hand-eye round trip:

from telekinesis.axon import CalibrationBenchmark, IntrinsicOptions
from telekinesis.axon.targets import CharucoTarget

target = CharucoTarget(squares_x=6, squares_y=9, square_length=0.012, marker_length=0.009)

bench = CalibrationBenchmark()
result = bench.run(
    images=my_images,
    target=target,
    options=IntrinsicOptions(),
    robot_poses=my_robot_poses,             # optional — enables the round-trip metric
    eye_in_hand_options=IntrinsicOptions(), # optional
    n_splits=5,
)
CalibrationBenchmark.save_json([result], "calibration_benchmark.json")
print(CalibrationBenchmark.format_results([result]))

Output (calibration_benchmark.json):

{
  "run_timestamp": "2026-05-18T...",
  "results": [
    {
      "backend_name": "OpenCV",
      "reprojection_error": 0.42,
      "held_out_reprojection_error": 0.61,
      "hand_eye_roundtrip_error": 1.3,
      "camera_matrix": [[fx, 0, cx], [0, fy, cy], [0, 0, 1]],
      "dist_coeffs": [...]
    }
  ]
}

Resources

Support

License

Proprietary — © Telekinesis. All rights reserved.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

telekinesis_axon-0.2.1-cp312-cp312-win_amd64.whl (47.3 MB view details)

Uploaded CPython 3.12Windows x86-64

telekinesis_axon-0.2.1-cp312-cp312-manylinux_2_39_x86_64.whl (77.1 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.39+ x86-64

telekinesis_axon-0.2.1-cp311-cp311-win_amd64.whl (47.3 MB view details)

Uploaded CPython 3.11Windows x86-64

telekinesis_axon-0.2.1-cp311-cp311-manylinux_2_39_x86_64.whl (77.1 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.39+ x86-64

File details

Details for the file telekinesis_axon-0.2.1-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for telekinesis_axon-0.2.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 553430fcf3bc331b77a93bd7a09da263624b7008ffedca7454fd9c083dd9394a
MD5 403e971b7f233898a30a669333b20a00
BLAKE2b-256 3d2998f711b7b35917fd912aa626c9249dca69a265685e52acf3acd3c4c0b643

See more details on using hashes here.

File details

Details for the file telekinesis_axon-0.2.1-cp312-cp312-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for telekinesis_axon-0.2.1-cp312-cp312-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 277ff15cabb5d91811570ec204bb85e3ca64fa9b0fc7341ad5b6eee8bc9d4903
MD5 33bdc04793b95a1e0e5896deb4f79e6a
BLAKE2b-256 080cf33419d79bb2530b6795875a88e51c50e7858e849e3b2767264da23f13b8

See more details on using hashes here.

File details

Details for the file telekinesis_axon-0.2.1-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for telekinesis_axon-0.2.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 1c439b2fc296754870f78b50a9ac8a88190c55f97484b6863b3b88ee011bf9e4
MD5 d6167869707c5b91c0afefb269b23113
BLAKE2b-256 1d83ea4be03a2e95ba83ddd11fb104fda8111ffa2a72839c7a58c21c514c029a

See more details on using hashes here.

File details

Details for the file telekinesis_axon-0.2.1-cp311-cp311-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for telekinesis_axon-0.2.1-cp311-cp311-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 e78391459c12b73d6813ce235320eb517f1f508d403cd5e6a749736ab962e93a
MD5 44c338ee5de287415b36b83977f7d910
BLAKE2b-256 724fbefc8686196010c81322877943daf7d296b02b21f9213f0669e9090c7a71

See more details on using hashes here.

Supported by

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