프로젝트 개요
인수인계 받은 조립 자동화 셀은 제우스(Zeus) 로봇이 흩어진 2x4 파트를 집어 파트를 컨베이어 벨트 위에 내려놓으면 그 리니어 액추에이터가 그 파트를 집어 팔레트에 조립하는 공정이다. 조립 자동화 셀에서 흩어진 파트를 비전으로 인식해 산업용 로봇이 집도록 하는 역할을 담당했다.
- 프로젝트: 비정형 적재 환경에서의 3D Pick & Place 시스템 개선
- 목표: 데모 데이 하루에 레고 2x4 블록 100개를 끊김 없이 조립
- 사용 기술: SAM-6D(zero-shot 6DoF 자세 추정), Eye-to-Hand 캘리브레이션, 깊이 기반 폐루프 재시도
- 하드웨어: 제우스 로봇 + 2-finger(parallel-jaw) 그리퍼, RGB-D 카메라(Kinect, 설비 고정형)
- 대상: 흩어진 레고 2x4 블록 (겹침·맞물림이 빈번)
- 성격: 양산 라인이 아니라 연구실 PoC. 24시간 가동이 아니라 데모 데이 하루를 기준으로 한 검증
문제 정의
기존 설비는 2D 카메라로 흩어진 블록을 인식했다. 하지만 흩어진 부품은 한 층으로 깔끔하게 펼쳐지지 않는다. 서로 위로 올라타고, 모서리가 걸치고, 둘이 맞물린 채 굴러다닌다. 2D 비전은 평면상의 위치(x, y)는 알아도 어느 블록이 위에 있고 어느 게 깔려 있는지, 즉 깊이 방향의 상하 관계를 보지 못한다. 그 결과 깔려 있는 블록을 집으려다 빗나가는 실패가 반복됐고, 데모 기준 평평하게 흩어진 부품만 집을 수 있어 수율이 약 60%에 머물렀다.
이에 3D Point Cloud까지 활용하여 부품의 6D Pose를 로봇에게 전달해야하는 기술이 필요했다.
3D 비정형 적재에는 크게 두 갈래가 있다. 객체의 6D 자세를 명시적으로 추정하는 방식과, 자세를 풀지 않고 깊이 영상에서 곧장 파지점을 출력하는 방식이다.
이 공정은 조립이 목적이라, 집은 블록을 정해진 자세로 다음 단계에 놓아야 했다. 그러려면 블록이 지금 어떤 방향인지를 알아야 했고, 그래서 자세를 명시적으로 주는 pose-based를 택했다.
그중 SAM-6D를 쓴 이유는 zero-shot이라는 점이다. CAD/타깃만 주면 객체별로 따로 학습하지 않아도 자세를 추정한다. 내부적으로는 분할(ISM)로 장면에서 인스턴스를 떼어내고, 자세 추정(PEM)으로 6D를 푸는 두 단계 구조다. 연구실에서 여러가지 블록이 있을 수 있고 그때마다 블록 데이터를 모아 라벨링하고 모델을 새로 학습시키는 부담을 덜 수 있었다는 생각에 zero-shot 기반의 SOTA 모델을 사용하였다.
시스템 구성

- 입력: RGB-D 카메라(Kinect)로 촬영한 장면의 컬러 + 깊이 영상
- 카메라 배치: 로봇이 아니라 설비 프레임에 고정된 Eye-to-Hand 구성. 셀 상단에서 작업 영역 전체를 내려다본다.
- 인식 모델: SAM-6D (ISM 인스턴스 분할 + PEM 6DoF 자세 추정)
- 그리퍼: 2-finger parallel-jaw
- 출력: 각 블록의 6D 자세 → 로봇 좌표계 Grasp Pose
- 평가 기준: 데모 데이 100개 투입 대비 성공 조립 개수(수율), 평균 사이클 타임
파이프라인 설계
전체 흐름은 다음과 같다.
RGB-D 촬영 → SAM-6D 분할·자세 추정 → 로봇 좌표계 변환 → 최상단 블록부터 파지 → 깊이 변화로 성공/실패 판정 → 실패 시 Z 오프셋 보정 후 재시도
[1] 좌표계 정합 (Hand-Eye Calibration)
카메라가 보는 좌표와 로봇이 움직이는 좌표를 묶어주는 변환이 필요하다. Eye-to-Hand 구성이므로 수학적으로 AX=XB 형태의 hand-eye calibration 문제다. OpenCV에 구현된 hand-eye calibration 기능으로 처리했다.
(캘리브레이션 오차를 mm 단위로 별도 기록하지는 않았다. 다만 뒤의 Z 값 문제를 보면 이 단계의 정밀도가 완벽하지는 않았다고 보는 것이 타당하다.)
[2] 파지 순서 및 자세 결정

