Skip to content

sequence

ujuguje edited this page Aug 8, 2026 · 4 revisions

SPOT · 로봇팔 연동 흐름

SPOT 이동 → 로봇팔 작업 → SPOT 복귀 시퀀스

sequenceDiagram
    participant 태블릿
    participant MQTT as MQTT
    participant SPOT
    participant OC as OC-SERVER
    participant 로봇팔

    태블릿-->>MQTT: 1. pub (이동 명령 토픽) {destination: "A"}
    MQTT-->>SPOT: 2. sub (이동 명령 토픽)
    MQTT-->>OC: 3. sub (이동 명령 토픽) → 진행 중 상태 변경

    SPOT-->>MQTT: 4. pub (이동 완료 토픽) {status: "arrived", location: "A"}
    MQTT-->>OC: 5. sub (이동 완료 토픽)
    OC-->>MQTT: 6. pub (로봇 팔 명령 토픽)

    MQTT-->>로봇팔: 7. sub (로봇 팔 명령 토픽)
    로봇팔-->>MQTT: 8. pub (로봇 팔 작업 완료) {status: "complete"}
    MQTT-->>OC: 9. sub (로봇 팔 작업 완료)

    OC-->>MQTT: 10. pub (이동 명령 토픽) {destination: "B"}
    MQTT-->>SPOT: 11. sub (이동 명령 토픽)
    SPOT-->>MQTT: 12. pub (이동 완료 토픽) {status: "arrived", location: "B"}
Loading

정책 제안 — SPOT · 로봇팔 연동

위 다이어그램에 대해 SPOT 쪽에서 제안하는 규칙입니다. 이견 있으면 알려주세요.

# 제안 왜
1 정밀 정렬은 SPOT 이 한다. 서버가 보낼 명령이 없다 로봇팔이 작업하려면 SPOT 이 cm 단위로 서 있어야 합니다. 적재 지점의 AprilTag 를 보고 SPOT 이 스스로 맞춥니다
2 이동 완료(4번)를 받은 뒤에 로봇팔에 지시(6번)한다 접수 응답은 "출발했다"일 뿐입니다. 도착 전에 팔이 움직이면 충돌합니다
3 이동이 실패하면 로봇팔 명령을 보내지 않는다 SPOT 이 없는 자리에서 팔이 작업하면 위험합니다
4 적재 지점에 AprilTag(36h11 / 146mm)를 붙인다 SPOT 이 자기 위치를 맞추는 기준입니다(팔을 위한 표식이 아닙니다). 웨이포인트 이동만으로는 오차가 수십 cm 라, 팔이 고정 좌표로 작업하려면 SPOT 이 매번 같은 자리에 서 줘야 합니다
5 적재 중에는 SPOT 에 다른 명령을 보내지 않는다 팔이 작업하는 동안 SPOT 이 움직이면 안 됩니다
6 목적지(destination)는 이름 붙인 지점만 쓴다 SPOT 이 waypoints 토픽(retained)으로 갈 수 있는 곳 목록을 발행합니다. 그 목록에 없는 값은 거부됩니다
7 이동 완료 응답에 결과 코드를 함께 싣는다 위 다이어그램의 {status:"arrived"} 는 성공만 표현합니다. 실패했을 때도 같은 토픽으로 이유가 와야 서버가 다음 판단을 할 수 있습니다 (자세한 값은 MQTT_SCHEMA-SPOT)

미검증 — 이 흐름은 아직 로봇팔과 함께 시험해보지 않았습니다. 정렬 정확도와 소요 시간은 합동 시험 후에 채우겠습니다.


SPOT 단독 시나리오

로봇팔이 관여하지 않는 SPOT 시나리오들입니다. 위 로봇팔 흐름과 같은 방식으로 그렸습니다 — 사람이 시작하는 명령은 태블릿이 발행하고, SPOT 과 OC 서버가 함께 구독합니다.

어디서 판단하고 어디서 실행하나

전시 컨셉은 고객의 요청을 받으면 시스템이 알아서 시나리오를 돌리는 것입니다. 그 "알아서" 가 일어나는 자리는 태블릿·OC 서버 쪽이고, SPOT 은 그 결과로 정해진 시나리오를 실행합니다.

고객 요청  →  어떤 시나리오를 돌릴지 판단  →  지령 발행  →  SPOT 이 실행
                   (태블릿 / OC 서버)                        (판단 안 함)

