Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

omni_kit

음성으로 산업용 협동로봇팔을 제어하는 통합 시스템. ROS 2 + LLM 에이전트 + 음성 파이프라인을 모노레포로 통합한 Phase 1 MVP 구현체입니다.

통과 마커

  • Phase 1 MVP (2026-04-30) — UR5 실기 + 마이크 + LLM 에이전트 + TTS 통합 시연 통과. 12 발화 시나리오 전부 정합 (실기 픽플 3회 / multi-turn 회상 / ask_clarification / 자연 응답 매칭 / 한국어 숫자 정규화).
  • Phase 1.5-α (2026-05-01) — 시연 자동화. 6 Terminal → 1 Terminal 단일 launch 통합. yaml-driven 4-tier launch 우선순위 (CLI > env > PC IP auto-detect > sample fallback). LLM warm-up 1160ms.
  • Phase 1.5-β (2026-05-02) — Docker 컨테이너화 통과. 동료 PC git pull 직후 즉시 진입 가능. 환경 의존성 0.

시연 시나리오

사용자: "안녕"
로봇: "안녕하세요. UR5 로봇 팔 준비 되었습니다."

사용자: "1번에서 5번으로 옮겨줘"
로봇: "1번 위치에서 5번 위치로 옮기는 거 맞을까요?"

사용자: "그렇게 해줘"
로봇: (UR5 픽-플레이스 진행) "1번에서 5번으로 옮겼습니다."

사용자: "9번 위치도 있어?"
로봇: "1번부터 8번 위치까지만 사용할 수 있어요. 다른 위치를 알려주세요."

사용자: "아까 어디로 옮겼지?"
로봇: "1번에서 5번으로 옮겼습니다."

사용자: "멈춰"
로봇: (즉시 정지)

LLM이 multi-turn context를 유지하면서 자연 응답("그렇게 해줘" / "어 그렇게 하면 돼")을 yes로, 취소 응답("아 미안 다르게 해줘")을 no로 매칭합니다. 8 슬롯 외 위치 입력 시 명확화 질문이 자동 발동합니다.


빠른 시작 (Docker)

사전 셋업 (PC당 한 번만)

# 1. NVIDIA Driver (580.x 권장) — nvidia-smi 통과 검증
nvidia-smi

# 2. Docker + nvidia-container-toolkit
sudo apt install -y docker.io docker-compose-plugin nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
sudo usermod -aG docker $USER
newgrp docker
docker compose version    # v2.x 통과 검증

코드 진입 + 환경 변수

git clone https://lab.ssafy.com/s14-final/S14P31S303.git ~/workspaces/voice_robot
cd ~/workspaces/voice_robot
git checkout develop && git pull

cp .env.example .env
# .env 열어 GMS_KEY 채우기 (정지용이 별도 공유)

PC IP 매칭 yaml 검증

hostname -I                       # 본인 PC IP 확인
ls omni_kit/config/network/       # 사용자별 yaml 목록
사용자 PC IP 매칭 yaml
정지용 192.168.1.101 jjy.yaml
손동완 192.168.1.100 lab.yaml
김경한 192.168.1.102 kimkh.yaml ⏳ (합의 후 추가 예정)

본인 IP 매칭 yaml이 없으면 두 가지 선택지:

# A. 기존 yaml로 강제 매칭 (env override)
echo "VOICE_ROBOT_PROFILE=lab" >> .env

# B. 신규 yaml 추가
cd omni_kit/config/network
cp sample.yaml <본인이름>.yaml
# pc.ip_cidr / pc.ethernet_interface 본인 환경값 채움

UR5 펜던트 External Control 설정

PolyScope 펜던트에서 본인 PC IP를 등록해야 외부 제어가 활성화됩니다.

  1. PolyScope 메인 화면 → Installation
  2. 좌측 메뉴 → URCapsExternal Control
  3. Host IP 필드에 본인 PC IP 입력 (예: 192.168.1.101)
  4. Host port = 50002 (default 그대로)
  5. 우상단 Save Installation — 변경 영구 저장
  6. Program 탭으로 이동
  7. 기존 program이 외부 제어 노드를 포함하면 그대로 / 없으면 AddURCapsExternal Control 추가
  8. Save Program

