TurtleBot3 Burger에 Raspberry Pi Camera Module 2 설정하기

1. TurtleBot3 SBC 기본 ROS 2 환경 확인

먼저 TurtleBot3 SBC에 SSH로 접속합니다.

Remote PC에서 다음과 같이 접속합니다.

예를 들어 Raspberry Pi IP가 192.168.0.20이면 다음과 같이 접속합니다.

ssh sjyong@192.168.210.12

접속 후 ROS 2 Humble 환경이 정상적으로 잡혀 있는지 확인합니다.

printenv | grep ROS

다음과 비슷한 값이 보여야 합니다.

ROS_VERSION=2
ROS_PYTHON_VERSION=3
ROS_DISTRO=humble
ROS_DOMAIN_ID=30

만약 ROS_DISTRO=humble이 보이지 않는다면 다음 명령으로 ROS 2 환경을 적용합니다.

source /opt/ros/humble/setup.bash

TurtleBot3 워크스페이스까지 사용 중이라면 다음도 적용합니다.

source ~/turtlebot3_ws/install/setup.bash

매번 자동으로 적용되게 하려면 .bashrc에 들어 있는지 확인합니다.

nano ~/.bashrc

다음 내용이 없다면 추가합니다. 적용되어 아래의 과정을 있으면 생략하세요.

source /opt/ros/humble/setup.bash
source ~/turtlebot3_ws/install/setup.bash
export ROS_DOMAIN_ID=200

수정 후 적용합니다.

source ~/.bashrc

2. ROS_DOMAIN_ID 확인

TurtleBot3 SBC와 Remote PC에서 서로 ROS 2 토픽을 주고받으려면 ROS_DOMAIN_ID가 같아야 합니다.

TurtleBot3 매뉴얼에서는 기본적으로 30 사용을 권장합니다. 따라서 TurtleBot3 SBC와 Remote PC 양쪽 모두 다음과 같이 설정합니다.

TurtleBot3 SBC에서 실행합니다.

echo 'export ROS_DOMAIN_ID=200 #TURTLEBOT3' >> ~/.bashrc
source ~/.bashrc

Remote PC에서도 실행합니다.

echo 'export ROS_DOMAIN_ID=200 #TURTLEBOT3' >> ~/.bashrc
source ~/.bashrc

확인은 다음 명령으로 합니다.

echo $ROS_DOMAIN_ID

출력값이 다음과 같으면 됩니다.

200

주의할 점이 있습니다. 같은 네트워크에 다른 ROS 2 장비가 있고 동일한 ROS_DOMAIN_ID를 사용하고 있다면 토픽이 섞일 수 있습니다. 실습실이나 교육장에서는 다른 조와 겹치지 않도록 Domain ID를 조정하셔야 합니다.

3. 카메라 설정 방식 선택

Raspberry Pi Camera Module 2는 CSI 카메라이므로 기본적으로는 libcamera 기반 방식이 더 적합합니다.

따라서 권장 방식은 다음과 같습니다.

권장 방식: camera-ros 패키지 사용
드라이버 구조: libcamera 기반
적합한 카메라: Raspberry Pi Camera Module 2, Camera Module 3 등 CSI 카메라

대체 방식은 다음과 같습니다.

대체 방식: v4l2_camera 패키지 사용
드라이버 구조: V4L2 기반
적합한 카메라: USB 카메라 또는 legacy camera stack을 사용하는 환경

실제 Raspberry Pi Camera Module 2를 TurtleBot3 Burger에 장착했다면 먼저 camera-ros 방식으로 시도하는 것이 좋습니다. 이 방식이 정상 동작하지 않거나 기존 프로젝트가 /dev/video0 기반으로 구성되어 있다면 v4l2_camera 방식을 검토하시면 됩니다.

4. camera-ros 방식으로 Raspberry Pi Camera 설정하기

먼저 TurtleBot3 SBC에서 패키지 목록을 업데이트합니다.

sudo apt update

필요한 도구를 설치합니다.

