newhaneul

[Robocup@Home 2026] 2026.01.13 (Cyclone DDS & Hand-Eye Calibration) 본문

3. Robotics/Robocup@Home 2026

[Robocup@Home 2026] 2026.01.13 (Cyclone DDS & Hand-Eye Calibration)

뉴하늘 2026. 1. 13. 23:09
728x90

 

Restaurant scenario PPT

restaurant scenario (1).pptx
0.16MB

 

 

RB-Y1 Eye-in-Hand Calibration (ROS 2 Humble)

handeye.zip
17.50MB

Environment & Dependencies

  • OS: Ubuntu 22.04 (Jammy)
  • ROS 2 Distro: Humble Hawksbill
  • Hardware:
    • Robot: 7-DOF Robot Arm (Right Arm)
    • Camera: Intel RealSense (Mounted on end-effector)
    • Target: ArUco Marker (ID: 0, Fixed on table)
  • Packages:
    • easy_handeye2
    • ros2_aruco
      • tf2_ros

 

1. Network Setup (Cyclone DDS)

로봇과 PC 간의 원활한 ROS 2 통신을 위해 Cyclone DDS를 설정하고 유니캐스트(Unicast) 방식을 사용함.

sudo apt install ros-humble-rmw-cyclonedds-cpp

 

** Cyclone DDS 통신이란? **

Cyclone DDS는 OMG(Object Management Group)에서 정한 DDS(Data Distribution Service) 표준을 구현한 오픈소스 라이브러리이다. 주로 로봇의 센서 데이터(카메라, 라이다 등)를 노트북으로 보내고, 노트북에서 계산된 이동 명령을 로봇으로 보낸다.

 

2. Configuration (cyclonedds.xml)

 멀티캐스트가 막힌 환경을 고려하여 로봇과 노트북 양쪽에 cyclonedds.xml 파일을 만들고, 상대방의 IP 주소를 Peers에 직접 등록한다.

  • Path: ~/cyclonedds.xml
  • Settings: <AllowMulticast>false</AllowMulticast> 및 <Peer Address="..."/> 추가

 

1단계: ROS_DOMAIN_ID 통일

  • 💻 노트북 (Laptop)
    • DOMAIN_ID: 71
newhaneul@newhaneul-950QDB:~/handeye$ echo $ROS_DOMAIN_ID
71
  • 🤖 로봇 (Robot)
    • DOMAIN_ID: 71
nvidia@tegra-ubuntu:~$ echo $ROS_DOMAIN_ID
71

 

2단계: IP 주소 확인

 먼저 로봇과 노트북 터미널에서 각각 'ip addr' 명령어를 입력하여 현재 할당받은 IP 주소를 확인한다.

 

  • 💻 노트북 (Laptop)
    • 사용할 인터페이스: wlp45s0 (2번 항목)
    • IP 주소: 192.168.50.223
newhaneul@newhaneul-950QDB:~$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: wlp45s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 1c:c1:0c:e2:f5:b3 brd ff:ff:ff:ff:ff:ff
    inet 192.168.50.223/24 brd 192.168.50.255 scope global dynamic noprefixroute wlp45s0
       valid_lft 83979sec preferred_lft 83979sec
    inet6 fe80::87a0:931:130b:647e/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

 

  • 🤖 로봇 (Robot)
    • 사용할 인터페이스: wlx782051154175 (10번 항목)
    • IP 주소: 192.168.50.190

 

nvidia@tegra-ubuntu:~$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enP1p5s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether 00:18:1a:f2:e9:15 brd ff:ff:ff:ff:ff:ff
3: enP1p3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 2c:53:4a:30:2c:13 brd ff:ff:ff:ff:ff:ff
    inet 192.168.30.2/24 brd 192.168.30.255 scope global noprefixroute enP1p3s0
       valid_lft forever preferred_lft forever
    inet6 fe80::789e:f058:e311:c905/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
4: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN group default qlen 10
    link/can 
5: can1: <NOARP,ECHO> mtu 16 qdisc noop state DOWN group default qlen 10
    link/can 
6: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 3c:6d:66:33:91:ae brd ff:ff:ff:ff:ff:ff
    inet 192.168.78.10/24 brd 192.168.78.255 scope global noprefixroute eno1
       valid_lft forever preferred_lft forever
    inet6 fe80::a5b4:9ad:98bf:db90/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