검증 — 컨테이너 안 launch terminal에 다음 로그가 출력되어야 정합:

[ur_ros2_control_node-1] [INFO] Robot connected to reverse interface. Ready to receive control commands.

함정 인지:

  • Host IP가 본인 PC IP와 일치하지 않으면 sentinel이 무한 대기합니다 (waiting for /io_and_status_controller/robot_program_running).
  • Save를 누르지 않으면 펜던트 재부팅 시 옛 IP로 복귀합니다.

네트워크 검증

ping -c 3 192.168.1.11    # UR5
ping -c 3 192.168.1.1     # OnRobot Compute Box

둘 다 0% loss여야 정합.

Image build (한 번만)

docker compose -f docker-compose.voice.yml build

최종 개발 이미지는 voice_robot:dev 하나를 사용한다. voice/RealSense/RViz 흐름 모두 repo를 컨테이너 안 /workspace에 mount하고 ROS workspace는 /workspace/omni_kit로 맞춘다.

소요 분해:

  • Layer 1 (apt: ROS 2 Humble + RViz + ffmpeg + 빌드 도구) — 약 5~7분
  • Layer 2 (pip: faster-whisper + edge-tts + anthropic 등) — 약 2~3분
  • Layer 2b (RealSense DDS-enabled pyrealsense2 + debug tools) — 장비/네트워크 상태에 따라 수분 이상
  • Layer 3 (vcs import + 외부 패키지 패치 + rosdep) — 약 3~5분
  • Layer 4 (외부 패키지 colcon build — UR Driver / OnRobot) — 약 3~5분

시연 진입

첫 진입 (또는 다른 PC에서 clone 직후) — stale build cache 정리

호스트에서 직전에 colcon build를 시도한 잔재(다른 절대경로) 또는 다른 환경에서 만든 build artifact가 남아있으면 컨테이너 안 빌드와 충돌합니다. 처음 진입 시 호스트 shell에서 한 번 정리합니다.

# 호스트 shell (컨테이너 진입 전, 첫 진입 시점만)
rm -rf omni_kit/build omni_kit/install omni_kit/log

⚠️ 호스트 shell에서 colcon build 직접 실행 금지. 본 컨테이너는 호스트의 ROS 2 / CUDA 환경 의존성 0이 의도이며, 빌드는 반드시 컨테이너 안에서만 실행해야 절대경로(/workspace/omni_kit/...)가 정합합니다.

빌드 통과 검증 (필수 — Python PackageNotFoundError 회피)

colcon build 박은 후 마지막 line 검증:

Summary: 26 packages finished [Xm Ys]

Failed / Aborted 박힌 시점 = launch 박지 마. 부분 빌드(특히 Ctrl+C 박은 시점)가 박힌 시점 Python ament 패키지(stt_node / tts_node / llm_agent / ur5_voice_app / ur5_waypoint_controller)의 setup.py develop 흐름 통과 X = egg-link metadata 누락 → launch 진입 시 PackageNotFoundError: No package metadata was found for <pkg> 함정. stderr 본문 검토 박은 후 별 분석.

펜던트 사전 검증 (UR Driver RTDE configuration timeout 회피)

launch 박기 직전 펜던트 PolyScope 박은 거 검증:

  1. External Control 프로그램이 PolyScope에 박혀있는 거 검증 (Program 탭 — 본인이 직전에 Add → URCaps → External Control 박은 거)
  2. External Control 프로그램 안 Host IP = 본인 PC IP 박혀있는 거 검증 (예: 192.168.1.100)
  3. ▶ Play 박은 후 PolyScope 화면에 Robot connected to reverse interface. Ready to receive control commands. 박힌 거 검증

박지 마 박힌 시점 launch 박힌 후 [ur_ros2_control_node-1] FATAL Could not get configuration package within timeout 박힘 — Dashboard(29999) 진입은 통과해도 RTDE(30004) 진입은 펜던트 ▶ Play 박혀야만 통과.

컨테이너 기동 + 빌드 + launch