sudo apt install -y python3-pip git python3-jinja2 \
libboost-dev libgnutls28-dev openssl libtiff-dev pybind11-dev \
qtbase5-dev libqt5core5a libqt5widgets5 meson cmake \
python3-yaml python3-ply \
libglib2.0-dev libgstreamer-plugins-base1.0-dev

다음으로 ROS 2 Humble용 camera-ros 패키지를 설치합니다.

sudo apt install ros-humble-camera-ros

각 패키지의 역할은 다음과 같습니다.

python3-jinja2, python3-ply : libcamera 빌드 과정에서 필요한 Python 도구
meson, cmake, ninja 계열 도구 : libcamera 빌드에 필요한 빌드 시스템
libglib2.0-dev, gstreamer 관련 패키지 : 영상 처리 및 스트리밍 관련 라이브러리
ros-humble-camera-ros : libcamera 기반 카메라 영상을 ROS 2 토픽으로 발행하는 패키지

5. Raspberry Pi용 libcamera 소스 내려받기

ROBOTIS 매뉴얼에서는 Raspberry Pi 카메라 모듈과의 호환성을 위해 Raspberry Pi 공식 libcamera 포크를 빌드하는 방법을 안내합니다.

TurtleBot3 SBC에서 다음 명령을 실행합니다.

cd download
git clone -b v0.5.2 https://github.com/raspberrypi/libcamera.git

다운로드가 완료되면 libcamera 디렉터리가 생성됩니다.

ls

다음과 같이 libcamera 폴더가 보이면 정상입니다.

libcamera

6. libcamera 빌드 및 설치

이제 libcamera를 빌드합니다.

cd libcamera

meson setup build --buildtype=release -Dpipelines=rpi/vc4,rpi/pisp -Dipas=rpi/vc4,rpi/pisp -Dv4l2=true -Dgstreamer=enabled -Dtest=false -Dlc-compliance=disabled -Dcam=disabled -Dqcam=disabled -Ddocumentation=disabled -Dpycamera=enabled

ninja -C build -j 1

sudo ninja -C build install -j 1

위의 명령어 실행 시 meson이 0.63 버전을 요구하는 에러가 발생할 경우에는 아래의 과정을 실행하세요.

cd ~/libcamera
python3 -m pip install --user --upgrade meson
~/.local/bin/meson --version

아래의 명령어들을 실행합니다.

cd /home/sjyong/download/libcamera

rm -rf build

PATH=/home/sjyong/.local/bin:$PATH \
PYTHONPATH=/home/sjyong/.local/lib/python3.10/site-packages \
/home/sjyong/.local/bin/meson setup build \
  --buildtype=release \
  -Dpipelines=rpi/vc4 \
  -Dipas=rpi/vc4 \
  -Dv4l2=true \
  -Dgstreamer=enabled \
  -Dtest=false \
  -Dlc-compliance=disabled \
  -Dcam=disabled \
  -Dqcam=disabled \
  -Ddocumentation=disabled \
  -Dpycamera=enabled

ninja -C build -j1

sudo ninja -C build install -j 1

설치 시 meson의 설치 문제로 아래와 같이 에러가 발생할 수 있습니다.

sudo env \
PATH=/home/sjyong/.local/bin:$PATH \
PYTHONPATH=/home/sjyong/.local/lib/python3.10/site-packages \
/home/sjyong/.local/bin/meson install -C build --no-rebuild

라이브러리 캐시를 갱신합니다.

sudo ldconfig

마지막으로 설치된 libcamera 경로를 환경 변수에 추가합니다.

export LD_LIBRARY_PATH=/usr/local/lib/aarch64-linux-gnu:$LD_LIBRARY_PATH

매번 자동 적용되도록 .bashrc에도 추가합니다.

echo 'export LD_LIBRARY_PATH=/usr/local/lib/aarch64-linux-gnu:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc

재부팅을 수행합니다.

7. 카메라 인식 확인

카메라 노드를 실행하기 전에 Raspberry Pi에서 카메라가 인식되는지 먼저 확인하는 것이 좋습니다.