SPOT 은 "무엇을 할지" 를 스스로 고르지 않습니다. 받은 시나리오를 어떻게 수행할지(경로, 자세, 정렬)만 정합니다.

SPOT 이 지령 없이 스스로 하는 일은 두 가지뿐입니다 — 이미 받은 명령을 마무리하는 것(추종 종료 후 위치 재확인 등)과 안전 동작(통신 두절 시 정지, 유휴 시 착석).

토픽·페이로드 상세는 MQTT_SCHEMA-SPOT 참조.


1. 지점 이동

sequenceDiagram
    participant 태블릿
    participant MQTT
    participant SPOT
    participant OC as OC-SERVER

    태블릿-->>MQTT: 1. pub (command) {action:"navigate_to", destination:"p2"}
    MQTT-->>SPOT: 2. sub (command)
    MQTT-->>OC: 3. sub (command) → 진행 중 상태 변경

    SPOT-->>MQTT: 4. pub (ack) {status:"ACCEPTED"}
    MQTT-->>OC: 5. sub (ack)

    Note over SPOT: 위치추정 확인 → 경로 계산 → 주행<br/>중간 경유지는 SPOT 이 알아서 지나간다

    loop 1Hz
        SPOT-->>MQTT: pub (state) {fsm:"NAVIGATING", current_waypoint_label:…}
        MQTT-->>OC: sub (state)
    end

    alt 도착
        SPOT-->>MQTT: 6. pub (ack) {status:"SUCCESS", location:"p2"}
        MQTT-->>OC: 7. sub (ack)
    else 자기 위치를 모름
        SPOT-->>MQTT: 6. pub (ack) {status:"FAULT_NAV", code:"NOT_LOCALIZED"}
        MQTT-->>OC: 7. sub (ack) → 운영자 호출
    end
Loading

정책 제안

# 제안 왜
1 목적지는 이름 붙인 지점만 보낸다 자동 생성 경유지(waypoint_7)는 길이지 장소가 아닙니다. 목록은 waypoints 토픽(retained)에 있습니다
2 경로는 발행자가 정하지 않는다 어느 경유지를 거칠지는 SPOT 이 계산합니다. 최종 목적지만 주면 됩니다
3 NOT_LOCALIZED 는 재시도하지 않는다 로봇이 자기 위치를 모르는 상태라 몇 번을 보내도 같은 실패입니다. 사람이 태그가 보이는 곳으로 옮겨야 풀립니다
4 그 외 FAULT_NAV 는 1회 재시도 후 다른 목적지로 재계획 사람이 길을 막고 있는 경우가 대부분이라 잠시 후면 풀립니다
5 이동 중 새 이동 명령은 BUSY 로 거절된다 앞 명령의 완료를 받고 다음을 보내주세요

속도 — 전시장 기본 0.15 m/s 로 고정입니다. 관객 사이를 다니므로 발행자가 올릴 수 없게 했습니다.

뒤로 걷지 않습니다 — 방향이 안 맞으면 회전해서 앞으로 갑니다. 관객 눈에 고장으로 보이고, 진행 방향을 카메라가 못 보기 때문입니다.


2. 시나리오 실행 (전시 안내)

sequenceDiagram
    participant 태블릿
    participant MQTT
    participant SPOT
    participant OC as OC-SERVER

    Note over MQTT,OC: 접속 시 scenarios (retained) 구독<br/>→ 실행 가능한 시나리오 목록 확보 (태블릿 메뉴를 이걸로 채운다)

    Note over 태블릿: 고객 요청을 받아 어떤 시나리오를 돌릴지 판단
    태블릿-->>MQTT: 1. pub (command) {action:"run_scenario", scenario_id:"guide"}
    MQTT-->>SPOT: 2. sub (command)
    MQTT-->>OC: 3. sub (command) → 진행 중 상태 변경

    SPOT-->>MQTT: 4. pub (ack) {status:"ACCEPTED"}
    MQTT-->>OC: 5. sub (ack)

    Note over SPOT: 어떤 동작들로 이루어졌는지는 SPOT 이 안다<br/>발행자는 이름만 보냈다

    SPOT-->>MQTT: 6. pub (plan) {step_index:0, total:3, status:"SUCCESS"}
    MQTT-->>OC: 7. sub (plan) → 진행률 갱신
    SPOT-->>MQTT: pub (plan) {step_index:1, …}
    MQTT-->>OC: sub (plan)
    SPOT-->>MQTT: pub (plan) {step_index:2, …}
    MQTT-->>OC: sub (plan)

    SPOT-->>MQTT: 8. pub (ack) {status:"SUCCESS"}
    MQTT-->>OC: 9. sub (ack)
