피지컬 AI 데이터 정리하다가, 판도라의 상자를 열어버린 이야기
혼돈의 카오스
로봇이 컵을 집어 서랍에 넣는 모습은 보고 있으면 신기합니다. 사람에게는 별일 아닌 동작을 기계가 해내려면 무엇이 필요할까요? 카메라는 컵과 서랍을 보고, 관절 센서는 팔의 위치를 알려 줍니다. 손목에 힘·토크 센서가 있다면 손목을 통해 전달되는 힘과 회전력을 기록할 수 있습니다. 손가락이 컵을 조이는 힘을 알려면 그리퍼나 손끝의 측정값도 살펴봐야 합니다. 여기에 제어 명령과 “컵을 서랍에 넣어”라는 언어 지시가 붙습니다. 그 짧은 동작 안에서도 여러 데이터가 함께 만들어지는 셈입니다.
그 장면을 데이터로 남기려 하면 조금 머리가 복잡해집니다. 엑셀처럼 가지런한 표 하나면 좋겠는데, 수백 Hz로 들어오는 숫자와 초당 수십 장의 이미지, 수만 개 이상의 점으로 표현한 3차원 공간, 로봇이 내린 명령이 서로 다른 주기로 쌓입니다. 파일 확장자도 .mcap, .bag, .h5, .bin, .parquet, .mp4 등 제각각입니다.
저는 이 많은 데이터를 어떻게 다시 꺼내 볼 수 있을지가 궁금했습니다. 로봇이 컵을 놓쳤다면 그 순간 무엇을 보고, 어떤 힘으로 잡고 있었는지 알고 싶기 때문입니다.
하지만, 이 동네 역시 혼돈의 카오스라는 사실을 깨닫는데는 긴 시간이 필요하지 않았습니다.
데이터로 보는 피지컬 AI
피지컬 AI는 로봇이나 자율주행차처럼 물리 세계를 인지하고, 상황을 이해·추론해 행동하는 시스템의 AI를 가리킵니다. 최근에는 생성형 AI와 월드 모델도 이 과정에 활용됩니다. 거리와 방향을 파악하고, 물체가 충돌하거나 미끄러지는 상황을 이해한 뒤 그 판단을 움직임으로 이어가야 합니다.
단계 | 처리하는 일 | 관련 기술과 모델 |
인지 | 카메라, LiDAR, IMU, 관절 센서의 입력을 해석합니다 | 비전 인코더, 3D 재구성 |
추론 | 상황과 언어 지시를 이해하고 다음 행동을 계획합니다 | VLA, 월드 파운데이션 모델 |
행동 | 관절의 위치·토크, 그리퍼, 조향 명령 등을 생성합니다 | 정책 모델, 강화학습, 모방학습 |
VLA는 Vision-Language-Action의 약자입니다. 이미지와 언어 지시를 바탕으로 행동을 출력하며, 로봇 상태를 추가로 입력받는지는 모델에 따라 다릅니다. 출력도 관절 명령이나 말단 이동량 등으로 달라지고, 제어 계층이 이를 실제 구동 명령으로 연결합니다. 따라서 기록된 액션이 어느 제어 단계의 값인지 확인해야 합니다.
LiDAR는 레이저로 거리를 측정하는 센서입니다. 여러 방향의 측정을 모으면 주변 공간을 3차원 점들의 집합인 포인트클라우드로 표현할 수 있습니다. IMU는 관성 측정 장치로, 가속도와 각속도를 측정합니다. 시스템에 따라 자세 추정값도 함께 제공합니다. 데이터를 해석할 때는 센서 이름과 함께 측정하는 물리량과 출력 형태를 확인해야 합니다.
창고의 자율이동로봇인 AMR, 물체의 자세에 따라 파지력을 조절하는 로봇팔, 수술 로봇, 휴머노이드는 모두 피지컬 AI의 활용 분야입니다. 자율주행차는 카메라·LiDAR·Radar로 주변을 인식하고 주행을 판단합니다. 공장과 창고 같은 스마트 공간에서는 고정 카메라로 사람·차량·로봇의 동선을 추적하고 이상 상황을 감지합니다. 용도가 다른 만큼 수집하는 데이터도 달라집니다.
피지컬 AI 데이터의 다섯 가지 구성 요소
파일 이름부터 하나씩 따라가다 보면 정작 무엇을 기록한 데이터인지 놓치기 쉽습니다. 우선 저장과 활용 방식을 기준으로 다섯 가지로 나누어 보겠습니다. 카메라도 센서의 일종이지만, 이미지·영상은 크기와 처리 방식이 달라 따로 구분했습니다. (이 장표 생성은 AI의 힘을 빌렸습니다!)

그림 1. 피지컬 AI 데이터의 종류와 통합 처리 흐름. 서로 다른 데이터를 시간·장비·에피소드와 해석 조건으로 연결해 분석과 학습에 활용합니다.
구성 요소 | 담고 있는 정보 | 대표적인 예 |
수치 센서와 공간 측정 | 몸의 상태와 주변 환경의 측정값 | 관절, IMU, 힘·토크, GPS·GNSS, 모터 RPM, LiDAR |
이미지와 영상 | 카메라가 관측한 장면 | 외부·손목 카메라, 스테레오, 깊이 영상 |
행동 | 로봇이나 차량에 실제로 내린 명령 | 관절·그리퍼 목표값, 조향·가속, 모터 출력 |
언어 | 수행할 작업과 그 의미 | “컵을 서랍에 넣어” 같은 지시문과 작업 설명 |
메타데이터 | 측정값과 행동을 해석하는 조건 | 카메라 내·외부 파라미터, 로봇 종류, 좌표계, 성공·실패 여부 |
관측 대상을 기준으로 보면 외부 환경을 보는 센서와 자기 몸의 상태를 재는 센서가 함께 쓰입니다.
구분 | 데이터 | 측정하거나 표현하는 내용 | 주로 활용하는 곳 |
외부 인지 | RGB 카메라 | 장면, 물체, 사람 | 로봇 조작, 자율주행, 스마트 공간 |
외부 인지 | 깊이, LiDAR, Radar | 3D 거리, 형상, 움직임 | AMR 주행, 자율주행, 3D 재구성 |
외부 인지 | GelSight·DIGIT 등 비전형 촉각, 힘 배열형 촉각 | 접촉 형상, 미끄러짐, 압력과 힘 분포 | 정밀 조작, 재질 인식 |
자기 상태 | 관절 위치·속도·토크 | 각 관절이 어디에 있고 어떻게 움직이는지 | 로봇 정책의 상태 입력 |
자기 상태 | IMU | 가속도, 각속도, 자세 | 휴머노이드·보행 로봇, 차량 측위 |
자기 상태 | 6축 힘·토크 | 말단의 3축 힘과 3축 토크 | 조립, 삽입, 힘 제어 |
자기 상태 | GPS·INS | 위치, 속도, 관성 항법 상태 | 자율주행, 실외 로봇 |
행동 | 관절 명령 또는 말단 이동과 그리퍼 명령 | 시스템이 실제로 수행하도록 지시한 행동 | 모방학습, VLA 학습의 정답 |
의미 | 언어 지시와 작업 설명 | 행동의 목적 | VLA의 조건 입력 |
합성 | 시뮬레이션 출력과 월드 모델 생성 데이터 | 가상 환경의 관측과 상태 | 데이터 부족 보완, 강화학습 |
ROS JointState의 표준 정의에서 회전 관절은 위치 rad, 속도 rad/s, 토크 Nm를, 직선 관절은 위치 m, 속도 m/s, 힘 N을 사용합니다. 관절 이름과 position, velocity, effort 배열은 같은 길이를 갖거나, 제공되지 않는 배열이면 비어 있을 수 있습니다. 실제 장비가 이 단위를 따르는지도 확인해야 합니다. 예를 들어 UBTECH의 손가락 인터페이스는 JointState를 쓰면서 값을 백분율로 정의합니다. 메시지 타입이 같다고 숫자의 뜻까지 같지는 않은 셈입니다.
더불어, 행동 데이터는 로봇마다 정의를 확인해야 합니다. Open X-Embodiment의 RT-X 설명에서는 말단의 x·y·z, roll·pitch·yaw, 그리퍼 개폐의 일곱 요소를 다룹니다. 각 값은 절대값, 변화량, 속도 중 무엇을 나타내는지 확인해야 합니다. 좌표계와 단위, 그리퍼 값의 의미도 함께 남겨야 서로 다른 로봇의 데이터를 해석할 수 있습니다. 이 일곱 요소가 모든 로봇의 행동을 표현하는 범용 규격은 아닙니다.
실제 장비를 보면 센서 구성과 기록 주기의 차이도 드러납니다. nuScenes의 자율주행 센서 세트는 카메라 6대, Radar 5대, LiDAR 1대로 구성됩니다. 6축 힘·토크 센서는 x·y·z 힘과 토크를 함께 내보내며, UBTECH Walker Tien Kung의 문서에는 1,000 Hz 보고 주기의 예가 나옵니다. 카메라 영상만으로 이런 고속 접촉 상태를 복원하기는 어렵습니다.

