sequence - zero1ne-26/doc GitHub Wiki

SPOT ์—ฐ๋™ ํ๋ฆ„

๊ฐฑ์‹  2026-08-28. ๋ช…๋ น์„ ๋ˆ„๊ฐ€ ๋ฐœํ–‰ํ•˜๋Š”๊ฐ€๊ฐ€ 08-08 ํŒ๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ์•„๋ž˜ ยง0 ์ด ์ง€๊ธˆ ๊ตฌ์กฐ์ด๊ณ , ๊ทธ ๋’ค ์‹œ๋‚˜๋ฆฌ์˜ค๋ณ„ ๊ทธ๋ฆผ์€ ๋กœ๋ด‡ ์ชฝ ๋™์ž‘(ack 2๋‹จ๊ณ„ยท์ƒํƒœยท ๋น„์ƒ์ •์ง€)์„ ์ฝ๋Š” ๋ฐ ์”๋‹ˆ๋‹ค.

๋กœ๋ด‡์ด ๋ฐ›๋Š” ํ† ํ”ฝยทํŽ˜์ด๋กœ๋“œ๋Š” MQTT_SCHEMA-SPOT, ๋„์ฐฉ ์ž๋™ํ™” ๊ทœ์น™ยทํ์˜ ์ž์„ธํ•œ ์„ค๊ณ„๋Š” LOCATION_AUTOMATION_DESIGN ์— ์žˆ์Šต๋‹ˆ๋‹ค.


0. ๋ˆ„๊ฐ€ ๋ช…๋ น์„ ๋‚ด๋Š”๊ฐ€ (2026-08-28 ํ˜„์žฌ)

๋กœ๋ด‡ ํ† ํ”ฝ robot/{robotId}/command ์— ๋ฐœํ–‰ํ•˜๋Š” ๊ฒƒ์€ OC ์„œ๋ฒ„๋ฟ์ž…๋‹ˆ๋‹ค. ํƒœ๋ธ”๋ฆฟ๋„ ๊ด€๋ฆฌ์ž ํ™”๋ฉด๋„ ์ง์ ‘ ์˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค โ€” ์„œ๋ฒ„์— ์š”์ฒญํ•˜๊ณ , ์„œ๋ฒ„๊ฐ€ ํ๋กœ ์ˆœ์„œ๋ฅผ ์ •ํ•ด ๋ƒ…๋‹ˆ๋‹ค.

flowchart TD
    T["ํƒœ๋ธ”๋ฆฟ<br/>์„ ํƒ์ง€๋ฅผ ๊ณ ๋ฅธ๋‹ค"] -->|"orchestration/{sess}/task(event)/option/select"| S
    A["๊ด€๋ฆฌ์žยทํ…Œ์ŠคํŠธ ์ฝ˜์†”"] -->|"orchestration/{sess}/spot/command"| S
    V["Vision<br/>vision/position/person"] -->|"์žฅ์†Œ ๋„์ฐฉ ๊ฐ์ง€"| S

    S["OC ์„œ๋ฒ„"] --> DB[("DB<br/>์„ ํƒ์ง€์˜ spot_action<br/>์žฅ์†Œโ†’์›จ์ดํฌ์ธํŠธ ๋ผ๋ฒจ<br/>๋„์ฐฉ ์ž๋™ํ™” ๊ทœ์น™")]
    DB --> S
    S --> Q["๋””๋ฐ”์ด์Šค ๋ช…๋ น ํ<br/>SQS FIFO ยท ๋””๋ฐ”์ด์Šค๋ณ„ ์ง๋ ฌ"]
    Q -->|"robot/spot-01/command"| R["SPOT"]
    R -->|"robot/spot-01/ack"| Q
    Q -->|"์™„๋ฃŒ๋˜๋ฉด ๋‹ค์Œ ์•ก์…˜"| Q
    R -->|"state ยท plan ยท waypoints"| S
    S -->|"orchestration/spot/{id}/*<br/>orchestration/{sess}/spot/*"| T
Loading

๋ช…๋ น์ด ์ƒ๊ธฐ๋Š” ์„ธ ๊ฐˆ๋ž˜