# 컨테이너 기동
docker compose -f docker-compose.voice.yml up -d
docker compose -f docker-compose.voice.yml exec voice_robot bash

# 컨테이너 안 — 자동으로 cwd /workspace/omni_kit 진입 + ROS 2 환경 source
colcon build --symlink-install     # 첫 진입 또는 코드 변경 시 (~3~5분, 26 packages)
source install/setup.bash
ros2 launch ur5_voice_app phase1_mvp.launch.py

launch가 sentinel wait 상태에 진입하면 5분 안에 펜던트 ▶ Play를 누르세요. 5분을 넘기면 펜던트의 External Control이 자체 stop됩니다 (idle timeout).

펜던트 ▶ Play 후 다음이 자동 진행됩니다:

  • sentinel exit
  • voice 노드 chain 진입 (STT / LLM / TTS)
  • LLM warm-up 호출 (~1.2초)
  • Greeting 발화 — "안녕하세요. UR5 로봇 팔 준비 되었습니다."

마이크 진입 (별 터미널)

docker compose -f docker-compose.voice.yml exec voice_robot bash
ros2 run stt_node audio_stub --mic

발화 패턴: Enter → 발화 → Enter (push-to-talk).

종료

# 호스트 shell
docker compose -f docker-compose.voice.yml down

CPU 모드 (GPU 없는 환경)

GPU 없는 EC2 / 동료 PC 는 별도 compose 파일로 진입:

docker compose -f docker-compose.voice.cpu.yml up -d --build

CPU 변형은 BASE_IMAGE=ubuntu:22.04 로 build (CUDA base 우회) 하고, stt_node 는 STT_* env override 로 device=cpu / compute_type=int8 / beam_size=1 / cpu_threads=4 / condition_on_previous_text=false / without_timestamps=true 가 declare-time 박힘 (코드 변경 0건). 상세 흐름·env 표·지연 측정 흐름은 README_DOCKER.md §2.9 참조.


장비 / 네트워크

하드웨어

구성 요소 모델 비고
로봇팔 Universal Robots UR5 (CB3) PolyScope 3.15.8
그리퍼 OnRobot 2FG7 외부 그립 73mm, 그립력 20140N, payload 11kg
그리퍼 컨트롤러 OnRobot Compute Box Modbus TCP (port 502)
비전 (Phase 3 R&D) OnRobot Eyes (RealSense D415 기반) Phase 1 미사용 (eye-in-hand 마운트만 유지)
제어 PC Ubuntu 22.04 + RTX 4070 (8GB) NVIDIA Driver 580.x, swap 16GB 권장

네트워크 매핑

장비/PC IP 비고
UR5 192.168.1.11 2026-05-01 lab 재구성 (.102 → .11)
OnRobot Compute Box 192.168.1.1 변경 없음
정지용 PC 192.168.1.101 jjy.yaml
손동완 PC 192.168.1.100 lab.yaml
김경한 PC 192.168.1.102 kimkh.yaml (합의 후 추가)

소프트웨어 스택

영역 기술
OS Ubuntu 22.04 LTS
ROS ROS 2 Humble
Robot driver ur_rtde 1.6.3 + URScript + Universal_Robots_ROS2_Driver
Gripper pymodbus + OnRobot Compute Box Modbus TCP
STT faster-whisper 1.2.1 (large-v3-turbo / CUDA float16)
LLM Claude Sonnet 4.5 (SSAFY GMS gateway 경유)
TTS edge-tts (ko-KR-SunHiNeural)
VAD faster-whisper 내장 VAD (Phase 1.5+ Silero VAD 도입 예정)
Container Docker 28.x + Compose v2 + nvidia-container-toolkit
Base image nvidia/cuda:12.6.3-cudnn-runtime-ubuntu22.04

CUDA 12 base는 faster-whisper의 CTranslate2 4.7.1 wheel이 cuBLAS 12 + cuDNN 9에 의존하기 때문입니다. host NVIDIA Driver 580.x는 CUDA 12와 13 모두 호환되므로 host 환경 추가 셋업은 불필요합니다.


저장소 구조

