시계열 어노테이터 스키마
Raw| 용어 | 의미 | 예시 |
|---|---|---|
| 트랙 (track) | 하나의 차트에 함께 표시되는 채널들의 그룹. 서로 다른 센서의 채널을 자유롭게 조합할 수 있다. | GPS 고도 + 기압 고도 + EKF 고도를 하나의 차트에 표시 |
| 채널 (channel) | 하나의 값 배열을 가진 개별 데이터 시리즈. timestamps와 동일한 길이의 숫자 배열이다. | battery_status__voltage_v |
| 채널 메타 (channelMeta) | 채널의 표시 정보 (이름, 단위, 색상, 차트 타입). | { name: "전압", unit: "V", color: "#ab47bc", chartType: "line" } |
프로젝트 카테고리
Section titled “프로젝트 카테고리”project.category |
|---|
time_series_annotation |
project.annotation_types[] | 설명 |
|---|---|
time_range | 시간 범위 어노테이션 |
라벨링 결과 구조
Section titled “라벨링 결과 구조”라벨링 결과는 공통 어노테이터 스키마의 annotatorData 최상위 구조를 그대로 따릅니다.
다른 어노테이터와 다른 점은 AssetId(에셋 키) 입니다. 이미지는 image_1, 오디오는 audio_1 같은 논리적 키를 쓰지만,
시계열은 task.data_unit.files에서 is_primary: true인 파일의 키를 그대로 사용합니다 (예: data_1).
| 최상위 키 | 시계열에서의 사용 |
|---|---|
extra | 트랙 순서·숨김 상태 저장 (아래 시계열 전용 extra 참고) |
annotations | time_range 어노테이션의 메타 정보 |
annotationsData | 각 어노테이션의 시간 구간 (section) |
relations | 사용하지 않음 (항상 빈 배열) |
annotationGroups | 조건부 사용 — 아래 설명 참고 |
assignmentId | 작업 식별자 (숫자) |
relations — 시계열 어노테이터에는 관계(relation) 도구도, 관계 패널도 없습니다. 최상위 키는 공통 스키마 호환을 위해 유지되지만 항상 빈 배열입니다.
annotationGroups — 시계열 어노테이터도 공통 어노테이션 그룹 패널을 사용합니다.
프로젝트 분류 스키마에 annotationGroup이 정의된 경우에만 그룹 추가 탭이 노출되며, 이때 생성된 그룹은 공통 스키마의 AnnotationGroupItem 형태로 저장됩니다.
정의되지 않았다면 빈 배열로 유지됩니다.
각 키는 작업 로드 시 { "<AssetId>": [] } 형태로 초기화되므로, 어노테이션이 하나도 없어도 키 자체는 존재합니다.
annotations 필드 구조
Section titled “annotations 필드 구조”| 필드 | 타입 | 설명 |
|---|---|---|
id | string | 어노테이션 고유 ID |
tool | "time_range" | 시계열은 항상 time_range |
isLocked | boolean | 편집 잠금 여부 (생성 시 false) |
isVisible | boolean | 화면 표시 여부 (생성 시 true) |
isValid | boolean | 유효성 여부 (생성 시 false, 분류 입력 후 검증 결과로 갱신) |
isDrawCompleted | boolean | 그리기 완료 여부. 시계열은 구간 생성 즉시 완료되므로 항상 true |
classification | Classification | null | 분류 정보 (관리자 정의 스키마를 flatten한 key-value) |
label | object[] | classification에서 파생된 표시용 라벨 (아래 참고) |
annotationData 구조 (time_range)
Section titled “annotationData 구조 (time_range)”| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
id | string | O | annotations[].id와 1:1 매칭 |
section.start | number | O | 구간 시작 시각 |
section.end | number | O | 구간 종료 시각 |
excludedTracks | string[] | X | 이 구간을 적용하지 않을 트랙 ID 목록 (미지정 시 전체 트랙 적용) |
excludedTracks
Section titled “excludedTracks”시간 구간 어노테이션은 기본적으로 모든 트랙에 걸쳐 표시됩니다.
특정 트랙에서만 “이 구간은 해당 없음”으로 처리하려면 해당 트랙 ID를 excludedTracks에 넣습니다.
- 빈 배열이거나 필드가 없으면 전체 트랙에 적용됩니다.
- 모든 트랙을 제외할 수는 없습니다 (최소 1개 트랙은 포함).
- 현재 트랙 목록에 없는 ID는 편집 시 무시됩니다.
트랙 ID는 데이터 유닛 구성 방식에 따라 다릅니다.
| 데이터 유닛 구성 | 트랙 ID |
|---|---|
| 통합 JSON | tracks[].id 값을 그대로 사용 (예: altitude-estimate) |
| CSV + 메타 JSON | view.subplots 순서대로 자동 생성 — track-0, track-1, … |
시계열 전용 extra
Section titled “시계열 전용 extra”extra[AssetId]에는 작업자의 트랙 레이아웃 상태가 저장되어 세션 간 유지됩니다.
| 키 | 타입 | 설명 |
|---|---|---|
trackOrder | string[] | 작업자가 재정렬한 트랙 ID 순서 |
hiddenTracks | string[] | 숨김 처리한 트랙 ID 목록 |
PX4 비행 로그(통합 JSON, origin: "absolute" → epoch_ms)를 라벨링한 결과 예시입니다.
label은 분류 스키마에서 파생되는 값이므로, 아래 샘플은 클래스 6종에 representativeCodes: ["class"]가
정의되고 vibration_anomaly에만 하위 속성(severity / axis)이 붙은 프로젝트를 가정한 결과입니다
(label 필드 설명 참고).
위 샘플에서 확인할 점:
data_1은task.data_unit.files의is_primary파일 키입니다. CSV 방식이라도 실데이터 파일 키(data_1)를 쓰며, 메타 JSON 키(data_meta_1)는 쓰지 않습니다. 에셋 키는 파일 키를 그대로 따르므로, 파일 키가data_1이 아닌 프로젝트에서는 그 키가 들어갑니다.section값은 epoch_ms입니다. 같은 데이터를 CSV +timeAxis.origin: "relative"/unit: "us"로 로드했다면191000000같은 마이크로초 값이 저장됩니다.- 트랙 ID와 시간 범위는 PX4 예제 데이터의 실제 값이고, 클래스 코드(
takeoff/hover/cruise/turn/landing/vibration_anomaly)도 해당 프로젝트의 분류 스키마와 동일합니다. vibration_anomaly구간은 위치 관련 트랙 4개를excludedTracks로 제외했고,isLocked: true로 편집이 잠겨 있습니다.classification의severity/axis는 하위 속성(attributes)까지 정의한 프로젝트를 가정한 확장 예시입니다. 하위 속성은 특정 클래스가 선택됐을 때만 노출되도록 정의되므로, 위처럼vibration_anomaly에만 붙는 형태가 됩니다. 클래스만 정의한 프로젝트라면classification은{ "class": "..." }하나뿐입니다.label의 첫 번째 요소는text만 비운 중복 항목입니다. 클래스만 있는 어노테이션은 2개, 하위 속성 2개가 붙은vibration_anomaly는 4개가 됩니다. 배열을 순회해 텍스트를 이어 붙일 때는 첫 요소를 건너뛰어야 합니다.label은classification에서 파생된 값이며, 작업을 다시 열 때 분류 스키마 기준으로 재계산되어 덮어써집니다. 저장된 값을 신뢰해 읽는 소비자는 없으므로, 외부에서 결과를 해석할 때는label이 아니라classification을 기준으로 삼아야 합니다.
초안
⬇️ ⬇️ 아래 데이터 유닛 섹션부터 문서 끝까지는 작성 중인 내용으로, 확정되지 않았습니다.
데이터 유닛
Section titled “데이터 유닛”시계열 데이터 유닛은 동일한 시간 범위를 공유하는 센서 채널들의 집합입니다.
task.data_unit.files에 실제 파일들이 담기며, 다음 두 가지 구성을 지원합니다.
| 구성 | files 구성 | 실데이터 | 뷰 정의 |
|---|---|---|---|
| 통합 JSON | data_N (.json, is_primary) | JSON 내 channels | 같은 JSON의 tracks / channelMeta |
| CSV + 메타 JSON | data_N (.csv, is_primary) + data_meta_N (.json) | CSV 파일 | 메타 JSON의 view.subplots |
is_primary인 파일이 실데이터이며, 로더는 그 URL의 확장자로 통합 JSON(.json) / CSV(.csv) 경로를 판별합니다. (file_type 필드는 사용하지 않습니다.)
task.data_unit.files
Section titled “task.data_unit.files”각 파일 항목은 다음과 같은 형태입니다. meta에는 파일 크기 등 스토리지 메타데이터가 담기며, 뷰 정의는 이 안에 들어가지 않습니다.
통합 JSON 방식에서는
data_meta_N없이data_N(.json) 하나만 존재합니다.
방식 1: 통합 JSON
Section titled “방식 1: 통합 JSON”ULG(ULog) 형식을 차용합니다. data_N(.json) 파일 하나에 데이터와 뷰 정의가 모두 담깁니다.
timestamps 및 meta.startTime / endTime은 기본적으로 Unix Epoch 기준 밀리초(epoch_ms) 를 사용합니다.
timeAxis.origin으로 timestamps의 기준(epoch/absolute/relative/index)을 명시하면 별도 사전 변환 없이 그대로 렌더링됩니다.
origin: "relative"인 데이터(예: 부팅 후 마이크로초)는 timeAxis.unit으로 원시 단위를 지정합니다.
화면 표시 형식은 timeAxis.format으로 지정합니다.
방식 2: CSV + 메타 JSON
Section titled “방식 2: CSV + 메타 JSON”data_N이 CSV(실측 데이터), data_meta_N이 뷰/시간축 정의를 담은 메타 JSON인 구성입니다.
컬럼이 많은 CSV에서 어떤 컬럼을 어떤 트랙으로 그릴지는 메타 JSON의 view.subplots가 결정합니다.
- x축(timestamps): CSV의
timestamp컬럼 값 (컬럼이 없으면 행 인덱스) - 채널:
view.subplots[].columns에 명시된 컬럼만 로드 (라인 차트) - 트랙:
subplot하나당 트랙 하나
메타 JSON 예시:
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
view.subplots | { name?, columns[] }[] | O | 트랙별로 로드/표시할 CSV 컬럼 (name 생략 시 Track N) |
view.timeAxis | { origin, unit?, format? } | X | 시간축 기준/단위 (미지정 시 absolute/epoch_ms) |
format_version 또는 total_rows | string / number | O | 메타 포맷 식별 필드 (둘 중 하나 이상 필요) |
classes | string[] | X | 어노테이션 클래스 목록 |
filename / csv_hash | string | X | 원본 CSV 식별용 |
ChartType
Section titled “ChartType”| 값 | 설명 |
|---|---|
line | 라인 차트 |
scatter | 산점도 |
area | 영역 차트 |
stacked_area | 누적 영역 차트 |
step | 계단 차트 |
bar | 막대 차트 |
band | 범위(min/max) 밴드 차트 |
box_plot | 박스 플롯(통계 범위 요약) |
waterfall | 워터폴(증감) 차트 |
TimeAxisOrigin
Section titled “TimeAxisOrigin”timeAxis.origin은 timestamps 값의 기준을 지정하며, ECharts 축 타입을 결정합니다. 지정하지 않으면 absolute(epoch_ms)로 간주합니다.
각 origin은 별도 사전 변환 없이 그대로 렌더링됩니다. 사용자가 표시 기준만 바꾸고 싶을 때는 displayOrigin을 사용합니다(데이터 origin은 유지, 포맷터에만 영향).
| 값 | 설명 |
|---|---|
absolute | timestamps가 epoch_ms. 벽시계 시각(format)으로 표시 (기본값) |
epoch | timestamps가 epoch_ms. 원시 숫자 그대로 표시 |
relative | 시작(0) 기준 경과 시간. 단위는 unit으로 지정 (예: PX4 부팅 후 마이크로초 → unit: "us") |
index | timestamps를 샘플 인덱스 기준으로 표시 |
TimeAxisUnit
Section titled “TimeAxisUnit”origin: "relative"일 때 timestamps의 원시 단위를 지정합니다. 지정하지 않으면 ms이며, 표시 시 자동으로 밀리초로 환산됩니다.
| 값 | 단위 |
|---|---|
us | 마이크로초 (PX4 로그 등) |
ms | 밀리초 (기본값) |
s | 초 |
min | 분 |
h | 시 |
ChannelThreshold
Section titled “ChannelThreshold”트랙의 Y축에 표시되는 배경색 구간입니다. tracks[].thresholds 배열의 각 요소입니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
color | string | O | 배경색 (rgba 권장) |
label | string | X | 구간 라벨 |
min | number | X | Y축 최소값 (미지정 시 -∞) |
max | number | X | Y축 최대값 (미지정 시 +∞) |
YRange
Section titled “YRange”트랙의 Y축 표시 범위를 고정합니다. tracks[].yRange 객체입니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
min | number | O | Y축 하한 |
max | number | O | Y축 상한 |
TimeAxisFormat
Section titled “TimeAxisFormat”화면에 표시할 시간 형식을 지정합니다. Day.js 포맷 문자열을 사용합니다.
| 예시 | 출력 |
|---|---|
HH:mm:ss | 14:05:32 |
HH:mm | 14:05 |
s.SSS | 5.320 |
MM-DD HH:mm | 02-18 14:05 |