Skip to content

DataCollector

SUMMARY

DataCollector drives a robot through a sweep of poses generated by PerturbationSampler, capturing a synchronized frame from every camera at each pose and saving a calibration dataset ready for EyeInHandCalibrator or MultiCameraCalibrator.

The Skill

python
from telekinesis import axon

collector = axon.DataCollector(
    robot,
    cameras,
    target,
    sampler,
    min_corners=12,
    require_all_cameras=True,
    settle_time=2.0,
)

The Code

python
from telekinesis import axon

collector = axon.DataCollector(
    robot,
    cameras,
    target,
    sampler,
    min_corners=12,
    require_all_cameras=True,
    settle_time=2.0,
)

result = collector.collect(data_dir, wipe=False)

result["ok"]                # True once at least 4 frames were captured
result["images"]            # images[cam_idx][frame_idx]
result["robot_T_tcp_list"]  # list of (4, 4) SE(3) matrices

Initialization

ParameterTypeDescription
robotobjectRobot object exposing set_cartesian_pose and get_cartesian_pose.
cameraslistCamera objects, each must implement either capture_color_image() -> ndarray or the Medulla capture_image() -> Image | ndarray API.
targetTargetCalibration target, any of ChessboardTarget, CharucoTarget, or ArucoTarget. Used to check each frame has at least min_corners detectable corners before it is saved.
samplerPerturbationSamplerOr any iterable yielding (home_pose_deg, [capture_pose_deg, ...]) groups, see PerturbationSampler.
min_cornersintMinimum detected corners per camera per frame for a pose to be kept. Default 12.
require_all_camerasboolSkip a frame unless every camera meets min_corners. Default True.
settle_timefloatSeconds to wait after each robot move before capturing. Default 2.0.

Frames are normalized to 3-channel BGR before saving, 4-channel frames are flattened and RGB frames are swapped, using the camera's OutputPixelFormat parameter when it exposes one, so Medulla/IDS cameras work with no extra wrapper.

Skills

SkillDescription
CollectCapture frames for every pose in the sampler and save a calibration dataset to disk.

Best Practices

CHECK THE SWEEP BOUNDS FIRST

PerturbationSampler's rotation_deg and translation_m are offsets from each home pose. Set them too wide relative to the home pose's clearance from joint limits or obstacles, and the generated set_cartesian_pose calls can fail or drive the robot somewhere unintended. Start conservative, then widen once you've confirmed the home pose has room on every side.

SettingGuidanceWhy
settle_timeTune to your robot rather than keeping the 2.0 defaultA stiff arm settles sooner; a fast move on a light arm may still be vibrating at 2 s. Capturing early yields motion blur or a slightly wrong pose, which degrades calibration silently instead of raising an error.
min_cornersRaise it if TargetConsistencyStats shows real deviation despite a large datasetA low threshold admits marginal detections (few corners, grazing angles) that add noise out of proportion to their count.
require_all_camerasKeep True for multi-camera rigsDropping it lets cameras miss frames, and MultiCameraCalibrator.calibrate() expects equal per-camera frame counts, so gaps must be reconciled first.
wipeLeave False to build a session incrementallycollect() resumes from next_multi_camera_capture_index, so a run interrupted by a robot fault can restart against the same data_dir instead of starting over.
LightingKeep it consistent for the whole sessionDrifting from daylight to artificial light, or crossing a shadow partway through, changes detection quality pose-to-pose in a way that is hard to separate from real calibration error afterward.