voice_robot/                          # 모노레포 root (저장소명은 S14P31S303)
├── README.md                         # 이 문서
├── docker-compose.voice.yml          # Phase 1.5-β voice 컨테이너 (standalone)
├── docker-compose.yml                # 웹 트랙 stack (postgres / redis / mosquitto / backend / ai-agent / sensevoice / nginx) — 별도 트랙
├── Dockerfile                        # voice 컨테이너 image 빌드 — 4-layer (apt / pip / vcs / colcon)
├── .env.example                      # 환경 변수 템플릿
│
├── omni_kit/                         # ROS 2 워크스페이스
│   ├── dependencies.repos            # 외부 ROS 2 패키지 (UR Driver / OnRobot ROS 2 / ros2_control)
│   ├── requirements.txt              # Python 의존성
│   ├── config/
│   │   └── network/                  # 사용자별 yaml (PC IP / robot IP / gripper IP 매핑)
│   │       ├── sample.yaml           # 신규 합류 템플릿
│   │       ├── jjy.yaml            # 정지용 (192.168.1.101)
│   │       └── lab.yaml              # 손동완 (192.168.1.100)
│   └── src/
│       ├── interfaces/
│       │   └── voice_robot_interfaces/   # msg / srv / action 정의
│       ├── core/
│       │   ├── robot_arm_base/           # RobotArm / GripperDriver 추상
│       │   ├── waypoint_store/           # YAML 기반 위치 저장소
│       │   ├── safety_guard/             # workspace bound / vel·acc 제한
│       │   └── scenario_runner/          # 시나리오 액션 서버
│       ├── voice/
│       │   ├── audio_gateway/            # 마이크 → /audio/utterance
│       │   ├── stt_node/                 # faster-whisper STT
│       │   ├── llm_agent/                # Claude Sonnet 4.5 + tool use 라우팅
│       │   └── tts_node/                 # edge-tts → 스피커
│       ├── robots/
│       │   └── ur5/                      # UR5 driver / gripper / waypoint controller
│       ├── vision/                       # Phase 3 R&D (object_detector / realsense_bringup)
│       ├── apps/
│       │   └── ur5_voice_app/            # phase1_mvp.launch.py (통합 진입점)
│       └── external/                     # vcs import target (UR Driver 등 — gitignore)
│
├── web/                              # 웹 트랙 (Phase 1.5+ 통합 예정)
│   ├── docs/                         # 웹 트랙 문서
│   └── sensevoice/                   # sensevoice STT 백엔드 (Phase 1.5+ Hybrid 흐름)
│
├── mosquitto/                        # MQTT broker config (웹 트랙 stack 의존)
│   └── config/
│
├── docs/                             # 다이어그램 / 부가 문서
└── scripts/
    └── setup/
        ├── docker_entrypoint.sh      # 컨테이너 진입 시 ROS 2 3-layer overlay
        ├── post_vcs_import.sh        # 외부 패키지 자동 patch (UR Driver RTDE recipe vs OnRobot URCap IO 충돌)
        └── voice_stack_cleanup.sh    # 시연 cleanup (vsclean)

통합 흐름 다이어그램

[마이크 (audio_stub --mic)]
     │ /audio/utterance (PCM 16kHz)
     ▼
[stt_node — faster-whisper large-v3-turbo (GPU)]
     │ /voice/transcript (한국어 텍스트)
     ▼
[llm_agent — Claude Sonnet 4.5 + tool use (multi-turn 누적)]
     │ tool_use blocks: speak / confirm_with_user / ask_clarification / pick_and_place / emergency_stop
     ▼
[RealToolClient]
     │ /ur5_command (slot key — "15" = pick_1 → place_1)
     ▼
[ur5_waypoint_controller (slot_runner)]
     │ trajectory_msgs/JointTrajectory
     ▼
[ur_robot_driver — UR Driver passthrough_trajectory_controller]
     │ RTDE / URScript (TCP 30001~30004)
     ▼
[UR5 CB3 + OnRobot 2FG7]

(병렬)
[llm_agent] ──► /tts/text ──► [tts_node — edge-tts] ──► sounddevice ──► 스피커

함정 인지 (시연 마찰 0 의도)