그림 2. nuScenes 수집 차량의 센서 배치. 카메라·LiDAR·Radar·IMU가 서로 다른 위치에서 같은 주행 상황을 관측합니다.
출처: nuScenes 공식 자료
사람이 촬영한 1인칭 영상은 로봇 학습의 사전학습 자원으로도 검토됩니다. Ego4D는 논문 발표 기준 931명이 수집한 3,670시간의 영상을 제공하며, 일부 데이터에는 오디오·IMU·시선·3D 스캔도 포함됩니다. 다만 이 영상에 로봇의 액션 정답이 자동으로 붙지는 않습니다. 관측을 학습하는 데이터와 행동을 직접 학습하는 데이터는 구분해야 합니다.
실제 환경에서 데이터를 수집하려면 비용이 들고 위험이 따를 수 있습니다. 디지털 트윈 시뮬레이션과 월드 파운데이션 모델은 합성 데이터를 생성하는 데 쓰입니다. 합성 데이터도 센서 종류, 좌표계, 시각, 생성 조건을 함께 관리해야 실데이터와 비교하거나 결합할 수 있습니다.
원시 로그 안에서는 어떤 모습일까
학습용으로 정리하기 전의 로그에는 서로 다른 주기의 스트림과 대용량 바이너리가 함께 들어갑니다. 로봇에서는 ROS 메시지를 rosbag이나 MCAP 같은 컨테이너에 기록하는 경우가 많습니다. 자율주행 데이터는 센서별 바이너리 파일이나 벤더 포맷으로도 제공됩니다.
메시지는 대체로 시각과 프레임 정보, 센서별 페이로드로 구성됩니다. header나 frame_id가 없는 메시지도 있으므로 실제 스키마를 확인해야 합니다. 파일 이름만으로 측정값의 의미를 판단하기 어렵고, 메시지 정의까지 읽어야 합니다.
같은 10밀리초 안에서도 데이터는 모두 다르더라!
다음 표는 센서별 주기와 메시지 크기의 차이를 보여 주는 예시입니다. 장비마다 주기와 크기는 달라질 수 있습니다.
토픽 | 메시지 타입 | 발생 빈도 예 | 메시지 크기 예 | 10 ms 동안의 메시지 수 |
/ft_sensor/wrench | WrenchStamped | 1 kHz | 수십 B의 힘·토크 값과 헤더 | 약 10개 |
/joint_states | JointState | 500 Hz | 수백 B, 7관절의 이름과 세 배열 등 | 약 5개 |
/imu/data | Imu | 200 Hz | 수백 B, 공분산 27개 포함 | 약 2개 |
/camera/color/image_raw | Image | 30 Hz | 약 0.9 MB, 640×480 RGB8 | 0개 또는 1개 |
/lidar/points | PointCloud2 | 10 Hz | 약 1.9 MB, 12만 점×16 B | 0개 또는 1개 |
토크 센서는 메시지 수가 많고, 카메라와 LiDAR는 저장하는 바이트 수가 큽니다. 위 RGB8 예시에서 이미지 한 장은 921,600 B입니다. 30 Hz로 수집하면 페이로드만 초당 약 27.6 MB가 됩니다. LiDAR는 1,920,000 B짜리 프레임이 10 Hz로 들어오므로 초당 약 19.2 MB입니다. 헤더·컨테이너 오버헤드를 제외해도 두 스트림을 합하면 초당 약 46.8 MB입니다. 작은 센서 메시지만 떠올리고 저장 공간을 잡았다면 당황할 만한 양이지요.
이미지 한 장이 약 0.9 MB라는 값은 해상도와 인코딩을 고정한 예시입니다. JPEG나 동영상 코덱으로 압축하면 실제 저장 용량이 크게 달라집니다. 인프라의 수집·보관 용량을 설계할 때는 메시지 수와 저장 바이트 수를 함께 계산해야 합니다.
측정 시각과 기록 시각도 서로 달라요.
시각이 찍혀 있으니 시간만 맞추면 되겠다고 생각하기 쉽습니다. 그런데 ROS 2 메시지를 MCAP으로 기록할 때는 측정·발행·기록 시각이 함께 존재할 수 있습니다. 어느 시각으로 맞출지부터 골라야 합니다.
시각 | 들어 있는 위치 | 의미 |
header.stamp | ROS 메시지 내부 | 메시지 정의와 드라이버가 부여한 측정·취득 시각 |
publish_time | MCAP Message 레코드 | 메시지가 발행된 시각이며, 알 수 없으면 log_time 사용 |
log_time | MCAP Message 레코드 | 레코더가 기록한 시각이며, MCAP의 시간 인덱스 기준 |
센서들이 관측한 물리적 사건을 맞추려면 가능한 경우 측정 시각을 기준으로 정렬하는 것이 좋습니다. 다만 header.stamp의 의미와 정확성은 드라이버에 달려 있습니다. 장치마다 시계 기준이 다른지, 시뮬레이션 시간을 쓰는지, 동기화 오차가 얼마나 되는지도 확인해야 합니다. 나노초 단위로 저장하더라도 센서 간 동기화 정확도가 나노초 수준이라는 뜻은 아닙니다.
로봇이 물체에 닿은 순간의 토크와 카메라 프레임을 비교한다고 해 보겠습니다. 네트워크 지연이 포함된 기록 시각만 맞추면 서로 다른 순간을 같은 순간으로 해석할 수 있습니다. 시간을 맞췄다고 생각했는데 토크와 영상이 엇갈린다면 꽤 답답할 겁니다. 측정·발행·기록 시각을 함께 보존해야 센서가 관측한 현상과 수집 과정의 지연을 나누어 분석할 수 있습니다.
MCAP의 바깥 계층과 안쪽 계층
MCAP은 Foxglove에서 개발한 메시지 컨테이너 포맷입니다. ROS 1·ROS 2 메시지뿐 아니라 Protobuf, JSON 등으로 직렬화한 메시지도 시각 정보와 함께 담을 수 있습니다. ROS 2의 rosbag2는 저장 플러그인을 사용하며, Iron 배포판에서 기본 저장 형식이 SQLite3에서 MCAP으로 바뀌었습니다. SQLite3도 계속 선택할 수 있으므로 사용 중인 배포판과 설정을 확인해야 합니다.
MCAP의 바깥 계층은 메시지 정의를 담는 Schema, 토픽과 인코딩을 연결하는 Channel, 실제 데이터를 담는 Message로 구성됩니다. 시각은 uint64 기반의 나노초 값으로 표현합니다. 다음은 ROS 2 CDR 메시지를 기록하는 경우의 구조 예시입니다. 실제 바이너리 덤프는 아니며, Header의 library 등 일부 필드는 생략했습니다.
[Magic: 0x89 M C A P 0x30 \r \n]
[Header: profile="ros2"]
[Schema: id=1, name="sensor_msgs/msg/JointState",
encoding="ros2msg", data=<메시지 정의>]
[Channel: id=1, schema_id=1, topic="/joint_states",
message_encoding="cdr"]
[Schema: id=2, name="sensor_msgs/msg/Imu",
encoding="ros2msg", data=<메시지 정의>]
[Channel: id=2, schema_id=2, topic="/imu/data",
message_encoding="cdr"]
[Message: channel_id=1, sequence=0,
log_time=1760597400002104000,
publish_time=1760597400001950000, data=<CDR 바이트>]
[Message: channel_id=2, sequence=0,
log_time=1760597400003311000,
publish_time=1760597400003120000, data=<CDR 바이트>]
[Message: channel_id=1, sequence=1, ...]
[Data End]
[선택적 Summary: Schema·Channel 사본, Chunk Index, Statistics]
[선택적 Summary Offset][Footer][Magic]
MCAP은 파일 안에 스키마를 포함할 수 있고, 청크 압축과 시간·토픽 인덱스를 지원합니다. 데이터를 해석할 단서를 파일 안에 함께 남길 수 있다는 점은 반갑습니다. 다만 Summary와 인덱스가 있는지는 기록 옵션에 따라 달라집니다. 원하는 구간을 빠르게 탐색할 수 있는지도 이 옵션을 확인해야 판단할 수 있습니다.
Message의 data를 디코딩하면 센서별 필드가 나옵니다. 관절 값, IMU, 힘·토크의 구조를 예시 숫자로 표현하면 다음과 같습니다.
# /joint_states : sensor_msgs/msg/JointState
header:
stamp: {sec: 1760597400, nanosec: 1812000}
frame_id: base_link
name: [joint1, joint2, joint3, joint4, joint5, joint6, joint7]
position: [0.012, -0.785, 0.003, -2.356, 0.001, 1.571, 0.785]
velocity: [0.0, 0.021, 0.0, -0.015, 0.0, 0.004, 0.0]
effort: [0.41, -12.8, 0.37, 9.62, 0.12, 1.05, 0.02]
---
# /imu/data : sensor_msgs/msg/Imu
header:
stamp: {sec: 1760597400, nanosec: 3010000}
frame_id: imu_link
orientation: {x: 0.0012, y: -0.0031, z: 0.7071, w: 0.7071}
orientation_covariance: [0.0001, 0, 0, 0, 0.0001, 0, 0, 0, 0.0001]
angular_velocity: {x: 0.002, y: -0.001, z: 0.013}
angular_velocity_covariance: [0.01, 0, 0, 0, 0.01, 0, 0, 0, 0.01]
linear_acceleration: {x: 0.08, y: -0.02, z: 9.81}
linear_acceleration_covariance: [0.01, 0, 0, 0, 0.01, 0, 0, 0, 0.01]
---
# /ft_sensor/wrench : geometry_msgs/msg/WrenchStamped
header:
stamp: {sec: 1760597400, nanosec: 3401000}
frame_id: ft_link
wrench:
force: {x: 0.52, y: -1.30, z: 4.87}
torque: {x: 0.011, y: 0.034, z: -0.002}
관절의 위치·속도·토크를 저장할 때는 배열의 각 값을 관절 이름과 대응시켜야 합니다. ROS Imu에는 자세 쿼터니언, 각속도 rad/s, 가속도 m/s²와 각각의 3×3 공분산이 들어갑니다. 공분산이 모두 0이면 불확실성을 모른다는 뜻이고, 첫 원소가 -1이면 해당 추정값이 없다는 뜻입니다. 이를 오차가 없는 값이나 정상적인 0으로 바꾸면 해석이 달라집니다. 힘·토크의 N·Nm와 함께 단위와 유효성도 보존해야 합니다.
같은 로그에 들어 있는 카메라와 LiDAR 메시지도 보겠습니다. 바이너리 부분은 길어서 크기만 표시했습니다.
# /camera/color/image_raw : sensor_msgs/msg/Image
header:
stamp: {sec: 1760597400, nanosec: 5980000}
frame_id: camera_color_optical_frame
height: 480
width: 640
encoding: rgb8
is_bigendian: 0
step: 1920
data: <921600 bytes>
---
# /lidar/points : sensor_msgs/msg/PointCloud2
header:
stamp: {sec: 1760597400, nanosec: 9500000}
frame_id: lidar_link
height: 1
width: 120000
fields:
- {name: x, offset: 0, datatype: 7, count: 1}
- {name: y, offset: 4, datatype: 7, count: 1}
- {name: z, offset: 8, datatype: 7, count: 1}
- {name: intensity, offset: 12, datatype: 7, count: 1}
is_bigendian: false
point_step: 16
row_step: 1920000
data: <1920000 bytes>
is_dense: true
이미지의 페이로드 크기는 행당 바이트 수인 step에 높이를 곱해 계산합니다. 위 예에서는 1,920×480 = 921,600 B입니다. PointCloud2는 fields 배열에 필드 이름·오프셋·타입을 기록하고, 실제 점들은 uint8 배열에 담습니다. 예시의 datatype 7은 FLOAT32이며, 점당 16 B에 12만 점이므로 1,920,000 B입니다.
같은 Message data 필드에 실수 배열이 들어가기도 하고, 메가바이트 단위의 바이너리가 들어가기도 합니다. 컨테이너를 읽은 뒤에는 안쪽 데이터를 해석하는 기능도 필요합니다.

