포스트

(Radar) 11. 좌표계와 좌표변환 — 안테나가 잰 각도가 지도 위 위경도가 되기까지

레이다가 잴 수 있는 것은 자기 정면 기준의 거리 하나와 각도 두 개뿐인데 지휘관은 위경도를 봐야 한다 — 그 사이를 메우는 좌표계들의 원점과 축 규약, 회전행렬이 삼각함수 덧셈정리 한 줄에서 나오는 과정, 안테나 좌표계의 세 얼굴(Polar·Cartesian·UV)과 위상배열이 굳이 UV를 쓰는 사정, INS가 바깥을 전혀 보지 않고도 자세를 아는 방법과 스트랩다운·짐벌의 갈림, NED와 ENU·ECEF와 ECI·타원체와 지오이드의 차이, 함정 고정형 안테나를 놓고 5단계 변환을 설계하고 되돌리는 과정, 그리고 그것을 C로 짜서 왕복 오차 10⁻⁹ m 까지 확인하기.

(Radar) 11. 좌표계와 좌표변환 — 안테나가 잰 각도가 지도 위 위경도가 되기까지

레이다가 “20 km 앞, 오른쪽으로 30도” 라고 말할 때 전시기에는 “북위 36.2337도, 동경 127.3643도” 가 찍혀야 한다. 둘은 같은 표적인데 말하는 사람이 다르다. 그 사이를 메우는 것이 좌표변환이다.

이 글은 그 통역 과정을 처음부터 끝까지 따라간다. 앞부분에서 좌표계 여섯 가지를 하나씩 소개하고, 중간에서 함선 레이다 하나를 놓고 변환 경로를 설계하며, 마지막에 그것을 C로 구현해 숫자로 확인한다. 사전 지식은 삼각함수와 행렬 곱셈 정도면 충분하고, 그마저도 필요한 곳에서 다시 설명한다. 본문의 모든 수치는 직접 짠 코드로 계산했고 독립 구현(Python/NumPy)과 교차 검증했다.


0. 시작하기 전에

0.1 좌표계는 왜 여러 개나 필요한가

레이다 안테나는 자기가 지금 어디를 보고 있는지 스스로는 모른다. 안테나가 아는 것은 딱 세 가지뿐이다.

  1. 전파가 갔다 오는 데 걸린 시간 → 거리
  2. 자기 정면에서 좌우로 몇 도
  3. 자기 정면에서 위아래로 몇 도

배가 어느 방향을 향하는지, 지금 위도가 몇 도인지는 안테나의 관심 밖이다.

반대로 지휘관이 보는 전시기는 지도다. 지도에 점을 찍으려면 위도·경도가 필요하다. 그런데 위경도는 지구 전체를 기준으로 한 값이고, 안테나가 준 “오른쪽으로 30도”와는 아무 관계가 없다.

이 간극을 메우려면 중간 단계가 필요하다. 안테나의 “오른쪽 30도”를 배 기준으로 바꾸고, 배 기준을 북쪽·동쪽 기준으로 바꾸고, 그걸 다시 지구 기준으로 바꾼다. 좌표계가 여러 개인 이유는 딱 이것이다.

핵심 좌표계는 “어디”를 말하는 언어다. 표적은 하나뿐인데 언어가 여러 개라서 화자를 바꿀 때마다 통역이 필요하다. 그 통역이 좌표변환이다.

같은 표적, 다섯 가지 대답

3절에서 실제로 계산할 표적 하나를 미리 보자. 아래 다섯 줄은 전부 같은 점을 가리킨다.

말하는 사람표적이 어디 있냐고 물으면
안테나내 정면에서 오른쪽 30°, 20 km
함선선수 기준 오른쪽 뒤 120°, 20 km
바다 위 이 지점남쪽으로 19 340 m, 동쪽으로 5 155 m, 위로 10 m
지구지구 중심에서 (−3 125 892, +4 093 775, +3 749 164) m
지도북위 36.2337°, 동경 127.3643°, 고도 41.5 m

다섯 문장 모두 맞다. 다른 것은 기준점(원점)과 기준 방향(축) 뿐이다.

0.2 좌표계를 읽는 세 가지 질문

새 좌표계를 만나면 아래 셋만 확인하면 된다. 1절의 모든 좌표계를 이 형식으로 설명한다.

질문왜 중요한가
① 원점이 어디인가?“0, 0, 0”이 물리적으로 어느 지점인가. 평행이동 계산의 기준이 된다.
② 축이 어디를 향하는가?특히 z가 위인지 아래인지. 항법 분야는 z를 아래로 두는 관습이 있어 처음엔 거의 반드시 헷갈린다.
③ 무엇에 붙어 있는가?배에 붙어 있으면 배가 흔들릴 때 좌표계도 같이 흔들린다. 표적이 가만히 있어도 좌표값이 변한다.

0.3 변환은 두 동작뿐

좌표변환이라고 하면 복잡한 수학처럼 들리지만 실제로 하는 일은 두 가지뿐이다.

  • 회전(rotation) — 기준 방향이 다를 때. “내 정면”과 “배의 정면”이 다르면 회전이 필요하다.
  • 평행이동(translation) — 기준 이 다를 때. 안테나가 무게중심에서 30 m 떨어져 있으면 그만큼 옮겨준다.

모든 단계는 이 둘 중 하나거나 둘 다다.

회전을 눈으로 보기

표적은 가만히 있다. 움직이는 것은 자(ruler) 다.

같은 표적을 안테나 좌표계와 함선 좌표계에서 읽은 결과

그림 0-1. 두 그림에서 주황색 화살표(표적)의 위치는 완전히 같다. 달라진 것은 축뿐이다.

안테나의 “정면”이 함선의 “우현”이기 때문에 같은 표적이 (+17 320, +10 000) 에서 (−10 000, +17 320) 으로 바뀐다 — 두 숫자가 자리를 바꾸고 부호 하나가 뒤집혔다. 이것이 90도 회전의 정체다.

회전행렬은 어디서 나오는가

90도처럼 딱 떨어지면 숫자를 바꿔치기하면 되지만 45도, 30도는 그렇게 안 된다. 그때 필요한 게 sin·cos이고, 그것을 표로 정리해 놓은 것이 회전행렬이다. 어렵게 외울 것이 아니라 삼각함수 덧셈정리 한 줄에서 바로 나온다.

2차원 회전 유도

그림 0-2. 회전행렬의 유도. 점을 극좌표로 쓰고 각도만 θ 만큼 더하면 끝이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
① 원래 점 (x, y) 를 극좌표로 쓴다
     x = r·cos α ,   y = r·sin α

② θ 만큼 더 돌리면 각이 (α + θ) 가 된다
     x′ = r·cos(α + θ) = r·cosα·cosθ − r·sinα·sinθ
     y′ = r·sin(α + θ) = r·sinα·cosθ + r·cosα·sinθ
                          (삼각함수 덧셈정리)

③ r·cosα = x,  r·sinα = y  를 되돌려 넣는다
     x′ = x·cos θ − y·sin θ
     y′ = x·sin θ + y·cos θ

④ 이 두 줄을 표로 적은 것이 Rz(θ) 다
     ⎡ x′ ⎤   ⎡ cos θ   −sin θ ⎤   ⎡ x ⎤
     ⎢    ⎥ = ⎢                 ⎥ × ⎢   ⎥
     ⎣ y′ ⎦   ⎣ sin θ    cos θ ⎦   ⎣ y ⎦

3차원에서는 “어느 축 둘레로 도느냐”에 따라 이 2×2 블록이 들어가는 자리만 달라진다. z축 둘레 회전이면 z는 그대로 두고 x·y 만 섞이므로, 위 2×2 를 왼쪽 위에 넣고 나머지를 단위행렬로 채우면 된다.

1
2
3
4
5
6
        ⎡ 1     0        0    ⎤        ⎡  cos β   0   sin β ⎤        ⎡ cos γ  −sin γ   0 ⎤
Rx(α) = ⎢ 0   cos α   −sin α  ⎥ Ry(β)= ⎢    0     1     0   ⎥ Rz(γ)= ⎢ sin γ   cos γ   0 ⎥
        ⎣ 0   sin α    cos α  ⎦        ⎣ −sin β   0   cos β ⎦        ⎣   0       0     1 ⎦

x축 둘레 회전                    y축 둘레 회전                    z축 둘레 회전
(= roll)                        (= pitch)                       (= yaw)

우리 문제의 90도 회전을 넣어 보면 위에서 눈으로 본 결과와 정확히 같다.

1
2
3
         ⎡ 0  −1   0 ⎤       ⎡ +17 320.5081 ⎤     ⎡ −10 000.0000 ⎤
Rz(90°) =⎢ 1   0   0 ⎥   ×   ⎢ +10 000.0000 ⎥  =  ⎢ +17 320.5081 ⎥
         ⎣ 0   0   1 ⎦       ⎣        0.0000 ⎦     ⎣        0.0000 ⎦

행렬을 쓰는 이유 세 가지

  1. x·y·z 세 축을 한 번에 처리한다.
  2. 회전을 여러 번 해야 할 때 행렬끼리 곱해서 하나로 합칠 수 있다. roll·pitch·yaw 세 회전도 곱 하나로 뭉쳐진다.
  3. 되돌아갈 때는 전치(행과 열 바꾸기)만 하면 된다. 역행렬을 따로 구할 필요가 없다.

세 번째 성질은 회전행렬이 직교행렬이기 때문에 성립한다. “직교행렬”이란 Aᵀ · A = I(단위행렬)를 만족하는 행렬이고, 회전은 길이와 각도를 바꾸지 않으므로 항상 이 성질을 갖는다. 3절의 단위 시험에서 실제로 이 성질을 확인한다.

평행이동은 그냥 더하기

회전이 끝났으면 원점 차이만 더해 주면 된다.

1
2
3
4
p_함선  =  Rz(90°) × p_안테나  +  레버암
                                 └─ (−30, 0, −10) m
                                     x = −30 : 30 m 뒤  (x는 앞이 +)
                                     z = −10 : 10 m 위  (z는 아래가 +)

이 오프셋을 레버암(lever arm) 이라고 부른다. 무게중심에서 센서까지 뻗은 “지렛대 팔”이라는 뜻이다.

0.4 이 문서의 표기 약속

좌표변환 버그의 대부분은 수식이 아니라 약속에서 나온다. 같은 기호가 문헌마다 반대 의미로 쓰이기 때문이다. 아래 다섯 가지를 먼저 못 박고 시작한다.

항목약속
z축 방향모든 좌표계에서 z는 아래. “10 m 위”는 z = −10.
회전행렬 이름C_ned_from_body = “동체 좌표를 NED 좌표로 바꾸는 행렬”. 이름에 방향을 명시한다.
역변환C_body_from_ned = (C_ned_from_body)ᵀ — 전치하면 된다.
오일러각 순서3-2-1 (yaw → pitch → roll). C_ned_from_body = Rz(yaw)·Ry(pitch)·Rx(roll)
각도 단위계산·저장은 라디안, 화면·인터페이스만 도(degree). 경계에서 한 번만 변환한다.

왜 이름에 방향을 넣는가 C_bn 이라는 변수명은 라이브러리마다 “b→n”이기도 하고 “n→b”이기도 하다. 방향이 반대여도 컴파일은 되고 값도 그럴듯하게 나온다. 그래서 이름에 방향을 박아 넣는 것이 가장 값싼 방어책이다. 3절의 단위 시험 T8이 이 유형의 버그를 겨냥한다.


1. 좌표계 여섯 가지