겹친 더미에서는 순서가 중요하다. 마스크별 깊이 최소값으로 정렬해 가장 위에 있는(카메라에 가장 가까운) 블록부터 집도록 했다. 위에 떠 있는 블록을 먼저 치우면 아래 깔린 블록이 드러나 다음 파지가 쉬워진다. 위에서부터 한 겹씩 벗겨내는 방식으로, 겹침에서 오는 간섭을 줄이는 가장 단순하고 확실한 선택이었다.
평면(x, y, yaw)만 보는 2.5D 방식이 아니라, z가 살아 있는 환경이라 추정된 6D 자세(roll/pitch/yaw 포함)에 맞춰 그리퍼를 정렬해 접근했다. 다만 자세에 따라 그리퍼를 극단적으로 꺾지는 않고, 제한된 범위 안에서 정렬해 옆면을 잡고 내려가는 방식으로 단순화했다. 객체별로 가능한 모든 antipodal(양쪽 마주 잡기) 후보를 풀로 탐색한 것은 아니다.

기존 2D 설비에서 쓰던 teach-and-repeat 구조를 유지했다. 대기 위치, 촬영 위치, 적재 위치는 미리 티칭한 고정 waypoint로 두고, 집는 지점 하나만 비전이 추정한 6D Grasp Pose로 매번 동적으로 치환하는 방식이다. 즉 전체 경로를 매 사이클 새로 planning하지 않고, 고정된 동선 골격에 비전 타깃만 갈아끼웠다.
다만 2D와 달리 6D에서는 그리퍼가 블록의 자세(roll/pitch/yaw)에 맞춰 기울어진 채 접근해야 했다. 추정 자세 위쪽에 pre-grasp(접근점)를 두고 거기서 grasp pose까지 직선으로 내려가게 했는데, 자세를 너무 크게 기울이면 로봇이 그 자세에 도달하지 못하거나 관절 한계에 걸렸다. 그리퍼 자세 변화 폭을 제한된 범위로 둔 것은 이 도달성(reachability) 한계 때문이었고, 동시에 이것이 옆으로 누운 블록에서 실패가 남은 이유이기도 하다.
[3] 성공/실패 판정

파지 동작 전후로 깊이 영상을 비교해, 집으려 한 자리의 깊이가 비었는지를 봤다. 블록을 제대로 들어 올리면 그 자리의 마스크가 사라지고 깊이가 멀어진다. 실패하면 블록이 그 자리에 남아 깊이가 거의 변하지 않는다. 이 변화를 성공 신호로 사용했다.
[4] 실패 시 Z 오프셋 재시도