# ๊ณ„๊ธฐ ์„œ๋ฒ„๊ฐ€ ํ•˜๋Š” ์ผ
1 ํƒœ๋ธ”๋ฆฟ์ด ์„ ํƒ์ง€๋ฅผ ๊ณ ๋ฆ„ ๊ทธ ์„ ํƒ์ง€์— spot_action ์ด ์„ค์ •๋ผ ์žˆ์œผ๋ฉด ์ฆ‰์‹œ ๋ฐœํ–‰. ์„ ํƒ ์ž์ฒด๊ฐ€ ์Šน์ธ์ด๋ผ ๋ณ„๋„ ํ™•์ธ ์ ˆ์ฐจ๊ฐ€ ์—†๋‹ค. navigate_to ๋ฉด ๋ชฉ์ ์ง€๋ฅผ ๊ทธ ์ž๋ฆฌ์—์„œ ๊ณ„์‚ฐํ•œ๋‹ค โ€” ์„ธ์…˜์˜ ๋‹ค์Œ ๋ฐฉ๋ฌธ ์žฅ์†Œ๋ฅผ ์ฐพ๊ณ , ๊ทธ ์žฅ์†Œ์— ๋งคํ•‘๋œ ์›จ์ดํฌ์ธํŠธ ๋ผ๋ฒจ์„ ๊บผ๋‚ธ๋‹ค
2 ๊ด€๋ฆฌ์žยทํ…Œ์ŠคํŠธ ์ฝ˜์†” orchestration/{sessionId}/spot/command ๋ฅผ ๋ฐ›์•„ ๊ทธ๋Œ€๋กœ ํ์— ๋„ฃ๋Š”๋‹ค. ์„ธ์…˜์— ๋ฐฐ์ •๋œ SPOT ์ด ์—†์œผ๋ฉด ๊ฑฐ์ ˆ
3 ์žฅ์†Œ ๋„์ฐฉ ์ž๋™ํ™” (2026-08-22 ์‹ ๊ทœ) Vision ์ด ๋ฐฉ๋ฌธ๊ฐ ์ขŒํ‘œ๋ฅผ ๊ณ„์† ๋ฐœํ–‰ โ†’ ์„œ๋ฒ„๊ฐ€ ์žฅ์†Œ๋กœ ๋งคํ•‘ โ†’ ์žฅ์†Œ๊ฐ€ ๋ฐ”๋€ ์ˆœ๊ฐ„ ๊ทธ (์‚ฌ์šฉ์žยท์žฅ์†Œยทํƒœ์Šคํฌ/์ด๋ฒคํŠธ) ์— ๊ฑธ๋ฆฐ ๊ทœ์น™์„ ์ฐพ์•„ ์ž๋™ ๋ฐœํ–‰. ๋ณด์œ  ์•„์ดํ…œยท์ฒซ ๋ฐฉ๋ฌธ ์—ฌ๋ถ€ ๊ฐ™์€ ์กฐ๊ฑด๊ณผ ์ฟจ๋‹ค์šด์„ ๋ณธ๋‹ค

ํ๊ฐ€ ํ•˜๋Š” ์ผ

Enqueue โ†’ ๋””๋ฐ”์ด์Šค๋ณ„ ๊ทธ๋ฃน(spot:{robotId})์œผ๋กœ ์ง๋ ฌํ™”
        โ†’ delay_ms ๋Œ€๊ธฐ โ†’ MQTT ๋ฐœํ–‰
        โ†’ ์™„๋ฃŒ ์‹ ํ˜ธ ๋Œ€๊ธฐ      SPOT ์€ ack ์˜ ์ข…๊ฒฐ status (SUCCESS/FAULT_*/ABORTED/TIMEOUT)
        โ†’ ๋‹ค์Œ ์•ก์…˜ ์ ์žฌ      ๊ทœ์น™ ์•ˆ์˜ ์•ก์…˜ ์ฒด์ธ
        โ†’ timeout_ms(๊ธฐ๋ณธ 30์ดˆ) ๋„˜์œผ๋ฉด timeout ์œผ๋กœ ๊ธฐ๋กํ•˜๊ณ  ๋‹ค์Œ์œผ๋กœ

