이기종 멀티로봇을 위한 End-to-End 원격조작·플릿 관제 플랫폼
A Unified Message Standard for Heterogeneous Multi-Robot Tele-Operation & Fleet Management
Figure 1. SYNAPSE 시스템 개요. 모든 컴포넌트는 중심의 synapse 표준을 import 하여 동일한 status·command 인터페이스로 대화한다. 의존성은 언제나 안쪽(표준)을 향한다.
status·command를 통일하면, 어떤 관제 화면이든 모든 로봇을 같은 인터페이스로 다룰 수 있다.
SYNAPSE는 모바일·매니퓰레이터·휴머노이드 등 이기종 멀티로봇을 단일 메시지 표준(synapse)으로 추상화하는 플랫폼이다. 로봇에 tom_and_gerri를 설치하는 것만으로 표준 status/command가 자동으로 노출되며, 별도 서버 연동 작업 없이 1:1 원격조작(COCKPIT)과 N:N 플릿 관제(NEXUS)가 하나의 코드베이스 위에서 동시에 활성화된다.
설계의 중심에는 클린 아키텍처가 있다. 모든 컴포넌트는 가장 안쪽의 synapse 표준을 import하고, 의존성은 언제나 안쪽을 향한다. 전송 계층(WebRTC), GUI, 데이터베이스, 로봇 SDK는 모두 바깥의 교체 가능한 세부사항이다. 상태의 원본은 로봇(엣지)이 소유하고, 서버는 그 사본(뷰)만 캐시한다 — Edge-Authoritative 원칙이다.
이 스프린트는 비용이 크지만, 얻는 것이 더 크다.SYNAPSE는 기술 표준과 팀 문화 둘 다를 겨냥한다.
synapse가 메시지·status·자료구조를 통일해 섬을 잇는다. standardize()가 dict·Pydantic 모두 수용 → 전면 재작성 없이 점진 마이그레이션.로봇에 tom_and_gerri를 설치하면 synapse 표준 status/command가 자동 노출된다.별도 작업 없이 NEXUS 플릿에서 즉시 관제 가능 — 한 번의 설치로 1:1 + N:N 동시 ON.
synapse 메시지 표준대로 status·command를 자동 발행한다. 별도 서버 연동 작업 불필요.바깥은 교체 가능한 세부사항, 안쪽은 안정적인 표준.의존 화살표는 항상 바깥에서 안쪽을 향하며, 안쪽은 바깥을 모른다.
synapse — 관제·로봇·UI의 메시지 계약 (독립 signaling은 import하지 않음)Figure 2. 레이어드 클린 아키텍처. synapse는 정의만 담고 실행 로직이 없다 — 여기를 바꾸면 전체가 흔들리므로 가장 신중히 관리된다.
Figure 3. 레포 의존 그래프. nexus는 tom_and_gerri·tag 코드를 import하지 않는다 — 오직 네트워크 표준으로만 대화한다(코드 결합도 0). tag는 gerri/ 밑에 clone(submodule 아님).
각 컴포넌트는 명확한 단일 책임을 가진다.TAG = TOM + AND + GERRI, 한 로봇 분(分)의 묶음이다.
standardize()를 정의한다. 정의만 하고 실행 로직은 없다._and_/). 현재 WebRTC(rtc2kng) 기반. 내부 버스(pypubsub)와 완전 분리되어 전송 방식 교체 시 GERRI 로직 불변. Sub는 AND 직접 사용 금지.python -m nexus 단일 명령 기동.window.__COCKPIT__ 설정 주입으로 동작. Standalone / NEXUS-context 두 모드.NEXUS는 관제·인증·상태 레지스트리·제어 세션·입장 승인을 담당하고, synapse-signaling이 WebRTC 연결 협상을 중계한다. 영상·오디오·teleop는 WebRTC peer 사이로 전달하며, 직결이 어려우면 별도 TURN을 거친다.
/ws/{robot_id}). status·mission_event 푸시, 관제 명령·제어 세션 수신. TOM이 outbound로 접속./ws/{room}으로 ready / leave · SDP / ICE만 중계한다. 미디어·teleop·상태 캐시는 담당하지 않는다./api/ice가 통화 직전에 발급하는 시간제한 값이다.Figure 4. NEXUS 관제와 독립 시그널링을 분리한다. synapse-signaling은 sender / receiver를 보고 연결 협상만 중계하며, WebRTC 데이터는 peer 사이에서 직결 또는 별도 TURN으로 전달된다.
2 ⇄ 3 전환은 클릭 한 번.N:N 관제와 1:1 조작 사이를 지연·재접속 없이 오간다.
"실패는 정상, 인간 개입 우선."FleetMission → RobotMission → Task 순으로 위임한다.Python 함수·JSON·REST 모두 지원.
depends_on으로 정의. NEXUS가 조율(FleetMissionRunner 구현됨), 로봇 점유·실행은 TOM 책임.MissionRunner가 관리. 상태는 로봇 측 보유 → 재접속 시 자동 복구. 개입: NEED_HELP → TELEOP → resume/abort.FleetMission — 커피 배달 예시 (DAG)
def coffee_delivery() -> FleetMission:
return FleetMission(
name="coffee_delivery", site="itp",
tasks={
"go": call("mobile_01", "go_to_coffee"),
"make": call("coffee_01", "make_americano",
depends_on=["go"]),
"transfer": call("arm_01", "transfer_cup",
depends_on=["make"]),
"deliver": call("mobile_01", "go_to_dest",
depends_on=["transfer"]),
})
RobotMission — 5층→1층 배달
def delivery_5f_to_1f() -> RobotMission:
return RobotMission(name="delivery", tasks=[
cap("undock", "undock"),
cap("go", "navigate_to_pose", x=1.0, y=2.0),
wait_input("confirm", prompt="도착했나요?",
buttons={"yes": "예"}),
cap("dock", "dock"),
notify("done", "배달 완료"),
])
초기 목표였던 "NEXUS UI로 모바일 로봇을 실제로 움직인다"(status→command→이동→N:N↔1:1)는 달성됐다.이후 플릿 조율·인간 개입·디지털 트윈·크로스랭귀지 SDK로 범위를 넓히고 있다.
FleetMissionRunner DAG 조율(/api/fleet/*) · SQLite 스냅샷 영속 · 표준맵 정렬 부착.ai_chat → 같은 두뇌 → capability·미션) · 한 명령의 end-to-end 경로를 보는 흐름 추적(trace.hop — 4레포 관통, 기본 꺼짐).