[Physical AI W1D1 · 4/5]
GPU도 로봇도 없이, 브라우저 안의 Colab 터미널만으로 ROS 2 Humble을 설치하고 Gazebo 시뮬레이터를 headless로 돌려 /clock 토픽까지 흘려보낸다. 모든 리눅스 명령어를 "무엇을·왜·어떤 결과"로 하나씩 풀어 설명하는 Day1 4편(실습).
이 글에서 직접 해보는 것
- Colab 터미널 환경 확인 (Ubuntu 버전·파이썬 버전)
- ROS 2 Humble이 요구하는 Python 3.10으로 맞추기
- ROS 2 Humble 설치 →
talker/listener로 통신 확인- Gazebo를 화면 없이(headless) 실행하고 토픽 들여다보기
- 시뮬레이터의 시간(
/clock)을 ROS 2 세계로 연결하는 브리지
(이 글은 2026년 6월, Physical AI 과정 Week1 Day1 기준입니다. 개념이 궁금하면 먼저 1~3편(개념편)을 보고 오시면 좋습니다.)
들어가며 — 왜 "터미널 실습"부터인가
앞선 1~3편(개념편)에서 피지컬 AI를 "인식 → 판단 → 행동 → 피드백"의 멈추지 않는 순환 고리라고 정리했습니다. 그런데 이 순환 고리를 실제로 돌리려면, 로봇의 여러 모듈이 데이터를 주고받을 통신 기반(ROS 2) 과, 실제 로봇 없이도 검증할 시뮬레이터(Gazebo) 가 먼저 깔려 있어야 합니다.
문제는 "비싼 GPU도, 로봇도, 우분투 PC도 없는데 어떻게 연습하지?"입니다. 이번 실습의 핵심 아이디어가 여기에 있습니다.
💡 이번 실습의 무대 — Colab 터미널
구글 Colab은 사실 우분투 22.04 리눅스 한 대입니다. 노트북 셀이 아니라 터미널을 열면, 그 안에서apt로 ROS 2를 설치하고 Gazebo를 돌릴 수 있습니다. 내 PC를 건드리지 않고, 무료로, 브라우저만으로요.
이번 4편에서 만들 최종 그림은 이렇습니다. (다음 5편에서 이 데이터를 브라우저까지 내보냅니다.)
[ Colab 터미널 = 우분투 리눅스 한 대 ]
Gazebo (headless 시뮬레이터)
│ 시뮬레이션 시간 /clock 생성
▼
ros_gz_bridge ──► ROS 2 /clock 토픽
│
▼
(5편) rclpy 노드가 /clock 구독 → WebSocket → 브라우저