함정 회피
펜던트 External Control idle timeout 펜던트 ▶ Play 후 5분 안에 첫 발화 (5분 넘기면 펜던트가 자체 stop). idle 후 복구는 펜던트 ▶ Play 다시 누르면 됨
PC IP yaml 매칭 실패 .envVOICE_ROBOT_PROFILE=<name> 명시 또는 신규 yaml 추가. 매칭 없으면 sample.yaml로 fallback (실기 IP와 어긋날 수 있음)
host PulseAudio 미가동 Ubuntu desktop session에서는 자동 가동. 헤드리스 SSH 진입 시 export XDG_RUNTIME_DIR=/run/user/$(id -u) 후 docker compose up
docker compose exec bash 진입 시 ROS 2 환경 누락 자동 해결 — Dockerfile의 ~/.bashrc가 3-layer overlay (ROS 2 base / image-baked external / host bind-mount workspace) 자동 source. cwd /workspace/omni_kit 자동 진입
다른 PC에서 clone 직후 빌드 실패 (절대경로 mismatch / tesla_ws·gae_ws 등 옛 workspace not found) 호스트 shell의 직전 colcon build 잔재 또는 호스트 ~/.bashrc의 옛 ROS workspace source가 원인. 첫 진입 시 호스트 shell에서 rm -rf omni_kit/build omni_kit/install omni_kit/log 후 컨테이너 안에서 빌드. 호스트에서 colcon build 직접 실행 금지
Python PackageNotFoundError (모든 노드) colcon build 박은 후 빌드 통과 검증 박지 마 박은 시점 (Failed / Aborted 또는 Ctrl+C 부분 빌드). Summary: 26 packages finished 검증 박은 후 launch
UR Driver Could not get configuration package within timeout 펜던트 External Control 프로그램 ▶ Play 박지 마 박힘 또는 program 안 Host IP가 본인 PC IP 박지 마 박힘. 펜던트 사전 검증(Host IP / ▶ Play / Robot connected... 로그) 박은 후 launch
GPU 없는 동료 PC 본 컨테이너는 nvidia/cuda base + faster-whisper GPU 의존 = GPU 필수. GPU 없는 환경은 Phase 1.5+ sensevoice 백엔드 통합 후 진입 가능

개발 흐름

모노레포 영역 분담

트랙 담당 영역
voice 정지용 omni_kit/src/voice/ (audio_gateway / stt_node / llm_agent / tts_node) + 통합 책임
robots 손동완 omni_kit/src/robots/ur5/ (driver / gripper / waypoint controller)
vision 김경한 omni_kit/src/vision/ (object_detector / realsense_bringup — Phase 3 R&D 진입 흐름, Phase 1 시연 범위 외)
web 웹 개발자 2명 web/ (안드로이드 클라이언트 / 백엔드 / sensevoice STT / 모니터링)

영역 자율성 원칙: 영역 외 코드는 직접 수정하지 않고 통보 후 담당자가 직접 갱신합니다.

Git workflow

  • feature 브랜치 push만 허용. develop 직접 push는 금지.
  • force push 금지 (--force-with-lease만 허용, 단 main / develop에는 금지).
  • --no-verify (hook 우회) 금지.
  • MR 통과 흐름: feature push → GitLab MR 생성 → reviewer 승인 → develop 머지 (Squash 미사용) → 로컬 cleanup (git checkout develop && git pull && git branch -d <feature>).

빌드 (host 환경 — Phase 1.5-α 흐름)

Docker 흐름이 표준이지만, host에 ROS 2 Humble + CUDA 12 + dependencies가 사전 설치된 환경에서는 host에서 직접 빌드도 가능합니다.

cd ~/workspaces/voice_robot/omni_kit
vcs import src/external < dependencies.repos
bash ../scripts/setup/post_vcs_import.sh
rosdep install --from-paths src --ignore-src -r -y --rosdistro humble
colcon build --symlink-install
source install/setup.bash
ros2 launch ur5_voice_app phase1_mvp.launch.py

라이선스

SSAFY 캡스톤 산학 협력 프로젝트 (S14P31S303). 시연·교육·포트폴리오 목적.

About

로봇팔과 그리퍼를 이용한 AI Agent 서비스

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages