Limo EKF 파라미터

EKF 설정 파일에서는 주로 다음 내용을 지정합니다.

  1. 필터 실행 주파수
  2. 2차원 주행 모드 사용 여부
  3. Odometry 입력 토픽
  4. IMU 입력 토픽
  5. 사용할 상태 변수
  6. 센서 데이터의 Differential 설정
  7. 센서 데이터의 Relative 설정
  8. TF 발행 여부
  9. map, odom, base_link 프레임 이름
  10. 센서 입력 대기 시간

평면을 주행하는 LIMO는 일반적으로 two_d_mode를 활성화해 Z축 위치, Roll, Pitch 등 불필요한 3차원 상태를 제한할 수 있습니다.

# For parameter descriptions, please refer to the template parameter files for each node.

ekf_filter_node_odom:
  ros__parameters:
    frequency: 30.0
    sensor_timeout: 0.2
    two_d_mode: true
    transform_time_offset: 0.0
    transform_timeout: 0.2
    print_diagnostics: true
    debug: false

    # map_frame: map
    odom_frame: odom
    base_link_frame: base_link
    world_frame: odom

    odom0: odom
    odom0_config: [true, true, false,
                  false, false, true,
                  true,  true,  false,
                  false, false, true,
                  false, false, false]
    odom0_queue_size: 10
    odom0_differential: true
    odom0_relative: true

    imu0: imu
    imu0_config: [false, false, false,
                  false, false, true,
                  false, false, false,
                  true,  true,  true,
                  true,  true, false]
    imu0_differential: false
    imu0_relative: true
    imu0_queue_size: 10
    imu0_remove_gravitational_acceleration: true

    use_control: false

    process_noise_covariance: [1e-3, 1e-3, 1e-3, 0.3, 0.3, 1e-3, 0.5, 0.5, 0.1, 0.3, 0.3, 1e-3, 0.3, 0.3, 0.3]

    initial_estimate_covariance: [1e-9, 1e-9, 1e-9, 1.0, 1.0, 1e-9, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

2D 지상 로봇을 대상으로 /odom과 /imu를 융합해서 odom → base_link 기준의 부드러운 로컬 위치 추정을 만드는 EKF 설정입니다.

robot_localization의 EKF 상태 벡터는 15개입니다. 모든 _config, process_noise_covariance, initial_estimate_covariance는 아래 순서를 사용합니다.

0   x
1   y
2   z

3   roll
4   pitch
5   yaw

6   vx
7   vy
8   vz

9   vroll
10  vpitch
11  vyaw

12  ax
13  ay
14  az

즉,

[x, y, z,
 roll, pitch, yaw,
 vx, vy, vz,
 vroll, vpitch, vyaw,
 ax, ay, az]

입니다.

1. EKF 실행 주기

frequency: 30.0

EKF가 상태 추정 결과를 생성하는 목표 주파수입니다.

30 Hz
→ 약 33.3 ms마다 상태 업데이트

센서 메시지가 최소 하나 들어와야 필터가 실제 계산을 시작합니다.

지상 이동 로봇에서는 일반적으로

20 Hz
30 Hz
50 Hz

정도를 많이 사용합니다.

30 Hz는 Nav2나 일반 모바일 로봇에서 무난한 설정입니다.

2. 센서 timeout

sensor_timeout: 0.2

센서 데이터가

0.2초 = 200 ms

이상 들어오지 않으면 해당 센서를 timeout으로 봅니다.

이때 EKF가 정지하는 것은 아닙니다.

센서 업데이트 없이:

Prediction
   ↓
Prediction
   ↓
Prediction

만 수행합니다.

즉,

정상 상태

Prediction
   ↓
Measurement
   ↓
Correction

에서 센서가 끊기면

Prediction only

상태가 됩니다. 공식 문서에서도 sensor_timeout 이후에는 correction 없이 prediction cycle을 수행한다고 설명합니다.

예를 들어 IMU가 100 Hz라면:

정상 주기 = 0.01초
timeout   = 0.2초

이므로 약 20개 IMU 메시지 시간이 지나도록 데이터가 없으면 timeout이라고 볼 수 있습니다.

3. 2D 모드

two_d_mode: true

이 설정은 매우 중요합니다.

로봇이 평면에서 움직인다고 가정합니다.

즉:

사용
x
y
yaw

제한
z     = 0
roll  = 0
pitch = 0

뿐만 아니라 관련 3D 속도/가속도도 0으로 제한합니다. robot_localization은 2D 모드에서 Z, roll, pitch와 관련 속도/가속도를 0 값으로 필터에 넣어 로봇 상태가 XY 평면에 붙어 있도록 합니다.

그래서 다음과 같은 차동구동 모바일 로봇에 적합합니다.

           +X
            ↑
            │
        ┌───────┐
        │ Robot │
        └───────┘
            ↻ yaw

+Y ←────────────

반면 드론이나 6DoF 로봇에서는 보통:

two_d_mode: false

로 사용해야 합니다.

4. TF 시간 offset

transform_time_offset: 0.0

EKF가 생성하는 TF timestamp에 추가하는 시간입니다.

현재는:

TF timestamp + 0초

즉 보정하지 않습니다.

일부 시스템에서는 미래 timestamp가 필요해서:

transform_time_offset: 0.05

처럼 사용하기도 합니다.

공식 문서에 따르면 이 값은 생성되는 map→odom 또는 odom→base_link TF의 timestamp에 더해집니다.

일반적인 경우에는:

0.0

을 권장합니다.

5. TF lookup timeout

transform_timeout: 0.2

센서 데이터를 변환할 때 필요한 TF가 없으면 최대 0.2초 기다립니다.

예를 들어 IMU frame이:

imu_link

이고 EKF 기준 frame이:

base_link

라면 EKF는 다음 TF가 필요합니다.

base_link
    │
    └── imu_link

TF가 즉시 없을 경우 최대:

200 ms

기다립니다.

다만 이 값은 조금 주의해야 합니다.

현재 EKF 주기는:

30 Hz
≈ 33 ms

인데

transform_timeout = 200 ms

입니다.

따라서 TF가 자주 늦으면 EKF가 TF lookup에서 block되어 30 Hz를 유지하지 못할 가능성이 있습니다. 공식 문서도 non-zero timeout은 더 정확한 TF를 얻는 대신 필터 실행을 일시적으로 block해서 출력 주파수에 영향을 줄 수 있다고 경고합니다.

TF 구조가 정상적이라면 :

transform_timeout: 0.0

또는 아주 짧게:

transform_timeout: 0.05

부터 시작하는 것이 유리합니다.

6. Diagnostic 출력

print_diagnostics: true

EKF 상태를:

/diagnostics

토픽으로 출력합니다.

문제가 있을 때 유용합니다.

확인:

ros2 topic echo /diagnostics

또는:

rqt

의 diagnostic 관련 플러그인을 사용할 수 있습니다.

7. Debug

debug: false

상세 내부 EKF 디버깅을 끕니다.

true로 하면 매우 많은 양의 내부 데이터가 생성될 수 있기 때문에 정상 운용에서는 false가 맞습니다. 공식 문서도 debug 모드에서 매우 많은 데이터가 출력된다고 명시합니다.

8. 좌표계 설정

# map_frame: map
odom_frame: odom
base_link_frame: base_link
world_frame: odom

현재 TF 구조의 핵심입니다.

설계는:

odom
 │
 │ EKF
 ↓
base_link

입니다.

odom_frame

odom_frame: odom

로컬 연속 좌표계입니다.

특징:

단기적으로 부드럽고 연속적
하지만 장시간에는 drift 가능

wheel odometry나 IMU 기반 로컬 위치추정에 적합합니다.

base_link_frame

base_link_frame: base_link

로봇 본체 중심 frame입니다.

보통 TF 구조:

odom
 └── base_link
      ├── laser
      ├── camera_link
      ├── imu_link
      ├── base_footprint
      └── ...

입니다.

9. world_frame

world_frame: odom

매우 중요합니다.

EKF가 어떤 세계 좌표계를 기준으로 상태를 출력할 것인지 지정합니다.

현재:

world_frame = odom

이므로 EKF는 일반적으로:

odom → base_link

transform을 만들어냅니다.

GPS처럼 절대 위치가 갑자기 보정될 수 있는 데이터가 없고 wheel odometry, visual odometry, IMU 같은 연속적인 센서만 융합한다면 world_frame: odom이 일반적인 설정입니다.

GPS까지 사용할 경우 일반적인 구조는 달라집니다.

map
 │
 ↓
odom
 │
 ↓
base_link

그리고 별도의 map EKF에서:

world_frame: map

을 사용합니다.

10. map_frame이 주석 처리된 이유

# map_frame: map

현재 EKF는 로컬 odometry만 담당하므로 없어도 됩니다.

즉:

Local EKF
wheel odom + IMU
        ↓
odom → base_link

구조입니다.

11. 첫 번째 Odometry 센서

odom0: odom

EKF가 구독할 odometry topic입니다.

즉:

/odom

입니다.

메시지 타입은 일반적으로:

nav_msgs/msg/Odometry

입니다.

확인:

ros2 topic type /odom
ros2 interface show nav_msgs/msg/Odometry

12. odom0_config

가장 중요한 부분 중 하나입니다.

odom0_config: [true, true, false,
               false, false, true,
               true,  true,  false,
               false, false, true,
               false, false, false]

15개의 boolean이 상태 벡터와 1:1 대응합니다.

풀어서 보면:

상태설정사용 여부
xtrue사용
ytrue사용
zfalse사용 안 함
rollfalse사용 안 함
pitchfalse사용 안 함
yawtrue사용
vxtrue사용
vytrue사용
vzfalse사용 안 함
vrollfalse사용 안 함
vpitchfalse사용 안 함
vyawtrue사용
axfalse사용 안 함
ayfalse사용 안 함
azfalse사용 안 함

즉 /odom에서 사용하는 값은:

Position
x
y

Orientation
yaw

Linear velocity
vx
vy

Angular velocity
vyaw

입니다.

공식 예제에서도 _config 배열은 이 15개 상태 중 어떤 값을 해당 센서로 correction할지 결정합니다.

시각화하면:

odom
 ├─ x       ✓
 ├─ y       ✓
 ├─ z       ✗
 │
 ├─ roll    ✗
 ├─ pitch   ✗
 ├─ yaw     ✓
 │
 ├─ vx      ✓
 ├─ vy      ✓
 ├─ vz      ✗
 │
 ├─ vroll   ✗
 ├─ vpitch  ✗
 ├─ vyaw    ✓
 │
 ├─ ax      ✗
 ├─ ay      ✗
 └─ az      ✗

13. odom0_differential

odom0_differential: true

이것도 매우 중요합니다.

Odometry의 absolute pose를 그대로 쓰지 않고:

현재 pose - 이전 pose

를 계산해서 변화량으로 사용합니다.

예를 들어:

t0:
x = 10.0

t1:
x = 10.1

이면 absolute 값 10.1 자체보다:

Δx = 0.1

을 이용합니다.

보다 정확히는 이 변화량을 시간으로 나눠 velocity 형태로 바꾸어 필터에 융합합니다.

개념적으로:

x(t) - x(t-1)
---------------- = vx
      Δt

입니다.

이 기능은 두 센서가 동시에 절대 pose를 제공해서 서로 약간 다른 값을 내놓을 때 EKF가 양쪽 사이를 왔다 갔다 하는 문제를 줄이는 데 특히 유용합니다.

14. odom0_relative

odom0_relative: true

첫 번째 센서 측정값을 원점으로 잡습니다.

예를 들어 첫 odom이:

x = 15
y = 30
yaw = 1.2

라 하더라도 EKF 관점에서는:

x = 0
y = 0
yaw = 0

에서 시작합니다.

이후:

x = 16
y = 32

이면 상대값으로:

x = 1
y = 2

를 사용합니다.

relative와 differential의 차이는 공식 문서에서 명확히 구분됩니다.

differential

measurement(t)
     -
measurement(t-1)
     ↓
velocity로 변환

반면:

relative

measurement(t)
     -
measurement(0)
     ↓
pose 상태로 사용

입니다.

현재 설정의 특이점

지금은:

odom0_differential: true
odom0_relative: true

둘 다 켜져 있습니다.

기능 목적이 상당히 겹칩니다.

보통은 의도를 명확하게 해서 둘 중 하나를 선택하는 편이 낫습니다.

Wheel odometry가 이미:

0,0,0

부터 시작한다면 일반적으로:

odom0_differential: false
odom0_relative: false

도 충분한 경우가 많습니다.

Wheel odometry의 절대 pose drift를 피하면서 velocity 성격으로 사용하고 싶다면:

odom0_differential: true
odom0_relative: false

가 더 명확합니다.

단순히 시작점을 0으로 만들고 싶다면:

odom0_differential: false
odom0_relative: true

가 목적에 맞습니다.

15. Odometry queue

odom0_queue_size: 10

센서 메시지를 처리하기 위한 queue 크기입니다.

Odometry가 EKF 처리보다 순간적으로 빨리 들어와도 일정 개수의 메시지를 buffering할 수 있게 합니다.

odom messages
 ↓
[1][2][3][4]...[10]
 ↓
EKF

10은 일반적인 값입니다.

16. IMU topic

imu0: imu

EKF가:

/imu

topic을 구독합니다.

일반적인 타입:

sensor_msgs/msg/Imu

확인:

ros2 topic type /imu

그리고:

ros2 interface show sensor_msgs/msg/Imu

17. imu0_config

imu0_config: [false, false, false,
              false, false, true,
              false, false, false,
              true,  true,  true,
              true,  true, false]

풀어보면:

IMU 상태설정
xfalse
yfalse
zfalse
rollfalse
pitchfalse
yawtrue
vxfalse
vyfalse
vzfalse
vrolltrue
vpitchtrue
vyawtrue
axtrue
aytrue
azfalse

즉 IMU에서:

yaw

roll angular velocity
pitch angular velocity
yaw angular velocity

x acceleration
y acceleration

을 사용하도록 되어 있습니다.

하지만 여기서 중요한 점이 있습니다.

two_d_mode: true

이므로 실제로는:

roll
pitch
vroll
vpitch
z
vz
az

같은 3D 상태가 0으로 제한됩니다.

따라서 현재 설정에서 실질적으로 중요한 IMU 값은 주로:

yaw
vyaw
ax
ay

입니다.

즉 이 부분:

true, true, true

중:

vroll  → 2D 모드로 억제
vpitch → 2D 모드로 억제
vyaw   → 사용

이라고 이해하시면 됩니다.

18. IMU differential

imu0_differential: false

IMU yaw를:

yaw(t) - yaw(t-1)

형태로 변환하지 않습니다.

즉 IMU orientation을 그대로 orientation 데이터로 취급합니다.

대부분의 IMU에서는 이 설정이 일반적입니다.

19. IMU relative

imu0_relative: true

IMU 시작 자세를 기준 0으로 설정합니다.

예를 들어 로봇이 켜질 때 IMU yaw가:

yaw = 2.1 rad

이어도 필터에는:

yaw = 0

부터 시작하도록 만들 수 있습니다.

이후 실제 IMU가:

2.4 rad

을 출력하면:

relative yaw = 0.3 rad

형태가 됩니다. relative는 첫 번째 측정을 모든 이후 측정에서 빼는 방식입니다.

지상 로봇에서:

로봇 시작 방향 = yaw 0

으로 쓰고 싶다면 상당히 유용합니다.

20. IMU queue

imu0_queue_size: 10

IMU 메시지 queue 크기입니다.

IMU가 보통:

50 Hz
100 Hz
200 Hz

등으로 빠르기 때문에 buffering을 위해 사용합니다.

21. 중력 제거

imu0_remove_gravitational_acceleration: true

매우 중요한 설정입니다.

가속도계는 실제 움직임뿐 아니라 중력도 측정합니다.

정지 상태라 해도 IMU 방향에 따라 대략:

9.80665 m/s²

에 해당하는 중력 성분이 측정됩니다.

EKF에서 linear acceleration을 사용하려면 이 중력 성분을 제거해야 합니다. robot_localization은 이 옵션이 활성화되면 IMU orientation 또는 필터 orientation을 이용해 중력 성분을 제거합니다.

개념:

IMU 측정 가속도
       │
       ├── 실제 로봇 가속도
       │
       └── 중력
              ↓
         gravity 제거
              ↓
        실제 움직임 가속도

현재:

ax: true
ay: true

이므로:

imu0_remove_gravitational_acceleration: true

는 의미가 있습니다.

22. 제어 입력 사용 여부

use_control: false

cmd_vel 같은 명령값을 EKF prediction에 사용하지 않습니다.

즉 EKF는:

Wheel odom
+
IMU

만으로 상태를 추정합니다.

use_control: true일 경우 command velocity를 이용해 acceleration prediction까지 할 수 있습니다. 일반적으로 작은 지연도 문제가 되는 경우 control term이 유용할 수 있다고 설명합니다.

대부분 모바일 로봇에서는 처음에는:

use_control: false

가 안전합니다.

23. process_noise_covariance

process_noise_covariance:
[
1e-3, 1e-3, 1e-3,
0.3, 0.3, 1e-3,
0.5, 0.5, 0.1,
0.3, 0.3, 1e-3,
0.3, 0.3, 0.3
]

EKF에서 가장 어려운 튜닝 파라미터 중 하나입니다.

보통:

Q

라고 부르는 process noise covariance입니다.

의미는:

EKF 자체 운동 모델의 예측값을 얼마나 불확실하다고 생각할 것인가?

입니다.

Q가 커질수록 해당 상태의 prediction uncertainty가 커지고, 결과적으로 새 센서 측정값을 더 빠르게 따라가게 된다고 알려져 있습니다.

현재 값을 해석하면:

상태Q
x0.001
y0.001
z0.001
roll0.3
pitch0.3
yaw0.001
vx0.5
vy0.5
vz0.1
vroll0.3
vpitch0.3
vyaw0.001
ax0.3
ay0.3
az0.3

여기서 중요한 부분은:

x/y    = 0.001  → 예측 모델을 비교적 신뢰
yaw    = 0.001  → yaw prediction을 비교적 신뢰

vx/vy  = 0.5    → 속도 모델은 덜 신뢰
ax/ay  = 0.3    → 가속도 모델도 덜 신뢰

입니다.

일반적으로:

Q 작음
→ 모델 신뢰 ↑
→ 센서 변화에 천천히 반응
→ 결과가 부드러움

반대로:

Q 큼
→ 모델 신뢰 ↓
→ 센서 신뢰 ↑
→ 새로운 measurement를 빠르게 따라감

입니다.

24. 왜 vx, vy가 0.5로 큰가?

vx: 0.5
vy: 0.5

로봇 속도는 짧은 시간 동안 크게 변할 수 있기 때문입니다.

예를 들어:

정지
0 m/s
   ↓
급가속
1 m/s

처럼 빠르게 변할 수 있습니다.

따라서 EKF가 기존 속도 예측에 너무 집착하지 않고 wheel odometry나 IMU 데이터를 빨리 반영하게 합니다.

25. initial_estimate_covariance

initial_estimate_covariance:
[
1e-9, 1e-9, 1e-9,
1.0, 1.0, 1e-9,
1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, 1.0
]

EKF의 초기 상태에 대한 불확실성입니다.

보통:

P

라고 부릅니다.

process_noise_covariance와 완전히 다른 개념입니다.

Q
= 모델 prediction noise

P
= 현재 state estimate uncertainty

입니다.

초기 covariance가 작으면 필터가 초기 상태를 매우 확신하기 때문에 센서 measurement에 천천히 수렴할 수 있고, 큰 값이면 초기 측정값을 빨리 받아들이는 효과가 있습니다.

26. 현재 P 값 해석

현재:

x   = 1e-9
y   = 1e-9
z   = 1e-9
yaw = 1e-9

입니다.

즉 시작할 때:

x   ≈ 0
y   ≈ 0
yaw ≈ 0

라는 것을 매우 강하게 신뢰합니다.

반대로:

roll  = 1.0
pitch = 1.0

vx    = 1.0
vy    = 1.0
vz    = 1.0

vroll  = 1.0
vpitch = 1.0
vyaw   = 1.0

ax = 1.0
ay = 1.0
az = 1.0

이므로 이 상태들은 초기에는 상당히 불확실하다고 봅니다.

그래서 센서 데이터가 들어오면 빨리 correction할 수 있습니다.

27. 이 설정의 전체 센서 융합 구조

현재 구성은 사실상 다음 구조입니다.

                 +------------------+
/odom ---------->|                  |
                 |                  |
                 |       EKF        |----> /odometry/filtered
                 | robot_localization|
/imu ------------>|                  |
                 +---------+--------+
                           |
                           v
                    odom → base_link

그리고 센서 역할을 나누면:

Wheel Odometry

x
y
yaw
vx
vy
vyaw
      │
      │
      ▼
     EKF
      ▲
      │
      │
IMU

yaw
vyaw
ax
ay

입니다.

28. 2D 모드까지 고려하면 실제 상태는

15차원 EKF 내부 구조는 유지하지만 실제 유효한 상태는 거의:

[x,
 y,
 yaw,
 vx,
 vy,
 vyaw,
 ax,
 ay]

중심이 됩니다.

즉 개념적으로:

ax, ay
↓
vx, vy
↓
x, y

IMU vyaw
↓
yaw

형태입니다.

Leave a Comment