Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
4dd39c8
hand-eye calibration branch created on relevant order between other d…
MithraGhlm Apr 9, 2026
c23f24a
Added the STag detector doc and rearranged the numbers
MithraGhlm Apr 20, 2026
8790c37
some text written for the STag marker detector.Related image added. T…
MithraGhlm Apr 20, 2026
a459c04
The STag detection video added.
MithraGhlm Apr 21, 2026
bd5c193
WIP: initial documentation draft
MithraGhlm Apr 21, 2026
0613b51
info for Aruco marker added.
MithraGhlm Apr 21, 2026
81dbf13
Decoupled the explanation of Marker detection from Hand-Eye calibration
MithraGhlm Apr 27, 2026
b5952af
Applied some grammatical, structural, and definitional improvements.
MithraGhlm Apr 27, 2026
413e081
canceled the small change made to the text.
MithraGhlm Apr 27, 2026
743eede
Renamed the file to show the marker detection process is generic
MithraGhlm Apr 27, 2026
a9a0028
The first version of introduction for the robot calibration guide.
MithraGhlm Apr 28, 2026
c0b4a83
added the screenshot of component configuration for the Hand-Eye cali…
MithraGhlm Apr 28, 2026
d904aeb
added calibration workflow.
MithraGhlm Apr 28, 2026
426fef6
one word replaced by a better one.
MithraGhlm Apr 28, 2026
c4da9af
added things that can be done with the acquired calibration info
MithraGhlm Apr 28, 2026
9ce7fec
corrected capital letter which was in the middle of the sentence.
MithraGhlm Apr 29, 2026
f2e20b7
adding a small frame to the image
MithraGhlm Apr 29, 2026
b12fd16
Added the missing word, Launcher.
MithraGhlm Apr 29, 2026
4f58281
sidebar position modified
MithraGhlm Apr 30, 2026
b290070
sidebar position modified
MithraGhlm Apr 30, 2026
8ec6d43
sidebar position modified
MithraGhlm Apr 30, 2026
94c8d66
The structure of the sentence improved.
MithraGhlm Apr 30, 2026
f256e5a
added fiducial to marker
MithraGhlm Apr 30, 2026
ce36b54
changed the name of the file to Fiducial Markers
MithraGhlm Apr 30, 2026
93f6f3f
structure of the sentence improved
MithraGhlm Apr 30, 2026
004055e
The structure of the sentence improved.
MithraGhlm Apr 30, 2026
b1d7970
Misspelling corrected
MithraGhlm Apr 30, 2026
07e4020
reminder to add the camera configuration file to the Camera Streamer …
MithraGhlm Apr 30, 2026
a4fa172
corrected the definition of Rate parameter of the STag Detector compo…
MithraGhlm Apr 30, 2026
d529009
the word stag_ replaced by the word Prefix
MithraGhlm Apr 30, 2026
43c9874
small typo corrected
MithraGhlm May 1, 2026
c59aa4a
adding the explanation of the Marker Size parameter
MithraGhlm May 1, 2026
e22827b
moved the robot camera calibration component explanation to the prope…
MithraGhlm May 1, 2026
a3bd7fc
screenshot of Robot Camera Calibration parameters added
MithraGhlm May 1, 2026
9d55015
app added for the HE calibration
MithraGhlm May 1, 2026
addc15b
the structure of some sentences enhanced
MithraGhlm May 1, 2026
6fea105
added the reminder to turn on the camera attached check
MithraGhlm May 1, 2026
c07b8c2
added the definition of Bundle file
MithraGhlm May 4, 2026
a747428
added the explanation for obtaining, downloading, and printing markers
MithraGhlm May 4, 2026
941b84b
rectified the file that Bundle File was explained in
MithraGhlm May 4, 2026
5417117
The wrong image removed
MithraGhlm May 4, 2026
b7b0bfc
typo correction
MithraGhlm May 8, 2026
346be2b
Some typo and font inconsistency corrected. Some definitions and pict…
MithraGhlm May 8, 2026
9c2edee
text added to explain the screenshot, HE caliberation configuration e…
MithraGhlm May 8, 2026
27e362f
Links for obtaining fiducial markers corrected
MithraGhlm May 13, 2026
f884fe8
screenshots for STag detector predicates added.
MithraGhlm May 13, 2026
f62b7e6
typo correction
MithraGhlm May 18, 2026
4ece868
some order and structur changes in the body of documentation. Some de…
MithraGhlm May 18, 2026
a9118c4
added the yaml file for the STag Detector
MithraGhlm May 20, 2026
50f36a1
Explanation for the Frame Broadcaster component added to the HE calib…
MithraGhlm Jun 2, 2026
1f0f3d8
Print Width corrected, set to 120
MithraGhlm Jun 10, 2026
7cd986b
Unintended changes to ur-harware-interface.md file reverted.
MithraGhlm Jun 10, 2026
83d2982
Removed hand-eye calibration guide to be placed in a separate PR
MithraGhlm Jun 10, 2026
b9375b2
reordered imports which were jumbled by the extension
MithraGhlm Jun 11, 2026
f906b18
stag detector parameters definition correction
MithraGhlm Jun 12, 2026
62b6ae3
formatted again just to be sure
MithraGhlm Jun 12, 2026
b5f63c3
some formatting nitpicks
MithraGhlm Jun 12, 2026
3300154
some small final formatting changes
MithraGhlm Jun 25, 2026
d0cce71
An extra unrelated leftover line deleted
MithraGhlm Jun 25, 2026
c92e3ba
Restore file to previous version
MithraGhlm Jun 10, 2026
f5ff3b8
added hand-eye-calibration file after deleting its branch, adding it …
MithraGhlm Jun 25, 2026
1cf3a19
Revert "Restore file to previous version"
MithraGhlm Jun 25, 2026
5ec88b1
Reordered some mess caused by Prettier extension.
MithraGhlm Jun 30, 2026
0c65460
Merge branch 'main' into docs/hand-eye-calibration-new
MithraGhlm Jul 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/core/examples/guides/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cSpell.words": ["AICA", "Freedrive", "Orbbec", "servoing", "URDF"]
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
332 changes: 332 additions & 0 deletions docs/core/examples/guides/hand-eye-calibration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,332 @@
---
sidebar_position: 15
title: Hand-Eye calibration
---

