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.0-cp312-cp312-win_amd64.whl (47.3 MB view details)

Uploaded CPython 3.12Windows x86-64

telekinesis_axon-0.2.0-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.0-cp311-cp311-win_amd64.whl (47.3 MB view details)

Uploaded CPython 3.11Windows x86-64

telekinesis_axon-0.2.0-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.0-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for telekinesis_axon-0.2.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 c8314c701fb5e04d3281e96f80d63865507ea60ed9f632f7da2f12728d90d1e8
MD5 13dc82ad15457da4bd2705443b475e67
BLAKE2b-256 63af95bf75823d64c0d080defec0afc653148f2e162327ce731b286e96fd2b9d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for telekinesis_axon-0.2.0-cp312-cp312-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 beb4ebf688d5863459dc0b60e955fe8f13bad06d82742203967ba17fa80754f2
MD5 2f3e991355c668d48e41d3ddc94d60f8
BLAKE2b-256 06331af817365491356c66e29397ecd806e7c416d78ccda7944b42fc4b584b2a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for telekinesis_axon-0.2.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 db297ef52325afefbef6303b95a2e73bb50aafd2f0fde49d61242fb02cdc915a
MD5 44d3ccb76ce00211335c8a02d8df4877
BLAKE2b-256 03f6136b4491eafbe293ef318953d5f404e081e1a3868a8053291fb8762eab79

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for telekinesis_axon-0.2.0-cp311-cp311-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 17bcd84ab4d46c886a784307b2779bc1387ac46d88a35406741960a6b857b7a6
MD5 29bd87f7fb65196f9765654b38c46815
BLAKE2b-256 eefef9b9d324224e21b7ec7580b6b6bb204e5342c6b00b496c5074377b6a6500

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