Loading

정책 제안

# 제안 왜
1 시나리오 이름만 보낸다 "세부 로직은 로봇에서 처리" 원칙을 지키는 방법입니다. 인사 동작·대기 시간 같은 건 발행자가 몰라도 됩니다
2 시나리오 목록은 scenarios 토픽(retained)에서 받는다 관리자 UI 에서 시나리오를 고치면 자동으로 반영됩니다. 태블릿·서버 코드를 고칠 필요가 없습니다
3 진행률은 plan 토픽으로 나간다 3단계 중 2단계라는 걸 태블릿에 보여줄 수 있습니다. 완료만 기다리면 그 사이가 깜깜합니다
4 시나리오 안의 낱개 동작은 ack 를 쏘지 않는다 보내지 않은 명령의 응답이 오면 혼란스럽습니다. 시나리오 전체에 대해 한 번만 옵니다
5 로봇이 못 하는 동작이 섞여 있으면 unsupported_steps 로 알린다 조용히 빼고 실행하면 완전히 수행된 줄 압니다

변수 치환 — 시나리오에 $spot 같은 자리가 있으면 variables 로 채웁니다. 무엇으로 채울지(태블릿에서 고른 목적지 등)는 발행하는 쪽이 정합니다.


3. 사람 추종

sequenceDiagram
    participant 태블릿
    participant MQTT
    participant SPOT
    participant OC as OC-SERVER

    태블릿-->>MQTT: 1. pub (command) {action:"follow", mode:"start"}
    MQTT-->>SPOT: 2. sub (command)
    MQTT-->>OC: 3. sub (command) → 진행 중 상태 변경

    SPOT-->>MQTT: 4. pub (ack) {status:"ACCEPTED"}
    MQTT-->>OC: 5. sub (ack)

    Note over SPOT: 제일 가까운 사람을 잡고 따라간다<br/>좌우로 둘러보는 중 = 아직 못 찾음

    alt 손님이 그냥 자리를 뜸
        Note over SPOT: 25초 동안 안 보이면 스스로 종료
        SPOT-->>MQTT: 6. pub (ack) {status:"SUCCESS", reason:"target_lost"}
    else 태블릿에서 종료
        태블릿-->>MQTT: pub (command) {action:"follow", mode:"stop"}
        MQTT-->>SPOT: sub (command)
        SPOT-->>MQTT: 6. pub (ack) {status:"SUCCESS"}
    end
    MQTT-->>OC: 7. sub (ack)

    Note over SPOT: 종료 후 자기 위치를 다시 잡는다<br/>추종은 맵 경로를 안 타서 위치가 흐려진다
Loading

정책 제안

# 제안 왜
1 대상은 시작 시점에 제일 가까운 사람 얼굴을 보지 않으므로 "누구"를 지정할 수 없습니다. 따라올 사람이 로봇 앞에 서면 됩니다
2 한 번 잡으면 다른 사람으로 바뀌지 않는다 관객이 앞을 스쳐도 유지합니다. 완전히 놓쳐야 다시 고릅니다
3 25초 동안 사람이 안 보이면 스스로 끝낸다 손님이 그냥 가버리는 게 전시에서 가장 흔합니다. 매번 종료 명령을 보내주기를 기대할 수 없습니다
4 한 번에 최대 5분 잊고 방치되는 것을 막습니다
5 종료 후 SPOT 이 스스로 위치를 다시 잡는다 추종은 맵 경로를 안 타서 끝나면 자기 위치가 흐려집니다. 이걸 안 하면 다음 이동 명령이 조용히 실패합니다
6 유지 거리 2m, 최대 0.2 m/s 발행자가 바꿀 수 없게 했습니다. 관객에게 빠르게 접근하는 일이 없어야 합니다

관객이 보는 신호 — 좌우로 크게 둘러보면 "아직 못 찾음", 멈추고 따라오면 "잡았음"입니다. 동작은 이 하나뿐입니다. 여러 개를 두면 관객이 구분하지 못합니다.