자, 그럼 한 단계씩 직접 쳐보겠습니다. 명령어마다 "무엇을 하는지 / 왜 하는지 / 어떤 결과가 나와야 하는지" 를 같이 적었습니다.
1. 실습 환경 확인 — 지금 내가 선 땅 파악하기
뭐든 설치하기 전에, 지금 이 리눅스가 무엇인지 부터 확인합니다. 엉뚱한 버전 위에서 삽질하지 않으려는 안전장치입니다.
lsb_release -a
python3 --version
- 무엇을:
lsb_release -a는 리눅스 배포판·버전을,python3 --version은 기본 파이썬 버전을 출력합니다. - 왜: ROS 2에는 버전마다 짝이 맞는 우분투/파이썬이 정해져 있습니다. 우리가 설치할 ROS 2 Humble은 우분투 22.04 + Python 3.10 조합을 공식 지원합니다. 이 짝이 맞는지부터 봐야 합니다.
- 기대 결과:
Ubuntu 22.04.x (jammy)가 보이면 OK. 파이썬은 환경에 따라3.10이 아니라3.11/3.12가 기본으로 잡혀 있을 수 있습니다 — 바로 이게 다음 단계에서 손볼 지점입니다.
💡 용어 한 줄 — jammy는 우분투 22.04의 코드네임입니다. ROS 2 Humble 문서에
jammy라고 나오면 "22.04용"이라는 뜻입니다.
2. Python을 3.10으로 맞추기 — Humble의 짝 맞추기
환경에 따라 기본 python3가 3.10이 아닌 버전을 가리키고 있으면, ROS 2 Humble의 파이썬 모듈(rclpy 등)을 불러올 때 버전 불일치로 에러가 납니다. 그래서 python3가 3.10을 가리키도록 바꿔줍니다.
sudo ln -sf /usr/bin/python3.10 /usr/bin/python3
hash -r
- 무엇을:
ln -sf로/usr/bin/python3라는 이름표가 3.10 실행 파일을 가리키도록 심볼릭 링크를 다시 겁니다.hash -r은 셸이 기억하던 옛 경로 캐시를 비웁니다. - 왜: ROS 2 Humble의 파이썬 패키지는 3.10용으로 빌드돼 있습니다.
python3가 다른 버전을 가리키면import rclpy가 깨집니다. 링크를 3.10에 맞추면 이후 모든python3호출이 3.10으로 실행됩니다. - 기대 결과: 다시
python3 --version→Python 3.10.x.hash -r없이 바로 확인하면 옛 버전이 보일 수 있으니 캐시를 꼭 비웁니다.
⚠️ 흔한 함정 ① —
hash -r을 빼먹으면 링크를 바꿔놓고도 셸이 옛 파이썬을 계속 실행해서 "분명 바꿨는데 왜 안 바뀌지?"가 됩니다. 링크 변경 →hash -r→ 버전 재확인을 한 세트로 외우세요.
(참고) Colab이 아니라 GCP VM 등 빈 우분투라면
Colab엔 3.10이 이미 깔려 있어 링크만 바꾸면 되지만, 맨바닥 우분투(GCP VM 등) 라면 3.10 자체를 먼저 설치해야 합니다.
sudo apt update
sudo apt install -y python3.10 python3.10-venv python3.10-dev python3-pip
sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1
- 무엇을: 3.10 본체와 가상환경(
venv)·개발 헤더(dev)·pip를 설치하고,update-alternatives로 시스템 기본python3를 3.10으로 등록합니다. - 왜:
update-alternatives는 여러 파이썬 버전이 있을 때 기본값을 체계적으로 관리하는 우분투의 표준 방식입니다. 단순 심볼릭 링크보다 나중에 버전 전환이 깔끔합니다. - 기대 결과:
python3 --version→Python 3.10.x,pip사용 가능.
3. ROS 2 Humble 설치 — 로봇 모듈들의 공용어 깔기
이제 본론입니다. ROS 2는 로봇의 인식·판단·제어 모듈이 토픽(topic) 으로 데이터를 주고받게 해주는 통신 프레임워크입니다. 1편(개념편)에서 "여러 기술을 연결하는 운영체제 같은 것"이라고 했던 그 ROS 2입니다.
설치는 공식 절차 그대로, 세 덩어리로 나뉩니다.
3-1. 패키지 저장소 등록
sudo apt update && sudo apt install -y curl gnupg lsb-release
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \
-o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] \
http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" \
| sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
- 무엇을: ROS 2 패키지가 올라가 있는 공식 apt 저장소를 우분투에 알려줍니다.
ros.key는 그 저장소가 진짜임을 검증할 GPG 서명 키,ros2.list는 저장소 주소입니다. - 왜: 우분투 기본 저장소엔 ROS 2가 없습니다. 출처를 등록하고 서명 키로 위변조를 검증해야
apt가 ROS 2 패키지를 안전하게 받을 수 있습니다. - 기대 결과: 에러 없이
/etc/apt/sources.list.d/ros2.list파일이 생성됩니다.
3-2. 본체 설치
sudo apt update
sudo apt install -y \
ros-humble-ros-base \
ros-humble-demo-nodes-cpp \
ros-humble-demo-nodes-py \
python3-colcon-common-extensions
- 무엇을:
ros-humble-ros-base(ROS 2 핵심), 통신 확인용 예제 노드(demo-nodes-cpp/demo-nodes-py), 빌드 도구(colcon)를 설치합니다. - 왜:
ros-base는 GUI 없이 통신·실행에 필요한 최소 핵심만 담은 묶음이라 Colab처럼 화면 없는 환경에 딱 맞습니다(데스크톱 GUI까지 든ros-humble-desktop은 더 무겁습니다). 예제 노드는 다음 단계에서 "설치가 정상인지" 확인하는 데 씁니다. - 기대 결과: 수백 MB 다운로드 후 설치 완료. 시간이 조금 걸립니다.
3-3. 환경 변수 등록
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
source ~/.bashrc
- 무엇을: 새 터미널을 열 때마다 ROS 2 환경을 자동으로 불러오도록
~/.bashrc에 한 줄을 추가하고, 지금 셸에도 즉시 적용합니다. - 왜:
setup.bash를 source 해야ros2명령과 ROS 2 환경 변수(어떤 패키지가 어디 있는지 등)가 셸에 잡힙니다. 이걸 안 하면ros2: command not found가 납니다. - 기대 결과:
ros2 --help가 동작. 확인용으로ros2 topic list를 치면/parameter_events,/rosout이 보입니다 — ROS 2가 살아 있다는 신호입니다.
⚠️ 흔한 함정 ② — 새 터미널 탭마다 환경을 다시 잡아야 합니다.
.bashrc에 넣어두면 자동이지만, 스크립트를nohup/&로 백그라운드 실행할 땐 그 안에서source /opt/ros/humble/setup.bash를 명시적으로 다시 해주는 게 안전합니다(5편에서 실제로 그렇게 합니다).
4. talker / listener — "통신이 진짜 되나?" 확인
설치가 끝났으면, ROS 2의 가장 기본 동작인 토픽 통신부터 검증합니다. 한쪽이 말하고(talker) 다른 쪽이 듣는(listener) 가장 단순한 예제입니다.
터미널 두 개(또는 탭 두 개)를 씁니다.
# 터미널 1 — 발행자(말하는 쪽)
ros2 run demo_nodes_cpp talker
# 터미널 2 — 구독자(듣는 쪽)
ros2 run demo_nodes_py listener
- 무엇을:
talker는chatter토픽으로 "Hello World" 메시지를 1초마다 발행하고,listener는 그 토픽을 구독해 받은 메시지를 출력합니다. - 왜: 피지컬 AI의 모든 모듈은 결국 이 발행–구독(pub/sub) 으로 데이터를 주고받습니다. 가장 단순한 형태가 동작한다는 건 "ROS 2 통신 토대가 정상"이라는 가장 확실한 증거입니다. (C++ 노드 ↔ Python 노드가 서로 통신한다는 점도 함께 확인됩니다.)
- 기대 결과: 터미널 1엔
Publishing: 'Hello World: 1, 2, 3...', 터미널 2엔I heard: [Hello World: 1, 2, 3...]가 1초 간격으로 올라옵니다. 이게 보이면 ROS 2 통신 성공입니다.Ctrl+C로 종료합니다.
5. Gazebo 연동 패키지 설치 — 시뮬레이터 붙이기
통신이 되는 걸 확인했으니, 이제 로봇이 살 가상 세계 = Gazebo를 붙입니다. 실제 로봇이 없어도 물리(중력·충돌·시간)가 도는 시뮬레이터 안에서 연습할 수 있게 해주는 핵심 도구입니다.
sudo apt install -y \
ros-humble-ros-gz \
ros-humble-ros-gz-bridge \
ros-humble-ros-gz-sim
- 무엇을: Gazebo와 ROS 2를 잇는 패키지 묶음을 설치합니다.
ros-gz-sim은 시뮬레이터 실행,ros-gz-bridge는 Gazebo ↔ ROS 2 사이의 데이터 다리,ros-gz는 이들을 묶은 메타 패키지입니다. - 왜: Gazebo와 ROS 2는 원래 서로 다른 메시지 체계를 씁니다. 둘을 연결하려면 번역 다리인
ros_gz_bridge가 반드시 필요합니다(8단계에서 실제로 사용). - 기대 결과: 설치 완료 후
ign gazebo(또는gz sim) 명령을 쓸 수 있게 됩니다.
6. Gazebo를 headless로 실행 — 화면 없이 시뮬레이션 돌리기
Colab엔 모니터가 없습니다. 그래서 Gazebo를 headless(화면 없이 계산만) 로 돌립니다.
ign gazebo -v 4 -s -r shapes.sdf
- 무엇을:
shapes.sdf라는 예제 월드(상자·구 같은 도형들이 놓인 가상 공간)를 시뮬레이션합니다. - 왜 이 옵션들인가:
-s= server-only. 그래픽 창(GUI) 없이 물리 계산만 합니다. → 모니터 없는 Colab의 핵심.-r= run. 켜자마자 시뮬레이션을 바로 돌립니다(일시정지 상태로 시작하지 않음).-v 4= verbose 4. 로그를 자세히 찍어 문제 추적을 쉽게 합니다.
- 기대 결과: Gazebo 서버가 뜨고 시뮬레이션 시간이 흐르기 시작합니다. 다른 터미널에서 토픽 목록을 봅니다.
ign topic -l
- 무엇을: 지금 Gazebo가 내보내는 토픽 목록을 출력합니다.
- 기대 결과:
/clock(시뮬레이션 시간)과/world/shapes/...류의 토픽들이 보입니다. 특히/clock이 보이는 게 다음 단계의 출발점입니다.
💡
/clock이 왜 중요한가 — 시뮬레이션 안의 시간은 현실 시간과 다르게 흐를 수 있습니다(빨리/느리게/멈춤). 그래서 시뮬레이터는 자기 시간을/clock으로 알려주고, ROS 2의 모든 모듈이 이 시계를 기준으로 움직이게 됩니다. 즉/clock은 시뮬레이션 세계의 표준 시계입니다.
7. /clock 브리지 — 시뮬레이터의 시간을 ROS 2로 끌어오기
마지막 단계입니다. 방금 본 /clock은 아직 Gazebo 쪽 토픽일 뿐, ROS 2는 그걸 그대로 못 읽습니다(메시지 체계가 다르니까요). 그래서 5단계에서 깐 브리지로 번역해 ROS 2 세계로 끌어옵니다.
ros2 run ros_gz_bridge parameter_bridge \
"/clock@rosgraph_msgs/msg/Clock[gz.msgs.Clock"
- 무엇을: Gazebo의
/clock을 ROS 2의/clock(메시지 타입rosgraph_msgs/msg/Clock)으로 변환해 흘려보냅니다. - 이 괴상한 문법 해석:
/clock@A[B형태에서@앞은 토픽 이름,A는 ROS 2 메시지 타입,B는 Gazebo 메시지 타입입니다.- 가운데 기호
[는 방향입니다.[는 Gazebo → ROS 2(단방향 입력)를 뜻합니다. (]면 반대,@면 양방향.) - 정리하면: "Gazebo의 Clock을 ROS 2의 Clock으로 한 방향으로 넘겨라."
- 기대 결과: 다른 터미널에서 확인합니다.
ros2 topic list # 목록에 /clock 이 보여야 함
ros2 topic echo /clock # sec, nanosec 값이 계속 갱신되며 출력
/clock이 ROS 2 토픽 목록에 나타나고 echo 했을 때 sec/nanosec 숫자가 계속 증가하면, Gazebo의 시간이 ROS 2 세계로 성공적으로 넘어온 것입니다.
⚠️ 흔한 함정 ③ — Gazebo 서버(6단계)가 떠 있어야
/clock이 흐릅니다. 브리지만 켜고 Gazebo를 안 켰거나 멈췄으면echo에 아무것도 안 나옵니다. "값이 안 올라온다"면 Gazebo가 살아 있는지부터 확인하세요.
4편 정리 — 여기까지의 성공 기준
이번 4편에서 우리는 빈 리눅스(Colab)에서 시작해, 시뮬레이터의 시간이 ROS 2로 흐르는 지점까지 만들었습니다. 단계별 "성공했다"의 기준을 표로 정리합니다.
| 단계 | 확인 명령 | 성공 기준 |
|---|---|---|
| 환경 확인 | lsb_release -a |
Ubuntu 22.04 (jammy) |
| 파이썬 맞춤 | python3 --version |
Python 3.10.x |
| ROS 2 설치 | ros2 topic list |
/rosout, /parameter_events 출력 |
| 통신 확인 | talker + listener |
I heard: [Hello World] 출력 |
| Gazebo 실행 | ign gazebo -v 4 -s -r shapes.sdf |
서버 실행 + 시간 흐름 |
| Gazebo 토픽 | ign topic -l |
/clock, /world/shapes/... 출력 |
| /clock 브리지 | ros2 topic echo /clock |
sec, nanosec 값 증가 |
핵심만 다시 짚으면:
- Colab 터미널 = 무료 우분투 리눅스 한 대 → 내 PC·GPU 없이 ROS 2 연습 가능
- ROS 2 Humble은 Python 3.10과 짝 → 버전부터 맞춰야
rclpy가 산다 talker/listener= ROS 2 통신(pub/sub) 이 살아 있다는 증거- Gazebo는 headless(
-s) 로 화면 없이 실행 ros_gz_bridge가 Gazebo의/clock을 ROS 2 세계로 번역해 넘긴다
다음 편 예고 — 이 데이터를 브라우저까지
지금 /clock은 ROS 2 안에서만 돌고 있습니다. 다음 5편에서는 이 토픽을 rclpy 파이썬 노드로 구독하고, WebSocket 서버 스크립트로 바깥에 흘려보낸 뒤, Cloudflare Tunnel로 외부에서 접속 가능한 주소까지 뽑아냅니다. 즉, 시뮬레이터의 시간이 실시간으로 브라우저 화면에 찍히는 데이터 파이프라인을 완성합니다.
pip install websockets==10.4— 왜 하필 이 버전인가(버전 함정)ros_clock_ws_server.py— rclpy 구독 + WebSocket 송출을 한 스크립트에서 (전체 코드 + 한 줄씩 해설)cloudflared tunnel— 내 Colab 포트를 외부로 안전하게 노출하기
📚 Week1 Day1 전체 목차 (총 5편)
- 1/5 화면 밖으로 나온 AI — 피지컬 AI란 무엇인가 (개념)
- 2/5 휴머노이드 로봇 전쟁 — 테슬라·보스턴 다이내믹스·중국 비교 (개념)
- 3/5 무엇을 배워야 하나 — ROS 2부터 Sim-to-Real까지 로드맵 (개념)
- 4/5 Colab에서 ROS 2 Humble + Gazebo headless 환경 만들기 — 이번 글 (실습)
- 5/5 ROS 2 /clock을 밖으로 — WebSocket 서버 + Cloudflare Tunnel (실습)
'피지컬AI' 카테고리의 다른 글
| [Physical AI W1D2] 1/6 — 리눅스 기초 체력: 쉘·파일시스템·핵심 명령어 (0) | 2026.06.14 |
|---|---|
| [Physical AI W1D1] 5/5 — ROS 2 /clock을 밖으로: WebSocket 서버 + Cloudflare Tunnel (1) | 2026.06.14 |
| [Physical AI W1D1] 3/5 — 무엇을 배워야 하나: ROS 2부터 Sim-to-Real까지 학습 로드맵 (0) | 2026.06.14 |
| [Physical AI W1D1] 2/5 — 휴머노이드 로봇 전쟁: 테슬라·보스턴 다이내믹스·중국 전략 비교 (1) | 2026.06.14 |
| [Physical AI W1D1] 1/5 — 화면 밖으로 나온 AI: 피지컬 AI란 무엇인가 (0) | 2026.06.14 |