### Complete UR5 + Kinect Eye-on-Base Example Launch File Source: https://context7.com/ifl-camp/easy_handeye/llms.txt This launch file demonstrates the setup for eye-on-base calibration using a UR5 robot and a Kinect camera with ArUco markers. It includes nodes for camera, ArUco detection, robot bringup, MoveIt!, and the easy_handeye calibration process. Ensure to provide the robot's IP address, marker size, and marker ID as arguments. ```xml ``` -------------------------------- ### Install dependencies Source: https://github.com/ifl-camp/easy_handeye/blob/master/README.md Satisfy the package dependencies using rosdep. ```bash cd .. # now we are inside ~/catkin_ws rosdep install -iyr --from-paths src ``` -------------------------------- ### Clone the repository Source: https://github.com/ifl-camp/easy_handeye/blob/master/README.md Clone this repository into your catkin workspace to get started. ```bash cd ~/catkin_ws/src # replace with path to your workspace git clone https://github.com/IFL-CAMP/easy_handeye ``` -------------------------------- ### Build the workspace Source: https://github.com/ifl-camp/easy_handeye/blob/master/README.md Build your catkin workspace after cloning the repository and installing dependencies. ```bash catkin build ``` -------------------------------- ### CMakeLists.txt for rqt_easy_handeye Source: https://github.com/ifl-camp/easy_handeye/blob/master/rqt_easy_handeye/CMakeLists.txt Defines the build and installation rules for the rqt_easy_handeye ROS package. It sets up Python scripts and installs plugin and resource files. ```cmake cmake_minimum_required(VERSION 3.0.2) project(rqt_easy_handeye) find_package(catkin REQUIRED) catkin_python_setup() catkin_package() catkin_install_python(PROGRAMS scripts/rqt_calibration_evaluator scripts/rqt_calibrationmovements scripts/${PROJECT_NAME} DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} ) install(FILES plugin.xml DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} ) install(DIRECTORY resource DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} ) ``` -------------------------------- ### Eye-on-Hand Calibration Launch Configuration Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Launches the calibration process for eye-on-hand scenarios. Ensure robot and tracking system drivers are started first. Configure robot and tracking tf frames, and movement parameters for automatic sampling. ```xml ``` -------------------------------- ### Take Calibration Sample Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Calls the 'take_sample' ROS service to capture current robot and tracking system transforms. Requires the robot to be in position and the marker to be visible. ```bash # Take a sample using rosservice rosservice call /my_robot_kinect_calib_eye_on_base/take_sample ``` ```yaml # Response contains the updated sample list: samples: hand_world_samples: - translation: {x: 0.5, y: 0.2, z: 0.3} rotation: {x: 0.0, y: 0.0, z: 0.0, w: 1.0} camera_marker_samples: - translation: {x: 0.1, y: 0.05, z: 0.8} rotation: {x: 0.0, y: 0.0, z: 0.707, w: 0.707} ``` -------------------------------- ### Python API: HandeyeCalibration - Initialization and File Operations Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Demonstrates how to create, save, and load HandeyeCalibration objects using parameters and a known transformation. Serialization to and from YAML files is supported. ```python #!/usr/bin/env python from easy_handeye.handeye_calibration import HandeyeCalibration, HandeyeCalibrationParameters # Create calibration parameters params = HandeyeCalibrationParameters( namespace='/my_calib/', move_group='manipulator', eye_on_hand=False, robot_base_frame='base_link', robot_effector_frame='tool0', tracking_base_frame='camera_link', tracking_marker_frame='marker', freehand_robot_movement=False ) # Create calibration with known transformation # Translation (x, y, z) and Quaternion (x, y, z, w) transformation = ((0.85, -0.12, 1.23), (0.5, -0.5, 0.5, -0.5)) calibration = HandeyeCalibration( calibration_parameters=params, transformation=transformation ) # Save to file HandeyeCalibration.to_file(calibration) # Saved to: ~/.ros/easy_handeye/my_calib.yaml # Load from file loaded_calib = HandeyeCalibration.from_file('/my_calib/') # Convert to YAML string yaml_string = HandeyeCalibration.to_yaml(calibration) print(yaml_string) # Load from YAML string calib_from_yaml = HandeyeCalibration.from_yaml(yaml_string) # Access transformation data t = calibration.transformation.transform print(f"X: {t.translation.x}, Y: {t.translation.y}, Z: {t.translation.z}") print(f"Quaternion: ({t.rotation.x}, {t.rotation.y}, {t.rotation.z}, {t.rotation.w})") ``` -------------------------------- ### Python API: HandeyeClient Initialization and Algorithm Management Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Initializes the HandeyeClient for programmatic access to the calibration server and demonstrates listing and setting calibration algorithms. Requires rospy and the easy_handeye library. ```python #!/usr/bin/env python import rospy from easy_handeye.handeye_client import HandeyeClient rospy.init_node('handeye_calibration_script') # Initialize client with calibration namespace client = HandeyeClient(namespace='/my_robot_kinect_calib_eye_on_base/') # List and set calibration algorithm algorithms = client.list_algorithms() print("Available algorithms:", algorithms.algorithms) print("Current algorithm:", algorithms.current_algorithm) client.set_algorithm('OpenCV/Park') ``` -------------------------------- ### Include eye-on-base calibration launch file Source: https://github.com/ifl-camp/easy_handeye/blob/master/README.md Include this snippet in your launch file to perform eye-on-base calibration. Ensure robot and tracking system drivers are running and specify the correct tf frames. ```xml ``` -------------------------------- ### Include eye-in-hand calibration launch file Source: https://github.com/ifl-camp/easy_handeye/blob/master/README.md Include this snippet in your launch file to perform eye-in-hand calibration. Ensure robot and tracking system drivers are running and specify the correct tf frames. ```xml ``` -------------------------------- ### Publish Multiple Calibrations with ROS Launch Source: https://github.com/ifl-camp/easy_handeye/blob/master/README.md Include the publish.launch file multiple times in your ROS launch script to publish several calibrations simultaneously. Ensure distinct 'namespace_prefix' arguments are used for each calibration to avoid conflicts. ```xml ``` -------------------------------- ### ROS Service: take_sample Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Samples the current robot and tracking system transforms and adds them to the calibration sample list. Call this service when the robot is in position and the marker is visible. ```APIDOC ## ROS Service: take_sample Samples the current robot and tracking system transforms and adds them to the calibration sample list. Call this service when the robot is in position and the marker is visible. ### Endpoint `/my_robot_kinect_calib_eye_on_base/take_sample` (example, replace with your namespace) ### Method ROSSERVICE CALL ### Request Example ```bash rosservice call /my_robot_kinect_calib_eye_on_base/take_sample ``` ### Response Example ```yaml samples: hand_world_samples: - translation: {x: 0.5, y: 0.2, z: 0.3} rotation: {x: 0.0, y: 0.0, z: 0.0, w: 1.0} camera_marker_samples: - translation: {x: 0.1, y: 0.05, z: 0.8} rotation: {x: 0.0, y: 0.0, z: 0.707, w: 0.707} ``` ``` -------------------------------- ### Automated Calibration Loop with MoveIt! Source: https://context7.com/ifl-camp/easy_handeye/llms.txt This script demonstrates an automated loop for robot hand-eye calibration using MoveIt!. It iterates through target poses, plans and executes movements, takes samples, and computes the final calibration. ```python if client.check_starting_pose().can_calibrate: target_poses = client.enumerate_target_poses() for i in range(len(target_poses.target_poses)): # Select and plan to target pose client.select_target_pose(i) plan_result = client.plan_to_selected_target_pose() if plan_result.success: # Execute movement and take sample client.execute_plan() rospy.sleep(1.0) # Wait for robot to settle samples = client.take_sample() print(f"Sample {i+1}: {len(samples.hand_world_samples)} total samples") # Compute and save calibration result = client.compute_calibration() if result.valid: print("Calibration computed successfully!") print(f"Translation: {result.calibration.transform.transform.translation}") print(f"Rotation: {result.calibration.transform.transform.rotation}") client.save() else: print("Calibration failed - need more samples") ``` -------------------------------- ### Python API: HandeyeCalibrationBackendOpenCV - Initialization and Properties Source: https://context7.com/ifl-camp/easy_handeye/llms.txt This backend class interfaces with OpenCV's hand-eye calibration functions, supporting multiple algorithms. It provides access to available algorithms and the minimum number of samples required for computation. ```python #!/usr/bin/env python from easy_handeye.handeye_calibration_backend_opencv import HandeyeCalibrationBackendOpenCV from easy_handeye.handeye_calibration import HandeyeCalibrationParameters # Initialize backend backend = HandeyeCalibrationBackendOpenCV() # Check available algorithms print("Available algorithms:", backend.AVAILABLE_ALGORITHMS.keys()) # Output: dict_keys(['Tsai-Lenz', 'Park', 'Horaud', 'Andreff', 'Daniilidis']) # Minimum samples required print("Minimum samples:", backend.MIN_SAMPLES) # Output: 2 # Compute calibration (typically called by HandeyeServer) # samples: list of dicts with 'robot' and 'optical' TransformStamped params = HandeyeCalibrationParameters( namespace='/test/', eye_on_hand=False, robot_base_frame='base_link', robot_effector_frame='tool0', tracking_base_frame='camera_link', tracking_marker_frame='marker', freehand_robot_movement=True ) ``` -------------------------------- ### Launch Calibration Publisher Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Launches the calibration publisher with options to specify eye on hand, namespace, and custom frame names. Multiple calibrations can be published simultaneously. ```xml ``` -------------------------------- ### List and Set Calibration Algorithms Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Lists available calibration algorithms and allows switching between them. The OpenCV backend supports Tsai-Lenz, Park, Horaud, Andreff, and Daniilidis algorithms. ```bash # List available algorithms rosservice call /my_robot_kinect_calib_eye_on_base/list_algorithms ``` ```yaml # Response: algorithms: ['OpenCV/Tsai-Lenz', 'OpenCV/Park', 'OpenCV/Horaud', 'OpenCV/Andreff', 'OpenCV/Daniilidis'] current_algorithm: 'OpenCV/Tsai-Lenz' ``` ```bash # Change algorithm rosservice call /my_robot_kinect_calib_eye_on_base/set_algorithm "new_algorithm: 'OpenCV/Park'" ``` ```yaml # Response: success: true ``` -------------------------------- ### Eye-on-Base Calibration Launch Configuration Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Launches the calibration process for eye-on-base scenarios. Requires robot and tracking system drivers to be running. Configure robot and tracking tf frames, and optionally MoveIt! parameters. ```xml ``` -------------------------------- ### Python API: HandeyeClient Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Client class for programmatic access to the calibration server. Provides methods for sampling, algorithm selection, calibration computation, and robot movement control. ```APIDOC ## Python API: HandeyeClient Client class for programmatic access to the calibration server. Provides methods for sampling, algorithm selection, calibration computation, and robot movement control. ### Initialization ```python import rospy from easy_handeye.handeye_client import HandeyeClient rospy.init_node('handeye_calibration_script') # Initialize client with calibration namespace client = HandeyeClient(namespace='/my_robot_kinect_calib_eye_on_base/') ``` ### Methods - **list_algorithms()**: Returns a structure containing available algorithms and the current algorithm. - **set_algorithm(new_algorithm)**: Sets the calibration algorithm. - **take_sample()**: Takes a sample of the current robot and tracking system transforms. - **compute_calibration()**: Computes the hand-eye calibration. - **save_calibration(filename=None)**: Saves the computed calibration to a file. - **remove_sample(sample_index)**: Removes a sample by its index. ### Example Usage ```python # List and set calibration algorithm algorithms = client.list_algorithms() print("Available algorithms:", algorithms.algorithms) print("Current algorithm:", algorithms.current_algorithm) client.set_algorithm('OpenCV/Park') # Take a sample client.take_sample() # Compute calibration result = client.compute_calibration() if result.valid: print("Calibration computed successfully.") # Access transform data from result.calibration.transform else: print("Calibration computation failed.") # Save calibration client.save_calibration() ``` ``` -------------------------------- ### Python API: HandeyeSampler - Acquiring and Managing Samples Source: https://context7.com/ifl-camp/easy_handeye/llms.txt This class facilitates the acquisition of transform samples from tf. It manages the sample list and performs necessary tf lookups. Samples can be taken iteratively, and individual samples can be removed. ```python #!/usr/bin/env python import rospy from easy_handeye.handeye_sampler import HandeyeSampler from easy_handeye.handeye_calibration import HandeyeCalibrationParameters rospy.init_node('manual_sampling') # Configure sampling parameters params = HandeyeCalibrationParameters( namespace='/manual_calib/', move_group='manipulator', eye_on_hand=False, robot_base_frame='base_link', robot_effector_frame='tool0', tracking_base_frame='camera_link', tracking_marker_frame='marker', freehand_robot_movement=True ) # Create sampler sampler = HandeyeSampler(handeye_parameters=params) # Take samples (call when robot is positioned and marker visible) for i in range(10): input(f"Press Enter to take sample {i+1}...") sampler.take_sample() print(f"Samples collected: {len(sampler.get_samples())}") # Access raw samples samples = sampler.get_samples() for i, sample in enumerate(samples): robot_tf = sample['robot'].transform optical_tf = sample['optical'].transform print(f"Sample {i}: Robot pos ({robot_tf.translation.x:.3f}, " f"{robot_tf.translation.y:.3f}, {robot_tf.translation.z:.3f})") # Remove a bad sample sampler.remove_sample(3) # Remove sample at index 3 ``` -------------------------------- ### Save Calibration to File Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Saves the computed calibration to a YAML file in ~/.ros/easy_handeye/. The saved file can be used to load and publish the calibration later. ```bash # Save the calibration to file rosservice call /my_robot_kinect_calib_eye_on_base/save_calibration ``` ```text # Output: Calibration saved to /home/user/.ros/easy_handeye/my_robot_kinect_calib_eye_on_base.yaml ``` ```yaml # The saved YAML file contains: parameters: namespace: /my_robot_kinect_calib_eye_on_base/ eye_on_hand: false robot_base_frame: base_link robot_effector_frame: tool0 tracking_base_frame: camera_link tracking_marker_frame: camera_marker transformation: x: 0.85 y: -0.12 z: 1.23 qx: 0.5 qy: -0.5 qz: 0.5 qw: -0.5 ``` -------------------------------- ### ROS Service: list_algorithms and set_algorithm Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Lists available calibration algorithms and allows switching between them. The OpenCV backend supports Tsai-Lenz (default), Park, Horaud, Andreff, and Daniilidis algorithms. ```APIDOC ## ROS Service: list_algorithms and set_algorithm Lists available calibration algorithms and switches between them. OpenCV backend supports Tsai-Lenz (default), Park, Horaud, Andreff, and Daniilidis algorithms. ### List Algorithms #### Endpoint `/my_robot_kinect_calib_eye_on_base/list_algorithms` (example, replace with your namespace) #### Method ROSSERVICE CALL #### Request Example ```bash rosservice call /my_robot_kinect_calib_eye_on_base/list_algorithms ``` #### Response Example ```yaml algorithms: ['OpenCV/Tsai-Lenz', 'OpenCV/Park', 'OpenCV/Horaud', 'OpenCV/Andreff', 'OpenCV/Daniilidis'] current_algorithm: 'OpenCV/Tsai-Lenz' ``` ### Set Algorithm #### Endpoint `/my_robot_kinect_calib_eye_on_base/set_algorithm` (example, replace with your namespace) #### Method ROSSERVICE CALL #### Request Example ```bash rosservice call /my_robot_kinect_calib_eye_on_base/set_algorithm "new_algorithm: 'OpenCV/Park'" ``` #### Response Example ```yaml success: true ``` ``` -------------------------------- ### Python API: HandeyeCalibrationBackendOpenCV Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Backend class that interfaces with OpenCV's hand-eye calibration functions. Supports multiple algorithms for computing the calibration. ```APIDOC ## Python API: HandeyeCalibrationBackendOpenCV ### Description Backend class that interfaces with OpenCV's hand-eye calibration functions. Supports multiple algorithms for computing the calibration. ### Method ```python from easy_handeye.handeye_calibration_backend_opencv import HandeyeCalibrationBackendOpenCV from easy_handeye.handeye_calibration import HandeyeCalibrationParameters # Initialize backend backend = HandeyeCalibrationBackendOpenCV() # Check available algorithms print("Available algorithms:", backend.AVAILABLE_ALGORITHMS.keys()) # Output: dict_keys(['Tsai-Lenz', 'Park', 'Horaud', 'Andreff', 'Daniilidis']) # Minimum samples required print("Minimum samples:", backend.MIN_SAMPLES) # Output: 2 # Compute calibration (typically called by HandeyeServer) # samples: list of dicts with 'robot' and 'optical' TransformStamped params = HandeyeCalibrationParameters( namespace='/test/', eye_on_hand=False, robot_base_frame='base_link', robot_effector_frame='tool0', tracking_base_frame='camera_link', tracking_marker_frame='marker', freehand_robot_movement=True ) ``` ``` -------------------------------- ### Freehand Robot Movement Calibration Launch Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Launches calibration while disabling automatic MoveIt! robot movements, allowing for manual robot positioning. Useful for robots without MoveIt! support or when using teach pendant control. Configure necessary tf frames. ```xml ``` -------------------------------- ### ROS Message Definitions for easy_handeye Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Defines the ROS message structures used for calibration services and topics within the easy_handeye package. These include messages for storing calibration samples and the final calibration transform, as well as service definitions for taking samples, computing calibration, and managing algorithms. ```python # HandeyeCalibration.msg # bool eye_on_hand # geometry_msgs/TransformStamped transform # SampleList.msg # geometry_msgs/Transform[] hand_world_samples # geometry_msgs/Transform[] camera_marker_samples # Service definitions: # TakeSample.srv: --- SampleList samples # RemoveSample.srv: int32 sample_index --- SampleList samples # ComputeCalibration.srv: --- bool valid, HandeyeCalibration calibration # ListAlgorithms.srv: --- string[] algorithms, string current_algorithm # SetAlgorithm.srv: string new_algorithm --- bool success ``` -------------------------------- ### Python API: HandeyeCalibration Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Core class for managing calibration data, including serialization to/from YAML files and parameter server operations. ```APIDOC ## Python API: HandeyeCalibration ### Description Core class for managing calibration data, including serialization to/from YAML files and parameter server operations. ### Method ```python # Create calibration parameters params = HandeyeCalibrationParameters( namespace='/my_calib/', move_group='manipulator', eye_on_hand=False, robot_base_frame='base_link', robot_effector_frame='tool0', tracking_base_frame='camera_link', tracking_marker_frame='marker', freehand_robot_movement=False ) # Create calibration with known transformation # Translation (x, y, z) and Quaternion (x, y, z, w) transformation = ((0.85, -0.12, 1.23), (0.5, -0.5, 0.5, -0.5)) calibration = HandeyeCalibration( calibration_parameters=params, transformation=transformation ) # Save to file HandeyeCalibration.to_file(calibration) # Saved to: ~/.ros/easy_handeye/my_calib.yaml # Load from file loaded_calib = HandeyeCalibration.from_file('/my_calib/') # Convert to YAML string yaml_string = HandeyeCalibration.to_yaml(calibration) print(yaml_string) # Load from YAML string calib_from_yaml = HandeyeCalibration.from_yaml(yaml_string) # Access transformation data t = calibration.transformation.transform print(f"X: {t.translation.x}, Y: {t.translation.y}, Z: {t.translation.z}") print(f"Quaternion: ({t.rotation.x}, {t.rotation.y}, {t.rotation.z}, {t.rotation.w})") ``` ``` -------------------------------- ### Compute Hand-Eye Calibration Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Computes the hand-eye calibration using collected samples and the selected algorithm. Requires at least two samples for accuracy. ```bash # Compute calibration rosservice call /my_robot_kinect_calib_eye_on_base/compute_calibration ``` ```yaml # Response: valid: true calibration: eye_on_hand: false transform: header: frame_id: "base_link" child_frame_id: "camera_link" transform: translation: {x: 0.85, y: -0.12, z: 1.23} rotation: {x: 0.5, y: -0.5, z: 0.5, w: -0.5} ``` -------------------------------- ### Enable freehand robot movement during calibration Source: https://github.com/ifl-camp/easy_handeye/blob/master/README.md This snippet enables freehand robot movement during calibration, requiring the user to manually publish the robot's pose to tf. Ensure the robot's pose is updated correctly in RViz before acquiring samples. ```xml ``` -------------------------------- ### Publishing Calibration Results Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Launches a node to publish previously computed calibration results as a tf transform. Supports multiple simultaneous calibrations with different namespaces. ```APIDOC ## Publishing Calibration Results Loads a previously computed calibration from file and publishes it as a tf transform. Multiple calibrations can be published simultaneously using different namespaces. ### Launch File Example ```xml ``` ### Arguments for publish.launch - **eye_on_hand** (bool): Set to true for eye-on-hand calibration, false for eye-on-base. - **namespace_prefix** (string): A unique identifier for this calibration. - **robot_base_frame** (string, optional): The name of the robot's base frame. Defaults to 'base_link'. - **tracking_base_frame** (string, optional): The name of the tracking system's base frame. Defaults to 'camera_link'. ``` -------------------------------- ### Easy Hand-Eye Calibration ROS API Source: https://github.com/ifl-camp/easy_handeye/blob/master/easy_handeye/README.md This section details the ROS topics and services provided by the easy_handeye package for performing hand-eye calibration. ```APIDOC ## ROS API All following topics and parameters live in the namespace specified by the top-level launch file (e.g. `robot_device_eye_on_{hand,base}`). This allows multiple calibrations to coexist. ### Topics/Services - `take_sample`: a sample of each transformation is added to the list - `remove_sample(int)`: removes the specified sample from the list - `compute_calibration`: the calibration transformation is computed from the lists of transformations - `save_calibration`: the calibration is saved in the parameters and to file - `sample_list`: after adding or removing a sample, the list is published here - `calibration_result`: after computation the transform is published on this topic ### Parameters - `namespace`: the calibrator script will save the result in `~/.ros/easy_handeye/$namespace`; the publisher will load the data from the same path. - `eye_on_hand`: if true, this is an eye-on-hand calibration, else eye-on-base. - `tracking_base_frame`: contains the tf id of the tracking system coordinate origin frame. - `tracking_marker_frame`: contains the tf id of the tracking system target. - `robot_base_frame`: contains the tf id of the robot's base link. - `robot_effector_frame`: contains the tf id of the robot's end effector link. ``` -------------------------------- ### Python API: HandeyeSampler Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Low-level class for acquiring transform samples from tf. Manages the sample list and performs tf lookups. ```APIDOC ## Python API: HandeyeSampler ### Description Low-level class for acquiring transform samples from tf. Manages the sample list and performs tf lookups. ### Method ```python import rospy from easy_handeye.handeye_sampler import HandeyeSampler from easy_handeye.handeye_calibration import HandeyeCalibrationParameters rospy.init_node('manual_sampling') # Configure sampling parameters params = HandeyeCalibrationParameters( namespace='/manual_calib/', move_group='manipulator', eye_on_hand=False, robot_base_frame='base_link', robot_effector_frame='tool0', tracking_base_frame='camera_link', tracking_marker_frame='marker', freehand_robot_movement=True ) # Create sampler sampler = HandeyeSampler(handeye_parameters=params) # Take samples (call when robot is positioned and marker visible) for i in range(10): input(f"Press Enter to take sample {i+1}...") sampler.take_sample() print(f"Samples collected: {len(sampler.get_samples())}") # Access raw samples samples = sampler.get_samples() for i, sample in enumerate(samples): robot_tf = sample['robot'].transform optical_tf = sample['optical'].transform print(f"Sample {i}: Robot pos ({robot_tf.translation.x:.3f}, " f"{robot_tf.translation.y:.3f}, {robot_tf.translation.z:.3f})") # Remove a bad sample sampler.remove_sample(3) # Remove sample at index 3 ``` ``` -------------------------------- ### ROS Service: save_calibration Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Saves the computed calibration to a YAML file in `~/.ros/easy_handeye/`. The calibration can later be loaded and published using `publish.launch`. ```APIDOC ## ROS Service: save_calibration Saves the computed calibration to a YAML file in `~/.ros/easy_handeye/`. The calibration can later be loaded and published using `publish.launch`. ### Endpoint `/my_robot_kinect_calib_eye_on_base/save_calibration` (example, replace with your namespace) ### Method ROSSERVICE CALL ### Request Example ```bash rosservice call /my_robot_kinect_calib_eye_on_base/save_calibration ``` ### Output Example ``` Calibration saved to /home/user/.ros/easy_handeye/my_robot_kinect_calib_eye_on_base.yaml ``` ### Saved YAML File Content Example ```yaml parameters: namespace: /my_robot_kinect_calib_eye_on_base/ eye_on_hand: false robot_base_frame: base_link robot_effector_frame: tool0 tracking_base_frame: camera_link tracking_marker_frame: camera_marker transformation: x: 0.85 y: -0.12 z: 1.23 qx: 0.5 qy: -0.5 qz: 0.5 qw: -0.5 ``` ``` -------------------------------- ### ROS Service: compute_calibration Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Computes the hand-eye calibration from collected samples using the currently selected algorithm. Requires at least 2 samples (more recommended for accuracy). ```APIDOC ## ROS Service: compute_calibration Computes the hand-eye calibration from collected samples using the currently selected algorithm. Requires at least 2 samples (more recommended for accuracy). ### Endpoint `/my_robot_kinect_calib_eye_on_base/compute_calibration` (example, replace with your namespace) ### Method ROSSERVICE CALL ### Request Example ```bash rosservice call /my_robot_kinect_calib_eye_on_base/compute_calibration ``` ### Response #### Success Response (200) - **valid** (bool) - Indicates if the calibration computation was successful. - **calibration** (object) - Contains the computed calibration data. - **eye_on_hand** (bool) - True if eye-on-hand, false if eye-on-base. - **transform** (object) - The resulting transformation. - **header** (object) - **frame_id** (string) - The parent frame of the transform. - **child_frame_id** (string) - The child frame of the transform. - **transform** (object) - **translation** (object) - The translation vector {x, y, z}. - **rotation** (object) - The rotation quaternion {x, y, z, w}. #### Response Example ```yaml valid: true calibration: eye_on_hand: false transform: header: frame_id: "base_link" child_frame_id: "camera_link" transform: translation: {x: 0.85, y: -0.12, z: 1.23} rotation: {x: 0.5, y: -0.5, z: 0.5, w: -0.5} ``` ``` -------------------------------- ### ROS Service: remove_sample Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Removes a specific sample from the list by index. Useful for discarding bad samples without restarting the calibration process. ```APIDOC ## ROS Service: remove_sample Removes a specific sample from the list by index. Useful for discarding bad samples without restarting the calibration process. ### Endpoint `/my_robot_kinect_calib_eye_on_base/remove_sample` (example, replace with your namespace) ### Method ROSSERVICE CALL ### Parameters #### Request Body - **sample_index** (int) - Required - The index of the sample to remove. ### Request Example ```bash rosservice call /my_robot_kinect_calib_eye_on_base/remove_sample "sample_index: 2" ``` ### Response The response contains the updated sample list, similar to the `take_sample` service response. ``` -------------------------------- ### Remove Calibration Sample Source: https://context7.com/ifl-camp/easy_handeye/llms.txt Removes a specific sample from the calibration sample list by its index. This is useful for discarding erroneous samples without restarting the entire calibration process. ```bash # Remove sample at index 2 rosservice call /my_robot_kinect_calib_eye_on_base/remove_sample "sample_index: 2" ``` ```text # Response contains updated sample list ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.