레이다 시스템에서 주로 쓰는 좌표계를 하나씩 살펴본다. 각 좌표계마다 ① 원점 ② 축 ③ 붙은 곳을 먼저 밝히고, 그다음 “왜 필요한가”와 “언제 쓰는가”를 설명한다.


1.1 안테나(Antenna) 좌표계: UV, Polar, Cartesian

안테나 좌표계는 레이다가 표적을 실제로 측정하는 곳이다. 모든 것이 여기서 시작한다.

질문
① 원점안테나 면의 중심(위상중심)
② 축x = 보어사이트(안테나가 정면으로 바라보는 방향)   y = 그 오른쪽   z = 아래
③ 붙은 곳배 (여기서 다루는 예제는 고정형이라 볼트로 고정 — 안테나가 따로 돌지 않는다)

보어사이트(boresight) 라는 말이 계속 나온다. 안테나 면에 수직으로 뻗은 방향, 즉 “안테나가 똑바로 바라보는 방향”이다. 손전등으로 치면 빛이 가장 센 한가운데 방향이다.

같은 방향을 가리키는 데에 세 가지 표현이 쓰인다. 셋 다 같은 정보를 담고 있고, 목적에 따라 골라 쓴다.

1.1.1 Polar (극좌표) — 측정값이 나오는 형태

레이다가 실제로 재는 것은 거리 하나와 각도 둘이다. 그래서 원측정값은 자연스럽게 극좌표다.

성분기호의미
시선거리R (Slant Range)안테나에서 표적까지의 직선 거리. 전파 왕복시간 × 빛의 속도 ÷ 2
방위각Az (Azimuth)보어사이트에서 오른쪽으로 잰 각
고각El (Elevation)안테나 수평면에서 위로 잰 각

안테나 극좌표 R, Az, El 의 정의

그림 1-1. 방위각 Az 는 위에서 본 그림에서, 고각 El 은 옆에서 본 그림에서 읽는다.

뒤에서 쓸 예제 입력값은 R = 20 km, Az = 30°, El = 0° 이다. 즉 “안테나 정면에서 오른쪽으로 30도 방향, 20 km 떨어진 곳, 높낮이는 정면과 같음”이라는 뜻이다.

주의 — Az/El 정의는 하나가 아니다 문헌에 따라 방위각을 재는 기준축이나 회전 순서가 다르다. 어느 정의를 쓰는지는 문서로 못 박아야 하고, 가장 확실한 방법은 아래 1.1.3의 방향코사인 수식을 함께 적어두는 것이다. 이 문서는 “보어사이트에서 오른쪽으로 Az, 그다음 위로 El” 순서(El-over-Az 계열)를 쓴다.

1.1.2 Cartesian (직교좌표) — 계산하기 좋은 형태

극좌표는 사람이 읽기 좋지만, 회전행렬을 곱하려면 x·y·z 세 성분으로 풀어써야 한다. 그래서 계산의 첫 단계는 항상 극좌표 → 직교좌표다.

1
2
3
4
5
6
7
8
x = R × cos(El) × cos(Az)      ← 보어사이트 방향 성분
y = R × cos(El) × sin(Az)      ← 오른쪽 방향 성분
z = −R × sin(El)               ← 아래 방향 성분 (위로 향하면 음수)

역변환:
R  = √(x² + y² + z²)
Az = atan2(y, x)
El = atan2(−z, √(x² + y²))

예제 값을 넣으면:

1
2
3
x = 20000 × 1 × cos30° = +17 320.5081 m
y = 20000 × 1 × sin30° = +10 000.0000 m
z = −20000 × sin0°     =        0.0000 m

atan2 이고 왜 asin 이 아닌가 역변환에서 El = asin(−z/R) 로 써도 수학적으로는 맞다. 하지만 두 가지 실용적인 문제가 있다. 첫째, 반올림 때문에 인자가 1.0000000000000002 가 되면 asinNaN(Not a Number)을 내놓고, NaN 은 아무 경고 없이 뒤 계산 전체로 번진다. 둘째, 인자가 ±1에 가까울수록(고각이 ±90°에 가까울수록) asin 의 정밀도가 급격히 나빠진다. atan2(분자, 분모) 형태는 두 문제가 모두 없다. 3절 구현도 atan2 를 쓴다.

1.1.3 UV (방향코사인 / 사인공간) — 위상배열이 실제로 다루는 형태

UV 좌표는 표적 방향을 안테나 면에 드리운 그림자로 표현한 것이다.

표적 방향을 가리키는 화살표를 길이 1로 줄인 다음, 그 화살표가 안테나 면 위에 만드는 그림자의 가로 위치가 u, 세로 위치가 v 다. 남은 성분 w 는 보어사이트 방향이다.

1
2
3
4
5
6
u = cos(El) × sin(Az)     ← 안테나 면의 가로(오른쪽) 성분
v = sin(El)               ← 안테나 면의 세로(위)    성분
w = cos(El) × cos(Az)     ← 보어사이트 성분

항상 성립:  u² + v² + w² = 1
가시영역 :  u² + v² ≤ 1   ← 원판 밖은 전파가 나가지 않는 영역

예제 값(Az 30°, El 0°)이면 u = 0.5, v = 0, w = 0.866 이다.

UV 가시영역과 예제 표적의 UV 위치

그림 1-2. UV 는 반지름 1 인 원판 안의 좌표다. 원판 밖은 전파가 나가지 않는 영역이다.

UV를 쓰는 이유 — 위상배열의 사정

현대 레이다는 대부분 위상배열(phased array) 안테나다. 접시가 돌아가는 대신, 안테나 면에 붙은 수백~수천 개의 작은 소자에 신호를 아주 조금씩 시간차를 두고 보내서 빔 방향을 전자적으로 바꾼다. 이 시간차(위상차)를 얼마로 줘야 하는가가 핵심 계산인데,

  • 각도(Az, El) 로는 이 관계가 복잡하다.
  • u, v 로는 정확히 비례한다. 소자 위치에 u, v를 곱하기만 하면 된다.

빔을 만들고 조향하는 계산이 UV 공간에서 덧셈·곱셈 수준으로 단순해지는 것, 이것이 UV를 쓰는 실질적인 이유다. 조금 더 구체적으로 보면,

1
2
3
4
5
소자 (m, n) 에 주어야 할 위상
    ψ_mn = −k · ( m·d_x·u₀  +  n·d_y·v₀ )
             └ k = 2π/λ (파수),  d_x, d_y = 소자 간격,  (u₀, v₀) = 빔을 보낼 방향

  → 소자 번호에 u₀, v₀ 를 곱하기만 하면 된다. 각도(Az, El) 로는 이렇게 단순해지지 않는다.

그 밖에도 UV 공간에서만 성립하는 편리한 성질이 있다.

  • 빔의 굵기가 조향각과 무관하게 일정하다. 각도 공간에서는 옆으로 조향할수록 빔이 굵어지고 이득이 떨어진다(배율 1/cos θ, 60°에서 2배·3 dB 손실). 고정형 다면 배열에서 면 하나가 담당할 각도 범위를 정하는 근거가 이 숫자다.
  • 격자로브(grating lobe) 위치가 u₀ ± λ/d 로 단순하게 나온다. 격자로브란 원하지 않는 방향으로 생기는 두 번째 빔이고, 소자 간격 d 가 넓으면 가시영역 안으로 들어와 엉뚱한 방향의 표적을 잡는다. 이를 막는 조건도 UV 로 쓰면 d/λ ≤ 1/(1 + |u|_max) 한 줄이다.
  • 각도 오차를 추정하는 모노펄스 계산이 u, v 에 대해 선형이다.
세 표현의 역할 정리
표현쓰이는 곳형태
Polar신호처리 출력, 운용자 화면, 외부 인터페이스R, Az, El
Cartesian좌표변환 계산 (회전행렬을 곱하는 곳)x, y, z
UV빔 조향·빔 형성, 배열 내부 계산u, v (+ w)

이 설계에서는 신호처리가 Polar로 값을 넘겨주고(④), 데이터처리는 이를 Cartesian으로 바꿔서 변환 체인을 태운다. UV는 안테나 내부(빔 제어)에서 쓰이므로 데이터처리 체인에는 직접 등장하지 않는다. 다만 개념을 확인할 수 있도록 3절 구현에 함수와 시험을 포함했다.


1.2 동체(Body/Platform) 좌표계

배에 실린 모든 장비의 공통 기준이다. 안테나도, 항법장치도, 무장도 결국 여기로 모인다.

질문
① 원점배의 무게중심(또는 도면상 정해진 기준점)
② 축x = 선수(앞)   y = 우현(오른쪽)   z = 아래
③ 붙은 곳배 (배와 함께 움직이고 함께 기운다)

축 배치의 머리글자를 따서 FRD(Forward-Right-Down)라고 부른다.

동체 좌표계 FRD 와 자세각 세 가지

그림 1-3. 동체 좌표계의 축과 roll·pitch·yaw. z축은 지면 속으로 들어간다.

자세각 세 가지

동체 좌표계가 로컬 좌표계(1.4)에 대해 얼마나 돌아가 있는지를 나타내는 값이다.

이름기호부호
rollφ좌우로 기우뚱 (횡동요)우현이 내려가면 +
pitchθ앞뒤로 끄덕 (종동요)선수가 들리면 +
yawψ선수가 어느 방위를 향하는가 (heading)진북에서 시계방향 +

세 회전을 합치는 순서는 3-2-1(yaw → pitch → roll)이 표준이다.

1
C_ned_from_body = Rz(yaw) · Ry(pitch) · Rx(roll)

순서가 왜 중요한가 회전은 곱셈 순서를 바꾸면 결과가 달라진다. 책상 위 책을 “옆으로 90도 돌린 뒤 세우기”와 “세운 뒤 옆으로 90도 돌리기”는 다른 자세가 된다. 그래서 순서를 문서로 고정해야 한다.

안테나 설치와 레버암

고정형 안테나는 배에 볼트로 고정되어 있으므로 안테나 ↔ 동체 관계가 항상 같다. 즉 그 회전행렬은 설치 도면이 정하는 상수다.

1
2
C_body_from_antenna = Rz(설치 방위) · Ry(백틸트)
p_body = C_body_from_antenna × p_antenna + 레버암
  • 설치 방위: 선수 기준으로 안테나가 몇 도 돌아가 있는가 (예제에서는 90°)
  • 백틸트: 안테나 면을 뒤로 젖혀 보어사이트를 위로 들어올린 각 (예제에서는 0°)
  • 레버암: 무게중심에서 안테나까지의 위치 차이 (예제에서는 30 m 뒤, 10 m 위)

다른 관습과 충돌 주의 항공·항법 분야는 FRD(앞-오른쪽-아래)를 쓰지만, 로보틱스(ROS 등)는 FLU(앞-왼쪽-위)를 쓴다. 같은 roll 값이 정반대 방향을 뜻하고 yaw 부호도 뒤집힌다. 외부 시뮬레이터나 시각화 도구를 붙일 때 가장 자주 사고가 나는 경계이므로, 변환 어댑터를 한 군데로 모아두는 것이 좋다.


1.3 INS 좌표계

INS(Inertial Navigation System, 관성항법장치) 는 자이로와 가속도계로 배의 위치·속도·자세를 스스로 계산해 내는 장비다. 좌표변환 관점에서 INS는 회전과 평행이동에 필요한 값을 공급해 주는 곳이다.

INS는 무엇을 재는가

INS 안에는 두 종류의 센서가 각각 3개씩 들어 있다. 둘 다 자기 자신에게 일어나는 일만 잰다.

