화면에 값이 있다는 사실보다 출처와 시각이 먼저다
로봇의 현재 미션과 배터리를 관제 화면에서 본다고 하자. 값이80%이고 연결 표시가 켜져 있어도 그 값이 언제 관측됐는지 없으면 현재 배터리 상태로 판단하기 어렵다. 서버가 마지막 값을 다시 그렸을 뿐일 수도 있다. 관제의 첫 목표는 보기 좋은 숫자를 늘리는 것보다 무엇을 어느 시각에 관찰했는지 드러내는 것이다.
텔레메트리(telemetry)는 원격 대상에서 수집하는 관측/상태 정보다. 읽기 전용 대시보드는 이를 해석/표시하는 경로이며, 그 자체가 로봇의 실행 허가나 실제 제어 성과를 만들지는 않는다. 이 단위는 단일 가상 대상 r1/bootA의 데이터를 읽는다. 화면의 모형도 실제 로봇과 연결되지 않는다.
상태 snapshot과 사건 event는 다르게 기록한다
snapshot은 어떤 시각의 상태 묶음이다. 예를 들어 배터리80%@900ms는 해당 시점에 제공된 값이다. event는 특정 시각에 일어난 사건/변경의 기록이다. 미션이 RUNNING에서 ERROR로 바뀌었다면 사건ID와 발생/수집 시각·대상/세대를 남긴다. 모든 event가 전체 상태를 담는 것은 아니다.
이 단위의 mission event는 미션 전체 값을 담는다. 따라서 최신 event의 미션 값은 알 수 있어도 별도 snapshot에만 있는 배터리/위치가 함께 갱신된 것은 아니다. 증분(delta)만 담는 사건이라면 빠진 사건 없이 기준 snapshot부터 재구성할 수 있는지도 확인해야 한다. 두 형식을 같은 합치기 규칙으로 처리하지 않는다.
| 정보 | 답할 수 있는 질문 | 추가로 필요한 근거 |
|---|---|---|
| snapshot의 배터리80%@900ms | 그 시점의 제공 값은 무엇인가 | 현재 시각/TTL·센서 출처·단위/유효성 |
| mission ERROR seq12@1140ms | 어느 대상/세대의 어떤 미션 값이 왔는가 | 앞뒤 사건/최신성·현재 원인/실제 정지 |
| 수신 heartbeat@1195ms | 수신 경로의 신호가 갱신됐는가 | 로봇 필드별 취득시각·동작/물리 관측 |
| 수신4건·고유3건 | 얼마나 도착/중복됐는가 | 집계 구간/분모·누락/재전송 원인 |
원발생 시각과 화면 수신 시각을 분리한다
OpenTelemetry Logs Data Model은 원발생 Timestamp와 수집 계통이 관측한 ObservedTimestamp를 구분한다. 여기의 합성 표는 같은 ClockA의 ms를 쓰며 공식 OTel wire/schema나 UNIX ns 형식이 아니다. 실제 시스템은 시계 ID/단위·동기화/매핑과 원본 stamp를 확인해야 한다.
서버가995ms에 데이터를 받았어도 로봇이 그 값을900ms에 취득했다면 화면의 수신 나이와 로봇 관측 나이는 다르다. UI갱신 시각으로 원본 stamp를 덮으면 오래된 관측을 새 값처럼 보이게 한다. 다른 시계의 숫자를 바로 빼서 지연이라고 쓰지도 않는다.
heartbeat는 수신 경로가 주기적으로 보내는 생존 신호다. TTL(time to live)은 현재 판단에 사용할 수 있는 나이 범위다. 이번 계약은 heartbeat나이≤100ms, 상태/필드나이≤200ms이며 경계를 포함한다. 교육용 값으로, 모든 장비/관제의 안전·실시간 성능 기준은 아니다.
연결 신호와 로봇 관측을 필드별로 읽는다
가상 snapshot은 배터리80%@900ms이고 초기 mission은 RUNNING seq10@900ms다. 다음 세 상황을 비교한다. 나이는 같은 ClockA의 now−stamp로 계산한다.
| 상황 | now / heartbeat | 연결 신호 나이 | 배터리/미션 관측 나이와 현재 표시 |
|---|---|---|---|
| 정상 | 1000 / 995ms | 5ms, 유효 | 100ms, 현재80%/RUNNING |
| 로봇 관측 지연 | 1150 / 1145ms | 5ms, 유효 | 250ms, 현재는미상·마지막80%/RUNNING@900ms별도 |
| 연결 신호 만료 | 1400 / 1145ms | 255ms, 만료 | 500ms, 현재미상·마지막값/시각별도 |
두 번째의 수신 신호가 유효하다고 오래된 배터리/미션까지 현재 정상으로 표시하면 안 된다. 마지막80%를 보존하는 것과 현재80%라고 표시하는 것은 다르다. 미확인 값을0%나 정상 상태로 채우면 운영자가 다른 의미로 받아들일 수 있다. 값·시각·유효/만료·미상이라는 문자 근거를 함께 제공하고 색만으로 구분하지 않는다.
원본이 미래 시각이거나 잘못된 시계/대상, 범위 밖 배터리/잘못된 순서 값이라면 유효한 현재 관측으로 쓰지 않는다. 기본 모형은 정해진 단일 r1/bootA/ClockA 자료만 받으며 형식/시각/식별자 오류를 거부한다. 이는 인증/운영 보안 시스템을 구현한 것이 아니다.
늦게 온 사건이 최신 상태를 되돌리지 않게 한다
사건 키를 (robot_id,boot_id,seq)로 정한다. boot_id는 재시작 등으로 새 수집 세대가 됐음을 구별하는 값이다. 같은 세대의 seq는 원본 순서를 나타내고, 도착 순서는 네트워크/큐의 지연으로 달라질 수 있다.
| 도착 순서 | 원본 seq/시각 | 미션 전체 값 | 수신 때 처리 |
|---|---|---|---|
| 1 | 10 / 900ms | RUNNING | 기준 이력 |
| 2 | 12 / 1140ms | ERROR | 최신 미션 갱신 |
| 3 | 11 / 1100ms | RUNNING | 늦은 원로그 보존, seq12를 되돌리지 않음 |
| 4 | 12 / 1140ms | ERROR | 동일 사건 중복, 새 고유 사건으로 세지 않음 |
수신은4건, 고유는3건, 같은 중복은1건이다. 최종 최신 seq는12·ERROR다. seq11이 늦게 왔다는 이유로 도착 순서의 마지막 RUNNING을 현재 상태로 붙이지 않는다. 같은 키인데 내용/시각이 다르면 단순 재전송으로 무시하지 말고 데이터 충돌로 처리한다.
seq12가 먼저 왔을 때11의 공백을 표시하고 필요하면 원로그/최신 snapshot으로 재동기화한다. 이 예의 seq12는 미션 전체 값이라 현재 미션을 제공하지만, 그 사건 하나가 다른 필드나 빠진 증분까지 복원한 것은 아니다. 재시작해bootB/seq1이 오면 bootA의 큰 seq와 단순 비교하지 않는다. 새 기준 상태/세대와 과거 이력을 분리해야 한다. 기본 모형의 자동 boot전환은 범위 밖이다.
최신 미션과 오래된 배터리는 동시에 존재할 수 있다
순서 역전/중복 상황의 현재는1200ms, heartbeat1195ms다. 최신 mission event는1140ms이므로 나이60ms로 유효하고 ERROR를 표시한다. 배터리는 여전히900ms 관측이라 나이300ms로 만료됐으므로 현재 미상이다. 미션이 갱신됐다고 배터리 stamp까지1140ms로 올리면 안 된다.
관제 기록에는 대상/세대·필드 출처/단위·원발생/수신시각·최신 seq/누락/중복·표시 판정과 원본 참조를 남긴다. 이벤트/필드가 같은 과업·로봇을 가리키는지도 확인한다. 실제 정지/물체 상태나 명령 진행은 필요한 별도 관측과 요청ID에 연결한다. ERROR라는 문자열 하나를 전체 물리 상태로 확대하지 않는다.
읽기 전용 표시를 실제 실행 권한과 구분한다
읽기 전용 모형에서 네 상황을 골라 위 계산을 비교할 수 있다. 선택은 고정 합성 기록만 바꾸며 실제 수집/명령/진도를 변경하지 않는다. 표 분석만으로 기본 실습을 수행할 수도 있다. 브라우저 모형은 실제 ROS·네트워크 장애·시간 동기화 성능을 측정하지 않는다.
실제 관제에서는 명령 버튼을 숨기는 것만으로 서버 권한이 읽기 전용이 됐다고 할 수 없다. 수집/읽기 권한과 요청/실행 권한, 변경/감사 기록은 별도로 설계한다. M34.03에서 다룬다. 먼저 관측을 정확히 표시한 다음 M34.02에서 3D장면과 좌표·시간·버전이 어떻게 맞아야 하는지 확인한다.
기존 6.6 평가 설계와 함께 읽는다. 관제의 유효/미상 표시와 실제 실행/안전 성과의 근거를 분리하는 것이 이 단위의 완료 기준이다.