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
from telekinesis import axon
collector = axon.DataCollector(
robot,
cameras,
target,
sampler,
min_corners=12,
require_all_cameras=True,
settle_time=2.0,
)The Code
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) matricesInitialization
| Parameter | Type | Description |
|---|---|---|
robot | object | Robot object exposing set_cartesian_pose and get_cartesian_pose. |
cameras | list | Camera objects, each must implement either capture_color_image() -> ndarray or the Medulla capture_image() -> Image | ndarray API. |
target | Target | Calibration target, any of ChessboardTarget, CharucoTarget, or ArucoTarget. Used to check each frame has at least min_corners detectable corners before it is saved. |
sampler | PerturbationSampler | Or any iterable yielding (home_pose_deg, [capture_pose_deg, ...]) groups, see PerturbationSampler. |
min_corners | int | Minimum detected corners per camera per frame for a pose to be kept. Default 12. |
require_all_cameras | bool | Skip a frame unless every camera meets min_corners. Default True. |
settle_time | float | Seconds 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
| Skill | Description |
|---|---|
| Collect | Capture 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.
| Setting | Guidance | Why |
|---|---|---|
settle_time | Tune to your robot rather than keeping the 2.0 default | A 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_corners | Raise it if TargetConsistencyStats shows real deviation despite a large dataset | A low threshold admits marginal detections (few corners, grazing angles) that add noise out of proportion to their count. |
require_all_cameras | Keep True for multi-camera rigs | Dropping it lets cameras miss frames, and MultiCameraCalibrator.calibrate() expects equal per-camera frame counts, so gaps must be reconciled first. |
wipe | Leave False to build a session incrementally | collect() 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. |
| Lighting | Keep it consistent for the whole session | Drifting 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. |