다음 명령을 실행합니다.

ls /dev/video*

환경에 따라 /dev/video0가 보일 수도 있고, libcamera 기반에서는 전통적인 /dev/video0 확인만으로 판단이 어려울 수도 있습니다.

다음 명령도 확인합니다.

sudo dmesg | grep -i camera

또는 IMX219 센서가 잡혔는지 확인합니다.

sudo dmesg | grep -i imx219

Raspberry Pi Camera Module 2는 IMX219 센서를 사용하므로, 관련 메시지가 보이면 카메라 연결이 어느 정도 인식된 것입니다.

만약 아무것도 보이지 않는다면 다음을 확인하셔야 합니다.

1. 카메라 리본 케이블 방향이 맞는지 확인합니다.
2. 카메라 커넥터가 완전히 잠겼는지 확인합니다.
3. Raspberry Pi 전원을 완전히 껐다가 다시 켭니다.
4. /boot/firmware/config.txt 설정이 꼬여 있지 않은지 확인합니다.
5. legacy camera stack 설정과 libcamera 설정을 동시에 섞어 쓰고 있지 않은지 확인합니다.

특히 camera-ros 방식을 사용할 때는 legacy camera stack 설정을 강제로 켜지 않는 것이 좋습니다.

8. TurtleBot3 카메라 노드 실행

이제 TurtleBot3 SBC에서 카메라 노드를 실행합니다.

ros2 launch turtlebot3_bringup camera.launch.py

위의 명령으로 실행할 경우 rqt의 image_view로 볼 수 없는 경우 NV12 포맷이 지원되지 않기 때문입니다.

먼저 다음과 같이 파라미터를 변경하여 카메라 토픽이 정상적으로 발행되는지를 확인합니다.

ros2 launch turtlebot3_bringup camera.launch.py format:=BGR888

rqt

정상적으로 이미지가 출력됩니다.

/image_raw/compressed 토픽을 보거나 사용하려면 보통 compressed_image_transport 패키지가 필요합니다.

sudo apt install ros-humble-compressed-image-transport

아래의 명령어로 launch 파일의 위치를 찾습니다.

ros2 pkg prefix turtlebot3_bringup

아래의 명령어는 이미지의 폭과 높이도 수정한 것입니다. 폭은 640에서 320으로, 높이는 480에서 240으로 모두 반으로 줄인것입니다.

ros2 launch turtlebot3_bringup camera.launch.py format:=BGR888 width:=320 height:=240

정상적으로 실행되면 카메라 노드가 올라오고, ROS 2 토픽으로 카메라 영상이 발행됩니다.

다른 터미널을 열어 TurtleBot3 SBC에 다시 SSH 접속한 뒤 토픽 목록을 확인합니다.

ros2 topic list

다음과 비슷한 카메라 관련 토픽이 보여야 합니다.

/camera/camera_info
/camera/image_raw
/camera/image_raw/compressed

토픽 이름은 패키지 버전이나 launch 설정에 따라 약간 달라질 수 있습니다. 중요한 것은 image_raw 또는 compressed 이미지 토픽이 발행되고 있는지입니다.

토픽이 실제로 발행되는지 확인하려면 다음 명령을 사용합니다.

ros2 topic hz /camera/image_raw

정상이라면 다음과 비슷하게 주기가 출력됩니다.

average rate: 30.000

압축 이미지 토픽을 확인하려면 다음과 같이 실행합니다.

ros2 topic hz /camera/image_raw/compressed

9. Remote PC에서 카메라 이미지 확인하기

카메라 영상은 TurtleBot3 SBC에서 발행되고, Remote PC에서 확인할 수 있습니다.

Remote PC에서 ROS 2 Humble 환경을 적용합니다.

source /opt/ros/humble/setup.bash
source ~/.bashrc

Domain ID를 확인합니다.

echo $ROS_DOMAIN_ID

TurtleBot3 SBC와 같은 값이어야 합니다.

200