import RobotCalibrationConfiguration from './assets/robot-calibration-configuration.png'
import RobotCameraCalibration from './assets/robot-camera-calibration-component.png'
import URCalibrationFile from './assets/UR-calibration-file.png'
import FrameBroadcasterExpectedFileFormat from './assets/frame-broadcaster-expected-file-format.png'
import FrameBroadcasterPublishManually from './assets/frame-broadcaster-publish-manually.png'
import FrameBroadcasterDirectFilepath from './assets/frame-broadcaster-direct-filepath.png'

# Hand-Eye calibration

Robot calibration is a fundamental prerequisite for any robotic system that relies on precise coordination between a
vision sensor and a manipulator. It establishes the spatial transformation between the robot’s end-effector and the
camera frame, enabling accurate mapping between observed features and actionable robot coordinates. Without proper
calibration, even high-quality perception or motion planning algorithms can yield significant positioning errors.

The AICA's `core-vision` package provides a structured workflow for performing hand–eye calibration efficiently and
reproducibly.

Accurate hand–eye calibration is critical in tasks such as visual servoing, object manipulation, inspection, and
assembly. This tool is designed to minimize discrepancies and provide reliable calibration outputs suitable for
industrial environments.

## Robot Camera Calibration component

The Robot Camera Calibration component is the component that does the main job of calculating the transformation between
the `camera` and the `robot end-effector`.

Click on the Robot Camera Calibration component block to view and edit the available parameters.

<div class="text--center">
<img src={RobotCameraCalibration} alt="Robot Camera Calibration parameters" style={{ borderRadius: "8px" }}/>
</div>

The parameters of the Robot Camera Calibration component are defined as follows:

- **Rate**: Determines the frequency at which transformations are acquired. This parameter does not affect the
component’s behavior.
- **Bundle file**: The filepath to a predefined marker bundle configuration. This additional feature is described in a
separate guide (coming soon).
- **Camera frame**: The name of the camera frame used in the application. This can be retrieved from the list of frames
in RViz.
- **Marker frame**: The name of the marker detected by the camera. It is indicated in the STag or ArUco marker detector
component used in the application.
- **Robot base frame**: The name of the robot's base frame, which can be found in RViz.
- **Robot end-effector frame**: The name of the robot’s end-effector frame. This is also available in the RViz frame
list.
- **Number of recorded points**: The number of transformations from `camera` to `robot end-effector` that are recorded.
These are computed from multiple pairs of `robot end-effector -> robot base` and `camera -> marker` transformations.
- **Distance between points**: The minimum spatial difference required between two consecutive transformations for them
to be recorded.
- **Epsilon time**:
- **Calibration folder path**: The directory where the final calibration file will be stored.
- **Calibration file**: The name of the output file generated after calibration, containing the computed calibration
data.
- **Points dataset file**: A file containing previously recorded transformations of the robot end-effector or marker,
which can be reused if available.
- **Reset calibration**: Setting this component to `True` resets the calibration. Meaning it starts the calibration
process again, even if the calibration matrices are already set.
- **Reset dataset**: If set to `True`, the recording process will re-start, even if the dataset of points already
exists.
- **Is camera attached**: This parameter should be set to `True` if the camera is attached to the robot end-effector.

## Robot Calibration using AICA Studio and a marker

After completing the camera calibration as described in the [Camera Calibration example](./camera-calibration.md), and
verifying marker detection as outlined in the [Fiducial Markers](./fiducial-markers.md) section, you can proceed with
the hand–eye calibration process.

This example demonstrates the eye-in-hand configuration (camera mounted on the robot arm). The procedure for the
eye-to-hand configuration (static camera) follows a similar workflow.

- Ensure that the camera is properly configured and operational.
- Connect all required components and controllers in the AICA application. Refer to the system setup illustration below
for guidance.
- Place the marker within the robot workspace, ensuring it is fully visible to the camera. To monitor the live camera
feed, enable `Launch RViz` from the Launcher settings, as described in the [marker detection](./marker-detection.md)
guide.
- Run the program and move the robot TCP (Tool Center Point) to capture images of the marker from multiple perspectives.
The application starts capturing images automatically.
- The robot TCP can be moved by jogging or Freedrive mode using the robot's teach pendant. In the case of using a
Universal Robot, AICA Studio offers the option of `Hand Guiding Controller` which facilitates and accelerates the
process. This controller is described in the [Hand Guiding Controller](./ur-harware-interface.md) page.
- Ensure sufficient variation in position and orientation to improve calibration accuracy.
- Once the number of captured images reaches the `Number of recorded points` indicated in the Robot Camera Calibration
component parameters, the system automatically generates a calibration file in YAML format in the following directory:

```bash
/tmp/calibration/camera_calibration.yaml
```

An example of the calibration file:

<div class="text--center">
<img src={URCalibrationFile} alt="An example showing a final calibration file" style={{ borderRadius: "8px" }}/>
</div>

:::info
The order of the data in the calibration file is `w, x, y, z` for the Orientation and `x, y, z` for the
Position.
:::

In the screenshot below you can see an example of the components configuration for the Hand-Eye calibration, that
resulted to the output above. Notice that the Camera and the marker detector components might differ based on the type
of hardware being used.

<div class="text--center">
<img src={RobotCalibrationConfiguration} alt="The configuration required for hand-eye calibration" style={{ borderRadius: "8px" }}/>
</div>

The following YAML snippet contains the full application of the image above:

<details>
<summary>Example application, Hand-Eye calibration</summary>