4. 비상정지와 복구

sequenceDiagram
    participant 운영자
    participant SPOT
    participant MQTT
    participant OC as OC-SERVER
    participant 태블릿

    Note over SPOT: 이동 중 (command_id: cmd-0042)

    운영자-->>SPOT: STOP (관리자 UI 또는 물리 버튼)
    Note over SPOT: MQTT 를 거치지 않는 최단 경로로 즉시 정지

    SPOT-->>MQTT: 1. pub (estop, retained) {active:true, reason:"soft_stop"}
    MQTT-->>OC: 2. sub (estop)
    MQTT-->>태블릿: 3. sub (estop) → 화면에 정지 표시

    SPOT-->>MQTT: 4. pub (ack) {command_id:"cmd-0042", status:"ABORTED"}
    MQTT-->>OC: 5. sub (ack)
    Note over OC,태블릿: 명령 발행 중단

    운영자-->>SPOT: RESUME
    SPOT-->>MQTT: 6. pub (estop, retained) {active:false}
    MQTT-->>OC: 7. sub (estop)
    MQTT-->>태블릿: 8. sub (estop) → 정지 표시 해제
Loading

정책 제안

# 제안 왜
1 정지는 MQTT 를 거치지 않는다 브로커가 죽어도 멈춰야 합니다. MQTT 로는 "멈췄다"는 사실만 알립니다
2 정지는 무엇보다 우선한다 BUSY 여도 받습니다. 다른 명령이 돌고 있어도 즉시 멈춥니다
3 기본 정지는 전원을 끄는 게 아니다 선 채로 멈춥니다. 바로 재개할 수 있습니다. 전원 차단은 별도 버튼입니다
4 진행 중이던 명령은 ABORTED 로 종료 보고한다 그 명령의 결과를 영원히 기다리지 않게
5 estop.active=true 동안 명령 발행을 멈춘다 보내봐야 거부되거나, 더 나쁘게는 사람이 개입 중인데 다시 움직입니다
6 복구는 사람이 한다 자동 복구를 넣지 않았습니다. 왜 멈췄는지 사람이 확인해야 합니다
7 estop 은 retained 로 발행한다 태블릿·서버가 나중에 켜져도 지금 정지 상태임을 즉시 압니다

정지 트리거

트리거 누가 결과 복구
STOP 운영자 즉시 멈춤, 선 채로 RESUME
STOP + SIT 운영자 멈추고 앉음 RESUME
하드 E-Stop 운영자 모터 전원 차단 RESUME
명령 만료 자동 조종자가 죽으면 3초 뒤 정지 연결 복구 후 재명령
데드맨 자동 통신 두절 30초 뒤 앉고 전원 차단 RESUME

5. 제어권 인수·인계

전시 중 관리자가 로봇을 직접 몰아야 하는 상황이 생깁니다 — 장애물 제거, 위치 조정 등. 로봇은 한 번에 한 명만 몰 수 있어서, 관리자가 가져가는 동안 발행된 명령은 실패합니다.

sequenceDiagram
    participant 관리자 as 관리자 노트북
    participant SPOT
    participant MQTT
    participant OC as OC-SERVER
    participant 태블릿

    Note over MQTT,태블릿: 평상시 — state: commands_accepted=true

    관리자-->>SPOT: 제어권 회수 (현장에서 직접 조작하려고)
    SPOT-->>MQTT: 1. pub (state, retained) {commands_accepted:false, lease_owner:"operator"}
    MQTT-->>OC: 2. sub (state)
    MQTT-->>태블릿: 3. sub (state) → "점검 중" 표시

    SPOT-->>MQTT: 4. pub (ack) {status:"FAULT_LEASE"}
    MQTT-->>OC: 5. sub (ack)
    Note over OC,태블릿: 명령 발행 중단하고 대기

    관리자-->>SPOT: 제어권 반납 (버튼을 눌러야 함 — 자동 반납 없음)
    SPOT-->>MQTT: 6. pub (state, retained) {commands_accepted:true, lease_owner:"orchestration"}
    MQTT-->>OC: 7. sub (state)
    MQTT-->>태블릿: 8. sub (state) → 정상 표시
Loading

정책 제안