Remote PC에서 토픽이 보이는지 확인합니다.

ros2 topic list

TurtleBot3 SBC에서 발행 중인 카메라 토픽이 Remote PC에서도 보여야 합니다.

/camera/image_raw
/camera/image_raw/compressed
/camera/camera_info

이제 rqt_image_view를 실행합니다.

rqt_image_view

GUI 창이 열리면 상단의 토픽 선택 박스에서 다음 중 하나를 선택합니다.

/camera/image_raw

또는 네트워크 지연이 있다면 압축 토픽을 선택합니다.

/camera/image_raw/compressed

정상이라면 TurtleBot3 Burger에 장착된 Raspberry Pi Camera Module 2의 영상이 Remote PC 화면에 출력됩니다.

10. image_raw와 compressed 토픽 선택 기준

카메라 영상 확인 시 /camera/image_raw/camera/image_raw/compressed 중 어떤 것을 선택할지 고민될 수 있습니다.

기준은 간단합니다.

/camera/image_raw
- 압축되지 않은 원본 이미지입니다.
- 영상 처리 노드에서 바로 사용하기 좋습니다.
- 네트워크 대역폭을 많이 사용합니다.
- Wi-Fi 환경이 좋지 않으면 지연이 커질 수 있습니다.

/camera/image_raw/compressed
- 압축된 이미지입니다.
- Remote PC에서 화면 확인할 때 유리합니다.
- 네트워크 부하가 줄어듭니다.
- 압축과 해제 과정에서 약간의 처리 비용이 생깁니다.

TurtleBot3 Burger를 Wi-Fi로 운용한다면 화면 확인용으로는 /camera/image_raw/compressed 사용이 더 안정적입니다.

영상 처리 알고리즘을 TurtleBot3 SBC 내부에서 직접 실행한다면 /camera/image_raw를 사용하는 것이 일반적입니다.

11. 정상 설치 오류 시 고려할 사항들

1) 빌드 디렉터리 소유권 복구

cd ~/download/libcamera

sudo chown -R "$USER":"$USER" build

소유권을 확인합니다.

find build ! -user "$USER" -ls

아무 출력도 없어야 정상입니다.

특히 문제가 발생한 디렉터리를 확인합니다.

ls -ld \
  build \
  build/meson-logs \
  build/meson-private

모두 다음처럼 sjyong sjyong 소유여야 합니다.

drwxr-xr-x ... sjyong sjyong ...

2) 기존 설치 로그 삭제

rm -f build/meson-logs/install-log.txt

로그 디렉터리에 쓰기 권한을 복구합니다.

chmod u+rwx build/meson-logs build/meson-private

3) staging 디렉터리도 새로 생성

rm -rf "$HOME/libcamera-install-stage"
mkdir -p "$HOME/libcamera-install-stage"

소유권을 확인합니다.

ls -ld "$HOME/libcamera-install-stage"

4) sudo 없이 staging 설치

~/.local/bin/meson install \
  -C build \
  --destdir="$HOME/libcamera-install-stage" \
  --no-rebuild

정상 설치되면 다음을 확인합니다.

find "$HOME/libcamera-install-stage" -maxdepth 5 -type f | head -30

일반적으로 다음 구조가 생성됩니다.

/home/sjyong/libcamera-install-stage/usr/local/bin/cam
/home/sjyong/libcamera-install-stage/usr/local/lib/...
/home/sjyong/libcamera-install-stage/usr/local/include/...

5) 시스템에 복사

tar -C "$HOME/libcamera-install-stage" -cf - . \
  | sudo tar --no-same-owner -C / -xf -

라이브러리 캐시를 갱신합니다.

sudo ldconfig

6) 설치 확인

find /usr/local -type f \
  \( -name 'cam' \
  -o -name 'libcamera.so*' \
  -o -name 'libcamera-base.so*' \) \
  2>/dev/null
ldconfig -p | grep -E 'libcamera|libcamera-base'
/usr/local/bin/cam -l

7) libcamera 0.5.0 설치 상태부터 확인

