- guard-history-fields.py: Windows cp949 stdin에서 한글 필드 정규식 미스매치로 발생하던 false block 및 에러 mojibake 수정 (stdin/stderr UTF-8 강제) - docs/geo-station-mapping.html: 지리정보·측점·프레임 맵핑 구조 + station 기준 재생 설계 문서 - docs/history: 2026-06-17 맵핑 구조 분석 기록 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.0 KiB
4.0 KiB
지리정보 + 측점 + 프레임 맵핑 구조 분석
작업일: 2026-06-17 작업명: 지리정보·측점·프레임 맵핑 구조 소스 분석 + station 기준 재생 HTML 문서화 소요 시간: 18분 Context 사용량: input 60k / output 8k tokens 이슈: #0
목적
영상 프레임 ↔ 측점 ↔ 지리정보(POI/중심선)가 현재 소스에서 어떻게 맵핑되는지 코드 기반으로 파악. 추가로 "시간 기준이 아닌 station(측점) 기준 재생"을 위한 맵핑 구조를 HTML 문서로 출력.
분석 대상 파일
- server/src/services/geoMatch.ts — 서버 투영/매칭 (평면근사 ENU)
- server/src/routes/geo.ts — geo API 엔드포인트
- client/src/utils/geoProjection.ts — 클라 투영 (EPSG:5186 TM, Python advanced_tuner_v2.py 동일)
- client/src/components/overlay/StationOverlay.tsx — 실시간 캔버스 오버레이
- client/src/components/geo/StationVerify.tsx — 측점→프레임 점프 검증 패널
- client/src/components/player/VideoPlayer.tsx — frame↔time 변환
핵심 결론
맵핑 키 = 프레임 번호
- 드론 CSV의
frame_cnt= 영상 프레임 ↔ GPS+자세 연결고리 time = frame / fps- fps 불일치 발견: 클라
VIDEO_FPS = 30000/1001 = 29.97, 서버DEFAULT_FPS = 30. seek는 frame번호 기반이라 실害 적으나 서버FrameMatch.time부정확.
데이터 소스 (GEO_DATA_DIR 기본 samplevideo/)
*회덕*.csv— 드론 비행로그 (frame_cnt, lat, lon, alt, yaw, pitch, roll, focal_len)building/*POI*위경도*.csv— 지장물 (타원체고 버전 우선)building/*측점*위경도*.csv— 측점pythonsource/input/center.csv— 선로 중심선 224점 (타원체고 col5)*.srt— terrain offset (로드만, 거의 미사용)
투영 파이프라인
geo(lat,lon,z) → ENU world(m) → 카메라 상대벡터 → 회전(yaw/pitch/roll) → 핀홀 투영 px,py(0~1)
- 월드 원점 = 첫 측점 (측량 기준점), 드론 frame[0] 아님 → 드론 GPS 오차 회피
- 서버/클라 투영 구현 2벌 (서버=cos(lat) 평면근사, 클라=EPSG:5186 TM proj4) — 정밀도 차이
두 방향 질의
findFramesForPoi(name): 측점명 → 전 프레임 투영 → FOV 안 → 연속구간 그룹화(GAP=30) → 구간별 중심 프레임. (StationVerify 점프)findPoisForFrame(n): 프레임 → 보이는 POI 목록.
클라 실시간 오버레이
- idle time에
Map<frameNum, {stationLabels, poiMarkers}>사전계산 - RAF 루프: Map 조회 + frameNum→+1 보간 + EMA 스무딩 → canvas
- 측점은 투영 전 가장 가까운 중심선 점에 스냅 (nearestCL, z도 중심선값)
- smoothFrame: 드론 자세 ±N프레임 이동평균으로 GPS/IMU 노이즈 제거
측점 순서
stationOrder: title\d+K\d+파싱 = km측점 ("12K345" = 12.345km). 서버/클라 동일 함수.
Station 기준 재생 관점
현재 구조는 "시간(프레임) → 지리정보" 단방향 표시 중심. station 기준 재생 = 측점 → 대표 프레임 → seek 역방향이 핵심.
- 이미 존재하는 빌딩블록:
findFramesForPoi(측점→최적 프레임),onSeekToFrame(프레임→currentTime(frame/fps)). - station 기준 타임라인을 만들려면: 전 측점에 대해
findFramesForPoi1회 일괄 호출 → 측점별 대표 프레임 테이블 구성 → km 순 정렬 → 측점 간 이동 = seek. - 산출물: 맵핑 구조 + station 기준 재생 설계를 정리한 HTML (
docs/geo-station-mapping.html).
후속 참고
- fps 불일치(30 vs 29.97) 정리 검토 가치 있음
- 서버/클라 투영 알고리즘 통일 여부 결정 필요 (현재 클라가 정밀)
- station 기준 재생용 측점→프레임 테이블 API(
/api/geo/station-index등) 신설 검토