์™œ ํ•œ ๊ณณ์œผ๋กœ ๋ชจ์•˜๋‚˜ โ€” SPOT ์€ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹คํ–‰ ์ค‘ ์ƒˆ ๋ช…๋ น์€ BUSY ๋กœ ๊ฑฐ์ ˆํ•ฉ๋‹ˆ๋‹ค(ยง9.1). ํƒœ๋ธ”๋ฆฟยท์ž๋™ํ™”ยท์ฝ˜์†”์ด ์„œ๋กœ ๋ชจ๋ฅธ ์ฑ„ ๊ฐ์ž ๋ณด๋‚ด๋ฉด ๋’ค์—ฃ๊ฒƒ์ด ๊ทธ๋ƒฅ ์ฃฝ์Šต๋‹ˆ๋‹ค. 2026-08-10 ์— ์„œ๋ฒ„๊ฐ€ ์ˆœ์„œ๋ฅผ ๋งก๊ธฐ๋กœ ์ •ํ–ˆ๊ณ , 08-22 ์— ๋””๋ฐ”์ด์Šค ๊ณตํ†ต ํ๋กœ ์ผ๋ฐ˜ํ™”๋์Šต๋‹ˆ๋‹ค.

๋กœ๋ด‡ ์ชฝ์€ ์ด ๋ณ€ํ™”๋กœ ๋ฐ”๋€ ๊ฒƒ์ด ์—†์Šต๋‹ˆ๋‹ค. ๋ฐ›๋Š” ํ† ํ”ฝยทํŽ˜์ด๋กœ๋“œยทack ๊ทœ์•ฝ์ด ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜ ๊ทธ๋ฆผ๋“ค์˜ ํ™”์‚ดํ‘œ ์ถœ๋ฐœ์ (ํƒœ๋ธ”๋ฆฟ)์€ ์˜› ํŒ์ด๋ผ ยง0 ์œผ๋กœ ์ฝ์–ด์ฃผ์„ธ์š”.


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 ์‹œ๋‚˜๋ฆฌ์˜ค๋“ค์ž…๋‹ˆ๋‹ค. ์‚ฌ๋žŒ์ด ์‹œ์ž‘ํ•˜๋Š” ๋ช…๋ น์€ ํƒœ๋ธ”๋ฆฟ์ด ์„ ํƒ์ง€ ์„ ํƒ์œผ๋กœ ์•Œ๋ฆฌ๊ณ , OC ์„œ๋ฒ„๊ฐ€ ๊ทธ๊ฒƒ์„ SPOT ๋ช…๋ น์œผ๋กœ ๋ฐ”๊ฟ” ๋ฐœํ–‰ํ•ฉ๋‹ˆ๋‹ค (ยง0). ํƒœ๋ธ”๋ฆฟ์€ ๋กœ๋ด‡ ํ† ํ”ฝ์— ์ง์ ‘ ์˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์–ด๋””์„œ ํŒ๋‹จํ•˜๊ณ  ์–ด๋””์„œ ์‹คํ–‰ํ•˜๋‚˜

์ „์‹œ ์ปจ์…‰์€ ๊ณ ๊ฐ์˜ ์š”์ฒญ์„ ๋ฐ›์œผ๋ฉด ์‹œ์Šคํ…œ์ด ์•Œ์•„์„œ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋Œ๋ฆฌ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ "์•Œ์•„์„œ" ๊ฐ€ ์ผ์–ด๋‚˜๋Š” ์ž๋ฆฌ๋Š” ํƒœ๋ธ”๋ฆฟยทOC ์„œ๋ฒ„ ์ชฝ์ด๊ณ , SPOT ์€ ๊ทธ ๊ฒฐ๊ณผ๋กœ ์ •ํ•ด์ง„ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๊ณ ๊ฐ ์š”์ฒญ  โ†’  ์–ด๋–ค ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋Œ๋ฆด์ง€ ํŒ๋‹จ  โ†’  ์ง€๋ น ๋ฐœํ–‰  โ†’  SPOT ์ด ์‹คํ–‰
             (๊ด€๋ฆฌ์ž๊ฐ€ ๋ฏธ๋ฆฌ DB ์— ์„ค์ • โ†’ OC ์„œ๋ฒ„๊ฐ€ ์กฐํšŒ)        (ํŒ๋‹จ ์•ˆ ํ•จ)

SPOT ์€ "๋ฌด์—‡์„ ํ• ์ง€" ๋ฅผ ์Šค์Šค๋กœ ๊ณ ๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฐ›์€ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์–ด๋–ป๊ฒŒ ์ˆ˜ํ–‰ํ• ์ง€(๊ฒฝ๋กœ, ์ž์„ธ, ์ •๋ ฌ)๋งŒ ์ •ํ•ฉ๋‹ˆ๋‹ค.