센서재는 것여기서 얻는 것
자이로(gyroscope) × 3각속도 — 초당 몇 도씩 돌고 있는가시간에 대해 적분하면 자세(roll·pitch·yaw)
가속도계(accelerometer) × 3비력(specific force) — 중력을 뺀 나머지 가속도두 번 적분하면 속도위치

핵심은 INS가 바깥 세상을 전혀 보지 않는다는 점이다. GPS처럼 위성 신호를 받지도 않고 지형을 관측하지도 않는다. 출발할 때의 위치·자세를 알려주면, 그 뒤로는 자기가 느낀 각속도와 가속도만 계속 더해서 “지금 어디 있고 어느 쪽을 보고 있는지”를 추측해 나간다.

그래서 두 가지 성질이 따라온다.

  • 장점: 외부 신호가 필요 없다. 전파방해를 받지 않고, 갱신 속도가 매우 빠르다(보통 100 Hz 이상).
  • 단점: 오차가 시간이 갈수록 쌓인다. 자이로의 미세한 편향(bias)이 적분되어 자세 오차가 되고, 그 자세 오차가 다시 가속도 성분을 잘못 나누어 위치 오차를 키운다. 그래서 실제 시스템은 GPS 같은 외부 기준과 결합(GPS/INS 통합)해 이 누적을 잡아 준다.

초기 정렬(initial alignment)이 필요한 이유 INS는 “출발점”을 스스로 알 수 없다. 그래서 출항 전에 가만히 세워 두고 중력 방향으로 수평을 잡고(leveling), 지구 자전 방향을 감지해 북쪽을 찾는(gyrocompassing) 절차를 거친다. 이 정렬이 끝나야 자세 출력이 의미를 갖는다. 정렬이 부정확하면 그 오차가 그대로 좌표변환 3단계에 실린다.

스트랩다운과 짐벌형

INS에는 역사적으로 두 방식이 있고, 이 차이가 “플랫폼 좌표계”라는 말의 의미를 갈라놓는다.

스트랩다운 INS와 짐벌형 INS

그림 1-7. 짐벌형은 수평 플랫폼이 물리적으로 존재하고, 스트랩다운은 계산상으로만 존재한다.

 짐벌형 (gimbaled)스트랩다운 (strapdown)
구조센서가 짐벌 위에 얹혀 있고, 모터가 짐벌을 돌려 늘 수평을 유지한다센서가 동체에 직접 볼트로 고정되어 배와 함께 기운다
수평 유지기계가 물리적으로 한다계산이 한다 (DCM 또는 쿼터니언을 계속 갱신)
“플랫폼 좌표계”실제로 존재하는 물리적 프레임소프트웨어 안의 상태값일 뿐
특징정밀하지만 크고 무겁고 비싸다작고 튼튼하며 저렴하다. 현대 함정 INS는 사실상 전부 이쪽

문서에서 “플랫폼 좌표계”라는 말을 볼 때 그것이 물리적 장치를 가리키는지 소프트웨어 상태를 가리키는지 확인해야 한다. 스트랩다운에서는 후자다.

“INS 좌표계”는 사실 하나가 아니다

INS 문헌에는 네 개의 프레임이 함께 나온다. INS는 이 넷의 관계를 계속 유지하는 장치다.

기호이름INS에서의 역할
i관성 프레임 (ECI)자이로·가속도계가 실제로 감지하는 기준. 뉴턴 법칙이 그대로 성립하는 곳
e지구고정 (ECEF)위치를 저장하고 GNSS(GPS)와 맞춰보는 기준
n항법 프레임 (NED)속도와 자세를 출력하는 기준
b센서 프레임 (Body)원측정값(각속도·가속도)이 나오는 프레임

즉 좁은 의미의 “INS 좌표계”는 b 프레임 — INS 안의 자이로·가속도계 3축이 실제로 향하는 방향이다.

왜 동체 좌표계와 따로 구분하는가

이상적으로는 INS의 센서 축과 배의 동체 축이 딱 맞아야 하지만, 실제로는

  • 설치 오차: 장착할 때 아주 미세하게 어긋난다 (보통 수 mrad = 수천분의 몇 라디안)
  • 선체 변형: 큰 배는 파도·하중·온도에 따라 선체가 휜다. INS 위치와 안테나 위치의 상대 자세가 시간에 따라 변한다
  • 위치 차이: INS가 무게중심에 있지 않으면 그만큼의 레버암이 또 생긴다

이 어긋남을 보정하는 절차를 정렬(alignment) 이라고 한다.

오차 감각 잡기 1 mrad은 약 0.0573°다. 거리 × 0.001 이 그대로 옆방향 오차가 된다. 10 km → 10 m, 100 km → 100 m, 300 km → 300 m. 즉 “1도도 안 되는 아주 작은 각”이 먼 거리에서는 큰 위치 오차가 된다.

이 상황에서는

INS가 플랫폼 무게중심과 축이 일치하게 설치되어 있다면?

이 조건 덕분에 위의 복잡한 이야기가 전부 사라진다.

1
INS 좌표계  =  동체(Body) 좌표계        (설치 오차 0, 레버암 0)

따라서 이번 설계에서는 INS 좌표계를 독립된 변환 단계로 두지 않는다. INS는 좌표계가 아니라 값의 공급원 역할만 한다.

INS가 주는 값어디에 쓰이는가
roll, pitch, yaw3단계 회전행렬 C_ned_from_body
위도, 경도, 고도4단계 로컬→ECEF 회전과 평행이동
(속도)표적 추적 필터·도플러 보정 (이 글의 범위 밖)

실무에서 확인해야 할 것 INS가 주는 heading이 진북 기준인지 자북·격자북 기준인지, 고도가 타원체고인지 해발고도인지, 자세 데이터에 유효시각(언제 측정한 값인가) 이 붙어 있는지. 셋 다 좌표변환 결과를 통째로 틀리게 만들 수 있다.


1.4 NED, ENU 좌표계

배가 지금 떠 있는 바다 위 한 지점에서 북쪽·동쪽 방향을 축으로 삼은 좌표계다. “로컬 좌표계” 또는 “국지수평 좌표계”라고 부르는 것이 보통 이것이다.

질문
① 원점배의 현재 위치 (또는 지정한 고정 기준점)
② 축NED: N=북, E=동, D=아래  /  ENU: E=동, N=북, U=위
③ 붙은 곳바다 위의 한 지점 — 배와 함께 이동하지만 함께 회전하지는 않는다

③번이 이 좌표계의 존재 이유다. 배가 아무리 흔들려도 북쪽은 계속 북쪽이다.

NED와 ENU의 차이

두 좌표계는 같은 개념의 축 순서·부호만 다른 형제다.

 첫째 축둘째 축셋째 축주로 쓰는 분야
NED북 (N)동 (E)아래 (D)항공우주·항법·무기체계
ENU동 (E)북 (N) (U)측지·측량·GIS·로보틱스

NED 와 ENU 축 비교

그림 1-4. 두 좌표계는 같은 정보를 담는다. 축 순서와 z 부호만 다르다.

1
2
NED 값이 (N, E, D) 일 때  →  ENU 값은 (E, N, −D)
ENU 값이 (E, N, U) 일 때  →  NED 값은 (N, E, −U)

NED를 쓰는 이유: 동체 좌표계(FRD: 앞-오른쪽-아래)와 축의 의미가 맞아떨어져서 자세 회전행렬이 자연스럽게 연결된다. 이번 설계도 NED를 쓴다. ENU를 쓰는 이유: 고도가 +z라 사람이 읽기 직관적이다. 지도·측량 쪽 데이터와 붙일 때 편하다.

어느 쪽이든 하나로 통일하는 것이 중요하다. 섞이면 남북이 뒤집히거나 고도 부호가 반대가 된다.

“아래”의 정확한 의미

D축(아래)은 지구 중심 방향이 아니다. 지구는 완전한 구가 아니라 적도 쪽이 부푼 타원체라서, 지표면에 세운 수직선(법선)은 지구 중심을 지나지 않는다.

1
2
3
4
5
6
7
8
       북극
        │
        │      ● 내가 서 있는 지점 P
        │     ↙ 법선 방향(= 진짜 '아래'의 반대)
        │   ↙
        ●───────────  적도
      지구중심
              ↖ 지구 중심 방향 (P에서 보면 법선과 살짝 다르다)

두 방향의 차이는 위도 45° 부근에서 최대 약 0.19° 다. 작아 보이지만 이는 지표에서 약 21 km에 해당하는 각도이므로, 구형 지구로 근사한 코드에 측지 위도를 그대로 넣으면 그만큼의 계통 오차가 전 체인에 실린다.

로컬 평면의 한계 — 지구는 둥글다

로컬 좌표계는 평평한 판이다. 원점 근처에서는 문제가 없지만, 멀어질수록 실제 지구 표면이 그 판 아래로 휘어 내려간다.

원점에서의 거리지구 표면이 평면보다 내려간 양
5 km약 2 m
10 km약 8 m
20 km약 31 m
50 km약 196 m
100 km약 783 m

(3절에서 실제로 확인한다. 20 km 표적의 고도가 로컬 평면 기준 10 m인데 측지 고도로는 41.5 m가 나오는 이유가 바로 이 31.5 m다.)


1.5 ECEF 좌표계, ECI 좌표계

여기서부터는 지구 전체를 다루는 좌표계다. 원점이 지구 중심으로 옮겨간다.

1.5.1 ECEF — Earth-Centered, Earth-Fixed (지구중심 지구고정)

질문
① 원점지구의 질량중심
② 축Z = 북극 방향   X = 적도면과 그리니치 자오선이 만나는 방향   Y = 오른손계를 완성하는 방향
③ 붙은 곳지구 — 지구와 함께 하루 한 바퀴 자전한다
1
2
3
4
5
6
7
8
9
        Z (북극)
        │
        │      ● 어떤 지점
        │    /
        │  /
        ●────────── Y (동경 90°)
       /
     /
   X (적도 ∩ 그리니치 자오선, 즉 경도 0°)

왜 필요한가. 로컬 좌표계에서 위경도로 곧장 넘어갈 수는 없다. 로컬 좌표계의 원점(배의 위치)이 지구 어디인지는 지구 기준 좌표로만 표현되기 때문이다. ECEF는 그 다리 역할을 한다. 또 여러 배·여러 레이다의 결과를 합칠 때 서로 자세가 다르니 공통 언어가 필요한데, ECEF가 그 역할을 한다.

특징. 미터 단위의 평범한 직교좌표라서 더하기·빼기가 그냥 된다. 다만 값이 600만 m 규모라 소수점 아래를 다루기엔 정밀도 여유가 적다. (가까운 두 점의 상대 위치는 ECEF가 아니라 로컬 좌표계에서 계산해야 한다.)

실현. 실제로 쓰는 ECEF는 WGS-84라는 국제 표준으로 정의되어 있고, GPS가 방송하는 좌표도 이것이다.

1.5.2 ECI — Earth-Centered Inertial (지구중심 관성)

질문
① 원점지구의 질량중심 (ECEF와 같다)
② 축특정 시각(보통 J2000.0)의 별자리 방향에 고정
③ 붙은 곳아무것도 아님 — 지구가 돌아도 축은 그대로 있다

ECEF와 원점은 같고 축이 도느냐 안 도느냐만 다르다.

ECEF 와 ECI 의 차이

그림 1-5. 원점은 같고 축이 도느냐 마느냐만 다르다.