```yaml
schema: 2-0-6
dependencies:
core: v5.1.0
on_start:
load:
- component: orbbec_camera
- component: robot_camera_calibration
- component: stag_detector
- hardware: hardware
components:
orbbec_camera:
component: orbbec_camera::OBCameraNodeDriver
display_name: Orbbec Camera
outputs:
color_image: /orbbec_camera/color_image
color_camera_info: /orbbec_camera/color_camera_info
robot_camera_calibration:
component: core_vision_components::calibration::RobotCameraCalibration
display_name: Robot Camera Calibration
events:
transitions:
on_load:
lifecycle:
component: robot_camera_calibration
transition: configure
on_configure:
lifecycle:
component: robot_camera_calibration
transition: activate
parameters:
camera_frame:
value: orbbec_camera_link
type: string
marker_frame:
value: stag_0
type: string
robot_base_frame:
value: world
type: string
robot_ee_frame:
value: ur_tool0
type: string
is_camera_attached:
value: true
type: bool
stag_detector:
component: core_vision_components::pose_detection::STagDetector
display_name: STag Detector
events:
transitions:
on_load:
lifecycle:
component: stag_detector
transition: configure
on_configure:
lifecycle:
component: stag_detector
transition: activate
parameters:
marker_selection:
value:
- stag_0
type: string_array
inputs:
image: /orbbec_camera/color_image
camera_info: /orbbec_camera/color_camera_info
hardware:
hardware:
display_name: Hardware Interface
urdf: Universal Robots 5e
rate: 500
events:
transitions:
on_load:
load:
- controller: robot_state_broadcaster
hardware: hardware
- controller: ur_hand_guiding_controller
hardware: hardware
parameters:
robot_ip: 192.168.42.20
controllers:
robot_state_broadcaster:
plugin: aica_core_controllers/RobotStateBroadcaster
events:
transitions:
on_load:
switch_controllers:
hardware: hardware
activate: robot_state_broadcaster
ur_hand_guiding_controller:
plugin: aica_ur_controllers/URHandGuidingController
parameters:
ft_sensor_name:
value: ur_tcp_fts_sensor
type: string
ft_sensor_reference_frame:
value: ur_tool0
type: string
force_limit:
value:
- 20
- 20
- 20
- 2
- 2
- 2
type: vector
events:
transitions:
on_load:
switch_controllers:
hardware: hardware
activate: ur_hand_guiding_controller
graph:
positions:
on_start:
x: 120
y: 0
stop:
x: 120
y: 100
components:
orbbec_camera:
x: 340
y: 0
robot_camera_calibration:
x: 340
y: 320
stag_detector:
x: 800
y: -80
hardware:
hardware:
x: 1260
y: -120
edges:
on_start_on_start_robot_camera_calibration_robot_camera_calibration:
path:
- x: 260
y: 60
- x: 260
y: 380
on_start_on_start_stag_detector_stag_detector:
path:
- x: 260
y: 60
- x: 260
y: -20
on_start_on_start_hardware_hardware:
path:
- x: 260
y: 60
- x: 260
y: -60
```

</details>

:::tip
Don't forget to modify the `robot_ip` according to the ip of the robot that you are using.
:::

There are several ways to use the transformation information obtained in the calibration file:

1. Adding the camera link to the URDF.
2. Publish the transformation with a `FrameBroadcaster` manually.
3. Using the calibration file path directly as a Frame Broadcaster component parameter to publish the transformations.

:::tip
In order to use the calibration file path as a `Frame Broadcaster` component parameter, the format of the
calibration file needs to be slightly modified. In the next part the expected format is explained in more detail.
:::

## Frame Broadcaster component

The **Frame Broadcaster** is a component that parses a frame from the parameters and/or frames from the provided file
and broadcasts all available frames to TF.

The parameters of the Robot Camera Calibration component are defined as follows:

- **Rate**: Determines the frequency of all periodic callbacks. This parameter does not affect the component’s behavior.
- **Filepath**: This shows the path to the file containing a frame in YAML format. An example of the expected file
format is shown in the screenshot below.

<div class="text--center">
<img src={FrameBroadcasterExpectedFileFormat} alt="The expected file format for the Frame Broadcaster" style={{ borderRadius: "8px" }}/>
</div>

- **Frame**: Name of the frame that we wish to broadcast.
- **reference frame**: The name of the reference frame that the frame is defined according to it.
- **Pose values**: The values of Position (meters) and Orientation (quaternions) concatenated as a vector, as in x, y,
z, qw, qx, qy, qz.
- **Broadcast periodically**: If this parameter is set to True, the frames are broadcasted periodically. Otherwise it
publishes once immediately.

:::info
You either need to fill in the Filepath, or provide the `Frame Broadcaster` component with Frame, Reference
frame, and the Pose values parameters.
:::

In the first screenshot below, you see an example of the `Frame broadcaster` component, and a transformation which is
being published manually.

<div class="text--center">
<img src={FrameBroadcasterPublishManually} alt="Inserting the transformation into the frame Broadcaster manually." style={{ borderRadius: "8px" }}/>
</div>

In this second example, you see how the calibration filepath is given as a parameter to publish the transformations.

<div class="text--center">
<img src={FrameBroadcasterDirectFilepath} alt="Using the calibration file path directly as a Frame Broadcaster component parameter to publish the transformations." style={{ borderRadius: "8px" }}/>
</div>