그림 4. EuRoC 영상·IMU를 MCAP으로 변환하고 SLAM 결과를 시각화한 예. 점집합과 경로는 후처리 결과이며 원시 센서값과 구분해야 합니다.
출처: Foxglove의 EuRoC·MCAP 튜토리얼
센서별 원시 표현을 한눈에 보기
데이터 | 대표적인 원시 표현 | 해석할 때 필요한 구조 |
카메라 | sensor_msgs/Image, Bayer RAW | height, width, encoding, step, uint8[] data. rgb8·mono16·bayer_rggb8 등에 따라 해석이 달라짐 |
스테레오 카메라 | ZED SVO | 좌·우 영상과 시각·센서 메타데이터. 보정 파일은 별도로 확보하고 SDK 재생 시 깊이 등을 계산. |
LiDAR ROS | sensor_msgs/PointCloud2 | fields의 타입·오프셋, point_step, row_step, data |
LiDAR KITTI | 프레임별 .bin | 점마다 float32 네 개인 x, y, z, reflectance. 점당 16 B |
LiDAR Waymo | Range image | 라이다·리턴별 구면 투영 배열. 카메라 데이터는 JPEG 바이트 등으로 제공 |
관절 상태 | sensor_msgs/JointState | 이름과 position·velocity·effort 배열. 회전·직선 관절의 단위 구분 |
IMU | sensor_msgs/Imu | 쿼터니언 자세, 각속도·가속도 Vector3, 각각 float64[9] 공분산 |
힘과 토크 | geometry_msgs/WrenchStamped | force(x,y,z), torque(x,y,z), 헤더와 좌표 프레임 |
비전형 촉각 | RGB 이미지 시퀀스 | 탄성체 변형의 영상 프레임과 보정 정보 |
힘 배열형 촉각 | 접촉점별 벡터 배열 | 접촉점별 압력 또는 힘. 3축 센서는 fx, fy, fz 벡터 |
액션과 궤적 | HDF5, 로그 토픽 | 스텝별 관절·말단 명령, 그리퍼 값과 시간 대응 |
원시 데이터와 학습용 데이터는 다르다는 것 아시나요?
공개 데이터셋에서 표처럼 정리된 파일을 만나면 한결 다루기 편하겠다는 생각이 듭니다. 다만 이런 파일은 센서의 서로 다른 주기를 맞추고, 영상을 줄이거나 압축한 뒤, 한 번의 작업을 에피소드와 스텝으로 묶은 결과일 수 있습니다. 쓰기 편해진 만큼 어떤 가공을 거쳤는지도 모르구요. 로봇이 처음 내보낸 데이터와 학습용으로 정리한 데이터의 차이를 확인해야 합니다.
구분 | 대표 포맷 | 주된 구조와 특징 |
원시 기록과 원본에 가까운 배포본 | MCAP, rosbag, SVO, .bin, HDF5 | 설정에 따라 센서별 주기와 시각을 보존. 손실 압축 여부와 이미 적용된 가공도 확인 |
Google 계열의 학습용 구조 | RLDS, TFRecord 기반 배포 | 에피소드 아래 스텝을 배치. observation, action, reward, is_first, is_last 등 포함 |
Hugging Face의 학습용 구조 | LeRobotDataset v3 | 상태·액션은 Parquet, 영상은 MP4, 메타데이터는 JSON·Parquet. 여러 에피소드를 파일에 묶고 오프셋으로 연결 |
RLDS는 에피소드와 스텝의 의미를 정의하는 데이터 구조이며, 흔히 TFRecord로 배포합니다. 스텝 경계를 표시하는 is_first·is_last가 필수이고 관측, 액션, 보상 등은 선택 필드입니다. 마지막 스텝에서 is_last가 참이면 액션·보상·discount는 유효한 값으로 취급하지 않습니다. is_terminal은 환경의 종결 여부를 나타내므로 기록의 마지막과도 구분해야 합니다. 언어 주석은 데이터셋 설계에 따라 연결됩니다.
LeRobotDataset v3는 상태·액션을 Parquet에, 영상을 MP4 등에 저장하고 JSON·Parquet 메타데이터로 연결합니다. 여러 에피소드를 한 파일에 묶어도 공통 API로 에피소드 단위로 읽을 수 있습니다. 파일 하나를 로봇의 한 번 동작과 일대일로 대응시켜서는 안 됩니다. RLDS의 공식 도구 저장소는 2025년 11월 29일 보관 처리되어 읽기 전용입니다. 이미 배포된 RLDS 데이터의 이용 가능성과 도구의 유지보수 상태는 따로 살펴봐야 합니다.