7: l4tbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 3e:c7:e7:79:f3:87 brd ff:ff:ff:ff:ff:ff
    inet 192.168.55.1/24 brd 192.168.55.255 scope global l4tbr0
       valid_lft forever preferred_lft forever
    inet6 fe80::1/128 scope link tentative 
       valid_lft forever preferred_lft forever
8: usb0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast master l4tbr0 state DOWN group default qlen 1000
    link/ether 9e:c6:29:cd:4a:49 brd ff:ff:ff:ff:ff:ff
9: usb1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast master l4tbr0 state DOWN group default qlen 1000
    link/ether 9e:c6:29:cd:4a:4b brd ff:ff:ff:ff:ff:ff
10: wlx782051154175: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 78:20:51:15:41:75 brd ff:ff:ff:ff:ff:ff
    inet 192.168.50.190/24 brd 192.168.50.255 scope global dynamic noprefixroute wlx782051154175
       valid_lft 81372sec preferred_lft 81372sec
    inet6 fe80::3437:3f77:a2bf:27ba/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
11: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 0a:6d:7e:b7:58:1d brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

 

 

2단계: cyclonedds.xml 파일 작성

 로봇과 노트북에 각각 파일을 생성한다. 

 

  • 💻 노트북 (Laptop)
    • 경로: /home/newhaneul
<?xml version="1.0" encoding="UTF-8" ?>
<CycloneDDS xmlns="https://cdds.io/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://cdds.io/config https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/master/etc/cyclonedds.xsd">
    <Domain Id="any">
        <General>
            <Interfaces>
                <NetworkInterface name="wlp45s0" priority="default" />
            </Interfaces>
            <AllowMulticast>false</AllowMulticast>
            <MaxMessageSize>65500B</MaxMessageSize>
        </General>
        <Discovery>
            <EnableTopicDiscoveryEndpoints>true</EnableTopicDiscoveryEndpoints>
            <ParticipantIndex>auto</ParticipantIndex>
            <MaxAutoParticipantIndex>50</MaxAutoParticipantIndex>
            <Peers>
                <Peer Address="127.0.0.1"/>
                <Peer Address="192.168.50.120"/>
                <Peer Address="192.168.50.190"/>
                
            </Peers>
        </Discovery>
        <Internal>
            <Watermarks>
                <WhcHigh>500kB</WhcHigh>
            </Watermarks>
        </Internal>
    </Domain>