1
2
ECEF :  지구와 함께 돈다   →  지상의 건물은 좌표가 안 변한다
ECI  :  돌지 않는다        →  지상의 건물은 좌표가 하루 한 바퀴 원을 그린다

왜 이런 게 필요한가. 물리 법칙 때문이다. 뉴턴의 운동법칙(F = ma)은 회전하지 않는 좌표계에서만 그대로 성립한다. 회전하는 좌표계에서 물체의 운동을 계산하려면 원심력·코리올리력 같은 실제로 존재하지 않는 가짜 힘을 추가로 넣어야 한다.

그래서 중력만 받고 날아가는 물체 — 인공위성, 탄도미사일 — 를 계산할 때는 ECI를 쓴다. ECI에서는 중력 하나만 넣으면 되지만, ECEF에서는 가짜 힘들을 전부 모델링해야 한다. (참고로 INS 내부 계산도 ECI를 기준으로 출발한다. 1.3의 i 프레임이 이것이다.)

ECEF ↔ ECI 변환. 지구 자전만 고려하면 z축 둘레 회전 하나로 끝난다.

1
2
p_ECI  = Rz(θ)  × p_ECEF        θ = 그리니치 항성시(GMST), 시각으로 계산
p_ECEF = Rz(θ)ᵀ × p_ECI

정밀도가 더 필요하면 세차·장동(지구 자전축이 천천히 흔들리는 현상)과 극운동까지 넣어야 하지만, 입문 단계에서는 “시각을 알면 각도가 나오고, 그 각도만큼 z축 둘레로 돌리면 된다“로 충분하다.

시각 정밀도 감각 지구는 적도에서 초속 약 465 m로 돈다. 즉 시각이 1 ms 어긋나면 적도에서 위치가 약 0.47 m 어긋난다. 여러 센서의 결과를 합칠 때 시각 동기가 왜 중요한지 보여주는 숫자다.

1.5.3 이 설계에 ECI가 필요한가

필요 없다. 여기서 다루는 표적은 항공기/수상함 수준이고, 결과를 지구 기준 위경도로 내면 된다. ECI는 표적을 관성 동역학으로 전파해야 할 때(탄도탄 방어, 위성 추적) 필요하다. 다만 개념 확인을 위해 3절 구현에 ECEF ↔ ECI 함수를 포함해 동작을 확인했다.


1.6 LLA 좌표계

우리가 아는 그 지도 좌표다. Latitude(위도) · Longitude(경도) · Altitude(고도).

질문
① 원점(직교좌표가 아니라 각도 좌표라 원점 개념이 다르다) 기준은 적도면그리니치 자오선
② 축위도 = 적도에서 남북으로 잰 각 / 경도 = 그리니치에서 동서로 잰 각 / 고도 = 타원체 표면에서 잰 높이
③ 붙은 곳지구

지구는 구가 아니라 타원체다

정확한 위경도를 다루려면 지구를 어떤 모양으로 볼 것인가를 먼저 정해야 한다. 그 표준이 WGS-84이고, GPS와 해도가 쓰는 것도 이것이다.

상수의미
a (장반경)6 378 137.0 m적도 방향 반지름
1/f (편평률의 역수)298.257223563얼마나 납작한가
b (단반경)6 356 752.314245 m극 방향 반지름 (계산으로 나옴)
e² (제1이심률 제곱)0.00669437999014타원 공식에 계속 등장

적도 반지름과 극 반지름의 차이가 약 21 km다. 지구 크기에 비하면 0.3 % 정도지만, 이걸 무시하고 구로 계산하면 위치 오차가 수십 km까지 벌어진다.

지구 타원체, 측지위도와 지심위도, 고도의 두 기준

그림 1-6. 타원체 법선은 지구 중심을 지나지 않는다. 그래서 측지위도와 지심위도가 다르고, 고도의 기준도 타원체(LLA)와 지오이드(해발)로 갈린다.

LLA ↔ ECEF 변환

LLA → ECEF (한 번에 계산됨)

1
2
3
4
N = a / √(1 − e²·sin²(위도))        ← 그 위도에서의 곡률반경
x = (N + 고도) × cos(위도) × cos(경도)
y = (N + 고도) × cos(위도) × sin(경도)
z = (N·(1 − e²) + 고도) × sin(위도)   ← (1 − e²) 빼먹는 실수가 가장 흔하다

ECEF → LLA (반복이 필요하다)

이 방향은 딱 떨어지는 공식이 없다. 위도를 알아야 N을 구하는데, N을 알아야 위도를 구할 수 있는 닭-달걀 관계이기 때문이다. 그래서 Bowring 공식으로 좋은 초기값을 잡고, 필요하면 몇 번 다듬는다.