# 제안 왜
1 현장 관리자가 발행자보다 우선한다 눈으로 보고 있는 사람이 판단할 수 있어야 합니다
2 state 에 commands_accepted 를 넣는다. 새 토픽은 만들지 않는다 이미 구독하는 state(1Hz, retained)에 불리언 하나면 충분합니다. 서버가 lease_owned 를 해석할 필요 없이 "지금 명령이 먹나" 를 바로 알 수 있습니다
3 commands_accepted:false 동안 발행을 멈춘다 보내면 전부 FAULT_LEASE 로 실패합니다
4 진행 중이던 명령은 FAULT_LEASE 로 종료 보고한다 그 명령의 결과를 영원히 기다리지 않게
5 자동 반납은 없다. 관리자가 직접 반납해야 한다 타이머로 자동 반납하면, 관리자가 로봇 옆에서 조치하는 중에 제어권이 넘어가 사람 옆에서 로봇이 움직입니다

commands_accepted 가 false 가 되는 경우 — 관리자 제어권 회수, 비상정지 중, 배터리 부족. 이유는 state 의 다른 필드(lease_owner, estop_state, battery_pct)로 구분할 수 있습니다.

관리자가 반납을 잊으면 전시가 멈춥니다(로봇은 서 있는데 명령이 전부 거부). 관리자 UI 상단에 제어권 보유가 항상 표시되고, 오래 쥐고 있으면 경고가 뜹니다.

공통 정책

시나리오를 가리지 않고 적용됩니다.

한 번에 하나

SPOT 은 명령을 하나씩만 실행합니다. 실행 중 새 명령은 BUSY 로 거절합니다 (STOP 제외).

제안 — 발행하는 쪽이 순서를 관리해주세요. 앞 명령의 완료 응답을 받은 뒤 다음을 보내는 방식이 가장 단순합니다.

태블릿과 OC 서버가 둘 다 발행할 수 있다면, 서로 모르는 채로 동시에 보내면 뒤엣것이 BUSY 로 거절됩니다. 누가 순서를 관리할지 정해야 합니다 (아래 협의 사항 1번).

배터리

수준 SPOT 동작 대응 제안
35% 이하 상태에 표시 긴 시나리오를 새로 시작하지 않기
30% 미만 전원 인가가 거부될 수 있음 충전 안내
25% 이하 새 이동 명령 거부 운영자 호출

유휴 시 자동 착석

3분 동안 명령이 없으면 SPOT 이 스스로 앉습니다. 다음 명령에 자동으로 다시 일어섭니다. 서 있는 것만으로 배터리가 빠르게 닳기 때문입니다. 따로 할 일은 없습니다.

로봇이 죽었을 때

state 토픽에 connection:"offline" 이 뜹니다. SPOT 이 발행하는 게 아니라 브로커가 대신 발행합니다(MQTT LWT). 브로커가 알아채는 데 최대 60초 걸리므로 timestamp 를 같이 보고 판단해주세요.


협의가 필요한 것

# 항목 지금 물어보고 싶은 것
1 동시 발행 정리 태블릿·OC 서버 둘 다 robot/+/command 쓰기 권한 보유 (브로커 ACL 확인) SPOT 은 한 번에 하나만 실행하고, 실행 중 새 명령은 BUSY 로 거절합니다. 둘이 서로 모르는 채로 보내면 뒤엣것이 거절됩니다. 누가 순서를 관리할지 정해야 합니다
2 시나리오 목록 발행 주체 관리자 UI 가 scenarios 토픽(retained)으로 발행 서버가 시나리오를 만들거나 관리할 계획이 있다면 발행 주체를 옮겨야 합니다. 지금 계획을 알려주세요

실제로 검증된 것

안 해본 것을 했다고 적으면 그걸 전제로 개발하시게 되므로 나눠 적었습니다.

항목 상태
지점 이동 완주 ✅ 2026-08-07, MQTT 경로로 웨이포인트 7개 통과
시나리오 실행 ✅ 3스텝 전부 성공, session_id 그대로 되돌아옴
사람 추종 시작·정지 ✅
추종 중 STOP ✅ 1초 안에 정지
1Hz 상태 발행 ✅
목적지 목록(retained) ✅
state.commands_accepted (5절 제안) ⬜ 제안 단계 — 미구현
충전 위치 복귀 ⬜ 미검증
로봇팔 연동 전체 흐름 ⬜ 미시험

Clone this wiki locally