그림 5. LeRobotDataset의 에피소드 기반(v2.1)과 파일 기반(v3.0) 구조 비교. v3에서는 파일 경계와 에피소드 경계가 달라질 수 있습니다.
출처: Hugging Face LeRobotDataset v3 공식 문서
원시 데이터를 학습용으로 바꾸면서 리샘플링, 해상도 변경, 압축, 필드 선택이 이루어질 수 있습니다. 변환본에 없는 깊이 정보나 카메라 파라미터가 나중에 필요해지면 원본으로 돌아가야 합니다. 어떤 정보를 보존할지는 개별 변환 파이프라인에서 선택하며, RLDS 형식 자체가 저장을 금지하는 것은 아닙니다. 그래서 저는 잘 정리된 변환본을 보더라도 원본에 무엇이 남아 있는지 함께 확인하고 싶습니다.
DROID의 원시 배포 폴더에는 ZED SVO, trajectory.h5, JSON 메타데이터와 MP4 영상이 들어갑니다. 공식 안내는 RLDS 배포본을 1.7 TB, 스테레오 HD MP4를 포함한 원시 배포본을 8.7 TB로 소개합니다. 스테레오 영상과 SVO를 제외한 선택적 다운로드는 5.6 TB입니다. 따라서 8.7 TB를 SVO 파일만의 크기로 해석하면 안 됩니다. 용량을 비교할 때는 버전과 포함 파일, 압축 조건을 함께 확인해야 합니다.