SPOT ์ด ์ง€๋ น ์—†์ด ์Šค์Šค๋กœ ํ•˜๋Š” ์ผ์€ ๋‘ ๊ฐ€์ง€๋ฟ์ž…๋‹ˆ๋‹ค โ€” ์ด๋ฏธ ๋ฐ›์€ ๋ช…๋ น์„ ๋งˆ๋ฌด๋ฆฌํ•˜๋Š” ๊ฒƒ(์ถ”์ข… ์ข…๋ฃŒ ํ›„ ์œ„์น˜ ์žฌํ™•์ธ ๋“ฑ)๊ณผ ์•ˆ์ „ ๋™์ž‘(ํ†ต์‹  ๋‘์ ˆ ์‹œ ์ •์ง€, ์œ ํœด ์‹œ ์ฐฉ์„).

ํ† ํ”ฝยทํŽ˜์ด๋กœ๋“œ ์ƒ์„ธ๋Š” MQTT_SCHEMA-SPOT ์ฐธ์กฐ.


1. ์ง€์  ์ด๋™

sequenceDiagram
    participant ํƒœ๋ธ”๋ฆฟ
    participant MQTT
    participant SPOT
    participant OC as OC-SERVER

    ํƒœ๋ธ”๋ฆฟ-->>MQTT: 1. pub (task/option/select) {option_id}
    MQTT-->>OC: 2. sub โ†’ DB ์กฐํšŒ (spot_action ยท ๋‹ค์Œ ์žฅ์†Œ โ†’ ์›จ์ดํฌ์ธํŠธ ๋ผ๋ฒจ) โ†’ ํ
    OC-->>MQTT: 3. pub (command) {action:"navigate_to", destination:"p2"}
    MQTT-->>SPOT: 4. 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/>โ†’ ์„ ํƒ์ง€์˜ scenario_id ํ›„๋ณด๋ฅผ ์ฑ„์šด๋‹ค

    Note over OC: ์„ ํƒ์ง€์— ์„ค์ •๋œ spot_action ยท scenario_id ๋ฅผ DB ์—์„œ ์กฐํšŒ
    ํƒœ๋ธ”๋ฆฟ-->>MQTT: 1. pub (option/select) {option_id}
    MQTT-->>OC: 2. sub โ†’ ์„ ํƒ์ง€์— ๊ฑธ๋ฆฐ scenario_id ๋ฅผ DB ์—์„œ ๊บผ๋ƒ„ โ†’ ํ
    OC-->>MQTT: 3. pub (command) {action:"run_scenario", scenario_id:"guide"}
    MQTT-->>SPOT: 4. 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 (option/select) {option_id}
    MQTT-->>OC: 2. sub โ†’ DB ์กฐํšŒ โ†’ ํ
    OC-->>MQTT: 3. pub (command) {action:"follow", mode:"start"}
    MQTT-->>SPOT: 4. 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 (option/select) โ†’ OC
        OC-->>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 ๋ฐœํ–‰์ž๊ฐ€ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ด€๊ฐ์—๊ฒŒ ๋น ๋ฅด๊ฒŒ ์ ‘๊ทผํ•˜๋Š” ์ผ์ด ์—†์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค

๊ด€๊ฐ์ด ๋ณด๋Š” ์‹ ํ˜ธ โ€” ์ขŒ์šฐ๋กœ ํฌ๊ฒŒ ๋‘˜๋Ÿฌ๋ณด๋ฉด "์•„์ง ๋ชป ์ฐพ์Œ", ๋ฉˆ์ถ”๊ณ  ๋”ฐ๋ผ์˜ค๋ฉด "์žก์•˜์Œ"์ž…๋‹ˆ๋‹ค. ๋™์ž‘์€ ์ด ํ•˜๋‚˜๋ฟ์ž…๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ๋‘๋ฉด ๊ด€๊ฐ์ด ๊ตฌ๋ถ„ํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.


3.5 ์žฅ์†Œ ๋„์ฐฉ ์ž๋™ํ™” (2026-08-22 ์‹ ๊ทœ)

ํƒœ๋ธ”๋ฆฟ์„ ๋ˆ„๋ฅด์ง€ ์•Š์•„๋„ ๋กœ๋ด‡์ด ์›€์ง์ด๋Š” ์œ ์ผํ•œ ๊ฒฝ๋กœ. ๊ด€๋žŒ๊ฐ์ด ๊ทธ ์žฅ์†Œ์— ๋„์ฐฉํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ๋ฏธ๋ฆฌ ์ •ํ•ด๋‘” ๋ช…๋ น์ด ๋‚˜๊ฐ‘๋‹ˆ๋‹ค.

