- 클라이언트(React/Vite): Video.js 플레이어, 하단 스테이션바, POI/구조물 영상 오버레이, 카메라 파라미터 보정, 미니맵/RoutePanel - 서버(Express): Range 스트리밍, HLS 변환, 프레임 추출, tus 업로드, 주석 API - 최근 작업: 스테이션바 종점역 표출/양끝 정렬/미도착(재생불가) 표시, POI 라벨 '구분' 우선·컴팩트 팝업·겹침제외 토글·동일좌표 다중행, 진행방향(상/하) 우선 표출, 커서 배지 크기·픽셀 떨림 개선 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
40 lines
2.2 KiB
Markdown
40 lines
2.2 KiB
Markdown
# 회전 종료 후 중심선·궤적선이 한 번 튀는 현상 — 에지보존 평활로 교체
|
|
|
|
**날짜**: 2026-06-24
|
|
**수정 파일**: `client/src/components/overlay/StationOverlay.tsx`
|
|
**선행**: [2026-06-24_0957_회전시-선오버레이-지연어긋남-적응형평활.md](2026-06-24_0957_회전시-선오버레이-지연어긋남-적응형평활.md)
|
|
|
|
## 증상
|
|
드론 회전이 끝난 직후 스테이션선·드론궤적선이 **한 번 튐**.
|
|
|
|
## 원인
|
|
직전 작업에서 넣은 **변화율 기반 적응형 창**(`effHalf = halfWin/(1+8·rate)`)의 부작용.
|
|
회전이 끝나 yaw 변화율이 급감하면 `effHalf`가 **한꺼번에 5~7 → 60프레임으로 재확장**됨.
|
|
그 순간 trailing window에 회전 프레임들이 다시 포함되어 평균 yaw가 급변 → 1회 튐.
|
|
|
|
## 조치 — 에지(회전 경계) 보존 적응형 창
|
|
변화율로 창 크기를 정하지 않고, **중심 yaw 와 차이가 임계 이내인 인접 프레임까지만** 확장:
|
|
```ts
|
|
const YAW_EDGE = 8; // deg
|
|
const near = idx => |최단각(frames[idx].yaw - frames[i].yaw)| <= YAW_EDGE;
|
|
let lo = i, hi = i;
|
|
while (lo > i-halfWin && near(lo-1)) lo--; // 회전 프레임 만나면 정지
|
|
while (hi < i+halfWin && near(hi+1)) hi++;
|
|
```
|
|
- 회전 구간이 직선 평균에 **섞이지 않음**(시간축 양방향 에지보존 = bilateral).
|
|
- 회전 중: 창이 자연히 좁아 실제 자세 즉시 추종(지연 없음).
|
|
- 회전 종료 후: 회전 프레임을 배제한 채 창이 **한 프레임씩** 부드럽게 재확장 → 튐 없음.
|
|
- 직선: yaw 거의 일정 → 풀창(±halfWin)으로 노이즈 억제(기존 효과 유지).
|
|
|
|
## 튜닝
|
|
- `YAW_EDGE`(8°): 작게 → 회전 추종↑·직선 노이즈억제↓, 크게 → 반대. GPS yaw 지터(보통 <8°)는
|
|
창 확장을 막지 않도록 8°로 설정.
|
|
- 단일 프레임 yaw 스파이크가 8° 초과하면 그 지점에서 창이 끊길 수 있으나, 창 경계가
|
|
중심 이동에 따라 1프레임씩만 변하므로 **튐은 발생하지 않음**(완만).
|
|
|
|
## 검증
|
|
- `npm run build -w client` (node20) tsc + vite build 통과.
|
|
|
|
**소요 시간**: 약 10분
|
|
**Context 사용량**: input ~200k / output ~4k tokens
|