그림 6. DROID의 수집 장비. 로봇팔과 그리퍼, 외부 카메라와 손목 카메라가 하나의 작업을 서로 다른 관점에서 기록합니다.
출처: DROID 프로젝트
SVO에서 깊이를 다시 얻을 때도 파일에 무엇이 들어 있는지 구분해야 합니다. Stereolabs의 현재 문서에 따르면 SVO는 영상과 시각·센서 메타데이터를 담고, 깊이·점집합은 SDK가 재생하면서 계산합니다. 보정 파라미터는 SVO 안에 저장되지 않으며, 재생 환경의 별도 보정 파일을 사용합니다. 같은 기록도 보정값과 SDK 설정이 바뀌면 결과가 달라질 수 있습니다. 원본 영상과 함께 보정 파일, SDK 버전, 처리 설정까지 남겨 두고 싶은 이유입니다.
공개 데이터셋의 구성과 배포 형태
공개 데이터셋에는 원본 센서 구조에 가깝게 제공되는 자율주행 데이터와 DROID·AgiBot World 같은 로봇 데이터가 있습니다. RLDS·LeRobot으로 변환된 학습용 배포본도 많습니다. 공개 데이터에도 익명화·압축·좌표 변환이 이미 적용되어 있을 수 있으므로, 가공 전 센서 원본인지 확인해야 합니다.
로봇 조작과 자율주행 데이터
데이터셋별 규모와 센서 구성은 다음과 같습니다. 수치는 해당 논문이나 대표 배포본의 소개 기준이며, 갱신에 따라 달라질 수 있습니다.
데이터셋 | 분야와 규모 | 포함하는 센서와 상태 | 제공 형태 |
DROID | Franka 로봇 조작. 약 7.6만 궤적, 350시간, 564개 장면 | 스테레오 카메라 3대, 관절·말단·그리퍼. 대표 수집 구성 1280×720, 15 Hz | SVO, trajectory.h5와 메타데이터, 영상 배포본. RLDS 별도 |
BridgeData V2 | WidowX 250 6자유도 로봇. 60,096개 궤적, 24개 환경, 13개 스킬 | 카메라와 로봇 상태·액션. 제어 주기 5 Hz | 원 배포의 이미지·궤적 자료와 학습용 변환본. NVIDIA LeRobot v3 변환본도 소개됨 |
PandaSet | 샌프란시스코·실리콘밸리 자율주행. 103개 장면, 각 8초. 소개 규모 약 4.8만 이미지·1.6만 LiDAR 스윕 | 기계식 LiDAR 1대, 솔리드스테이트 LiDAR 1대, 카메라 6대, GPS·IMU | LiDAR·주석 .pkl.gz, 카메라 .jpg, 보정·포즈·시각 .json과 devkit |
ZOD | 유럽 14개국에서 2년간 수집. Frames 10만 개, Sequences 1,473개, Drives 29개 | 카메라, LiDAR, GNSS·IMU 등. Sequences·Drives에 Radar도 추가 제공 | Frames는 선별 이미지와 주변 2초의 보조 센서 데이터. Sequences 20초, Drives 수 분 |
A2D2 | 독일 남부 3개 도시. 어노테이션 41,277프레임, 비라벨 연속 392,556프레임 | 카메라 6대, LiDAR 5대, 차량 CAN 버스 | 시간 대응 정보가 있는 카메라·LiDAR·버스 데이터 |
comma2k19 | 캘리포니아 280 고속도로. 33시간 이상, 1분 세그먼트 2,019개, 약 100 GB | 전방 카메라, 9축 IMU, 원시 GNSS, CAN | raw_log.bz2의 Cap’n Proto 로그, video.hevc, 프레임 타임스탬프 |
AgiBot World Alpha | 모바일 양팔 로봇 등의 조작 데이터 | 깊이, 센서·액추에이터 상태, 작업·장면 메타데이터 | 깊이 PNG, 상태 H5, 메타 JSON 등을 포함하는 배포 구조 |
DROID와 BridgeData V2는 모두 로봇 조작을 다루지만, 로봇 구조와 주기, 카메라 구성, 액션의 의미가 다릅니다. BridgeData V2는 수집 시기에 따라 카메라가 추가되어 궤적마다 제공되는 뷰가 다를 수 있습니다. 기대한 카메라 영상이 없으면 파일부터 다시 받고 싶어질 수 있겠지요. 그 전에 파일 오류로 빠진 것인지, 원래 수집하지 않은 것인지 구분해야 합니다.
PandaSet, ZOD, A2D2는 카메라·LiDAR·위치 데이터를 함께 제공해도 내부 표현과 연속 구간의 정의가 서로 다릅니다. 예를 들어 ZOD의 Frames와 Sequences를 같은 연속 시계열로 취급하면 분석 범위가 달라집니다. comma2k19는 압축 로그와 별도의 HEVC 영상을 시간 정보로 연결해야 합니다.
드론 비행 로그와 시뮬레이션 데이터도 한번 살펴봤는데…
드론 데이터에는 비행 제어기의 수치 로그, 실제 비행 영상, 시뮬레이션 출력이 함께 등장합니다.
데이터셋 | 수집 대상과 규모 | 센서와 주기 | 원시 또는 배포 형태 |
PX4 Flight Review 공개 로그 | 실제 사용자들의 다양한 기체·PX4 버전·보드·비행 모드 | 기록 설정에 따른 IMU, 자세, 모터 출력, GPS 등 비행 제어기 내부 토픽 | ULog .ulg. pyulog로 읽거나 CSV 변환. 일괄 다운로드 스크립트 제공 |
TartanAir V2 | 가상 환경의 로봇·드론 이동. 현재 공식 환경 문서는 65개 환경으로 설명 | 스테레오 RGB, 깊이, 세그멘테이션, LiDAR 점집합, 카메라 포즈 등 | 이미지·배열·포즈 파일 등으로 제공하는 합성 데이터 |
EuRoC MAV | 실내 비행 11개 시퀀스. 시각·관성 SLAM 평가에 널리 사용 | 스테레오 흑백 카메라 20 Hz, IMU 200 Hz, Vicon·레이저 트래커 정답 | rosbag 또는 카메라 이미지·IMU CSV·센서 YAML |
UZH-FPV Drone Racing | 고속 레이싱 비행. 대표 소개 기준 27개 이상 시퀀스, 10 km 이상 | 카메라, IMU, 이벤트 카메라, 레이저 트래커 정답. 구성에 따라 960×800 흑백 40 Hz와 IMU 200 Hz 등 | rosbag과 텍스트·바이너리 배포본 |
Blackbird | 공격적인 실내 비행 168회, 10시간 이상. 대표 전체 규모 약 4.9 TB | IMU 100 Hz, 모터 RPM 약 190 Hz, 모캡 정답 360 Hz, 가상 카메라 120 Hz | rosbag. RPM·PWM은 전용 ROS 메시지 포함 |
ALFA | 고정익 UAV의 고장·이상 탐지. 가공 시퀀스 47개, 엔진 정지 23회와 7종 조종면 고장 24회 | 비행 제어기 상태와 센서, 고장 종류·발생 시각 정답 | 가공본 CSV·MAT·BAG와 별도의 수 시간 원시 비행 BAG |
PX4 공개 로그는 기체와 소프트웨어 버전이 다양합니다. 같은 토픽 이름이라도 메시지 정의와 기록 주기가 달라질 수 있습니다. 수집 대상의 버전과 실제 로그 설정을 확인하고, 필요한 내부 토픽이 해당 파일에 기록되어 있는지 살펴봐야 합니다.