MULTIARCH="$(dpkg-architecture -qDEB_HOST_MULTIARCH)"

echo "MULTIARCH=$MULTIARCH"

echo "===== 기본 pkg-config ====="
pkg-config --modversion libcamera
pkg-config --variable=pcfiledir libcamera

echo "===== /usr/local 우선 pkg-config ====="
PKG_CONFIG_PATH="/usr/local/lib/${MULTIARCH}/pkgconfig:/usr/local/lib/pkgconfig" \
pkg-config --modversion libcamera

PKG_CONFIG_PATH="/usr/local/lib/${MULTIARCH}/pkgconfig:/usr/local/lib/pkgconfig" \
pkg-config --variable=pcfiledir libcamera

정상적인 결과는 다음과 비슷해야 합니다.

0.5.0
/usr/local/lib/aarch64-linux-gnu/pkgconfig

기본 pkg-config에서는 0.1.0, /usr/local 우선 설정에서는 0.5.0이 나온다면 원인이 확정됩니다.

설치 파일도 확인합니다.

find /usr/local/lib \
  \( -name 'libcamera.so*' -o -name 'libcamera-base.so*' \) \
  -ls

그리고 cam 프로그램이 실제로 0.5.0을 사용하는지 확인합니다.

ldd /usr/local/bin/cam | grep -E 'libcamera|libcamera-base'

정상적인 경우:

libcamera.so.0.5 => /usr/local/lib/aarch64-linux-gnu/libcamera.so.0.5
libcamera-base.so.0.5 => /usr/local/lib/aarch64-linux-gnu/libcamera-base.so.0.5

카메라를 직접 실행합니다.

LIBCAMERA_LOG_LEVELS=*:INFO /usr/local/bin/cam -l

여기서는 반드시 다음처럼 나와야 합니다.

libcamera v0.5.0

Raspberry Pi libcamera에서는 cam -l을 기본 카메라 검증 방법으로 사용합니다.

8) 현재 camera_ros가 어느 libcamera에 연결됐는지 확인

CAMERA_COMPONENT="$HOME/turtlebot3_ws/install/camera_ros/lib/libcamera_component.so"

readelf -d "$CAMERA_COMPONENT" \
  | grep NEEDED \
  | grep -E 'libcamera|libcamera-base'

ldd "$CAMERA_COMPONENT" \
  | grep -E 'libcamera|libcamera-base'

현재는 다음처럼 나올 가능성이 높습니다.

libcamera.so.0.1
libcamera-base.so.0.1

또는:

libcamera.so.0.1 => /opt/ros/humble/lib/aarch64-linux-gnu/libcamera.so.0.1

이 경우 LD_LIBRARY_PATH만 바꿔서는 해결되지 않습니다. 바이너리가 libcamera.so.0.1을 요구하기 때문에 camera_ros를 완전히 다시 빌드해야 합니다.

9) 기존 camera_ros 빌드 캐시 제거

실행 중인 카메라 노드를 먼저 종료합니다.

pkill -f component_container || true
pkill -f camera_node || true

워크스페이스에서 camera_ros 빌드 결과만 삭제합니다.

cd ~/turtlebot3_ws

rm -rf build/camera_ros
rm -rf install/camera_ros

소스가 있는지 확인합니다.

colcon list | grep camera_ros

다음처럼 나와야 합니다.

camera_ros    src/camera_ros    (ament_cmake)

없다면 현재 workspace의 실제 소스 경로를 확인합니다.

find ~/turtlebot3_ws/src \
  -name package.xml \
  -exec grep -Hl '<name>camera_ros</name>' {} \;

10) 새 터미널 환경과 동일하게 ROS 환경 구성

기존 workspace의 install/setup.bash는 아직 source하지 마십시오. 기존 0.1.0 경로가 다시 환경에 포함될 수 있습니다.

cd ~/turtlebot3_ws

source /opt/ros/humble/setup.bash

MULTIARCH="$(dpkg-architecture -qDEB_HOST_MULTIARCH)"