1
2
3
4
5
ρ     = √(x² + y²)
경도  = atan2(y, x)
θ     = atan2(z·a, ρ·b)
위도  = atan2( z + e'²·b·sin³θ ,  ρ − e²·a·cos³θ )      ← Bowring 초기값
고도  = ρ·cos(위도) + (z + e²·N·sin(위도))·sin(위도) − N

3절 구현은 여기에 개선 반복 2회를 더해 고고도 표적까지 기계정밀도로 수렴하게 했다.

고도의 함정 — 타원체고 vs 해발고도

LLA의 “고도”는 타원체 표면에서 잰 높이(타원체고, HAE)다. 그런데 해도나 고도계가 말하는 “고도”는 보통 평균해면 기준 높이(해발고도, MSL)다.

1
해발고도  =  타원체고  −  지오이드고

지오이드란 “바다가 육지 안까지 이어져 있다면 만들어질 평균 해수면”이다. 중력이 균일하지 않아서 이 면은 타원체와 일치하지 않고, 전 지구적으로 약 −107 m ~ +86 m 차이가 난다. 한국 근해에서는 대략 +20 ~ +25 m 다.

여기에 항공기가 쓰는 기압고도까지 끼어들면 기준이 셋이 된다. 시스템 내부에서는 한 가지로 통일하고, 표시할 때만 변환하는 것이 안전하다. 이번 설계는 내부적으로 타원체고를 쓴다.


1.7 한눈에 보는 정리

#좌표계원점붙은 곳주 용도
1.1안테나안테나 면 중심x=보어사이트, y=오른쪽, z=아래표적 측정 (R, Az, El) / 빔 조향 (u, v)
1.2동체(Body)배 무게중심x=선수, y=우현, z=아래탑재 장비의 공통 기준
1.3INSINS 설치 위치자이로·가속도계 3축위치·자세·속도 공급
1.4NED / ENU배의 현재 위치N,E,D / E,N,U바다 위 지점 (회전 안 함)데이터 처리(추적·필터링)
1.5ECEF지구 중심Z=북극, X=적도∩그리니치지구 (자전함)지구 기준 공통 좌표, 위경도로 가는 다리
1.5ECI지구 중심별자리에 고정없음 (회전 안 함)위성·탄도 표적의 운동 계산
1.6LLA(적도면 / 그리니치)위도·경도·고도지구지도 표시, 외부 전달

변환 체인 한 장 요약

좌표변환 체인 전체도

그림 1-8. 각 단계의 회전과 평행이동을 무엇이 공급하는지가 오차 예산의 항목이 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 신호처리
    │  R, Az, El  (안테나 극좌표)
    ▼
[1.1] 안테나 좌표계  ── 극좌표 → 직교좌표
    │  회전: C_body_from_antenna (설치 도면, 상수)
    │  이동: 레버암
    ▼
[1.2] 동체 좌표계
    │  회전: C_ned_from_body (INS 자세 — roll, pitch, yaw)     ← [1.3] INS가 공급
    ▼
[1.4] 로컬(NED) 좌표계  ── ★ 데이터 처리를 여기서 수행
    │  회전: C_ecef_from_ned (INS 위치 — 위도, 경도)           ← [1.3] INS가 공급
    │  이동: 배의 ECEF 위치
    ▼
[1.5] ECEF 좌표계
    │  Bowring 공식
    ▼
[1.6] LLA 좌표계  ── 전시기·통제제어로 전달

2. 실전 설계 — 함선 고정형 레이다

좌표계를 하나씩 봤으니 이제 실제 시스템을 하나 놓고 설계해 보자. 신호처리가 넘겨준 측정값을 받아 데이터 처리를 거쳐 운용 전시기까지 보내는 경로다.

2.1 상황

  • 플랫폼 — 해상을 달리는 함선. 레이다는 고정형 안테나(기계적으로 돌지 않는다)
  • 안테나 설치 — 선수 기준 시계방향 90도를 바라보고, 무게중심에서 30 m 뒤 / 10 m 위
  • INS 설치 — 플랫폼 무게중심과 축이 일치
  • 입력 — 신호처리가 주는 값은 안테나 기준 거리·방위각·고각
  • 처리 — 데이터 처리는 로컬 좌표계에서 수행
  • 출력 — 결과를 위/경/고도안테나 극좌표(극좌표) 두 가지로 통제제어에 전달

2.1.1 각 조건이 설계를 어떻게 묶는가

조건내용설계에 미치는 영향
① 플랫폼해상 함선, 고정형 안테나안테나가 기계적으로 돌지 않는다 → 안테나↔동체 회전행렬이 상수. 대신 배가 흔들리는 것을 전부 계산으로 보상해야 한다
② 안테나 설치선수 기준 시계방향 90°, 무게중심에서 30 m 뒤 / 10 m 위설치 방위 = 90°, 백틸트 = 0°, 레버암 = (−30, 0, −10) m
③ INS 설치무게중심과 축 일치INS 좌표계 = 동체 좌표계 → 변환 단계 하나가 통째로 생략된다
④ 입력안테나 기준 거리·방위각·고각체인의 출발점이 안테나 극좌표로 확정
⑤ 처리로컬 좌표계에서 수행체인의 중간 목적지가 NED로 확정
⑥ 출력위/경/고도 + 안테나 극좌표정변환뿐 아니라 역변환도 필요하다

즉 ④·⑤·⑥ 이 체인의 출발점·중간점·도착점을 이미 지정하고 있다. 설계자가 결정할 것은 그 사이를 어떤 좌표계로 어떻게 이을 것인가다.

2.1.2 전체 데이터 흐름

1
2
3
4
5
6
7
8
9
┌──────────┐   R, Az, El     ┌────────────────────────┐   위/경/고도   ┌────────────┐
│  신호처리  │ ─────────────> │       데이터 처리        │ ────────────> │  통제제어   │
│          │  (안테나 극좌표)  │  (좌표변환 + 추적·필터링)  │   R, Az, El   │   전시기    │
└──────────┘                 └────────────────────────┘ ────────────> └────────────┘
                                     ▲
                                     │  위도·경도·고도, roll·pitch·yaw
                                ┌─────────┐
                                │   INS    │
                                └─────────┘

데이터 처리 내부는 다시 세 부분으로 나뉜다.

1
2
3
4
 [입력 변환]  안테나 극좌표 ──> 로컬(NED)        ... 2.1.4의 1~3단계
 [처리]       로컬 좌표계에서 추적·필터링         ... ⑤
 [출력 변환]  로컬 ──> 위/경/고도  (정변환)       ... 2.1.4의 4~5단계
              로컬 ──> 안테나 극좌표 (역변환)     ... 2.1.5

2.1.3 단계별 좌표계 선정과 그 이유

단계선정한 좌표계표현선정 이유
0안테나 좌표계 — 극좌표(Polar)R, Az, El④. 레이다가 물리적으로 잴 수 있는 것이 거리와 두 각도뿐이므로 원측정값은 필연적으로 극좌표다
1안테나 좌표계 — 직교좌표(Cartesian)x, y, z회전행렬을 곱하려면 벡터 형태여야 한다. 극좌표끼리는 회전을 합성할 수 없다
2동체(Body) 좌표계x, y, z안테나·INS·무장이 만나는 유일한 공통 기준. 안테나는 배에 붙어 있으므로 배를 거치지 않고 바깥 세상으로 나갈 방법이 없다. 또 여러 안테나·센서를 붙일 때 이 단계가 확장점이 된다
3로컬(NED) 좌표계N, E, D⑤. 배가 흔들려도 이 좌표계는 흔들리지 않는다. 표적이 실제로 움직인 것과 배가 흔들린 것을 구분할 수 있어야 추적 필터가 성립한다. ENU가 아니라 NED를 고른 것은 동체 FRD와 축 의미가 맞아 자세 회전이 자연스럽게 연결되기 때문
4ECEF 좌표계X, Y, Z로컬 좌표계에서 위경도로 곧장 갈 수 없다. 로컬 원점(배 위치)이 지구 어디인지는 지구 기준 좌표로만 표현되므로, 지구중심 직교좌표를 다리로 삼는다
5LLA 좌표계위도, 경도, 고도⑥. 전시기·통제제어가 지도 위에 표시하는 형식
안테나 좌표계 — 극좌표R, Az, El⑥의 두 번째 출력. 처리 결과를 운용자가 안테나 기준으로 확인할 수 있어야 한다
선정하지 않은 좌표계와 그 이유
좌표계왜 쓰지 않는가
INS 좌표계 (별도 단계로)③에 의해 동체 좌표계와 일치. 별도 변환 단계를 두면 항등행렬을 곱하는 셈이라 계산만 늘고 오류 가능성만 커진다. INS는 좌표계가 아니라 값의 공급원으로 설계에 반영한다
UV 좌표계빔 조향·빔 형성은 안테나 내부(신호처리 이전)의 일이다. 데이터 처리 체인에 등장할 필요가 없다. 다만 신호처리 인터페이스가 UV로 넘어올 경우를 대비해 변환 함수는 구현해 둔다
ECI 좌표계표적을 관성 동역학으로 전파할 때 필요하다(위성·탄도탄). 이 설계는 지구 기준 위치 산출이 목적이므로 불필요
ENU 좌표계NED와 정보량이 같다. 둘 다 쓰면 축 순서·부호 혼동만 생기므로 하나로 통일한다

2.1.4 단계별 좌표변환 과정

각 단계에서 무엇이 회전을 공급하고, 무엇이 평행이동을 공급하는지를 함께 적는다.


1단계 — 안테나 극좌표 → 안테나 직교좌표

변환 종류: 표현 변경 (회전·이동 없음)

1
2
3
x_a = R × cos(El) × cos(Az)
y_a = R × cos(El) × sin(Az)
z_a = −R × sin(El)

이유: 회전행렬은 벡터에만 곱할 수 있다. 각도로 표현된 방향을 세 성분으로 풀어쓰는 준비 단계다.


2단계 — 안테나 좌표계 → 동체 좌표계

변환 종류: 회전 + 평행이동

1
2
3
4
5
6
7
8
C_body_from_antenna = Rz(ψ_mount) · Ry(θ_mount)
p_body = C_body_from_antenna × p_antenna + r_lever

  ψ_mount = 90°           (조건2: 선수 기준 시계방향 90도)
  θ_mount = 0°            (조건2에 백틸트 언급 없음)
  r_lever = (−30, 0, −10) m
            └ x = −30 : 30 m 뒤 (동체 x축은 앞이 +)
              z = −10 : 10 m 위 (동체 z축은 아래가 +)

회전의 공급원: 설치 도면 (고정형이므로 상수, 조건1·2) 평행이동의 공급원: 설치 도면 (레버암, 조건2)

왜 레버암을 반영해야 하는가: 20 km 표적에 30 m는 무시해도 될 것 같지만, 이 오차는 거리가 멀어져도 줄지 않는다. 근거리 표적이나 정밀 사격통제에서 그대로 문제가 되고, 안테나가 여러 개일 때는 안테나마다 다른 레버암 때문에 같은 표적의 트랙이 갈라진다. (3.2절에서 30 m 어긋남을 실제로 확인한다.)


3단계 — 동체 좌표계 → 로컬(NED) 좌표계

변환 종류: 회전만 (원점을 배 위치에 두므로 이동 없음)

1
2
C_ned_from_body = Rz(yaw) · Ry(pitch) · Rx(roll)
p_ned = C_ned_from_body × p_body

회전의 공급원: INS의 자세각 (조건3에 의해 INS 좌표계 = 동체 좌표계)

이 단계가 설계의 핵심인 이유: 고정형 안테나(①)이기 때문에, 배의 흔들림을 보상할 기계적 수단이 없다. 전부 이 회전행렬이 감당한다. 따라서 이 단계의 정확도가 시스템 전체의 지향 정확도를 결정한다.

예제 배치도 — 방위각이 더해지는 관계

그림 2-1. 배가 기울지 않았을 때는 세 각도가 그대로 더해진다: 45° + 90° + 30° = 165°.

왜 각도 덧셈으로는 안 되는가 배가 기울지 않았다면 진북 기준 방위 = yaw + 설치방위 + Az 로 간단히 더해진다 (45° + 90° + 30° = 165°). 그러나 roll이나 pitch가 조금이라도 있으면 이 덧셈은 즉시 깨진다. 세 축의 회전이 서로 섞이기 때문이다. 3.2절에서 roll 20°만으로 고각이 0°에서 −17°로 바뀌는 것을 확인한다. 해상 플랫폼에서 회전행렬은 선택이 아니라 필수다.

이 단계에서 반드시 챙겨야 할 것 — 자세 데이터의 시각

회전행렬을 정확히 만들어도, 언제 측정한 자세인가가 틀리면 소용이 없다. 배는 파도에 계속 흔들리고 있으므로 자세는 매 순간 변한다.

1
2
3
4
5
함정 횡동요 각속도 10°/s 일 때 지연에 따른 지향 오차

    지연  2 ms  →  0.020°  (0.35 mrad)
    지연 10 ms  →  0.100°  (1.75 mrad)     ← 20 km 에서 약 35 m
    지연 50 ms  →  0.500°  (8.73 mrad)     ← 20 km 에서 약 175 m

이 값은 대개 INS 자체의 자세 정확도보다 크다. 즉 좋은 INS를 쓰고도 시각 처리를 잘못하면 그 성능을 그대로 버리는 셈이다. 설계에서 챙길 것은 세 가지다.

  1. INS가 보내는 자세에 유효시각(언제 측정한 값인가) 타임스탬프를 함께 받는다.
  2. 각속도를 이용해 실제 측정이 일어난 시각으로 자세를 외삽한다.
  3. 레이다와 INS를 같은 시각원(PTP/IRIG-B 등)에 물려 시계를 맞춘다.

(뒤에 나오는 예제는 플랫폼이 고정되어 있어 이 문제가 드러나지 않지만, 실제 해상 운용에서는 3단계의 정확도를 좌우하는 가장 큰 요인이다.)


【 데이터 처리 구간 】 조건5

로컬(NED) 좌표계에서 추적·필터링을 수행한다. 이 좌표계를 고른 이유는 위에서 설명한 대로 배의 흔들림과 무관하기 때문이다. 안테나 좌표계에서 추적하면 배가 롤링할 때마다 표적이 좌우로 튀는 것처럼 보여 필터가 발산한다.

(이 글은 변환 검증이 목적이므로 필터를 두지 않고 값을 그대로 통과시킨다. 그 덕분에 역변환 결과가 입력과 정확히 같아야 한다는 강력한 검증 조건이 생긴다.)


4단계 — 로컬(NED) 좌표계 → ECEF 좌표계

변환 종류: 회전 + 평행이동

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
① 배의 위치를 ECEF로 변환 (LLA → ECEF 공식)
   N = a / √(1 − e²·sin²(lat))
   p_ecef_platform = ( (N+h)·cos(lat)·cos(lon),
                       (N+h)·cos(lat)·sin(lon),
                       (N·(1−e²)+h)·sin(lat) )

② 로컬 벡터를 지구 방향으로 회전
                     ⎡ −sin(lat)·cos(lon)  −sin(lat)·sin(lon)   cos(lat) ⎤
   C_ned_from_ecef = ⎢       −sin(lon)            cos(lon)          0     ⎥
                     ⎣ −cos(lat)·cos(lon)  −cos(lat)·sin(lon)  −sin(lat) ⎦

   C_ecef_from_ned = (C_ned_from_ecef)ᵀ

③ 더한다
   p_ecef_target = p_ecef_platform + C_ecef_from_ned × p_ned

회전의 공급원: INS의 위치(위도·경도). 지구 위 어디에 있느냐에 따라 “북쪽”이 지구 기준으로 어느 방향인지가 완전히 달라지기 때문이다. 평행이동의 공급원: 배의 ECEF 위치


5단계 — ECEF 좌표계 → LLA 좌표계

변환 종류: 좌표계 종류 변경 (직교 → 각도)

1
2
3
4
5
6
ρ    = √(x² + y²)
lon  = atan2(y, x)
θ    = atan2(z·a, ρ·b)
lat  = atan2( z + e'²·b·sin³θ ,  ρ − e²·a·cos³θ )        ← Bowring
N    = a / √(1 − e²·sin²(lat))
h    = ρ·cos(lat) + (z + e²·N·sin(lat))·sin(lat) − N

주의점: 여기서 나온 고도는 타원체고다. 전시기가 해발고도를 요구하면 지오이드고를 빼서 변환해야 한다(1.6 참조). 시스템 내부는 타원체고로 통일한다.

2.1.5 출력 2종과 역변환

조건 ⑥ 은 결과를 두 가지 형태로 요구한다.

출력얻는 방법
위/경/고도위의 정변환 1→5단계 결과 그대로
안테나 극좌표처리 결과를 역변환해서 안테나 기준으로 되돌린다

역변환은 새로 배울 것이 없다. 세 가지만 지키면 된다.

1
2
3
① 회전은 전치(transpose)     C_ned_from_body  →  (C_ned_from_body)ᵀ
② 평행이동은 빼기            + 레버암          →  − 레버암
③ 순서는 거꾸로
1
2
3
4
5
6
7
8
표적 LLA
  → ECEF                                    (정변환과 같은 공식)
  → 로컬 NED    C_ned_from_ecef × (표적_ecef − 배_ecef)
  → 동체        (C_ned_from_body)ᵀ × p_ned
  → 안테나      (C_body_from_antenna)ᵀ × (p_body − 레버암)
  → 극좌표      R  = √(x² + y² + z²)
                Az = atan2(y, x)
                El = atan2(−z, √(x² + y²))

역변환이 곧 검증 수단이 된다 필터를 거치지 않았다면 역변환 결과는 입력값과 정확히 같아야 한다. 부호 하나, 전치 방향 하나만 틀려도 이 왕복 시험은 즉시 실패한다. 3절에서 실제로 이것을 첫 번째 단위 시험으로 삼았다. (실제 운용에서는 필터가 값을 다듬으므로 필터가 보정한 만큼만 달라진다. 그 차이가 예상 범위를 벗어나면 필터나 변환 중 하나가 이상하다는 신호다.)

2.1.6 설계 결정 요약

결정 항목선택근거
데이터 처리 좌표계NED (로컬)조건 ⑤ + 배의 흔들림과 무관
로컬 좌표계 종류NED (ENU 아님)동체 FRD와 축 의미 일치 → 자세 회전이 자연스럽게 연결
로컬 원점배의 현재 위치배가 고정되어 있으므로 고정 원점과 동일. 이동 플랫폼이면 원점 갱신 정책 필요
z축 방향아래(Down) 로 전 좌표계 통일섞이면 고도 부호가 뒤집힌다
오일러각 순서3-2-1 (yaw→pitch→roll)항법 분야 표준
고도 기준타원체고(HAE) 내부 통일해발고도는 표시 단계에서만 변환
INS 좌표계 처리별도 단계 없음조건 ③ (무게중심·축 일치)
레버암반영거리와 무관한 계통 오차이므로
각도 역계산atan2 사용 (asin 아님)NaN 방지 + 극단 각도에서의 정밀도
검증 방법왕복 시험 + 행렬 성질 시험부호·전치 오류를 즉시 검출

3. C 로 짜서 확인하기

3.1 구현과 실행

3.1.1 파일 구성과 빌드

1
2
3
4
5
6
code/
├── coord_frames.h    좌표계 타입·상수·API 선언   (180줄)
├── coord_frames.c    변환 구현                    (약 330줄)
├── main.c            예제 입력값 실행 프로그램
├── test_frames.c     단위 시험 (9종 31항목)
└── Makefile          빌드 스크립트
1
2
3
4
make          # 빌드
make run      # 예제 입력값 실행  (./radar_coord)
make test     # 단위 시험 실행    (./test_frames)
make clean    # 산출물 삭제

컴파일 옵션은 아래와 같이 엄격하게 두었고, 경고 0건으로 빌드된다.

1
-std=c99 -Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wstrict-prototypes -O2

-Wconversionintdouble 사이의 암묵적 변환까지 잡아낸다. 좌표변환처럼 실수 계산이 많은 코드에서는 이런 변환 하나가 조용히 정밀도를 깎아먹으므로 켜 두는 편이 좋다.

3.1.2 API 설계 — 초심자를 위한 세 가지 원칙

좌표변환 버그의 특징은 컴파일도 되고 값도 그럴듯해 보인다는 것이다. 그래서 애초에 실수하기 어렵게 만드는 것이 중요하다.

① 함수 이름에 변환 방향을 박아 넣는다
1
2
3
4
5
6
7
/* 나쁜 예 — 방향을 알 수 없다 */
mat3_t get_dcm_bn(double roll, double pitch, double yaw);

/* 좋은 예 — 이름만 봐도 방향이 보인다 */
cf_mat3_t cf_dcm_ned_from_body(const cf_attitude_t *att);
cf_vec3_t cf_ned_from_body(const cf_attitude_t *att, cf_vec3_t p_body);
cf_vec3_t cf_body_from_ned(const cf_attitude_t *att, cf_vec3_t p_ned);
② 좌표계마다 다른 타입을 쓴다

double[3] 이나 void* 로 다니면 NED 벡터를 동체 함수에 넣어도 컴파일러가 잡아주지 못한다.

1
2
3
4
5
typedef struct { double range_m, az_rad, el_rad; } cf_polar_t;     /* 안테나 극좌표 */
typedef struct { double u, v, w; }                 cf_dircos_t;    /* UV            */
typedef struct { double lat_rad, lon_rad, alt_m; } cf_geodetic_t;  /* LLA           */
typedef struct { double roll_rad, pitch_rad, yaw_rad; } cf_attitude_t;
typedef struct { double yaw_rad, pitch_rad; cf_vec3_t lever_arm_b; } cf_mount_t;
③ 변수 이름에 단위를 붙인다

range_m, az_rad, alt_m — 주석은 읽히지 않지만 이름은 읽힌다. 라디안과 도(degree)를 섞는 실수는 좌표변환에서 가장 흔한 버그다.

3.1.3 구현에서 신경 쓴 부분

항목무엇을
asin 대신 atan2El = atan2(−z, √(x²+y²))asin 은 인자가 반올림으로 1을 넘으면 NaN을 내놓고, ±1 근처에서 정밀도가 급격히 떨어진다. atan2 는 두 문제가 모두 없다
Bowring + 개선 반복ECEF→LLA를 Bowring 초기값 + 반복 2회Bowring 1회만으로도 지상~40 km는 충분하지만, 고고도 표적까지 기계정밀도로 수렴시키기 위해 반복을 더했다
극점 분기 처리ρ = √(x²+y²) → 0 이면 별도 처리극점에서는 경도가 정의되지 않고 ρ/cos(위도) 가 0/0 이 된다
고도 계산의 안정형h = ρ·cos(lat) + (z + e²N·sin(lat))·sin(lat) − N교과서 형태 h = ρ/cos(lat) − N 은 고위도에서 1/cos 이 폭발한다. 위 항등식은 극점 포함 전 구간에서 안전하다
널 포인터 방어포인터 인자마다 검사 후 CF_ERR_NULL라이브러리로 쓰일 코드의 기본
상태 코드 반환cf_status_t 열거형실패를 조용히 넘기지 않는다

3.1.4 실행 결과

입력

구분
Slant Range20 km
Azimuth30°
Elevation
플랫폼 위도 / 경도 / 고도36.408° / 127.307° / 0 m
플랫폼 자세 (roll, yaw, pitch)0° / 45° / 0°
안테나 설치선수 기준 시계방향 90°, 30 m 뒤 / 10 m 위

전체 실행 출력 (make run)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
────────────────────────────────────────────────────────────────────
 입력 조건
────────────────────────────────────────────────────────────────────
  신호처리 측정값   R = 20000.0 m,  Az = 30.000 deg,  El = 0.000 deg
  플랫폼 위치       lat = 36.408000 deg,  lon = 127.307000 deg,  alt = 0.000 m
  플랫폼 자세       roll = 0.000,  pitch = 0.000,  yaw = 45.000  [deg]
  안테나 설치       방위 = 90.000 deg,  백틸트 = 0.000 deg
  레버암(FRD)       (-30.0, +0.0, -10.0) m   = 30 m 뒤, 10 m 위

────────────────────────────────────────────────────────────────────
 1단계  안테나 극좌표 → 안테나 직교좌표 / UV
────────────────────────────────────────────────────────────────────
  방향코사인(UV)             u = +0.500000000000  (면 가로·오른쪽)
                             v = +0.000000000000  (면 세로·위)
                             w = +0.866025403784  (보어사이트)
  ‖(u,v,w)‖ − 1              +0.000e+00
  안테나 직교 p_ant            +17320.5081        +10000.0000            -0.0000  [m]
      x = 보어사이트 방향,  y = 오른쪽,  z = 아래

────────────────────────────────────────────────────────────────────
 2단계  안테나 좌표계 → 동체 좌표계  (회전 + 평행이동)
────────────────────────────────────────────────────────────────────
  C_body_from_antenna = Rz(90°)·Ry(0°)
      [  +0.000000000   -1.000000000   +0.000000000 ]
      [  +1.000000000   +0.000000000   +0.000000000 ]
      [  +0.000000000   +0.000000000   +1.000000000 ]
      det = +1.000000000000000,   |A^T·A − I|max = 0.000e+00
  회전만 적용                  -10000.0000        +17320.5081            +0.0000  [m]
  + 레버암 → p_body            -10030.0000        +17320.5081           -10.0000  [m]
      선수 기준 방위 120.074374 deg,  수평거리 20015.0169 m

────────────────────────────────────────────────────────────────────
 3단계  동체 좌표계 → 로컬(NED) 좌표계  (회전)
────────────────────────────────────────────────────────────────────
  C_ned_from_body = Rz(45°)·Ry(0°)·Rx(0°)
      [  +0.707106781   -0.707106781   +0.000000000 ]
      [  +0.707106781   +0.707106781   +0.000000000 ]
      [  +0.000000000   +0.000000000   +1.000000000 ]
      det = +1.000000000000000,   |A^T·A − I|max = 0.000e+00
  p_ned  (N, E, D)                  -19339.7297         +5155.1677           -10.0000  [m]
      진북 기준 방위 165.074374 deg,  수평거리 20015.0169 m,  평면고도 10.0000 m

────────────────────────────────────────────────────────────────────
 4단계  로컬(NED) → ECEF
────────────────────────────────────────────────────────────────────
  C_ned_from_ecef(lat, lon)
      [  +0.359730742   -0.472094436   +0.804810933 ]
      [  -0.795399439   -0.606085581   +0.000000000 ]
      [  +0.487784302   -0.640146165   -0.593531265 ]
      det = +1.000000000000000,   |A^T·A − I|max = 2.220e-16
  플랫폼 ECEF                  -3114830.1107      +4087762.8525      +3764723.0978  [m]
  표적   ECEF                   -3125892.5014      +4093774.9599      +3749164.2072  [m]

────────────────────────────────────────────────────────────────────
 5단계  ECEF → LLA (Bowring)
────────────────────────────────────────────────────────────────────
  표적 위도                  36.233700252 deg
  표적 경도                  127.364344961 deg
  표적 고도(타원체고)        41.4952 m
  로컬 평면 기준 고도        10.0000 m   (차이 31.5 m = 지구 곡률)

────────────────────────────────────────────────────────────────────
 역변환  LLA → ECEF → 로컬 → 동체 → 안테나 극좌표
────────────────────────────────────────────────────────────────────
  시선거리 R                 20000.000000 m
  방위각   Az                30.000000000 deg
  고각     El                0.000000000 deg
  왕복오차                   ΔR = 3.602e-10 m,  ΔAz = 1.520e-12 deg,  ΔEl = 9.432e-13 deg

────────────────────────────────────────────────────────────────────
 최종 출력  —  통제제어 전달 값
────────────────────────────────────────────────────────────────────
  [1] 위/경/고도 좌표계
        위도  36.233700252 deg
        경도  127.364344961 deg
        고도  41.4952 m  (WGS-84 타원체고)
  [2] 안테나 좌표계 (극좌표)
        시선거리  20000.0000 m
        방위각    30.000000 deg
        고각      0.000000 deg

3.1.5 단계별 결과 해설

1단계 결과
1
2
u = +0.500000000000        v = +0.000000000000        w = +0.866025403784
p_ant = ( +17 320.5081,  +10 000.0000,  0.0000 ) m

u = sin(30°) = 0.5 로 딱 떨어지고, ‖(u,v,w)‖ = 1 이 정확히 성립한다. 직교좌표는 20000 × cos30° = 17320.5, 20000 × sin30° = 10000 으로 손으로 검산할 수 있다.

2단계 결과
1
2
3
회전만   : ( −10 000.0000,  +17 320.5081,  0.0000 )   ← 두 숫자가 자리를 바꾸고 부호 하나가 뒤집혔다
+ 레버암 : ( −10 030.0000,  +17 320.5081, −10.0000 )
선수 기준 방위 120.074374°

90° + 30° = 120° 가 예상값인데 실제로는 120.074°가 나왔다. 차이 0.074°는 레버암 30 m가 만든 것이다. 20 km 거리에서 30 m는 각도로 atan(30/20000) ≈ 0.086° 이므로 크기가 맞다.

3단계 결과
1
2
p_ned = ( N −19 339.7297,  E +5 155.1677,  D −10.0000 ) m
진북 기준 방위 165.074374°,  수평거리 20 015.02 m

45°(함수) + 90°(설치) + 30°(측정) = 165° 와 일치한다(레버암분 0.074° 제외). D가 −10 이므로 표적은 로컬 평면보다 10 m 에 있다.

4·5단계 결과
1
2
표적 ECEF = ( −3 125 892.5014,  +4 093 774.9599,  +3 749 164.2072 ) m
표적 LLA  = 36.233700252°N,  127.364344961°E,  41.4952 m

고도가 왜 10 m가 아니라 41.5 m인가. 레이다는 수평(El = 0°)으로 쐈고 안테나는 10 m 높이에 있으니 “표적 고도 10 m”일 것 같다. 그런데 빔은 직진하는 반면 바다 표면은 멀어질수록 아래로 휘어 내려간다. 20 km 지점에서 그 차이가 31.5 m이고, 10 + 31.5 = 41.5 m가 된다. 로컬 평면 좌표를 그대로 고도로 쓰면 안 되는 이유가 바로 이것이다.

지구 곡률 때문에 생기는 고도 차이

그림 3-1. 빔은 직진하지만 바다 표면은 멀어질수록 내려간다. 그 차이가 거리의 제곱에 비례해 커진다.

(실제로는 대기 굴절 때문에 빔도 아래로 살짝 휘어서 이보다 조금 작아진다. 정밀 고도 산출에서는 4/3 지구 모델 등으로 굴절을 함께 고려한다.)

3.1.6 단위 시험

좌표변환은 “적당히 그럴듯한 값”이 나오기 때문에 눈으로 봐서는 검증되지 않는다. 각 시험이 특정 유형의 버그를 겨냥하도록 설계했다.

시험무엇을 확인하는가어떤 버그를 잡는가
T1 행렬 성질모든 회전행렬에 대해 det = +1, AᵀA = I회전행렬 구성 오류, 부호 실수
T2 극↔직교 왕복극좌표 → 직교 → 극좌표가 제자리로sin/cos 자리바꿈, z 부호
T3 UV↔극 왕복방향코사인 정의 일관성, ‖(u,v,w)‖ = 1UV 정의 오류
T4 LLA↔ECEF 왕복20만 개 무작위 지점에서 왕복(1−e²) 누락, Bowring 오타
T5 전체 체인 왕복측정값 → LLA → 측정값단계 연결·레버암 부호
T6 기지값아래 예제 입력값의 기대 출력전체 구현 정합성
T7 특이점극점, El = ±90°, R = 0, 경도 ±180°NaN/Inf, 0 나눗셈
T8 비대칭 자세roll·pitch·yaw를 전부 다른 값으로전치 방향 뒤바뀜
T9 부호 민감도부호를 뒤집으면 결과가 달라지는가그 항이 실제로 안 쓰이는 실수

T8이 왜 따로 필요한가 전치 방향이 뒤바뀐 버그는 roll = pitch = 0 같은 대칭적인 자세에서는 드러나지 않는다. 단위행렬 테스트도 두 방향 모두 통과한다. roll·pitch·yaw를 전부 다른 값으로 두어야만 잡힌다.

T9가 왜 따로 필요한가 “부호를 뒤집었는데 결과가 똑같다”는 것은 그 항이 실제로는 계산에 쓰이지 않고 있다는 뜻이다. 레버암을 더하는 코드를 빼먹었는데도 값이 그럴듯하게 나오는 상황이 여기에 해당한다.

단위 시험 전체 출력 (make test)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
════════════════════════════════════════════════════════════════════
 coord_frames 단위 시험
════════════════════════════════════════════════════════════════════

T1  회전행렬 성질 (det = +1, 직교)
  [ OK ] |det − 1| 최대                              4.44e-16 (허용 1e-12)
  [ OK ] |AᵀA − I| 최대                            4.44e-16 (허용 1e-12)

T2  안테나 극좌표 ↔ 직교좌표 왕복
  [ OK ] 거리 오차 [m]                               1.16e-10 (허용 1e-06)
  [ OK ] 방위각 오차 [rad]                          2.22e-16 (허용 1e-12)
  [ OK ] 고각 오차 [rad]                             2.22e-16 (허용 1e-13)

T3  UV(방향코사인) ↔ 극좌표 왕복
  [ OK ] ‖(u,v,w)‖ − 1                             2.22e-16 (허용 1e-14)
  [ OK ] 방위각 오차 [rad]                          2.22e-16 (허용 1e-13)
  [ OK ] 고각 오차 [rad]                             2.22e-16 (허용 1e-13)

T4  LLA ↔ ECEF 왕복 (Bowring)
  [ OK ] 고도 오차 [m]                               3.22e-09 (허용 1e-06)
  [ OK ] 위치 왕복 오차 [m]                        3.17e-09 (허용 1e-06)

T5  전체 체인 왕복 (측정값 → LLA → 측정값)
  [ OK ] 거리 오차 [m]                               2.68e-09 (허용 1e-06)
  [ OK ] 방위각 오차 [rad]                          1.04e-11 (허용 1e-10)
  [ OK ] 고각 오차 [rad]                             8.80e-12 (허용 1e-10)

T6  기지값 — 예제 입력값
  [ OK ] 표적 위도 오차 [deg]                      6.15e-11 (허용 1e-08)
  [ OK ] 표적 경도 오차 [deg]                      5.63e-11 (허용 1e-08)
  [ OK ] 표적 고도 오차 [m]                        3.76e-06 (허용 1e-03)
  [ OK ] 역변환 거리 오차 [m]                     3.60e-10 (허용 1e-06)
  [ OK ] 역변환 방위 오차 [deg]                   1.52e-12 (허용 1e-09)
  [ OK ] 역변환 고각 오차 [deg]                   9.43e-13 (허용 1e-09)
  [ OK ] p_ant.x 기대 +17320.5081                      1.12e-08 (허용 1e-06)
  [ OK ] p_body.x 기대 −10030.0000                   3.64e-12 (허용 1e-06)
  [ OK ] p_ned.N  기대 −19339.7297                   1.92e-05 (허용 1e-04)
  [ OK ] 진북방위 기대 165.074374°                4.21e-07 (허용 1e-05)

T7  특이점 처리 (NaN / Inf 없음)
  [ OK ] 극점 부근 고도 오차 [m]                 9.31e-10 (허용 1e-04)
  [ OK ] El = 0/±90° 왕복 오차 [rad]               0.00e+00 (허용 1e-12)
  [ OK ] 거리 0 에서 NaN 없음                      0.00e+00 (허용 0e+00)
  [ OK ] 경도 ±180° 경계 오차 [deg]              0.00e+00 (허용 1e-09)

T8  비대칭 자세 — 전치 방향 검출
  [ OK ] C 적용 후 Cᵀ 적용 = 원본 [m]           4.58e-13 (허용 1e-09)
  [ OK ] 정변환 ≠ 역변환 (구분됨)             2.26e+03 (허용 1e+00)

T9  부호 민감도
  [ OK ] roll 부호 반전 → 결과 변함            5.86e+03 (허용 1e+00)
  [ OK ] 레버암 z 부호 반전 → 결과 변함     1.96e+01 (허용 1e+00)

════════════════════════════════════════════════════════════════════
 결과 : 통과 31 / 실패 0
════════════════════════════════════════════════════════════════════
허용치(tolerance)를 정한 근거

시험을 통과시키려고 허용치를 느슨하게 잡으면 의미가 없다. 물리적·수치적 근거로 정했다.

시험허용치근거
T1 행렬 성질1e−12배정밀도 반올림이 몇 번 누적된 수준. 실제 측정값은 4.4e−16
T2·T3 각도 왕복1e−13 radatan2 를 쓰면 삼각함수 자체의 반올림(≈2e−16)만 남는다
T4 위치 왕복1e−6 mBowring + 개선반복이면 기계정밀도. 실제 3.2e−9 m
T5 전체 체인 각도1e−10 radECEF는 6.4e6 m 규모다. 배정밀도의 상대정밀도 2.2e−16 → 이 크기에서 표현 가능한 최소 간격 약 1.4e−9 m. 체인이 여러 번 더하고 빼면 대략 1e−8 m가 쌓인다. 이 시험의 최단 거리 100 m로 나누면 1e−8 / 100 = 1e−10 rad 이 이론적 바닥이다
T6 기지값위경도 1e−8°, 고도 1e−3 m독립 구현(Python/NumPy)과의 교차 검증 오차 수준

T5의 허용치 유도가 이 코드에서 가장 실용적인 교훈이다. ECEF에서 미터 이하를 다루면 배정밀도의 유효 자릿수 절반을 이미 써 버린 상태가 된다. 그래서 가까운 두 점의 상대 위치는 반드시 로컬 좌표계에서 계산해야 한다.

3.1.7 최종 출력값

조건 ⑥ 이 요구한 두 가지 출력

[1] 표적 위도 / 경도 / 고도
항목
위도36.233700252° N
경도127.364344961° E
고도41.4952 m (WGS-84 타원체고)
[2] 표적 안테나 기준 시선거리 / 방위각 / 고각
항목입력값과의 차이
시선거리20 000.0000 m8.3e−10 m
방위각30.000000°1.5e−12°
고각0.000000°9.4e−13°

역변환 결과가 입력값과 컴퓨터 반올림 수준까지 일치한다. 추적 필터를 넣지 않았으므로 이는 예상되는 결과이며, 동시에 변환 체인 전체가 서로 정확히 역관계임을 보여주는 가장 강력한 증거다.


3.2 추가 확인 실험

설계에서 강조한 세 가지 판단이 실제로 근거가 있는지 코드로 확인했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[A] 레버암 유무 비교
  반영 : lat 36.233700252  lon 127.364344961  alt 41.4952
  무시 : lat 36.233891036  lon 127.364581163  alt 31.4479
  NED 차 : dN -21.213  dE -21.213  dD -10.000  [m]  수평 30.00 m

[B] 자세에 따른 진북방위·고각 (같은 측정값)
  (roll,pitch,yaw)        단순합 실제방위 실제고각 표적고도
  (   0,   0,  45)                 165       165.07         0.03         41.5
  (   0,   0,  60)                 180       180.07         0.03         41.5
  (  10,   0,  45)                 165       165.45        -8.61      -2967.0
  (  20,   0,  45)                 165       166.64       -17.19      -5885.8
  (   0,  10,  45)                 165       164.70        -4.96      -1700.6
  (  20,  10,  45)                 165       163.53       -22.21      -7539.4

[C] 거리별 지구 곡률 효과 (El=0, 안테나 10 m)
  R=     5 km -> 평면고도    10.00 m, 측지고도      11.98 m, 차      1.98 m
  R=    10 km -> 평면고도    10.00 m, 측지고도      17.89 m, 차      7.89 m
  R=    20 km -> 평면고도    10.00 m, 측지고도      41.50 m, 차     31.50 m
  R=    50 km -> 평면고도    10.00 m, 측지고도     206.67 m, 차    196.67 m
  R=   100 km -> 평면고도    10.00 m, 측지고도     796.42 m, 차    786.42 m

[D] ECEF <-> ECI 간이 변환 확인 (학습 1.5)
  GMST(JD 2461284.625) = 25.296375856 deg
  ECEF -3114830.1107 +4087762.8525 +3764723.0978
  ECI  -4562851.5737 +2364816.5410 +3764723.0978
  크기 보존 오차 0.000e+00 m,  왕복 오차 6.585e-10 m
  지구 자전 1 ms = 적도상 0.465 m

실험 A — 레버암을 빼먹으면

 위도경도고도
레버암 반영36.233700252°127.364344961°41.50 m
레버암 무시36.233891036°127.364581163°31.45 m
차이약 21 m약 21 m10 m

수평으로 정확히 30 m, 고도로 10 m — 레버암 그 자체다. 이 오차는 거리가 멀어져도 줄지 않는다.

실험 B — 배가 기울면 각도 덧셈이 깨진다

배가 기울면 빔이 실제로 향하는 방향

그림 3-2. 안테나는 배에 고정되어 있으므로 배가 기울면 안테나도 같이 기운다. 레이다는 여전히 “고각 0도”라고 보고하지만 그건 안테나 기준일 뿐이다.

같은 측정값(Az 30°, El 0°)에 자세만 바꿔 넣은 결과다.

배 자세 (roll, pitch, yaw)단순 덧셈실제 방위실제 고각표적 고도
(0°, 0°, 45°)165°165.07°+0.03°41.5 m
(0°, 0°, 60°)180°180.07°+0.03°41.5 m
(10°, 0°, 45°)165°165.45°−8.61°−2 967 m
(20°, 0°, 45°)165°166.64°−17.19°−5 886 m
(0°, 10°, 45°)165°164.70°−4.96°−1 701 m
(20°, 10°, 45°)165°163.53°−22.21°−7 539 m

roll이 20°만 되어도 고각이 0°에서 −17.19° 로 바뀐다. 레이다는 여전히 “고각 0도”라고 보고하지만 그건 안테나 기준일 뿐이고, 세상 기준으로는 바다 쪽 17도 아래를 보고 있다는 뜻이다. 20 km 거리에서 이는 고도로 약 5.9 km 차이다(표의 표적 고도가 음수인 이유).

각도를 더하는 방식으로는 이 효과를 만들어낼 수 없다. 세 축의 회전이 서로 섞이기 때문이다. 행렬 곱셈이 이 섞임을 자동으로 처리해 준다. 이것이 2.1.4의 3단계가 설계의 핵심인 이유다.

실험 C — 지구 곡률

거리로컬 평면 기준 고도측지 고도차이
5 km10.00 m11.98 m1.98 m
10 km10.00 m17.89 m7.89 m
20 km10.00 m41.50 m31.50 m
50 km10.00 m206.67 m196.67 m
100 km10.00 m796.42 m786.42 m

차이가 거리의 제곱에 비례해서 커진다. 로컬 평면 좌표를 고도로 그대로 쓸 수 없다는 2.1.4의 5단계 주의사항을 뒷받침한다.

실험 D — ECEF ↔ ECI (학습 항목 1.5 확인)

1
2
3
4
5
GMST(JD 2461284.625) = 25.296375856°
ECEF  (−3 114 830.1107,  +4 087 762.8525,  +3 764 723.0978)
ECI   (−4 562 851.5737,  +2 364 816.5410,  +3 764 723.0978)
크기 보존 오차 0.0 m,   왕복 오차 6.6e−10 m
지구 자전 1 ms = 적도상 0.465 m

z 성분이 그대로인 것이 눈에 띈다. ECEF↔ECI 변환이 z축 둘레 회전이기 때문이다. 크기(원점으로부터의 거리)도 보존된다 — 회전은 길이를 바꾸지 않는다.


부록 A. 자주 하는 실수 10가지

#실수증상예방책
1z 방향 혼동 (위 vs 아래)고도 부호가 뒤집힌다. 표적이 땅속에 있다전 좌표계에서 z를 아래로 통일. “10 m 위 = z −10”
2전치 방향 뒤바뀜자세가 0일 때는 정상, 기울면 틀림함수 이름에 방향 명시 (ned_from_body). roll·pitch·yaw를 전부 다른 값으로 시험
3라디안/도 혼용결과가 57배 또는 1/57배로 엉뚱변수 이름에 단위 (az_rad, az_deg). 경계에서 한 번만 변환
4z = (N·(1−e²)+h)·sin(lat) 에서 (1−e²) 누락위도가 조금씩 틀림. 적도에선 안 보이고 고위도에서 커짐LLA→ECEF→LLA 왕복 시험
5atan(y/x) 사용x가 음수일 때 방위가 180° 틀림항상 atan2(y, x)
6asin 인자 클램프 누락특정 입력에서 NaN이 나오고 조용히 번짐atan2 형태로 바꾸거나 클램프
7레버암 누락결과가 항상 일정량 어긋남 (거리 무관)부호 민감도 시험 (T9)
8로컬 평면 고도를 그대로 사용먼 표적일수록 고도가 낮게 나옴반드시 LLA로 환산
9타원체고와 해발고도 혼동고도가 20 m 남짓 계통 오차내부는 타원체고로 통일, 표시만 변환
10오일러각 순서 불일치큰 자세각에서만 틀림3-2-1로 고정하고 문서에 명시

부록 B. 용어집

용어
보어사이트 (Boresight)안테나가 정면으로 바라보는 방향. 안테나 면의 수직 방향
시선거리 (Slant Range)안테나에서 표적까지의 직선 거리. 지표를 따라 잰 거리가 아니다
방위각 (Azimuth)기준 방향에서 좌우로 잰 각. 기준이 보어사이트인지 진북인지 항상 명시할 것
고각 (Elevation)수평면에서 위아래로 잰 각
레버암 (Lever arm)무게중심에서 센서까지의 위치 차이 벡터
백틸트 (Back tilt)안테나 면을 뒤로 젖혀 보어사이트를 위로 들어올린 각
DCM (Direction Cosine Matrix)방향코사인 행렬 = 회전행렬. 좌표계 사이의 회전 관계를 담은 3×3 행렬
전치 (Transpose)행렬의 행과 열을 바꾸는 것. 회전행렬에서는 곧 역회전
직교행렬Aᵀ·A = I 를 만족하는 행렬. 회전행렬은 항상 직교행렬이다
FRDForward-Right-Down. 앞-오른쪽-아래 축 배치
NED / ENUNorth-East-Down / East-North-Up. 국지수평 좌표계의 두 관습
ECEFEarth-Centered Earth-Fixed. 지구중심 지구고정 직교좌표계
ECIEarth-Centered Inertial. 지구중심 관성좌표계 (자전하지 않음)
LLALatitude-Longitude-Altitude. 위경도 고도 좌표계
WGS-84지구 타원체의 국제 표준. GPS·해도가 쓴다
타원체고 (HAE)타원체 표면에서 잰 높이. LLA의 고도가 이것
지오이드 (Geoid)중력이 만드는 평균 해수면. 해발고도의 기준
INSInertial Navigation System. 관성항법장치
정렬 (Alignment)센서 축과 동체 축의 어긋남을 추정·보정하는 절차
GMSTGreenwich Mean Sidereal Time. ECEF↔ECI 회전각을 주는 시각
방향코사인 (Direction cosine, u·v·w)단위 방향벡터를 각 축에 정사영한 성분. UV 좌표가 이것
가시영역 (Visible region)u² + v² ≤ 1 인 원판. 이 밖으로는 빔을 만들 수 없다

부록 C. 오차는 어디서 오는가

좌표변환을 “정확히” 한다는 것이 무슨 뜻인지 감을 잡으려면, 각 단계의 오차가 최종 표적 위치에 얼마나 영향을 주는지 알아야 한다. 각도 오차는 거리에 비례해서 커지고, 위치 오차는 거리와 무관하게 그대로 남는다 — 이 두 문장이 핵심이다.

오차원어느 단계최종 위치에 미치는 영향20 km 표적 기준
안테나 각도 측정 오차 1 mrad1단계거리 × 1e−320 m
안테나 설치 정렬 오차 1 mrad2단계거리 × 1e−320 m
레버암 누락 30 m2단계거리와 무관하게 30 m30 m
INS 자세 오차 1 mrad3단계거리 × 1e−320 m
자세 데이터 지연 10 ms (roll 10°/s)3단계거리 × 1.75e−335 m
INS 위치 오차 10 m4단계거리와 무관하게 10 m10 m
지구 곡률 무시5단계거리² / (2R) — 고도 성분31 m (고도)
지오이드고 무시5단계고도에 계통 오차20~25 m (고도)

여기서 읽어야 할 것

  1. 1 mrad = 0.0573° 이고, 이것이 거리 20 km에서 20 m가 된다. “1도도 안 되는 작은 각”이 실제로는 큰 위치 오차라는 감각을 갖는 것이 중요하다.
  2. 자세 지연이 자세 정확도보다 클 수 있다. 표에서 지연 10 ms의 기여(35 m)가 INS 자세 오차 1 mrad(20 m)보다 크다. 좋은 INS를 쓰고도 시각 처리를 잘못하면 그 성능이 그대로 사라진다.
  3. 레버암과 INS 위치 오차는 거리가 멀어져도 줄지 않는다. 원거리 표적에서는 각도 성분에 묻히지만, 근거리 표적이나 정밀 사격통제에서는 지배적인 항이 된다.
  4. 고도 오차는 별도로 관리해야 한다. 곡률과 지오이드는 수평 위치에는 거의 영향을 주지 않지만 고도에는 수십 미터씩 실린다.

이 표는 규모 감각을 잡기 위한 것이고, 실제 오차 예산은 각 항을 제곱합해서(RSS) 합산하고 상관관계를 고려해야 한다. 다만 어느 항이 지배적인지를 먼저 아는 것이 설계에서 훨씬 중요하다.


부록 D. 코드

본문에 나온 모든 수치는 아래 구성으로 짠 C 코드에서 나왔다. 외부 의존성은 표준 C 라이브러리(libm)뿐이고, -Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wstrict-prototypes경고 0건으로 빌드된다.

파일내용
coord_frames.h좌표계 타입 · WGS-84 상수 · API 선언
coord_frames.c벡터/행렬, 5단계 변환, 전체 체인 구현
main.c예제 입력값 실행 — 단계별 중간값 전부 출력
test_frames.c단위 시험 9종 31항목
Makefile빌드 스크립트
1
2
3
make          # 빌드 (경고 0건)
make run      # 예제 입력값에 대한 단계별 출력
make test     # 단위 시험 31항목 — 전부 통과

coord_frames.h 하나만 들고 가면 다른 프로젝트에도 그대로 붙일 수 있게 만들었다. 프레임 이름을 타입과 함수명에 박아 넣어서(cf_ned_from_body, pos_ecef_t 같은 식) 좌표계를 헷갈리면 컴파일 단계에서 걸리도록 한 것이 설계 의도다.


요약

  1. 좌표계는 “누구 입장에서 말하는가” 이고, 좌표변환은 그 통역이다.
  2. 변환의 재료는 회전과 평행이동 둘뿐이다.
  3. 이번 설계의 체인은 안테나 → 동체 → 로컬(NED) → ECEF → LLA 이고, 각 단계는 앞 단계 없이는 성립하지 않는다.
  4. 회전은 INS의 자세와 위치가, 평행이동은 설치 도면(레버암)과 배의 위치가 공급한다.
  5. 조건3(INS 축 일치) 덕분에 INS 좌표계는 별도 단계로 두지 않는다.
  6. 돌아올 때는 전치하고, 빼고, 순서를 뒤집는다. 왕복 결과가 원래 값이면 구현이 맞은 것이다.
  7. 고정형 안테나는 배의 흔들림을 전부 계산으로 보상한다. 그래서 회전행렬이 필수다 — roll 20°에서 고각이 0°→ −17°로 바뀐다.
  8. 로컬 평면 좌표를 고도로 그대로 쓰면 안 된다. 20 km에서 31.5 m가 어긋난다.

최종 결과

1
2
3
4
5
6
7
8
9
[1] 표적 위/경/고도
      위도  36.233700252 °N
      경도  127.364344961 °E
      고도  41.4952 m  (WGS-84 타원체고)

[2] 표적 안테나 기준 극좌표
      시선거리  20 000.0000 m
      방위각    30.000000 °
      고각      0.000000 °
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.