</CycloneDDS>

 

  • <AllowMulticast>false</AllowMulticast>: 멀티캐스트를 아예 끄고 IP 지정 방식만 사용하겠다는 의미. (
  • <Peer address="...">: 통신하고 싶은 상대방의 IP를 모두 적어줌.

 

  • 🤖 로봇 (Robot)
    • 경로: /home/nvidia/temp_cyclone/cyclonedds.xml

 

<?xml version="1.0" encoding="UTF-8" ?>
<CycloneDDS xmlns="https://cdds.io/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://cdds.io/config https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/master/etc/cyclonedds.xsd">
    <Domain Id="any">
        <General>
            <Interfaces>
                <NetworkInterface name="wlx782051154175" priority="default" />
		<!-- <NetworkInterface name="eno1" priority="default"/>-->
            </Interfaces>
            <AllowMulticast>true</AllowMulticast>
            <MaxMessageSize>65500B</MaxMessageSize>
        </General>
        <Discovery>
            <EnableTopicDiscoveryEndpoints>true</EnableTopicDiscoveryEndpoints>
            <ParticipantIndex>auto</ParticipantIndex>
            <MaxAutoParticipantIndex>50</MaxAutoParticipantIndex>
            <Peers>
                <Peer Address="127.0.0.1"/>
                <Peer Address="192.168.50.192"/>
		<Peer Address="192.168.78.10"/>
		<Peer Address="192.168.30.4"/>
                <Peer Address="192.168.50.190"/>
                <Peer Address="192.168.50.37"/>
                <Peer Address="192.168.50.172"/>
                <Peer Address="192.168.50.223"/>
            </Peers>
        </Discovery>
        <Internal>
            <Watermarks>
                <WhcHigh>32MB</WhcHigh>
            </Watermarks>
        </Internal>
    </Domain>
</CycloneDDS>

 

3단계: Environment Variables 

 이제 ROS 2가 이 설정 파일을 읽도록 환경 변수를 설정해야 한다. 터미널에 다음 명령어를 입력한다. 이때 cyclonedds.xml 파일이 있는곳에서 실행해야한다. 매번 터미널에 입력하기 번거로우므로 '~/.bashrc'에 작성하여 둔다.

export CYCLONEDDS_URI=file:///home/$USER/cyclonedds.xml
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp

 

4단계: 통신 확인

  • 💻 노트북 (Laptop)
newhaneul@newhaneul-950QDB:~/handeye$ export CYCLONEDDS_URI=file:///home/newhaneul/cyclonedds.xml
newhaneul@newhaneul-950QDB:~/handeye$ ros2 run demo_nodes_cpp listener
[INFO] [1768310337.072999716] [listener]: I heard: [Hello World: 9]
[INFO] [1768310338.089548632] [listener]: I heard: [Hello World: 10]
[INFO] [1768310339.104400038] [listener]: I heard: [Hello World: 11]
  • 🤖 로봇 (Robot)
nvidia@tegra-ubuntu:~$ export CYCLONEDDS_URI=file:///home/nvidia/temp_cyclone/cyclonedds.xml
nvidia@tegra-ubuntu:~$ ros2 run demo_nodes_cpp talker
[INFO] [1768310279.313015501] [talker]: Publishing: 'Hello World: 1'
[INFO] [1768310280.313132262] [talker]: Publishing: 'Hello World: 2'
[INFO] [1768310281.312898030] [talker]: Publishing: 'Hello World: 3'
[INFO] [1768310282.312906642] [talker]: Publishing: 'Hello World: 4'

 

주의점

 

 방화벽(ufw)이 켜져 있으면 ROS 2 통신이 차단될 확률이 매우 높다. DDS는 수많은 UDP 포트를 동적으로 사용하기 때문에, 방화벽이 이를 막아버리면 설정이 완벽해도 데이터가 오가지 않는다. 로봇과 노트북 양쪽 모두에서 다음 절차를 따라 방화벽을 확인하고 해제한다.

 

 

1. 방화벽 상태 확인

 터미널에 다음 명령어를 입력하세요.

sudo ufw status
  • Status가 inactive라면 방화벽이 꺼져있는 상태
  • Status가 active라면 방화벽이 켜져 있는 상태

 

2. 방화벽 끄기 (추천)

sudo ufw disable
  • 입력 후 Firewall stopped and disabled on system startup 메시지가 나오면 된다.

 

3. 방화벽을 끄기 싫다면 (특정 IP 허용)

 보안상 방화벽을 켜두어야 한다면, 상대방 IP에서의 모든 통신을 허용해주는 규칙을 추가해야 한다.

  • 🤖 로봇 터미널에서: (노트북 IP 허용)
    sudo ufw allow from 192.168.50.223
  • 💻 노트북 터미널에서: (로봇 IP 허용)
    sudo ufw allow from 192.168.50.190
newhaneul@newhaneul-950QDB:~$ sudo ufw status
Status: inactive

 

 

3. Vision System Setup

3.1 Camera

  카메라가 인식한 마커의 위치를 TF 트리로 송출해야 한다.

 

터미널 1

newhaneul@newhaneul-950QDB:~/handeye$ ls
calib  easy_handeye2_ws
newhaneul@newhaneul-950QDB:~/handeye$ ros2 launch realsense2_camera rs_launch.py
[INFO] [launch]: All log files can be found below /home/newhaneul/.ros/log/2026-01-13-21-42-00-563939-newhaneul-950QDB-9068
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [launch.user]: 🚀 Launching as Normal ROS Node
[INFO] [realsense2_camera_node-1]: process started with pid [9069]
[realsense2_camera_node-1] [INFO] [1768308120.994945552] [camera.camera]: RealSense ROS v4.56.4
[realsense2_camera_node-1] [INFO] [1768308120.995147917] [camera.camera]: Built with LibRealSense v2.56.4
[realsense2_camera_node-1] [INFO] [1768308120.995179312] [camera.camera]: Running with LibRealSense v2.56.4
[realsense2_camera_node-1]  13/01 21:42:00,996 WARNING [128721914689088] (backend-hid.cpp:1285) Failed to read busnum/devnum. Custom HID Device Path: /sys/bus/platform/drivers/hid_sensor_custom/HID-SENSOR-2000e1.17.auto
[realsense2_camera_node-1]  13/01 21:42:00,997 WARNING [128721914689088] (backend-hid.cpp:1285) Failed to read busnum/devnum. Custom HID Device Path: /sys/bus/platform/drivers/hid_sensor_custom/HID-SENSOR-2000e1.4.auto
[realsense2_camera_node-1]  13/01 21:42:00,997 WARNING [128721914689088] (backend-hid.cpp:1285) Failed to read busnum/devnum. Custom HID Device Path: /sys/bus/platform/drivers/hid_sensor_custom/HID-SENSOR-2000e1.3.auto
[realsense2_camera_node-1]  13/01 21:42:00,997 WARNING [128721914689088] (backend-hid.cpp:1285) Failed to read busnum/devnum. Custom HID Device Path: /sys/bus/platform/drivers/hid_sensor_custom/HID-SENSOR-2000e1.2.auto
[realsense2_camera_node-1]  13/01 21:42:00,997 WARNING [128721914689088] (backend-hid.cpp:1285) Failed to read busnum/devnum. Custom HID Device Path: /sys/bus/platform/drivers/hid_sensor_custom/HID-SENSOR-2000e1.8.auto
[realsense2_camera_node-1]  13/01 21:42:00,997 WARNING [128721914689088] (backend-hid.cpp:1285) Failed to read busnum/devnum. Custom HID Device Path: /sys/bus/platform/drivers/hid_sensor_custom/HID-SENSOR-2000e1.14.auto
[realsense2_camera_node-1]  13/01 21:42:00,997 WARNING [128721914689088] (backend-hid.cpp:1285) Failed to read busnum/devnum. Custom HID Device Path: /sys/bus/platform/drivers/hid_sensor_custom/HID-SENSOR-2000e1.7.auto
[realsense2_camera_node-1]  13/01 21:42:00,997 WARNING [128721914689088] (backend-hid.cpp:1285) Failed to read busnum/devnum. Custom HID Device Path: /sys/bus/platform/drivers/hid_sensor_custom/HID-SENSOR-2000e1.13.auto
[realsense2_camera_node-1]  13/01 21:42:00,997 WARNING [128721914689088] (backend-hid.cpp:1285) Failed to read busnum/devnum. Custom HID Device Path: /sys/bus/platform/drivers/hid_sensor_custom/HID-SENSOR-2000e1.18.auto
[realsense2_camera_node-1]  13/01 21:42:00,997 WARNING [128721914689088] (backend-hid.cpp:1285) Failed to read busnum/devnum. Custom HID Device Path: /sys/bus/platform/drivers/hid_sensor_custom/HID-SENSOR-2000e1.5.auto
[realsense2_camera_node-1]  13/01 21:42:00,997 WARNING [128721914689088] (backend-hid.cpp:1285) Failed to read busnum/devnum. Custom HID Device Path: /sys/bus/platform/drivers/hid_sensor_custom/HID-SENSOR-2000e1.11.auto
[realsense2_camera_node-1] [INFO] [1768308121.006388624] [camera.camera]: Device with serial number 335122271196 was found.
[realsense2_camera_node-1] 
[realsense2_camera_node-1] [INFO] [1768308121.006432472] [camera.camera]: Device with physical ID /sys/devices/pci0000:00/0000:00:14.0/usb4/4-1/4-1.3/4-1.3:1.0/video4linux/video2 was found.
[realsense2_camera_node-1] [INFO] [1768308121.006441528] [camera.camera]: Device with name Intel RealSense D405 was found.
[realsense2_camera_node-1] [INFO] [1768308121.006589007] [camera.camera]: Device with port number 4-1.3 was found.
[realsense2_camera_node-1] [INFO] [1768308121.006599079] [camera.camera]: Device USB type: 3.2
[realsense2_camera_node-1] [INFO] [1768308121.006655540] [camera.camera]: getParameters...
[realsense2_camera_node-1] [INFO] [1768308121.007033815] [camera.camera]: JSON file is not provided
[realsense2_camera_node-1] [INFO] [1768308121.007072844] [camera.camera]: Device Name: Intel RealSense D405
[realsense2_camera_node-1] [INFO] [1768308121.007103481] [camera.camera]: Device Serial No: 335122271196
[realsense2_camera_node-1] [INFO] [1768308121.007130652] [camera.camera]: Device physical port: /sys/devices/pci0000:00/0000:00:14.0/usb4/4-1/4-1.3/4-1.3:1.0/video4linux/video2
[realsense2_camera_node-1] [INFO] [1768308121.007159144] [camera.camera]: Device FW version: 5.17.0.10
[realsense2_camera_node-1] [INFO] [1768308121.007191029] [camera.camera]: Device Product ID: 0x0B5B
[realsense2_camera_node-1] [INFO] [1768308121.007215837] [camera.camera]: Sync Mode: Off
[realsense2_camera_node-1] [INFO] [1768308121.112373907] [camera.camera]: Set ROS param depth_module.depth_profile to default: 848x480x30
[realsense2_camera_node-1] [INFO] [1768308121.112698487] [camera.camera]: Set ROS param depth_module.color_profile to default: 848x480x30
[realsense2_camera_node-1] [INFO] [1768308121.113008561] [camera.camera]: Set ROS param depth_module.infra_profile to default: 848x480x30
[realsense2_camera_node-1] [INFO] [1768308121.115045004] [camera.camera]: Stopping Sensor: Depth Module
[realsense2_camera_node-1] [INFO] [1768308121.120084430] [camera.camera]: Starting Sensor: Depth Module
[realsense2_camera_node-1] [INFO] [1768308121.122817793] [camera.camera]: Open profile: stream_type: Color(0), Format: RGB8, Width: 848, Height: 480, FPS: 30
[realsense2_camera_node-1] [INFO] [1768308121.122842999] [camera.camera]: Open profile: stream_type: Depth(0), Format: Z16, Width: 848, Height: 480, FPS: 30
[realsense2_camera_node-1] [INFO] [1768308121.124974433] [camera.camera]: RealSense Node Is Up!

 

3.2 ArUco Detection

 'ros2_aruco' 패키지를 설치 및 실행하여 '/aruco_poses' 토픽을 발행한다.

newhaneul@newhaneul-950QDB:~/handeye$ colcon build --symlink-install
Starting >>> easy_handeye2_msgs
Starting >>> ros2_aruco
Starting >>> ros2_aruco_interfaces
Finished <<< ros2_aruco [0.89s]                                        
Finished <<< ros2_aruco_interfaces [3.84s]                                 
Finished <<< easy_handeye2_msgs [14.4s]                       
Starting >>> easy_handeye2
Finished <<< easy_handeye2 [0.79s]           

Summary: 4 packages finished [15.5s]

newhaneul@newhaneul-950QDB:~/handeye$ source install/setup.bash

 

터미널 2

newhaneul@newhaneul-950QDB:~/handeye$ PYTHONNOUSERSITE=1 ros2 launch ros2_aruco aruco_recognition.launch.py
[INFO] [launch]: All log files can be found below /home/newhaneul/.ros/log/2026-01-13-21-49-11-291250-newhaneul-950QDB-13868
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [aruco_node-1]: process started with pid [13869]
[aruco_node-1] [INFO] [1768308551.798582214] [aruco_node]: Marker size: 0.12
[aruco_node-1] [INFO] [1768308551.798879664] [aruco_node]: Marker type: DICT_ARUCO_ORIGINAL
[aruco_node-1] [INFO] [1768308551.799129939] [aruco_node]: Image topic: /camera/camera/color/image_rect_raw
[aruco_node-1] [INFO] [1768308551.799369250] [aruco_node]: Image info topic: /camera/camera/color/camera_info

 

터미널 3

newhaneul@newhaneul-950QDB:~/handeye/calib$ python3 aruco_tf.py
[INFO] [1768308721.850600480] [aruco_tf_broadcaster]: ArUco TF Broadcaster has started!

 

3.3 TF Broadcasting (Custom Node)

 '/aruco_poses'는 단순 데이터일 뿐이므로, 이를 TF(camera -> marker)로 변환해주는 Python 노드를 작성하여 실행함.

  • Node Name: aruco_tf_broadcaster
  • Input Topic: /aruco_poses (ros2_aruco_interfaces/msg/ArucoMarkers)
  • Output TF: camera_color_optical_frame -> aruco_marker_0

 

4. Calibration Execution (Easy Handeye)

 

4.1 Frames Configuration

 Calibration을 위한 TF 체인 설정.

  • Robot Base (고정): base
  • Robot Effector (움직임): ee_right
  • Tracking Base (카메라): camera_color_optical_frame
  • Tracking Marker (마커): aruco_marker_0

이제 UPC에서 로봇 pose publish을 하기 위해 RB-Y1을 구동 및 상태 발행 (Robot Bringup) 한다. Calibration tool은 현재 로봇 팔이 어디에 있는지 알아야 한다. 이 과정은 로봇 내부 PC인 UPC에서 드라이버를 실행하여, 로봇의 관절 상태 '/joint_states'와 링크 간의 변환 정보 '/tf'를 네트워크로 뿌려준다.

 

  • 🤖 로봇 터미널에서: 

터미널 4

nvidia@tegra-ubuntu:~$ export CYCLONEDDS_URI=file:///home/newhaneul/cyclonedds.xml
nvidia@tegra-ubuntu:~$ ros2 launch rby1_bringup bringup.launch.py robot_ip:=192.168.30.1:50051
[INFO] [launch]: All log files can be found below /home/nvidia/.ros/log/2026-01-13-14-01-17-087131-tegra-ubuntu-100665
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [robot_state_publisher-1]: process started with pid [100671]
[INFO] [ros2_control_node-2]: process started with pid [100673]
[INFO] [ros2-3]: process started with pid [100675]
[INFO] [spawner-4]: process started with pid [100677]
[robot_state_publisher-1] [WARN] [1768312877.620697714] [kdl_parser]: Converting unknown joint type of joint 'world_to_base' into a fixed joint
[robot_state_publisher-1] [INFO] [1768312877.621953529] [robot_state_publisher]: got segment base
[robot_state_publisher-1] [INFO] [1768312877.622722346] [robot_state_publisher]: got segment ee_finger_l1
[robot_state_publisher-1] [INFO] [1768312877.622752810] [robot_state_publisher]: got segment ee_finger_l2
[robot_state_publisher-1] [INFO] [1768312877.622765897] [robot_state_publisher]: got segment ee_finger_r1
[robot_state_publisher-1] [INFO] [1768312877.622775945] [robot_state_publisher]: got segment ee_finger_r2
[robot_state_publisher-1] [INFO] [1768312877.622785257] [robot_state_publisher]: got segment ee_left
[robot_state_publisher-1] [INFO] [1768312877.622794665] [robot_state_publisher]: got segment ee_right
[robot_state_publisher-1] [INFO] [1768312877.622803753] [robot_state_publisher]: got segment link_head_0
[robot_state_publisher-1] [INFO] [1768312877.622813961] [robot_state_publisher]: got segment link_head_1
[robot_state_publisher-1] [INFO] [1768312877.622822824] [robot_state_publisher]: got segment link_head_2
[robot_state_publisher-1] [INFO] [1768312877.622832424] [robot_state_publisher]: got segment link_left_arm_0
[robot_state_publisher-1] [INFO] [1768312877.622841608] [robot_state_publisher]: got segment link_left_arm_1
[robot_state_publisher-1] [INFO] [1768312877.622850632] [robot_state_publisher]: got segment link_left_arm_2
[robot_state_publisher-1] [INFO] [1768312877.622859688] [robot_state_publisher]: got segment link_left_arm_3
[robot_state_publisher-1] [INFO] [1768312877.622868775] [robot_state_publisher]: got segment link_left_arm_4
[robot_state_publisher-1] [INFO] [1768312877.622877863] [robot_state_publisher]: got segment link_left_arm_5
[robot_state_publisher-1] [INFO] [1768312877.622887239] [robot_state_publisher]: got segment link_left_arm_6
[robot_state_publisher-1] [INFO] [1768312877.622895815] [robot_state_publisher]: got segment link_right_arm_0
[robot_state_publisher-1] [INFO] [1768312877.622904615] [robot_state_publisher]: got segment link_right_arm_1
[robot_state_publisher-1] [INFO] [1768312877.622913319] [robot_state_publisher]: got segment link_right_arm_2
[robot_state_publisher-1] [INFO] [1768312877.622922086] [robot_state_publisher]: got segment link_right_arm_3
[robot_state_publisher-1] [INFO] [1768312877.622931302] [robot_state_publisher]: got segment link_right_arm_4
[robot_state_publisher-1] [INFO] [1768312877.622940358] [robot_state_publisher]: got segment link_right_arm_5
[robot_state_publisher-1] [INFO] [1768312877.622949414] [robot_state_publisher]: got segment link_right_arm_6
[robot_state_publisher-1] [INFO] [1768312877.622959206] [robot_state_publisher]: got segment link_torso_0
[robot_state_publisher-1] [INFO] [1768312877.622967814] [robot_state_publisher]: got segment link_torso_1
[robot_state_publisher-1] [INFO] [1768312877.622976709] [robot_state_publisher]: got segment link_torso_2
[robot_state_publisher-1] [INFO] [1768312877.622987269] [robot_state_publisher]: got segment link_torso_3
[robot_state_publisher-1] [INFO] [1768312877.622996165] [robot_state_publisher]: got segment link_torso_4
[robot_state_publisher-1] [INFO] [1768312877.623005445] [robot_state_publisher]: got segment link_torso_5
[robot_state_publisher-1] [INFO] [1768312877.623014341] [robot_state_publisher]: got segment wheel_l
[robot_state_publisher-1] [INFO] [1768312877.623022852] [robot_state_publisher]: got segment wheel_r
[robot_state_publisher-1] [INFO] [1768312877.623031972] [robot_state_publisher]: got segment world
[ros2_control_node-2] [WARN] [1768312877.657896604] [controller_manager]: [Deprecated] Passing the robot description parameter directly to the control_manager node is deprecated. Use '~/robot_description' topic from 'robot_state_publisher' instead.
[ros2_control_node-2] [INFO] [1768312877.658677004] [resource_manager]: Loading hardware 'rby1_hardware' 
[ros2_control_node-2] [INFO] [1768312877.707944299] [resource_manager]: Initialize hardware 'rby1_hardware' 
[ros2_control_node-2] [INFO] [1768312877.725463029] [rby1_hw_node]: Joint commands publishing initially DISABLED (will be enabled by MoveIt action)
[ros2_control_node-2] [INFO] [1768312877.727502157] [rby1_hw_node]: Created service: /rby1_hardware/enable_joint_commands
[ros2_control_node-2] [INFO] [1768312877.727586699] [resource_manager]: Successful initialization of hardware 'rby1_hardware'
[ros2_control_node-2] [INFO] [1768312877.727925669] [resource_manager]: 'configure' hardware 'rby1_hardware' 
[ros2_control_node-2] Control Manager state is normal. No faults detected.
[ros2_control_node-2] Enabling Control Manager...
[ros2_control_node-2] Control Manager enabled successfully.
[ros2_control_node-2] [INFO] [1768312877.748975690] [resource_manager]: Successful 'configure' of hardware 'rby1_hardware'
[ros2_control_node-2] [INFO] [1768312877.749065544] [resource_manager]: 'activate' hardware 'rby1_hardware' 
[ros2_control_node-2] [INFO] [1768312877.751334972] [rby1_hw_node]: 🔄 Starting spin thread for service handling
[ros2_control_node-2] [INFO] [1768312877.751425786] [resource_manager]: Successful 'activate' of hardware 'rby1_hardware'
[ros2_control_node-2] [INFO] [1768312877.761652850] [controller_manager]: update rate is 20 Hz
[ros2_control_node-2] [INFO] [1768312877.761726801] [controller_manager]: Spawning controller_manager RT thread with scheduler priority: 50
[ros2_control_node-2] [WARN] [1768312877.761964268] [controller_manager]: No real-time kernel detected on this system. See [https://control.ros.org/master/doc/ros2_control/controller_manager/doc/userdoc.html] for details on how to enable realtime scheduling.
[spawner-4] [INFO] [1768312878.183841759] [spawner_rby1_wholebody_controller]: waiting for service /controller_manager/list_controllers to become available...
[ros2-3] could not connect to display 
[ros2-3] This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
[ros2-3] 
[ros2-3] Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, xcb.
[ros2-3] 
[ros2-3] [ros2run]: Process exited with failure 1
[ERROR] [ros2-3]: process has died [pid 100675, exit code 1, cmd 'ros2 run rqt_controller_manager rqt_controller_manager --force-discover'].
[ros2_control_node-2] [INFO] [1768312878.938734377] [controller_manager]: Loading controller 'rby1_wholebody_controller'
[ros2_control_node-2] [WARN] [1768312878.991966041] [rby1_wholebody_controller]: [Deprecated]: "allow_nonzero_velocity_at_trajectory_end" is set to true. The default behavior will change to false.
[spawner-4] [INFO] [1768312879.015159828] [spawner_rby1_wholebody_controller]: Loaded rby1_wholebody_controller
[ros2_control_node-2] [INFO] [1768312879.017226604] [controller_manager]: Configuring controller 'rby1_wholebody_controller'
[ros2_control_node-2] [INFO] [1768312879.018620689] [rby1_wholebody_controller]: No specific joint names are used for command interfaces. Using 'joints' parameter.
[ros2_control_node-2] [INFO] [1768312879.018770286] [rby1_wholebody_controller]: Command interfaces are [position] and state interfaces are [position].
[ros2_control_node-2] [INFO] [1768312879.018875756] [rby1_wholebody_controller]: Using 'splines' interpolation method.
[ros2_control_node-2] [INFO] [1768312879.021127456] [rby1_wholebody_controller]: Controller state will be published at 100.00 Hz.
[ros2_control_node-2] [INFO] [1768312879.028322931] [rby1_wholebody_controller]: Goals with partial set of joints are allowed
[ros2_control_node-2] [INFO] [1768312879.028397682] [rby1_wholebody_controller]: Action status changes will be monitored at 50.00 Hz.
[spawner-4] [INFO] [1768312879.164640748] [spawner_rby1_wholebody_controller]: Configured and activated rby1_wholebody_controller
[INFO] [spawner-4]: process has finished cleanly [pid 100677]

 

 

  • 💻 노트북 터미널에서: 데이터가 잘 넘어오는지 확인

터미널 5

newhaneul@newhaneul-950QDB:~/handeye$ ros2 topic echo /joint_stateses

 

4.2 캘리브레이션 툴 실행 (Easy Handeye Launch)

 easy_handeye2 프로그램을 실행한다. 이 프로그램은 [로봇의 손 위치]와 [카메라가 본 마커 위치] 두 가지 데이터를 받아, 방정식을 풀 준비를 한다.

  • eye_in_hand: 카메라가 로봇 손에 달려 있음을 명시
  • tracking_base_frame: 카메라의 기준 좌표계
  • tracking_marker_frame: 카메라가 보고 있는 타겟(마커) 좌표계

 

터미널 6

newhaneul@newhaneul-950QDB:~/handeye$ ros2 launch easy_handeye2 calibrate.launch.py \
  name:=right_arm_handeye \
  calibration_type:=eye_in_hand \
  robot_base_frame:=base \
  robot_effector_frame:=ee_right \
  tracking_base_frame:=camera_color_optical_frame \
  tracking_marker_frame:=aruco_marker_0
Package 'easy_handeye2' not found: "package 'easy_handeye2' not found, searching: ['/opt/ros/humble']"
newhaneul@newhaneul-950QDB:~/handeye$ source install/setup.bash
newhaneul@newhaneul-950QDB:~/handeye$ ros2 pkg list | grep easy_handeye2
easy_handeye2
easy_handeye2_msgs
newhaneul@newhaneul-950QDB:~/handeye$ ros2 launch easy_handeye2 calibrate.launch.py \
  name:=right_arm_handeye \
  calibration_type:=eye_in_hand \
  robot_base_frame:=base \
  robot_effector_frame:=ee_right \
  tracking_base_frame:=camera_color_optical_frame \
  tracking_marker_frame:=aruco_marker_0
[INFO] [launch]: All log files can be found below /home/newhaneul/.ros/log/2026-01-13-22-30-55-308131-newhaneul-950QDB-15611
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [static_transform_publisher-1]: process started with pid [15612]
[INFO] [handeye_server-2]: process started with pid [15614]
[INFO] [rqt_calibrator.py-3]: process started with pid [15616]
[static_transform_publisher-1] [INFO] [1768311055.368351454] [dummy_publisher]: Spinning until stopped - publishing transform
[static_transform_publisher-1] translation: ('0.000000', '0.000000', '0.100000')
[static_transform_publisher-1] rotation: ('0.000000', '0.000000', '0.000000', '1.000000')
[static_transform_publisher-1] from 'ee_right' to 'camera_color_optical_frame'
[handeye_server-2] [INFO] [1768311055.895432978] [handeye_server]: Read parameters for calibration "right_arm_handeye"
[rqt_calibrator.py-3] [INFO] [1768311056.481234427] [handeye_rqt_calibrator]: Configuring HandeyeClient for calibration with namespace: right_arm_handeye
[rqt_calibrator.py-3] [INFO] [1768311056.481554733] [handeye_rqt_calibrator]: Waiting for sampling services
[handeye_server-2] [INFO] [1768311057.901105952] [handeye_server]: Checking that the expected transforms are available in tf
[handeye_server-2] [INFO] [1768311057.901658401] [handeye_server]: Robot transform: base -> ee_right
[handeye_server-2] [INFO] [1768311057.902060922] [handeye_server]: Tracking transform: camera_color_optical_frame -> aruco_marker_0

 

 

 

 

728x90