실패 장면을 분석하니 z 값을 약간 못 잡는 경우가 많았다. 위치는 거의 맞는데 살짝 덜 내려가 블록을 스치고 마는 식이었다. 단일 시점 카메라(한 대)라 깊이가 완벽하지 않았던 점도 영향을 줬을 것이다.
그래서 실패로 판정된 경우에만 z 방향으로 오프셋을 줘서 조금 더 내려가 다시 집게 했다. 재시도는 블록 하나당 2회까지. 그래도 실패하면 그 블록은 포기하고 다음으로 넘어갔다.
실행 및 평가
- 평가 환경: 데모 데이, 파트 100번 Pick and Place 실행
- 지표: 수율(성공 개수 ÷ 100), 평균 사이클 타임
- 비교 기준: 개선 전 2D 비전 기반 동작
| 항목 | 개선 전 | 개선 후 |
| 수율 (성공 ÷ 투입 100개) | 약 60% | 약 92.4% |
| 평균 사이클 타임 | 기준 | 약 +8초 |
수율 92%는 재시도를 포함한 최종 성공률이다. 한 번에 깔끔하게 집은 비율이 아니라, 2회까지 재시도해 결국 건진 것까지 더한 값이다. 첫 시도 성공률만 떼면 이보다 낮다. 이 구분을 흐리지 않기 위해 명시해 둔다.
수율 +32%p 개선의 출처는 두 가지로 나뉜다.
하나는 인식 차원 자체를 올린 것이다. 기존 2D는 z 값을 고려하지 못해 평평하게 놓인 블록만 잡을 수 있었고, 높이가 다르거나 비스듬한 블록은 대부분 놓쳤다. 성공률이 낮은 게 당연했다. 3D로 z를 확보하면서 이 한계가 풀렸다.
다른 하나는 폐루프 재시도다. 3D Vision으로 넘어오며 인식이 정교해진 것보다, 실패를 감지해 z 오프셋으로 다시 집는 루프의 기여가 생각보다 컸다. 인식을 끝까지 정교화하기보다, 틀릴 수 있다는 전제로 보정 루프를 둔 설계가 실제 수율을 끌어올렸다.
재시도 보정의 폐루프 재시도는 수율을 끌어올리는 강력한 수단이지만, z 오프셋을 키울수록 그리퍼가 바닥과 충돌해 파손될 위험도 함께 커진다. 보정의 효과와 장비 손상 위험이 같은 방향으로 움직이기 때문에, 오프셋 크기와 재시도 횟수의 상한을 어디에 두느냐가 핵심이 된다.
카메라 한 대로 보면 가려진 면과 깊이 결손이 생긴다. Z 오프셋 보정이 이 약점을 부분적으로 메웠지만, 깊이가 모자란 게 아니라 애초에 접근 방향이 안 맞는 실패는 보정으로 살릴 수 없다.
이번 결과는 데모 데이 하루를 기준으로 한 PoC다. 며칠에 걸쳐, 더 다양한 배치에서도 같은 수율이 재현되는지는 아직 검증하지 못한 영역이다.
남은 한계 가장 자주 실패한 것은 옆으로 누운 블록이었다. 평범하게 놓인 블록은 잘 잡는데, 옆으로 누우면 자주 놓쳤다. 블록이 누우면 잡아야 할 면의 방향이 접근 범위를 벗어나거나, 위에서 내려가는 동선으로는 그 면에 닿지 못했다. antipodal 후보를 전부 탐색해 옆에서 접근하는 방식이었다면 살릴 수 있었겠지만, 거기까지는 가지 않았다. z 보정으로 못 살린 케이스가 끝까지 남은 실패의 정체에 가깝다.
프로젝트 회고
잘한 점
- 3D Point Cloud를 처음 다뤄봤고, 이를 제대로 쓰기 위해 Point Cloud의 구조와 처리 방식을 직접 이해하고 들어갔다.
- 비전과 로봇을 연결하는 부분을 직접 구성했고, 그리퍼는 3D 프린터로 출력해 셋업을 손수 꾸렸다.
- 한 번에 성공시키려는 대신 실패 감지 + 재시도 폐루프를 설계해, 인식의 불완전함을 시스템 레벨에서 흡수했다.
아쉬운 점
- 파지 자세를 제한된 접근 방향으로 단순화한 탓에, 옆으로 누운 블록에서 끝까지 실패가 남았다.
- 성공 판정 임계값, 캘리브레이션 오차 등 정량 기록을 충분히 남기지 못했다.
다시 수행한다면
- z 보정에만 기대지 않고, 자세에 따라 접근 방향 자체를 바꾸는 antipodal 후보 탐색을 붙여 누운 블록까지 가져가겠다.
- 단일 시점의 깊이 결손을 줄이기 위해 다중 시점 또는 깊이 후처리를 검토하겠다.
- MoveIt 같은 모션 플래닝 라이브러리를 써서 경로 생성 단계에 특이점(singularity)까지 계산에 넣겠다. 연구실 데모 수준에서는 동선이 정형화돼 있어 특이점 문제가 크게 불거지지 않았지만, 더 다양한 자세를 다루는 산업 환경이라면 이 부분이 반드시 필요할 것이라고 본다.
'스마트팩토리 프로젝트' 카테고리의 다른 글
| [연구실 과제] VLA 성능 향상을 위한 데이터 수집 (1) | 2026.06.29 |
|---|---|
| [연구실 과제] 조립 공정 통합 관제 시스템 개발 (0) | 2026.06.29 |
| [연구실 과제] 조립 불량 검사 기반 제품 적재 공정 자동화 (0) | 2026.06.29 |
| [산학과제] 도메인 분리 표현 학습으로 내부 균열 탐지 모델 성능 개선 (0) | 2026.06.24 |
| [팀 프로젝트] PINN을 활용하여 외삽 구간 SoC 성능 추정 (0) | 2026.06.24 |