export PKG_CONFIG_PATH="/usr/local/lib/${MULTIARCH}/pkgconfig:/usr/local/lib/pkgconfig:${PKG_CONFIG_PATH:-}"

export LD_LIBRARY_PATH="/usr/local/lib/${MULTIARCH}:/usr/local/lib:${LD_LIBRARY_PATH:-}"

export CMAKE_PREFIX_PATH="/usr/local:${CMAKE_PREFIX_PATH:-}"

검색 결과를 반드시 다시 확인합니다.

which pkg-config

pkg-config --modversion libcamera
pkg-config --variable=pcfiledir libcamera
pkg-config --libs libcamera
pkg-config --cflags libcamera

반드시 다음 조건이어야 합니다.

version: 0.5.0
pcfiledir: /usr/local/lib/aarch64-linux-gnu/pkgconfig

여기서 아직 0.1.0이 나오면 재빌드하면 안 됩니다.

11) CMake가 실제로 사용할 파일 확인

LIBCAMERA_PC="$(pkg-config --variable=pcfiledir libcamera)/libcamera.pc"

echo "$LIBCAMERA_PC"
grep -E '^(prefix|libdir|includedir|Version|Libs|Cflags):' "$LIBCAMERA_PC"

정상 예:

prefix=/usr/local
libdir=/usr/local/lib/aarch64-linux-gnu
Version: 0.5.0

prefix=/opt/ros/humble 또는 Version: 0.1.0이면 경로 우선순위가 아직 잘못된 것입니다.

12) camera_ros 완전 재빌드

cd ~/turtlebot3_ws

colcon build \
  --packages-select camera_ros \
  --symlink-install \
  --cmake-clean-cache \
  --cmake-args \
    -DCMAKE_BUILD_TYPE=Release \
  --event-handlers console_direct+

빌드 출력에서 다음과 같은 내용을 확인합니다.

Found libcamera
libcamera version 0.5.0

13) 새 컴포넌트 연결 상태 확인

빌드가 끝난 직후 아직 launch하지 말고 확인합니다.

CAMERA_COMPONENT="$HOME/turtlebot3_ws/install/camera_ros/lib/libcamera_component.so"

readelf -d "$CAMERA_COMPONENT" \
  | grep NEEDED \
  | grep -E 'libcamera|libcamera-base'

ldd "$CAMERA_COMPONENT" \
  | grep -E 'libcamera|libcamera-base'

정상 결과:

libcamera.so.0.5
libcamera-base.so.0.5

그리고:

libcamera.so.0.5 => /usr/local/lib/aarch64-linux-gnu/libcamera.so.0.5
libcamera-base.so.0.5 => /usr/local/lib/aarch64-linux-gnu/libcamera-base.so.0.5

여기서 계속 0.1이 나오면 CMake가 여전히 이전 pkg-config 정보를 사용한 것입니다.

14) 라이브러리 캐시 등록 확인

printf "/usr/local/lib\n/usr/local/lib/%s\n" "$MULTIARCH" \
  | sudo tee /etc/ld.so.conf.d/libcamera-local.conf

sudo ldconfig

확인합니다.

ldconfig -p | grep -E 'libcamera\.so|libcamera-base'

0.5와 0.1이 모두 표시되어도 괜찮습니다. 중요한 것은 새 camera_ros 바이너리가 libcamera.so.0.5를 요구하는 것입니다.

15) 재실행

source /opt/ros/humble/setup.bash
source ~/turtlebot3_ws/install/setup.bash

MULTIARCH="$(dpkg-architecture -qDEB_HOST_MULTIARCH)"

export LD_LIBRARY_PATH="/usr/local/lib/${MULTIARCH}:/usr/local/lib:${LD_LIBRARY_PATH:-}"

ros2 launch turtlebot3_bringup camera.launch.py format:=BGR888

정상적으로 바뀌면 로그가 다음처럼 나와야 합니다.

INFO Camera camera_manager.cpp:... libcamera v0.5.0

Leave a Comment