Skip to main content
Glama
Alonbbar6

robot-runtime

by Alonbbar6

원격 로봇 정책을 위한 제어 런타임

시뮬레이션된 Franka Panda가 픽 앤 플레이스를 수행하며, HTTP 경계 뒤에 있는 정책에 의해 구동됩니다 — 그리고 그 경계가 오작동해도 계속 작동합니다.

서버 중단을 견디고 재개하는 런타임

흥미로운 부분은 로봇 팔이 아닙니다. 팔과 모델 사이의 모든 것이 핵심입니다: 액션 청크 스케줄링, 오래된 데이터 거부, 백오프가 있는 재시도, 회로 차단기, 스스로 해제되는 보호 홀드, 그리고 에이전트가 셀을 손상시키지 않고 구동할 수 있게 해주는 MCP 도구 표면.

전적으로 노트북에서 실행됩니다. GPU 없음, ROS 설치 없음, 하드웨어 없음.


네트워크가 어려운 부분인 이유

조작 정책은 GPU를 원합니다. 로봇은 실시간 제어 루프를 원합니다. 둘은 거의 같은 머신이 아니므로, 실제로는 모델이 네트워크 홉 뒤에 있습니다 — 이것이 정책이 단일 스텝 대신 액션 청크를 방출하는 이유입니다. 50Hz로 추론 서버를 왕복할 수는 없지만, 한 번에 400ms 분량의 액션을 요청하고 다음 청크가 전송되는 동안 계속 실행할 수 있습니다.

이 저장소의 모든 어려운 문제는 그 하나의 홉에서 비롯됩니다:

  • 청크는 관측이 이루어졌을 때 존재했던 세계를 설명합니다. 도착하는 시점에는 이미 오래된 것입니다. 얼마나 오래된 것이 너무 오래된 것인가?

  • 제어 루프는 서버가 응답했는지 여부와 관계없이 20ms마다 팔을 명령해야 합니다. 실행할 유효한 것이 없을 때 무엇을 하는가?

  • 요청은 실패하고, 재시도되며, 순서가 뒤섞여 도착합니다. 더 오래된 응답이 더 새로운 응답을 덮어쓰는 것을 무엇이 막는가?

  • 모델은 NaN을 방출할 수 있고, 버전이 잘못된 서버는 다른 로봇을 위한 목표를 보낼 수 있습니다. 그것을 액추에이터에 전달하는 것을 무엇이 거부하는가?

Related MCP server: omni-kit-mcp

결과

조건당 25개 시드, 실제 HTTP, 시드된 RNG에서 주입된 결함. python experiments/latency_sweep.py --seeds 25 --ablations

조건

작업 성공

안전 종료

중앙값 시간

홀드

복구 횟수

p50 지연

오래된 데이터 거부

재시도

clean

100%

100%

6.4 s

0.0 s

0

20 ms

0

0

lan — 20 ms ± 5

100%

100%

6.7 s

0.0 s

0

40 ms

0

0

wan — 150 ms ± 40

100%

100%

11.1 s

0.0 s

0

160 ms

0

0

congested — 250 ms ± 150, 5% 손실

100%

100%

12.6 s

0.36 s

68

280 ms

222

64

lossy — 20% 손실

100%

100%

9.8 s

0.26 s

50

60 ms

197

222

flaky_server — 20% 5xx

100%

100%

8.1 s

0.0 s

0

60 ms

0

248

outage — 서버 3초 중단

100%

100%

13.9 s

6.2 s

25

60 ms

0

24

작업 성공은 큐브가 목표 지점에 놓였는지입니다. 안전 종료는 의도적으로 별도의 열입니다: 실행이 작업에 실패해도 여전히 올바를 수 있습니다. 정지가 때로는 올바른 답이기 때문입니다. 둘을 합치면 네트워크가 나빴다로봇이 하지 말아야 할 일을 했다의 차이가 숨겨집니다.

표 전체의 패턴이 설계 목표입니다: 링크가 저하될수록 로봇은 더 느려질 뿐, 틀려지지는 않습니다. 250ms 혼잡 링크는 사이클 시간을 두 배로 늘리고 222개의 오래된 청크를 거부합니다. 큐브를 떨어뜨리거나 닿지 말아야 할 곳에 닿지 않습니다.

제거 실험 — 모든 완화 조치 제거

실패하는 것을 본 적 없는 안전 검사는 작동한다고 주장할 수 없는 안전 검사입니다.

제거된 조치

작업 성공

중앙값 시간

비고

(없음 — 기준 congested)

100%

12.6 s

홀드에서 복구 (outage)

0%

0.5 s

래칭 정지, 재개되지 않음

오래된 데이터 검사 (congested)

88%

23.7 s

움직인 세계에 대한 계획을 실행함