그림 7. PX4 Flight Review의 3축 가속도 그래프 예시. 수치 로그를 시간축에 펼치면 축별 변화와 진동을 비교할 수 있습니다.
출처: PX4 공식 가이드: Flight Review
TartanAir는 시뮬레이션 데이터입니다. RGB, 깊이, 세그멘테이션, 광류, 포즈 같은 정답을 함께 확보할 수 있다는 점이 매력적입니다. 다만 버전에 따라 파일 표현이 달라집니다. 기존 예제는 깊이를 .npy 배열로 제공하지만, V2 문서는 float32 깊이의 바이트를 4채널 PNG에 무손실로 담는 방식을 설명합니다. 색상 사진처럼 읽으면 깊이가 나오지 않습니다. 같은 .png라도 정해진 디코딩 규칙을 알아야 하는 사례입니다.

그림 8. TartanAir의 여러 데이터 표현. 스테레오 영상, 깊이·세그멘테이션, 카메라 포즈·IMU, 점유 지도, 광류, LiDAR를 함께 보여 줍니다.
출처: CMU AirLab TartanAir 프로젝트
EuRoC와 UZH-FPV는 영상과 IMU를 연결해 위치·자세를 추정하는 실험에 적합한 구조입니다. UZH-FPV는 일부 평가용 시퀀스의 정답을 공개하지 않으므로 파일 누락과 구분해야 합니다. Blackbird는 실제 비행의 IMU·모터 RPM·모캡과 가상 카메라 영상을 함께 다룹니다. ALFA는 가공본과 원시 BAG 외에 텔레메트리·Dataflash 로그도 제공합니다. 관측값, 합성 영상, 정답 주석이 어느 단계에서 만들어졌는지 확인해야 합니다.
Hugging Face의 NVIDIA Physical AI 컬렉션에서도 다양한 데이터셋을 찾아볼 수 있습니다.
파일 확장자만으로는 데이터를 정확하게 해석하기 매우 매우 힘듭니다.
파일을 처음 받았을 때는 확장자를 보고 읽기 도구를 고르게 됩니다. 그다음에는 스키마와 메타데이터를 확인해야 실제로 어떤 데이터가 담겼는지 알 수 있습니다.
CSV·JSON·YAML·XML: 자주 만나는 텍스트 포맷
CSV나 JSON처럼 익숙한 이름이 나오면 조금 반갑습니다. 피지컬 AI 데이터 폴더에도 CSV·JSON·YAML·XML이 자주 등장합니다. 센서 값을 담는 표, 작업 정보를 담는 객체, 보정 설정, 로봇의 구조를 설명하는 파일이 함께 쓰입니다. 같은 텍스트 형식이어도 맡는 역할은 다릅니다.
다음 예시는 각 형식의 표기법을 보여 주기 위한 독립적인 설명용 조각입니다.
포맷 | 주로 담는 내용과 실제 사례 | 간단한 표현 예시 |
CSV .csv | 행·열로 센서 시계열을 저장합니다. EuRoC의 IMU CSV, PX4 로그의 CSV 변환처럼 수치 분석에 쓰입니다. | t_ns,joint1_rad 1760597400001812000,0.012 |
JSON .json | 객체와 배열로 관측·이벤트·에피소드 정보를 표현합니다. LeRobot의 info.json 같은 메타데이터에 쓰이고, MCAP의 메시지 페이로드로도 기록할 수 있습니다. | { "episode_id": "demo_001", "success": true } |
YAML .yaml / .yml | 설정과 보정 정보를 사람이 편집하기 쉽게 담습니다. EuRoC의 sensor.yaml, rosbag2의 metadata.yaml이 예입니다. | camera: resolution: [640, 480] frame_id: camera_link |
XML .xml / .urdf | 태그와 속성으로 계층 구조를 표현합니다. ROS의 XML 기반 URDF(.urdf)는 로봇의 링크·관절·형상을 정의합니다. | <robot name="demo"> <link name="base_link"/> </robot> |
CSV를 읽을 때는 열 이름과 구분자, 단위와 시각 기준을 확인해야 합니다. JSON·YAML·XML도 필드나 태그의 의미를 알려 주는 스키마나 명세가 필요합니다. 특히 JSON으로 큰 나노초 타임스탬프를 주고받을 때는 파서가 정수를 정확히 보존하는지 확인해야 합니다. URDF에 정의한 로봇 구조와 실제로 측정한 관절 상태도 구분해야 합니다.
이런 텍스트 파일은 전문 컨테이너와 함께 쓰입니다. 영상 옆에 IMU CSV와 보정 YAML이 놓일 수 있고, MCAP 안에 JSON 메시지를 담을 수도 있습니다. JSON Lines(.jsonl)는 각 줄을 독립적인 JSON 값으로 기록해 순차 처리하기 쉽게 만든 형식입니다. 일반 JSON 파일 전체를 읽는 방식과 구분해야 합니다. 센서 값뿐 아니라 이를 해석하는 설정과 로봇 모델도 연결해 관리해야 합니다.
로봇 로그와 컨테이너
포맷과 확장자 | 주로 쓰이는 곳 | 담는 내용과 확인 사항 |
MCAP .mcap | ROS 2와 일반 메시지 기록 | Schema·Channel·Message. 시간은 나노초, 페이로드는 채널별 CDR·Protobuf·JSON 등 |
rosbag .bag | ROS 1 | 여러 토픽의 직렬화된 메시지와 연결 정보 |
rosbag2 .db3와 metadata.yaml | SQLite 저장 플러그인을 사용하는 ROS 2 | bag 디렉터리의 메타데이터와 실제 저장 파일. .mcap을 사용하는 구성도 있음 |
ZED SVO .svo / .svo2 | DROID 등의 스테레오 카메라 기록 | 영상·시각·센서 메타데이터. SVO2는 고주기 센서와 사용자 데이터 지원. 보정 파일·SDK 버전 별도 관리 |
HDF5 .h5 | DROID trajectory.h5, AgiBot 상태·궤적 | 관절·상태·액션의 계층형 배열. dataset 경로와 차원 정의 확인 |
Cap’n Proto 압축 로그 .bz2 | comma2k19 raw_log.bz2 | CAN·GNSS·IMU 등의 구조화 로그를 bzip2로 압축. 압축 해제 후 스키마에 따라 해석 |
HEVC .hevc | comma2k19 영상 | 전방 카메라 영상 스트림. 프레임 시각과 로그의 대응 필요 |
ROS를 사용하지 않는 시스템에서는 길이 정보가 붙은 Protobuf 메시지를 이어 기록하거나, HDF5 안에 바이트 배열을 담는 자체 포맷도 사용합니다. HDF5 파일에도 관절 배열이나 영상 바이트 등 서로 다른 데이터가 들어갈 수 있습니다.
자율주행과 로봇 데이터의 센서별 파일
데이터셋과 항목 | 확장자 | 표현 방식 |
KITTI LiDAR | .bin | float32 네 개인 x, y, z, reflectance가 점마다 반복. 점당 16 B |
KITTI 시각 | .txt | timestamps.txt 등에 프레임별 시각 저장 |
KITTI GPS·IMU OXTS | .txt | 프레임당 30개 값. 위치·자세·속도 등 필드 정의 확인 |
KITTI 카메라 | .png | image_0X/data/0000000000.png 형태의 프레임 파일 |
nuScenes 카메라 | .jpg | 카메라 영상을 처리해 JPEG로 제공. Bayer 원본과 배포 영상의 차이 구분 |
nuScenes LiDAR | .pcd.bin | float32 다섯 개인 x, y, z, intensity, ring이 점마다 반복 |
nuScenes Radar | .pcd | PCD 헤더와 바이너리 필드. x·y·z, rcs, vx·vy 등 |
Waymo Perception v2 | .parquet | LiDAR range image와 카메라 JPEG 바이트 등을 컴포넌트별 컬럼으로 저장 |
AgiBot World | .png, .mp4, .h5, .json | 깊이·영상, 센서·액추에이터 상태와 명령, 작업·메타데이터 |
KITTI의 .bin과 nuScenes의 .pcd.bin은 모두 점집합이지만, 점마다 반복되는 필드 수가 다릅니다. PointCloud2는 메시지에 필드 정의를 담습니다. 반면 이 바이너리 파일들은 데이터셋의 명세를 읽어야 해석할 수 있습니다. x·y·z 값이 센서 좌표계인지 차량 좌표계인지도 확인해야 합니다.
Waymo v2의 Parquet에는 스칼라와 함께 이미지 바이트와 배열도 들어갑니다. Parquet 파일이라고 해서 평범한 숫자 표로 취급하면 안 됩니다. 저장 컨테이너와 그 안에 담긴 센서 데이터의 구조를 구분해야 합니다.
드론과 시뮬레이션 데이터의 파일
데이터셋과 항목 | 확장자와 경로 예 | 표현 방식 |
PX4 비행 로그 | .ulg | ULog 바이너리의 토픽별 시계열. pyulog의 ulog2csv로 CSV 변환 가능 |
EuRoC 카메라 | .png, cam0/data/<타임스탬프>.png | 흑백 WVGA, 20 Hz. 파일명에 나노초 시각 사용 |
EuRoC IMU | .csv, imu0/data.csv | 각속도와 가속도, 200 Hz |
EuRoC 센서 보정 | .yaml, sensor.yaml | 카메라 내부 파라미터와 바디·센서 좌표 변환 |
EuRoC 전체 대안 배포 | .bag | 같은 관측을 ROS bag으로 제공 |
UZH-FPV | .bag | 카메라, IMU, 이벤트 카메라, 정답 포즈. 센서별 메시지 타입 확인 |
Blackbird | .bag | IMU·모터 RPM·PWM·모캡. 전용 ROS 메시지 정의 필요 |
TartanAir RGB 예제 | .png, image_left/000000_left.png | 기존 배포 예제의 좌·우 이미지. 버전별 폴더 규칙 확인 |
TartanAir 깊이·세그멘테이션·광류 예제 | .npy | NumPy 배열. 깊이는 대표 예제에서 float32, 미터 단위 |
TartanAir 카메라 포즈 예제 | .txt, pose_left.txt | 프레임별 위치·자세. 좌표계와 회전 표현 확인 |
ALFA 가공 비행 시퀀스 | .csv, .mat, .bag | 47개 시퀀스의 고장 종류·발생 시각 정답을 이용하는 구조 |
ALFA 원시 비행 기록 | .bag | 수동·자율 비행 전체 기록. Pixhawk와 수정 ArduPilot을 mavros로 기록하며 주석 연결은 별도 확인 |
학습용 변환 포맷
포맷 | 대표 확장자 | 구조 |
RLDS 기반 배포 | .tfrecord 분할 파일 등 | 에피소드 안의 스텝에 observation·action·reward와 경계 플래그 등을 배치 |
LeRobotDataset v3 | .parquet, .mp4, .json | 상태·액션, 영상, 메타데이터를 분리하고 에피소드와 시간 정보로 연결 |
확장자도 많지만, 같은 확장자 안에서도 센서 필드가 다르고 센서마다 발생 주기가 다릅니다. 같은 사건을 분석하려면 여기에 시각과 좌표계, 단위, 원본·변환본의 관계까지 맞춰야 합니다.
휴..이거 통일해야 하지 않나?
포맷을 묶는 작업은 이미 진행 중입니다. MCAP은 서로 다른 직렬화 방식의 메시지를 한 컨테이너에 기록하고, RLDS는 에피소드와 스텝의 구조를 정의합니다. LeRobot은 수치와 영상 파일을 메타데이터로 연결해 공통 API로 읽게 합니다. 자율주행의 ASAM OpenLABEL은 JSON으로 여러 센서의 주석과 좌표계·변환을 표현합니다.
공통 스키마에는 단위와 좌표계도 들어가야 합니다. ROS REP-103만 보더라도 로봇 몸체는 x 전방·y 좌측·z 위쪽을, 카메라 광학 좌표계는 z 전방·x 우측·y 아래쪽을 사용합니다. 같은 x·y·z 배열을 복사하는 것만으로 두 관측을 맞출 수는 없습니다. 이런 규칙을 기계가 읽고 변환할 수 있어야 데이터 통합이 한 단계 쉬워집니다.
앞으로 공통 포맷을 설계한다면 장비·센서·에피소드 식별자, 시각과 시계 기준, 단위·좌표계, 데이터 형상과 인코딩을 함께 표현했으면 합니다. 영상·점집합의 원본 위치와 보정·변환 이력도 필요합니다. 로봇마다 다른 관절 수나 센서 구성은 확장 필드로 남기고, 비교 가능한 부분부터 공통으로 읽는 방식입니다. 이는 현재 완성된 범용 표준의 설명이 아니라, 이 글에서 기대하는 발전 방향입니다.
이 데이터를 처리할 인프라는 무엇을 해야 할까
수치 센서 스트림과 이미지·영상·점집합은 특성에 맞게 나누어 저장할 수 있습니다. 다만 저장 위치가 달라도 같은 장비의 같은 사건으로 찾아갈 수 있어야 합니다.
수치 스트림은 센서 이름과 측정 시각을 중심으로 저장해야 합니다.
관절, IMU, 힘·토크, GNSS, 모터 RPM 같은 수치 스트림은 센서 이름·측정 시각·값으로 펼쳐 저장할 수 있습니다. 예를 들어 joint1의 위치와 속도에 각각 이름을 붙이고, 실제 측정 시각의 값을 적재하는 방식입니다. 시계열 데이터베이스는 이런 저장과 조회를 맡을 수 있습니다.
센서 이름 측정 시각 값
robot01/joint1/position 1760597400001812000 ns 0.012
robot01/joint1/velocity 1760597400001812000 ns 0.0
robot01/imu/angular_velocity/z 1760597400003010000 ns 0.013
robot01/ft/force/z 1760597400003401000 ns 4.87
위 표는 적재 모델을 설명하는 예시이며 실행 SQL은 아닙니다. 적재할 때는 ROS 배열·벡터를 디코딩해 센서 이름과 값으로 매핑해야 합니다. 단위와 좌표계, 원 메시지의 식별자, 품질 정보, 발행·기록 시각도 별도 메타데이터나 관련 레코드로 보존합니다. 배열을 숫자 행으로 펼친 뒤에도 원래 메시지의 문맥을 추적할 수 있어야 합니다.
이 구조를 활용하면 특정 시간 구간의 관절과 힘 값을 함께 조회하거나, 토크가 급증한 구간을 먼저 찾을 수 있습니다. 관련 영상과 점집합까지 함께 보려면 수치 값에서 원본 파일의 해당 구간으로 이어지는 연결 정보가 필요합니다.
이미지와 점집합은 원본을 보존하고 참조 정보를 연결해야 하구요.
이미지·영상·LiDAR 점집합은 파일이나 오브젝트 스토리지 등에 원본을 보존하고, 검색 정보를 별도로 관리하는 방안을 고려할 수 있습니다. 장비·세션·토픽과 측정 시각을 기준으로 파일 URI, 프레임 번호나 청크 위치, 인코딩, 크기, 보정 정보의 버전을 연결하는 방식입니다.
토크 센서에서 접촉 이벤트를 찾은 뒤, 그 시간 전후의 카메라 영상과 점집합을 가져오는 분석을 생각해 볼 수 있습니다. 영상 전체를 수치 테이블에 펼치거나 수치 분석을 위해 모든 영상을 내려받을 필요가 줄어듭니다. 필요한 부분만 읽는 방식이 얼마나 효율적인지는 포맷의 인덱스·압축·저장 옵션과 읽기 구현에 따라 검증해야 합니다.
저장 경로를 나누어도 분석에서는 연결되어야 합니다
인프라의 역할 | 구체적으로 처리할 내용 | 필요한 이유 |
수집과 해석 | MCAP·rosbag·ULog·HDF5 등의 스키마와 버전을 읽고 원본을 보존 | 파일을 받아 두는 것만으로는 센서 값을 해석할 수 없음 |
시각 관리 | 측정·발행·기록 시각과 장치의 시계 기준을 보존 | 센서 현상과 전송 지연을 구분하고 같은 사건을 정렬 |
시계열 저장 | 센서·장비별 고속 적재, 시간 범위 조회, 집계 | 많은 수의 작은 수치 메시지를 반복 분석 |
대용량 저장과 참조 | 영상·점집합의 원본, 청크·프레임 위치와 메타데이터 관리 | 큰 바이너리를 필요한 구간과 연결해 사용 |
의미와 보정 관리 | 단위, 좌표계, 관절·액션 정의, 카메라 보정 이력 | 같은 숫자의 다른 의미를 섞지 않고 비교 |
학습용 데이터 생성 | 에피소드·스텝 구성, 리샘플링·압축 정책과 버전 관리 | RLDS·LeRobot 변환 결과를 원본에서 재현 |
품질과 변환 이력 | 누락·중복·순서 뒤바뀜, 출처·변환 이력 관리 | 잘못된 데이터와 가공 과정을 확인하고 추적 |
“로봇이 컵을 놓친 순간을 찾아 달라”는 요청을 받았다고 해 보겠습니다. 영상에서 컵이 떨어지는 장면을 찾으면, 다음에는 왜 놓쳤는지가 궁금해집니다. 힘·토크 변화로 후보 구간을 찾고, 관절 상태와 그리퍼 명령을 비교한 뒤, 그 시점의 손목 카메라를 확인해야 합니다. 필요하면 카메라 보정값과 좌표 변환을 적용해 물체와 말단의 관계도 분석합니다. 이 결과를 학습에 다시 쓰려면 원본에서 어떤 규칙으로 스텝을 만들었는지 재현할 수 있어야 합니다.
이 과정을 매번 파일 이름을 찾아가며 수작업으로 연결하기는 어렵습니다. 분석자가 컵을 놓친 원인에 집중할 수 있도록, 파일을 찾고 연결하는 수고를 인프라가 맡아 주면 정말 좋겠지요. 이를 위해서는 인프라가 수치와 바이너리를 특성에 맞게 보관하되, 공통 식별자와 시간·메타데이터를 통해 함께 읽을 수 있어야 합니다.
어려운 일입니다.
마치면서
컵 하나를 옮긴 기록을 다시 읽는 데도 이렇게 많은 형식과 약속이 필요합니다. 파일은 열었는데 단위가 다르고, 시간은 맞췄는데 좌표계가 다릅니다. 같은 메시지 이름을 믿고 값을 합쳤다가 의미가 서로 다른 것이었다는 사실을 알게 된다면 꽤 허탈할 것 같습니다.
이러한 혼돈의 데이터를 처리할 인프라는 반드시 필요합니다. 원본을 보존하면서 시간과 좌표계, 센서·행동의 의미를 연결하고, 어떤 변환을 거쳤는지 추적할 수 있어야 합니다. 저장 장치나 데이터베이스를 고르는 일과 함께 이 공통 규칙을 설계해야 합니다.
MCAP, RLDS, LeRobot, OpenLABEL을 보면 데이터를 함께 다루기 위한 약속은 이미 여러 곳에서 만들어지고 있습니다. 그러나, 각자 기록·학습·주석이라는 다른 문제를 풀고 있으므로, 어느 하나가 모든 피지컬 AI 데이터를 통일했다고 말할 수는 없습니다.
저는 앞으로 이런 형식들이 공통 데이터 모델과 변환 규칙으로 이어질 것이라고 예상합니다. 원본은 각자의 형식으로 남아 있더라도, 분석하는 사람은 같은 방식으로 센서 기록과 영상, 행동을 꺼내 볼 수 있도록 말입니다. 그렇지만, 어떤 표준이 자리 잡을지, 어디까지 합의할 수 있을지는 잘 모르죠.
지금처럼 새로운 데이터를 받을 때마다 해석 방법부터 다시 배워야 한다면, 로봇이 늘어날수록 그 부담도 커질 겁니다. 언젠가는 이 수많은 데이터를 시간과 의미를 보존한 통일된 포맷으로 읽고 처리할 수 있어야 하지 않을까요? 마크베이스 네오를 통해 어떻게 저장,처리할 수 있을까 살펴보다가 그만 판도라의 상자를 열어버린 것 같습니다. 앞에서 말씀드린 “혼돈의 카오스”..
이게 이 동네를 지칭하는 정말 정확한 표현이라고 생각됩니다. 아무래도 당분간은 이 분야에서 데이터 처리 때문에 한참이나 고생을 해야 할 것 같다는 생각이 듭니다.