sequenceDiagram
    participant V as Vision
    participant MQTT
    participant OC as OC-SERVER
    participant SPOT

    V-->>MQTT: vision/position/person {์ขŒํ‘œ, zone_id}
    MQTT-->>OC: sub (๊ณ„์† ๋“ค์–ด์˜จ๋‹ค)
    Note over OC: zone โ†’ ์žฅ์†Œ ๋งคํ•‘<br/>**์žฅ์†Œ๊ฐ€ ๋ฐ”๋€ ์ˆœ๊ฐ„๋งŒ** ์•„๋ž˜๋กœ ์ง„ํ–‰

    Note over OC: ์ด (์‚ฌ์šฉ์žยท์žฅ์†Œยทํƒœ์Šคํฌ/์ด๋ฒคํŠธ) ์— ๊ฑธ๋ฆฐ ๊ทœ์น™์„ ์ฐพ๋Š”๋‹ค<br/>๋ณด์œ  ์•„์ดํ…œ ยท ์ฒซ ๋ฐฉ๋ฌธ ์—ฌ๋ถ€ ยท ์ฟจ๋‹ค์šด ๊ฒ€์‚ฌ
    OC-->>MQTT: pub (command) {action, params}
    MQTT-->>SPOT: sub (command)
    SPOT-->>MQTT: ack {status:"ACCEPTED"}
    SPOT-->>MQTT: ack {status:"SUCCESS"}
    MQTT-->>OC: sub (ack)
    Note over OC: ์™„๋ฃŒ๋ฅผ ๋ฐ›์œผ๋ฉด **๊ทœ์น™ ์•ˆ์˜ ๋‹ค์Œ ์•ก์…˜**์„ ํ์— ๋„ฃ๋Š”๋‹ค<br/>(๋กœ๋ด‡ํŒ”ยท๋ฐ˜๋ ค๋กœ๋ด‡ยทHub ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค)
Loading
๋ฌด์—‡์ด ๋ฐœํ™”ํ•˜๋‚˜ ์žฅ์†Œ ์ž์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ (์‚ฌ์šฉ์ž, ์žฅ์†Œ, ํƒœ์Šคํฌ/์ด๋ฒคํŠธ) ๋งคํ•‘์ด ์ •ํ•œ๋‹ค. ๊ฐ™์€ "์ง‘"์ด๋ผ๋„ ์„ธ์…˜๋งˆ๋‹ค ๋‹ค๋ฅด๋‹ค
์•ˆ ๋‚˜๊ฐ€๋Š” ๊ฒฝ์šฐ ๊ทœ์น™์ด ์š”๊ตฌํ•˜๋Š” ์•„์ดํ…œ์ด ์—†์œผ๋ฉด missing_item, ๊ทธ ์žฅ์†Œ์— ๋””๋ฐ”์ด์Šค๊ฐ€ ๋งคํ•‘ ์•ˆ ๋ผ ์žˆ์œผ๋ฉด no device ๋กœ ๊ฑด๋„ˆ๋›ด๋‹ค
๋กœ๋ด‡์ด ์•„๋Š” ๊ฒƒ ์—†๋‹ค. ๋กœ๋ด‡์—๊ฒŒ๋Š” ํ‰๋ฒ”ํ•œ robot/spot-01/command ๋กœ ๋ณด์ธ๋‹ค

๋งˆ์ง€๋ง‰ ์ค„์ด ์š”์ ์ž…๋‹ˆ๋‹ค โ€” ๋กœ๋ด‡ ์ชฝ์€ ์ด ๊ธฐ๋Šฅ์ด ์ƒ๊ฒจ๋„ ๋ฐ”๋€ ๊ฒƒ์ด ์—†์Šต๋‹ˆ๋‹ค.


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์ ˆ ์ œ์•ˆ) โฌœ ์ œ์•ˆ ๋‹จ๊ณ„ โ€” ๋ฏธ๊ตฌํ˜„
์ถฉ์ „ ์œ„์น˜ ๋ณต๊ท€ โฌœ ๋ฏธ๊ฒ€์ฆ
๋กœ๋ด‡ํŒ” ์—ฐ๋™ ์ „์ฒด ํ๋ฆ„ โฌœ ๋ฏธ์‹œํ—˜
โš ๏ธ **GitHub.com Fallback** โš ๏ธ