재시도 (congested)

96%

17.5 s

적응형 리드 (congested)

100%

12.4 s

그러나 홀드 1.10 s 대 0.36 s

재시도 (lossy)

100%

7.9 s

없는 편이 더 빠름 — 아래 참조

결함 스윕이 실제로 발견한 것

둘 다 실제 결함이었습니다. 어느 것도 정상적인 localhost 서버에서는 보이지 않았고, 둘 다 스윕이 처음 실행된 순간 나타났습니다.

1. 보호 정지에 복귀 경로가 없었습니다. outage 프로파일에서 런타임은 죽은 서버를 올바르게 감지하고, 위치를 유지하고, e-stop을 래칭했습니다 — 그런 다음 3초 후 서버가 돌아왔을 때 그대로 앉아 있었습니다. 올바르지만 쓸모없었습니다. 네트워크가 잠깐 끊길 때마다 인간이 걸어와서 재무장해야 하는 로봇은 2주 차에 플러그가 뽑힙니다.

수정은 하나의 개념을 둘로 나눕니다: 유효한 청크가 도착하는 즉시 스스로 해제되는 보호 홀드와, 그렇지 않을 경우 8초 후에 작동하는 래칭 e-stop. outage는 0% → 100%가 되었고, 같은 변경이 congested도 수정했습니다. 맨 위의 그림이 그 수정이 작동하는 모습입니다.

2. 요청 리드 시간이 지연 시간보다 짧았습니다. 런타임은 120ms의 액션이 남았을 때 다음 청크를 요청했습니다. 혼잡 링크에서 왕복은 280ms였습니다. 모든 요청이 유용하려면 140ms 늦게 발행되었으므로, 팔은 거의 모든 청크 경계에서 굶주렸습니다. 너무 늦게 보낸 요청은 아무리 재시도해도 고쳐지지 않습니다 — 더 일찍 요청해야 합니다.

런타임은 이제 자체 p95 지연 시간을 측정하고 리드를 그에 맞게 조정합니다. congested에서 홀드 시간은 1.10s에서 0.36s로 줄었습니다.

3. 비용 대비 효과가 없는 완화 조치. lossy 프로파일에서 재시도를 끄는 것이 성공률 손실 없이 더 빨랐고 (7.9s 대 9.8s), 197개의 오래된 데이터 거부를 제거했습니다. 저지연 링크에서는 청킹이 이미 중복성을 제공합니다: 재시도가 도착할 즈음에는 새로운 요청이 더 유용했을 것입니다. 재시도는 congested에서 그 자리를 얻고 (96% → 100%) lossy에서는 그렇지 않습니다. 작동한 완화 조치만 보고하는 것이 작동하지 않는 조치를 출시하는 방법이기 때문에 표에 포함했습니다.

작동 방식

        robot side                          │            policy side
                                            │
  ┌──────────────────────────────┐          │       ┌────────────────────┐
  │ runtime.py  50 Hz loop       │          │       │ server.py          │
  │   1 collect ── poll ─────────┼── HTTP ──┼──────▶│  POST /predict     │
  │   2 request ── submit        │          │       │  obs → 20 actions  │
  │   3 act                      │◀─────────┼───────│                    │
  │   4 check                    │          │       └────────────────────┘
  └──┬────────┬────────┬─────────┘          │        stateless; knows
     │        │        │                    │        nothing about episodes
     ▼        ▼        ▼                    │        or scheduling
  client   scheduler  safety                │
  retries  staleness  NaN/limits/workspace  │
  backoff  ordering   rate limit            │
  breaker  discards   e-stop                │

모듈

하나의 역할

contracts.py

네트워크를 건너는 모든 타입, 한 번 정의됨

clock.py

시간, 주입 가능 — 실제 또는 가상

sim.py

여섯 개의 메서드 뒤의 MuJoCo; 여기서 하드웨어로 교체

policies/scripted.py

VLA 대용: 상태 없음, 청크형, 반응형

server.py

HTTP 뒤의 정책

client.py

제출/폴링, 데드라인, 재시도, 백오프, 회로 차단기

scheduler.py

어떤 청크를 신뢰하고 어떤 액션을 실행할지

safety.py

정책이 틀렸다고 가정함

runtime.py

50Hz 루프

recording.py

MCAP 로깅

mcp_server.py

MCP 도구로서의 셀

언급할 가치가 있는 세 가지 결정:

루프는 네트워크에서 절대 블로킹하지 않습니다. 2단계가 제출하고, 1단계가 폴링하며, 아무것도 기다리지 않습니다. 느린 서버가 멈출 수 있는 제어 루프는 제어 루프가 아닙니다.

오래된 데이터는 도착 시간이 아닌 observed_at에서 측정됩니다. 돌아오는 데 300ms가 걸린 청크는 도착하는 순간 300ms 오래된 것입니다.

안전 검사는 두 가지 다른 속도로 실행됩니다. 청크 검증은 비쌉니다 (모든 액션에 대한 정기구학) 그리고 신뢰 경계에서 청크당 한 번 실행됩니다. 속도 제한은 저렴하고 매 틱 실행됩니다. 잘못된 계획을 통째로 거부하는 것이 미묘하게 잘못된 무언가로 클램핑하는 것보다 낫습니다.

클록 트릭

가상 시간은 실제 시간보다 ~100배 빠르게 흐르므로, 400ms의 로봇 시간은 4ms의 벽시계 시간에 경과합니다 — localhost에 대한 HTTP 왕복보다 빠릅니다. 주의하지 않으면 모든 응답이 늦게 보이고 실험이 런타임 대신 하네스를 측정하게 됩니다.

그래서 SimClock.settle()은 가상 시간을 진행시키지 않고 실제 초 단위로 블로킹합니다. 런타임이 관찰하는 유일한 지연은 결함 프로파일이 요청한 지연입니다. 동일한 클라이언트 코드, 동일한 재시도 경로, 동일한 오래된 데이터 로직 — 하드웨어에서 WallClock 아래에서는 settle()이 no-op입니다. 이것이 위의 모든 숫자를 비트 단위로 재현 가능하게 만드는 것입니다.

에이전트에서 구동하기 (MCP)

python -m robot_runtime.mcp_server

열두 개의 도구. 여섯 개는 읽기 전용 (상태, 카메라, 결함 프로파일, 녹화, 감사 로그), 여섯 개는 로봇을 움직입니다. 게이팅은 프롬프트의 요청이 아니라 서버 측 상태입니다:

run_pick_and_place  → {"ok": false, "error": "cell is not armed",
                       "hint": "call arm_cell with a reason before commanding motion"}
arm_cell("  ")      → {"ok": false, "error": "a reason is required"}
arm_cell("demo")    → {"ok": true, "armed": true, "expires_in_s": 120.0}
emergency_stop()    → {"ok": true, "estopped": true}
run_pick_and_place  → {"ok": false, "error": "cell is e-stopped"}
clear_estop()       → {"ok": false, "error": "confirmation required"}
  • 모션은 게이팅되고, 읽기는 그렇지 않으며, 정지 버튼은 절대 그렇지 않습니다. 인증해야 도달할 수 있는 안전 제어는 안전 제어가 아닙니다.

  • 무장에는 사유가 필요하고 만료되며, 그 사유는 기록됩니다.

  • 오류는 hint가 있는 구조화된 결과이며, 예외가 아닙니다. hint: start the policy server를 읽는 에이전트는 문제를 고칠 수 있습니다. 스택 트레이스는 추측하게 만듭니다.

  • 모든 호출은 감사 로그에 추가되며 같은 인터페이스로 읽을 수 있어서, "정확히 무엇을 호출했는가?"에는 항상 답이 있습니다.

관측 가능성과 재생

모든 에피소드는 MCAP — ROS 2가 로깅하는 컨테이너 — 에 네 개의 토픽으로 기록됩니다: /observation, /action_chunk, /command, /event. 이벤트 토픽이 가장 중요한데, 데이터가 아닌 결정을 기록하기 때문입니다:

3.28s  request_failed:     unreachable
3.52s  breaker_rejected:   circuit open, request not sent
3.80s  protective_hold:    no valid action for 0.50s
6.66s  hold_released:      resumed on chunk 136

첫 번째 버전이 작성한 128줄이 아닌 아홉 줄 — 반복되는 이벤트는 축소됩니다. 차단기가 열려 있는 동안 초당 50틱마다 요청을 거부하고, 50개를 모두 쓰는 것은 첫 번째 것이 말하지 않은 것을 말하지 않습니다.

녹화를 재생하면 정확한 명령을 새로 시드된 시뮬레이터에 다시 실행합니다:

$ python experiments/replay.py recordings/outage-seed0.mcap
  commands_replayed: 533
  placement_error_m: 0.007850735794278705   # live run: 0.007850735794278705
  time drift: 0.000 ms

비트 단위로 정확합니다. 처음에는 그렇지 않았습니다: /command가 소수점 여섯 자리로 반올림되어 기록되었고, 이로 인해 실행과 자체 재생 사이에 미크론 단위의 드리프트가 생겼습니다. 작았습니다 — 그러나 "정확히 재현한다"를 거짓으로 만들었고, 그것이 녹화의 전부입니다.

이것이 현장 결함이 수정되는 방식이기도 합니다: 현장에서 MCAP를 가져와서, 재생하고, 팔이 노트북에서 다시 잘못된 일을 하는 것을 지켜봅니다.

실행하기

python3 -m venv ~/.venvs/robotarm && ~/.venvs/robotarm/bin/pip install -r requirements.txt

venv는 의도적으로 내부 디스크에 둡니다 — 이 저장소는 exFAT 볼륨에 있으며, macOS는 MuJoCo의 플러그인 로더가 dlopen하려다 죽는 AppleDouble ._ 파일을 흩뿌리고, git은 그 위에서 팩 인덱스를 유지할 수 없습니다.

python experiments/latency_sweep.py --seeds 25 --ablations   # the results table
mjpython demos/run_with_viewer.py --profile outage           # watch it hold and recover
python experiments/replay.py recordings/outage-seed0.mcap    # replay a recording
python -m robot_runtime.mcp_server                           # agent-facing tools
mjpython demos/pick_and_place.py                             # the original scripted demo
pytest -q                                                    # 38 tests, ~5 s

뷰어가 있는 것은 python 대신 mjpython — macOS에서는 창이 메인 스레드를 소유해야 합니다.

테스트

38개 테스트, 약 5초, 테스트 대상에 대한 목(mock) 없음. 클라이언트 테스트는 가짜 전송을 사용하지만 실제 결함 주입기를 사용하고, 런타임 테스트는 스레드의 실제 서버에 대한 실제 HTTP를 통해 진행됩니다.

그중 세 개는 위의 결함이며 회귀 테스트로 유지됩니다: test_server_outage_holds_then_recovers, test_adaptive_lead_reduces_time_spent_holding, 그리고 test_the_stage_machine_does_not_oscillate — 이전 정책은 높이를 위치보다 먼저 확인했기 때문에 lift→carry→lift→carry를 오가며 진동했습니다.

이것이 아닌 것

솔직히 말하면, 로보틱스 엔지니어에게 과장된 주장을 하는 것은 스크리닝 단계가 아니라 인터뷰에서 탈락하는 길이기 때문입니다.

  • 시뮬레이션 전용. 하드웨어도, sim-to-real 전이도, 실제 Panda 로봇에 대한 접촉 모델 보정도 없습니다.

  • 정책은 학습된 것이 아니라 수작업으로 작성되었습니다. 의도적으로 VLA와 같은 형태—상태 비저장, 청크 단위, 언어 조건부, 반응형—로 설계되어 실제 모델이 사용할 때와 동일하게 런타임이 작동합니다. 그러나 여기에는 학습된 것이 없으며, 모델 품질에 대한 어떤 주장도 하지 않습니다.

  • 객체 포즈는 인식이 아닌 시뮬레이터에서 가져옵니다. 관측 데이터에는 카메라 이미지가 포함되고 계약도 이를 지원하지만, 스크립트된 정책은 픽셀을 무시합니다. 실제 배포에는 인식 스택이 필요하며, 이 격차가 여기서 가장 큰 부분입니다.

  • 단일 암, 단일 강체 객체, 단일 작업.

  • ROS가 아님. MCAP은 올바른 컨테이너이고 생태계가 이를 읽을 수 있기 때문에 사용되지만, 노드도, TF 트리도, launch 파일도 없습니다.

  • 약 하루 만에 구축된, 런타임 계층에 초점을 맞춘 데모입니다.

다음 단계

가치가 높은 순서대로:

  1. 인식 루프 통합 — 시뮬레이터 대신 카메라 이미지에서 포즈를 추출합니다. 이 목록에서 가장 큰 격차를 해소합니다.

  2. 정책 학습. 스크립트된 컨트롤러로 데모를 생성하고, 액션 청킹 행동 클로닝 모델을 피팅한 후, 동일한 /predict 계약을 통해 서빙합니다. 런타임은 한 줄도 변경할 필요가 없어야 합니다—이것이 Policy 인터페이스가 주장하는 바이며, 현재 검증되지 않은 상태입니다.

  3. 이중 암 — 청크 스케줄링이 단순한 기록 관리 문제가 아닌 진정한 조정 문제가 됩니다.

  4. 실제 Pandasettle()이 no-op이 되고 이 README의 모든 지연 시간 수치가 실제로 다시 측정됩니다.

크레딧

Panda 모델: MuJoCo Menagerie (Apache 2.0). 물리 엔진: MuJoCo. 로깅: MCAP.

F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Hosted MCP endpoint with realistic fake data for prototyping agents. 12 tools, no setup.

  • A comprehensive Model Context Protocol (MCP) server that enables AI assistants to control Unreal E…

  • Control plane for autonomous software labor. Agents claim objectives over MCP with audit trail.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Alonbbar6/robot-runtime'

If you have feedback or need assistance with the MCP directory API, please join our Discord server