학습 목표
- IMU 가 재는 것과 절대 못 재는 것을 구분할 수 있다.
- 적분이 오차를 어떻게 키우는지 숫자로 설명할 수 있다.
- 편향을 재고 빼는 절차를 수행할 수 있다.
- Imu 메시지의 각 항목과 좌표계 규약을 바르게 다룰 수 있다.
- 자세 추정에서 무엇이 관측 가능하고 무엇이 아닌지 안다.
1. IMU 가 재는 것과 못 재는 것
IMU 는 로봇에서 가장 오해받는 센서입니다. 이름 때문에 "관성으로 위치를 안다"고 생각하기 쉽지만, IMU 는 위치를 절대 재지 못합니다.
IMU 가 실제로 재는 것은 두 가지뿐입니다.
① 가속도계 — 지금 얼마나 세게 밀리고 있는가.
여기서 함정이 하나 있습니다. 가만히 놓아둔 IMU 도 0 을 내놓지 않습니다. 중력이 위쪽으로 약 9.81 만큼 나옵니다. 가속도계는 중력과 운동에 의한 가속을 구분하지 못하기 때문입니다.
이것은 결함이 아니라 오히려 쓸모입니다. 가만히 있을 때 중력이 어느 방향인지 알려 주므로 로봇이 얼마나 기울어졌는지를 알 수 있습니다.
② 자이로 — 지금 얼마나 빨리 돌고 있는가.
각도가 아니라 각속도입니다. "지금 초당 30도로 돌고 있다"까지만 말해 주고 "지금 몇 도 돌아가 있다"는 말하지 않습니다.
③ 지자기 센서 — 자주 같이 들어 있습니다.
지구 자기장의 방향을 재서 어느 쪽이 북쪽인지 알려 줍니다. 다만 로봇에서는 거의 쓸모없을 때가 많습니다. 모터, 배터리, 철제 구조물이 자기장을 심하게 흐트러뜨리기 때문입니다.
그래서 IMU 로 무엇을 할 수 있는가. 기울기는 잘 압니다. 중력 방향을 보면 되니까요. 회전 속도도 잘 압니다. 하지만 위치와 방위는 IMU 혼자서는 알 수 없습니다. 다음 절에서 그 이유를 숫자로 봅니다.
| 재는 것 | 직접 얻는 값 | IMU 만으로 되는가 |
|---|---|---|
| 기울기 (앞뒤·좌우) | 중력 방향에서 | 됨 — 가만히 있을 때 |
| 회전 속도 | 자이로에서 직접 | 됨 |
| 회전 각도 | 각속도를 적분 | 짧은 시간만 |
| 방위 (어느 쪽이 북쪽) | 지자기 또는 다른 센서 | 실내에서는 어려움 |
| 속도 | 가속도를 적분 | 거의 불가능 |
| 위치 | 가속도를 두 번 적분 | 불가능 |
| IMU가 잘하는 것 | IMU만으로 해결하기 어려운 것 |
|---|---|
| 초당 수백 번의 빠른 변화 측정 | 시간이 지날수록 커지는 적분 오차 |
| 조명과 무늬에 관계없는 측정 | 절대 위치와 절대 방위 추정 |
| 짧은 시간의 회전·충격 포착 | 정지 상태에서도 생기는 표류 |
| 중력으로 롤·피치 보정 | 이동 거리의 장시간 추정 |
IMU 는 아주 빠르고 아주 짧게만 정확합니다. 다른 센서와 정반대의 성질이라 서로를 잘 보완합니다.
주의 가속도계가 중력을 포함한다는 사실을 잊으면 모든 계산이 틀립니다. 로봇이 기울어지면 중력이 세 축에 나뉘어 들어오는데, 이것을 로봇이 가속하고 있다고 착각하면 속도 추정이 순식간에 발산합니다.
2. 적분의 저주
이 절이 IMU 를 이해하는 핵심입니다.
자이로는 각속도를 줍니다. 각도를 알고 싶으면 더해 나가면 됩니다. 가속도계는 가속도를 줍니다. 위치를 알고 싶으면 두 번 더하면 됩니다.
원리는 맞습니다. 그런데 실제로는 처참하게 실패합니다. 왜 그럴까요.
작은 편향이 시간과 함께 눈덩이가 되기 때문입니다.
자이로의 경우 — 오차가 시간에 비례해 늘어납니다.
초당 0.5도의 편향이 있다고 합시다. 아주 좋은 센서의 값입니다. 10초 뒤에는 5도, 1분 뒤에는 30도, 5분 뒤에는 150도 틀립니다. 로봇이 어디를 보고 있는지 완전히 모르게 됩니다.
가속도계의 경우 — 오차가 시간의 제곱으로 늘어납니다.
이쪽은 재앙에 가깝습니다. 0.1 m/s² 의 작은 편향이 있다면 1초 뒤 5 cm, 10초 뒤 5 m, 1분 뒤에는 180 m 틀립니다.
그래서 IMU 로 위치를 추정하는 것은 사실상 불가능합니다. 몇 초라면 몰라도, 몇 분을 버티는 것은 군사·항공용의 아주 비싼 장비나 가능합니다.
그러면 IMU 는 왜 쓰는가.
짧은 시간 동안은 대단히 정확하기 때문입니다. 초당 수백 번 갱신되고, 조명·무늬·가림과 무관합니다. 다른 센서가 느리거나 잠깐 안 보이는 사이를 메워 줍니다.
결론은 이것입니다. IMU 는 혼자 쓰는 센서가 아닙니다. 느리지만 표류하지 않는 센서와 짝지어야 비로소 힘을 냅니다. 이것이 다음 화면의 센서 융합입니다.
자기 IMU 의 편향을 재서 이 값에 넣어 보십시오. 몇 초 안에 쓸 수 있는 센서인지 아닌지가 바로 드러납니다.
# 적분이 오차를 어떻게 키우는지 직접 봅니다
# python3 drift.py
GYRO_BIAS_DPS = 0.5 # 자이로 편향 [도/초] — 좋은 센서의 값
ACC_BIAS_MS2 = 0.1 # 가속도계 편향 [m/s^2] — 흔한 값
def main():
print(' 경과시간 자이로 각도오차 가속도 위치오차')
print(' ' + '-' * 45)
for t in (1, 5, 10, 30, 60, 300):
# 한 번 적분 : 시간에 비례해서 커진다
angle_err = GYRO_BIAS_DPS * t
# 두 번 적분 : 시간의 제곱으로 커진다
pos_err = 0.5 * ACC_BIAS_MS2 * t * t
warn = ''
if angle_err > 90:
warn = ' <- 방향을 완전히 잃음'
elif pos_err > 10:
warn = ' <- 위치를 완전히 잃음'
print(f' {t:4d} 초 {angle_err:8.1f} 도 '
f'{pos_err:9.2f} m{warn}')
print()
print('자이로 오차는 시간에 비례하고, 가속도 오차는 제곱으로 커집니다.')
print('그래서 IMU 로 위치를 추정하는 것은 사실상 불가능합니다.')
if __name__ == '__main__':
main()
# 실행 결과
# 경과시간 자이로 각도오차 가속도 위치오차
# ---------------------------------------------
# 1 초 0.5 도 0.05 m
# 5 초 2.5 도 1.25 m
# 10 초 5.0 도 5.00 m
# 30 초 15.0 도 45.00 m <- 위치를 완전히 잃음
# 60 초 30.0 도 180.00 m <- 위치를 완전히 잃음
# 300 초 150.0 도 4500.00 m <- 방향을 완전히 잃음
| 시간 | 1초 | 5초 | 10초 | 30초 | 60초 | 300초 |
|---|---|---|---|---|---|---|
| 자이로 각도 오차 | 0.5° | 2.5° | 5° | 15° | 30° | 150° |
| 가속도 위치 오차 | 0.05 m | 1.25 m | 5 m | 45 m | 180 m | 4,500 m |
같은 크기의 편향이라도 한 번 적분하면 직선으로, 두 번 적분하면 곡선으로 커집니다. 시간이 조금만 지나도 차이가 압도적입니다.
주의 "좋은 IMU 를 사면 되지 않나"는 자연스러운 생각이지만 답은 아닙니다. 편향을 열 배 줄여도 버틸 수 있는 시간은 세 배 남짓 늘어날 뿐입니다. 제곱으로 커지는 오차는 더 좋은 부품으로 해결되지 않습니다. 구조를 바꿔야 합니다. 즉 다른 센서와 합쳐야 합니다.
3. 편향을 재고 빼기
적분이 재앙인 이유가 편향이라면, 편향을 재서 빼면 되지 않을까요. 맞습니다. 그리고 이것은 반드시 해야 하는 기본 작업입니다.
방법은 아주 단순합니다. 로봇을 완전히 정지시키고 몇 초 동안 값을 모아 평균을 냅니다. 가만히 있으니 각속도의 참값은 0 이고, 따라서 평균값이 곧 편향입니다.
언제 하는가. 로봇을 켤 때마다 하는 것이 좋습니다. 많은 드라이버가 시작할 때 자동으로 하고, 그래서 켤 때 로봇을 움직이면 안 됩니다. 이것을 모르고 로봇을 들고 켜면 엉뚱한 편향이 박혀 버립니다.
그런데 편향은 고정된 값이 아닙니다.
온도에 따라 변합니다. 켠 직후와 30분 뒤의 편향이 다릅니다. 전자 부품이 데워지면서 특성이 바뀌기 때문입니다. 정밀한 작업이라면 예열 시간을 두는 것이 좋습니다.
시간에 따라서도 천천히 흘러갑니다. 그래서 아무리 잘 보정해도 몇 분 뒤에는 다시 어긋납니다. 이것이 앞 절에서 말한 "더 좋은 부품으로 해결되지 않는다"의 이유입니다.
가속도계의 편향은 재기가 더 까다롭습니다. 중력이 섞여 있기 때문입니다. 로봇이 완전히 수평이라는 보장이 없으면 무엇이 기울기이고 무엇이 편향인지 구분할 수 없습니다. 그래서 여러 자세로 놓고 재는 절차가 필요합니다.
| 편향이 변하는 이유 | 얼마나 | 대응 |
|---|---|---|
| 켤 때마다 다름 | 매번 다른 값 | 켤 때마다 다시 잼 |
| 온도가 오르면서 | 수십 분에 걸쳐 변함 | 예열 후 측정 |
| 시간이 지나면서 | 분 단위로 천천히 | 다른 센서로 계속 보정 |
| 진동과 충격 | 순간적으로 크게 | 기계적 완충 |
| 기울어진 채 보정 | 중력이 섞여 들어감 | 수평을 확인하고 잴 것 |
정지 상태의 az 가 9.81 근처가 아니면 축 규약이나 장착 자세가 다른 것입니다. 이것부터 맞춰야 나머지가 뜻을 가집니다.
# IMU 의 편향과 잡음을 재는 코드
# 로봇을 완전히 정지시키고 실행하십시오.
# 여기서 나온 두 숫자가 뒤의 융합 단계에서 그대로 쓰입니다.
import rclpy
from rclpy.node import Node
from rclpy.qos import qos_profile_sensor_data
from sensor_msgs.msg import Imu
import statistics
import math
class ImuBias(Node):
def __init__(self):
super().__init__('imu_bias')
self.samples = {'gx': [], 'gy': [], 'gz': [],
'ax': [], 'ay': [], 'az': []}
self.create_subscription(
Imu, 'imu/data_raw', self.on_imu, qos_profile_sensor_data)
self.get_logger().info('로봇을 움직이지 마십시오. 500개를 모읍니다.')
def on_imu(self, msg):
g = msg.angular_velocity
a = msg.linear_acceleration
for key, value in (('gx', g.x), ('gy', g.y), ('gz', g.z),
('ax', a.x), ('ay', a.y), ('az', a.z)):
self.samples[key].append(value)
if len(self.samples['gz']) < 500:
return
self.report()
raise SystemExit
def report(self):
print()
print('축 평균(편향) 표준편차(잡음)')
print('-' * 42)
for key in ('gx', 'gy', 'gz'):
xs = self.samples[key]
mean = statistics.mean(xs)
sd = statistics.pstdev(xs)
print(f'{key} {math.degrees(mean):+8.4f} 도/s '
f'{math.degrees(sd):7.4f} 도/s')
for key in ('ax', 'ay', 'az'):
xs = self.samples[key]
mean = statistics.mean(xs)
sd = statistics.pstdev(xs)
print(f'{key} {mean:+8.4f} m/s2 {sd:7.4f} m/s2')
az = statistics.mean(self.samples['az'])
print()
print(f'정지 상태의 az 는 {az:.3f} m/s2 입니다.')
if abs(az - 9.81) > 0.5:
print(' 경고: 9.81 에서 크게 벗어났습니다.')
print(' 로봇이 기울었거나 축 방향 규약이 다릅니다.')
else:
print(' 좋습니다. 중력이 Z 축 양의 방향으로 나옵니다.')
def main():
rclpy.init()
try:
rclpy.spin(ImuBias())
except SystemExit:
pass
# 실행 결과 예
# 축 평균(편향) 표준편차(잡음)
# ------------------------------------------
# gx -0.3120 도/s 0.0841 도/s
# gy +0.1874 도/s 0.0793 도/s
# gz +0.5031 도/s 0.0902 도/s
# ax +0.0412 m/s2 0.0231 m/s2
# ay -0.0197 m/s2 0.0248 m/s2
# az +9.8043 m/s2 0.0302 m/s2
#
# 정지 상태의 az 는 9.804 m/s2 입니다.
# 좋습니다. 중력이 Z 축 양의 방향으로 나옵니다.
주의 로봇을 들고 있거나 흔들면서 전원을 켜지 마십시오. 많은 드라이버가 시작 직후 몇 초 동안 편향을 재는데, 그 사이의 움직임이 그대로 편향으로 기록됩니다. 이후 로봇은 가만히 있어도 계속 돌고 있다고 믿습니다.
4. Imu 메시지와 축 규약
표준 IMU 메시지에는 세 덩어리와 각각의 분산 배열이 들어 있습니다.
① 자세 — 이미 계산된 결과.
이것이 중요합니다. 자세는 IMU 가 직접 재는 값이 아니라 센서 안의 칩이나 드라이버가 계산해서 넣어 준 것입니다. 어떤 IMU 는 이 계산을 하지 않습니다.
계산하지 않았다면 그 사실을 표시해야 합니다. 관례는 분산 배열의 첫 항목을 음수로 두는 것입니다. 이것을 안 하면 뒤의 융합 단계가 비어 있는 값을 진짜로 믿고 씁니다.
② 각속도 — 자이로의 원본 값. 초당 라디안입니다.
③ 선가속도 — 가속도계의 원본 값. 초당 제곱 미터이고 중력이 포함되어 있습니다.
축 방향 규약이 매우 중요합니다. 앞 화면에서 배운 대로 X 가 앞, Y 가 왼쪽, Z 가 위입니다. 정지 상태에서 Z 축 가속도가 대략 +9.81 로 나와야 합니다.
여기서 자주 문제가 생깁니다. IMU 칩 제조사들은 저마다 다른 축 규약을 쓰고, 드라이버가 그것을 ROS 규약으로 바꿔 주지 않는 경우가 있습니다. 그러면 -9.81 이 나오거나 엉뚱한 축에 중력이 잡힙니다.
증상은 조용합니다. 값은 그럴듯한데 뜻이 반대입니다. 로봇이 왼쪽으로 도는데 오른쪽으로 돈다고 보고합니다. 앞 화면에서 배운 "조용히 틀림"의 전형입니다.
그래서 IMU 를 연결하면 반드시 손으로 돌려 보십시오. 왼쪽으로 돌릴 때 Z 축 각속도가 양수로 나와야 합니다. 이것 하나만 확인해도 절반은 검증된 것입니다.
| 항목 | 무엇인가 | 주의 |
|---|---|---|
| orientation | 계산된 자세 | 없으면 분산 첫 항목을 음수로 |
| angular_velocity | 자이로 원본 (rad/s) | 왼쪽 회전이 Z 양수 |
| linear_acceleration | 가속도 원본 (m/s²) | 중력 포함, 정지 시 Z 는 +9.81 |
| 각 covariance | 얼마나 믿을지 | 비워 두면 융합이 잘못됨 |
| header.frame_id | IMU 몸체 좌표계 | TF 에 연결되어 있어야 함 |
손으로 돌려 보며 부호를 확인하는 것이 가장 확실한 검증입니다. 값을 읽는 것만으로는 축이 뒤집힌 것을 알 수 없습니다.
# ── 정지 상태에서 축 규약을 확인한다 ────────────────────
ros2 topic echo /imu/data --field linear_acceleration --once
# x: 0.04
# y: -0.02
# z: 9.80 <- 이 값이 +9.81 근처여야 정상
#
# -9.81 이 나오면 Z 축이 뒤집힌 것이고,
# x 나 y 에 9.81 이 나오면 축 자체가 바뀐 것입니다.
# ── 손으로 돌려 보며 부호를 확인한다 (가장 중요) ─────────
ros2 topic echo /imu/data --field angular_velocity
#
# 로봇을 왼쪽(반시계)으로 돌리면서 본다.
# z 가 양수로 커지면 -> 규약이 맞습니다.
# z 가 음수로 커지면 -> 부호가 뒤집혀 있습니다.
# x 나 y 가 커지면 -> 축이 바뀌어 있습니다.
# ── 자세를 계산해 주는 IMU 인지 확인한다 ────────────────
ros2 topic echo /imu/data --field orientation_covariance --once
# [-1.0, 0.0, ...] <- 첫 항목이 -1 이면 자세를 안 준다는 뜻
# [0.01, 0.0, ...] <- 자세를 주고 이 정도 믿으라는 뜻
# ── 갱신 주기와 지연 ──────────────────────────────────
ros2 topic hz /imu/data
ros2 topic delay /imu/data
# IMU 는 보통 100~1000 Hz 입니다. 이보다 훨씬 느리면
# 드라이버 설정이나 통신 경로에 문제가 있습니다.
# ── TF 에 연결되어 있는지 ─────────────────────────────
ros2 run tf2_ros tf2_echo base_link imu_link
주의 IMU 를 로봇의 회전 중심에서 멀리 달면 회전할 때 원심 가속도가 섞입니다. 제자리 회전만 하는데도 가속도계가 옆으로 밀린다고 보고합니다. 가능한 한 회전 중심 가까이, 진동이 적은 곳에 다는 것이 원칙입니다.
5. 무엇을 알 수 있고 무엇을 알 수 없는가
자세는 세 가지 각도로 이루어집니다. 앞뒤 기울기, 좌우 기울기, 그리고 방위. IMU 로 이 셋을 얻는 난이도가 완전히 다릅니다.
앞뒤와 좌우 기울기는 알 수 있습니다.
중력이 어느 방향인지 보면 됩니다. 로봇이 앞으로 기울면 중력이 X 축에도 나뉘어 들어오고, 그 비율로 기울기를 계산할 수 있습니다. 표류하지 않는 절대 기준이 있는 셈입니다.
방위는 알 수 없습니다.
로봇을 제자리에서 돌려도 중력 방향은 전혀 변하지 않습니다. 그래서 가속도계만으로는 로봇이 어느 쪽을 보고 있는지 알 방법이 없습니다. 자이로로 적분할 수는 있지만 앞에서 본 대로 표류합니다.
그래서 방위는 다른 곳에서 와야 합니다. 지자기 센서, 바퀴 회전, 라이다로 본 주변 모양, 위성 항법 중 하나입니다.
두 성질을 합치는 것이 자세 추정의 기본 발상입니다.
자이로는 짧은 시간 동안 정확하고 길게는 표류합니다. 가속도계는 순간적으로는 흔들리지만 길게 보면 중력이라는 절대 기준이 있습니다.
그러면 자이로를 주로 믿되, 가속도계로 천천히 끌어당기면 됩니다. 이것이 상보 필터의 발상이고, 더 정교하게 하면 다음 화면의 칼만 필터가 됩니다.
여기에 결정적인 단서가 하나 더 있습니다. 가속도계로 기울기를 알아내려면 중력 외의 가속이 없어야 합니다. 로봇이 급출발하면 그 가속이 중력과 섞여 기울었다고 착각합니다. 그래서 좋은 구현은 가속도의 크기가 9.81 에서 많이 벗어나면 그 값을 안 씁니다.
| 알고 싶은 것 | IMU 로 되는가 | 어디서 오는가 | 표류하는가 |
|---|---|---|---|
| 앞뒤 기울기 | 됨 | 중력 방향 | 표류 안 함 |
| 좌우 기울기 | 됨 | 중력 방향 | 표류 안 함 |
| 방위 | 안 됨 | 지자기·바퀴·라이다·위성 | 자이로만 쓰면 표류 |
| 회전 속도 | 됨 | 자이로 직접 | 해당 없음 |
| 속도·위치 | 안 됨 | 바퀴·라이다·카메라·위성 | 적분하면 발산 |
자이로 각속도 적분 → 가속도 크기 검사 → 중력 방향으로 롤·피치 보정 → 외부 센서로 요 보정 → 안정된 자세 출력
자이로를 주로 믿되 가속도계로 천천히 끌어당깁니다. 급가속 중에는 가속도계를 쓰지 않는 것이 요령입니다.
주의 IMU 가 자세를 이미 계산해서 주더라도 그것을 그대로 믿지 마십시오. 많은 칩이 어떤 알고리즘으로 계산했는지 알려 주지 않고, 방위는 자기장에 의존해 실내에서 크게 틀립니다. 기울기만 쓰고 방위는 다른 곳에서 받는 구성이 안전합니다.
6. IMU 를 검증하는 순서
IMU 는 조용히 틀리기 가장 쉬운 센서입니다. 값이 항상 그럴듯하게 나오기 때문입니다. 그래서 검증 순서가 특히 중요합니다.
① 정지 시험 — 가장 먼저.
완전히 정지시키고 값을 봅니다. Z 축 가속도가 +9.81 근처인가. 아니면 축 규약이 다릅니다. 각속도가 0 근처인가. 그 차이가 편향입니다.
② 회전 시험 — 부호 확인.
손으로 왼쪽으로 돌리며 Z 축 각속도가 양수인지 봅니다. 이것 하나로 축 뒤집힘의 대부분이 걸러집니다.
③ 기울임 시험 — 축 대응 확인.
로봇 앞쪽을 들어 올리며 어느 축의 가속도가 변하는지 봅니다. 예상과 다른 축이 변하면 축이 바뀌어 있는 것입니다.
④ 적분 시험 — 표류 확인.
정확히 90도 돌린 뒤 적분값이 얼마인지 봅니다. 80도나 100도가 나오면 배율이 틀렸고, 가만히 두었는데 값이 계속 늘어나면 편향이 남아 있는 것입니다.
⑤ 진동 시험 — 실전 조건.
모터를 켜고 로봇을 실제로 주행시키며 값을 봅니다. 책상 위에서 멀쩡하던 IMU 가 주행 중에는 잡음이 열 배가 되는 일이 흔합니다. 이때 잰 잡음이 진짜 잡음입니다.
⑥ 자기 간섭 시험 — 지자기를 쓴다면.
모터를 껐다 켜며 방위값이 튀는지 봅니다. 튄다면 실내에서 지자기는 쓰지 않는 편이 낫습니다.
요점
- 정지 상태에서 az 가 +9.81 근처인지 — 축 규약의 기본
- 왼쪽으로 돌릴 때 z 각속도가 양수인지 — 부호 확인
- 정지 상태의 각속도 평균 — 이것이 편향
- 정지 상태의 표준편차 — 이것이 잡음, 융합에 그대로 씀
- 90도 회전 시험 — 배율 확인
- 모터를 켜고 주행하며 재기 — 진짜 잡음은 여기서 나옴
- orientation_covariance 의 첫 항목 — 자세를 주는지 여부
- IMU 가 회전 중심에서 얼마나 떨어져 있는지
| 증상 | 원인 | 확인·대응 |
|---|---|---|
| 정지인데 az 가 -9.81 | Z 축이 뒤집힘 | 드라이버 축 설정 |
| 정지인데 ax 가 9.81 | 축이 서로 바뀜 | 장착 자세와 드라이버 |
| 왼쪽 회전에 z 가 음수 | 자이로 부호 반전 | 드라이버 설정 |
| 가만히 있는데 각도가 늘어남 | 편향이 남음 | 정지 상태에서 재보정 |
| 90도 돌렸는데 80도 | 배율 오차 | 눈금 보정 |
| 주행 중에만 잡음이 큼 | 모터 진동 | 완충재, 장착 위치 |
| 제자리 회전에 가속도 발생 | IMU 가 회전 중심에서 멂 | 중심 가까이로 이동 |
| 방위가 자꾸 튐 | 자기장 교란 | 지자기 대신 다른 센서 |
| 융합 결과가 이상함 | 분산이 비었거나 잘못됨 | covariance 확인 |
이 코드는 편향과 배율을 한 번에 드러냅니다. 가만히 둘 때와 돌릴 때를 나눠서 보면 두 문제를 구분할 수 있습니다.
# ── 90도 회전 시험 : 배율과 편향을 함께 확인 ────────────
python3 - <<EOF
import rclpy, math
from rclpy.node import Node
from rclpy.qos import qos_profile_sensor_data
from sensor_msgs.msg import Imu
class Integrate(Node):
def __init__(self):
super().__init__('gyro_integrate')
self.yaw = 0.0
self.prev = None
self.create_subscription(Imu, '/imu/data_raw',
self.cb, qos_profile_sensor_data)
self.create_timer(1.0, self.report)
self.get_logger().info('로봇을 천천히 정확히 90도 돌리십시오.')
def cb(self, msg):
now = self.get_clock().now()
if self.prev is not None:
dt = (now - self.prev).nanoseconds / 1e9
self.yaw += msg.angular_velocity.z * dt
self.prev = now
def report(self):
self.get_logger().info(f'적분한 각도 {math.degrees(self.yaw):+7.2f} 도')
rclpy.init(); rclpy.spin(Integrate())
EOF
# 읽는 법
# 가만히 두었는데 값이 계속 늘어난다 -> 편향이 남아 있음
# 90도 돌렸는데 80도가 나온다 -> 배율이 작음
# 90도 돌렸는데 100도가 나온다 -> 배율이 큼
# 돌린 방향과 부호가 반대다 -> 축 부호 반전
주의 책상 위에서 잰 잡음은 실제 잡음이 아닙니다. 모터가 돌고 바퀴가 바닥의 요철을 넘는 동안의 진동이 IMU 에 그대로 들어옵니다. 융합 단계에 넣을 분산값은 반드시 주행 중에 잰 것이어야 합니다. 책상 값을 쓰면 필터가 IMU 를 지나치게 믿게 됩니다.
7. 실제 IMU는 어떻게 생겼는가
IMU는 하나의 외형을 뜻하지 않습니다. 스마트폰과 드론에는 손톱보다 작은 MEMS 칩, 교육용 로봇에는 칩을 납땜한 브레이크아웃 보드, 자율주행 장비에는 방수·방진 케이스와 정밀 시간 동기 기능을 갖춘 산업용 모듈이 쓰입니다. 보드가 커 보이더라도 실제로 진동을 감지하는 부분은 중앙의 수 mm 크기 검은 칩입니다. 주변 회로는 전원 안정화, 통신, 온도 측정과 보호를 담당합니다.

왼쪽부터 핀 헤더가 달린 교육용 브레이크아웃 보드, 커넥터와 고정 나사를 갖춘 로봇 내장형 모듈, 알루미늄 케이스의 산업용 IMU를 재현한 교육용 이미지입니다. 자와 원형 크기 표식을 함께 두어 실제 크기 차이를 짐작할 수 있게 했습니다.
MEMS 가속도계 내부에는 미세한 질량과 스프링 구조가 있습니다. 몸체가 가속하면 질량이 상대적으로 움직이고, 전극 사이 정전용량의 변화를 측정해 가속도로 바꿉니다. MEMS 자이로는 진동하는 구조물에 생기는 코리올리 힘을 이용해 각속도를 측정합니다. 움직이는 부품은 있지만 크기가 매우 작아 칩 안에 들어갑니다.
| 형태 | 장점 | 주의할 점 | 주 사용처 |
|---|---|---|---|
| 칩·브레이크아웃 보드 | 저렴하고 작음 | 전원·레벨·축 방향을 직접 확인 | 교육, 소형 로봇, 드론 |
| 내장형 모듈 | 커넥터와 고정 구조가 안정적 | 드라이버와 시간 동기 지원 확인 | 이동 로봇, 매니퓰레이터 |
| 산업용 밀폐형 | 온도 보상, 낮은 잡음, 견고함 | 가격, 무게, 통신 규격 | 자율주행, 측량, 중장비 |
보드 색이나 크기로 성능을 판단하지 마십시오. 중요한 사양은 자이로·가속도 범위, 출력 데이터율, 잡음 밀도, 영점 불안정성, 온도 특성, 타임스탬프 방식입니다.
8. 좌표계와 장착 방향: REP-103을 실제 로봇에 적용하기
ROS의 몸체 좌표계는 오른손 좌표계를 사용하며 일반적인 지상 로봇은 x 전방, y 좌측, z 위쪽입니다. 양의 회전은 각 축을 바라볼 때 오른손 법칙을 따릅니다. 위에서 보아 반시계 방향 회전은 양의 z 각속도입니다.
센서 보드에 인쇄된 X·Y·Z가 ROS 축과 같다는 보장은 없습니다. 센서가 옆으로 눕거나 뒤집혀 장착되면 고정 TF로 실제 자세를 표현해야 합니다. 원시 숫자의 축만 임의로 바꾸고 TF는 그대로 두는 방식은 유지보수 때 오류를 만듭니다.
# base_link에서 본 imu_link의 고정 자세 확인
ros2 run tf2_ros tf2_echo base_link imu_link
# 예: IMU가 base_link와 같은 방향이고 8 cm 위에 있을 때
ros2 run tf2_ros static_transform_publisher \
--x 0.0 --y 0.0 --z 0.08 \
--roll 0 --pitch 0 --yaw 0 \
--frame-id base_link --child-frame-id imu_link
항공·해양 장비가 자주 쓰는 NED(x 북, y 동, z 아래)와 ROS의 ENU 계열 규약을 혼동하지 마십시오. 드라이버 설명서가 NED라고 밝히면 드라이버 또는 변환 노드에서 명시적으로 변환하고, 출력 프레임 이름에도 그 의미를 반영해야 합니다.
9. 범위, 해상도, 단위와 포화
측정 범위는 넓을수록 무조건 좋은 것이 아닙니다. ±2 g 가속도 범위는 작은 기울기와 진동을 세밀하게 보지만 충격에 쉽게 포화됩니다. ±16 g는 충격을 담을 수 있지만 같은 비트 수에서 한 단계가 더 큽니다. 자이로도 ±125 °/s와 ±2,000 °/s 사이에서 같은 절충이 있습니다.
ROS 메시지에서는 각속도를 rad/s, 선가속도를 m/s²로 표현합니다. 센서 레지스터의 degree/s와 g를 그대로 넣으면 약 57.3배 또는 9.81배의 오류가 생깁니다.
import math
gyro_rad_s = math.radians(gyro_deg_s)
accel_m_s2 = accel_g * 9.80665
포화는 그래프 끝이 평평하게 잘리는 현상입니다. 로봇의 최대 회전·충격에서 값이 범위 끝에 자주 붙으면 범위를 한 단계 넓히십시오. 반대로 포화가 전혀 없고 작은 움직임이 계단처럼 보이면 범위를 줄이는 편이 낫습니다.
10. 출력 주기, 에일리어싱과 진동
샘플링 주파수는 관찰하려는 가장 높은 주파수의 두 배보다 높아야 한다는 나이퀴스트 조건이 출발점입니다. 하지만 실제 필터는 이상적이지 않으므로 여유를 둬야 합니다. 80 Hz 진동을 보고 싶다면 160 Hz가 아니라 400 Hz 이상으로 측정하고 적절한 저역 통과 필터를 적용하는 편이 안전합니다.
바퀴 톱니, 프로펠러, 기어박스 진동이 샘플링 주기와 섞이면 낮은 주파수의 가짜 움직임처럼 보이는 에일리어싱이 생깁니다. 소프트웨어 필터만으로 이미 접힌 신호를 되돌릴 수 없으므로 센서 내부의 아날로그·디지털 저역 통과 필터 설정도 확인해야 합니다.
ros2 topic hz /imu/data_raw
ros2 topic bw /imu/data_raw
ros2 topic delay /imu/data_raw
# 20초 동안 기록하여 정지/모터 켬/주행 상태를 비교
ros2 bag record -o imu_vibration_test /imu/data_raw /tf /tf_static
11. 오차의 종류와 Allan 편차의 의미
한 숫자인 ‘정확도’만으로 IMU를 평가할 수 없습니다. 정지 상태에서도 백색 잡음, 일정한 영점 오차, 온도에 따른 변화, 장시간에 걸친 랜덤 워크가 함께 나타납니다.
| 오차 | 관찰되는 모습 | 기본 대응 |
|---|---|---|
| 바이어스 | 정지 평균이 0이 아님 | 시작 시 평균을 빼기 |
| 백색 잡음 | 평균 주위의 빠른 흔들림 | 저역 통과, 적절한 공분산 |
| 바이어스 불안정성 | 평균이 천천히 이동 | 온도 보상, 외부 관측 융합 |
| 스케일 팩터 | 90° 회전에 86°처럼 비례 오차 | 기준 회전으로 배율 보정 |
| 축 비직교·교차축 | 한 축 운동이 다른 축에 나타남 | 다축 보정 행렬 |
Allan 편차는 긴 정지 데이터를 여러 평균 시간으로 묶어 잡음 종류와 안정 시간을 보는 방법입니다. 처음부터 복잡한 계수를 모두 추정하기보다, 먼저 30분 이상 정지 기록을 남겨 ‘몇 초 평균할 때 가장 안정적인가’를 찾는 데 활용하십시오.
12. 가속도계 6면 보정과 자이로 보정
자이로 영점은 정지 상태 평균으로 비교적 쉽게 구합니다. 가속도계는 중력이 항상 섞이므로 보드를 +X, -X, +Y, -Y, +Z, -Z가 위를 향하도록 여섯 번 놓아 각 자세에서 충분히 평균냅니다. 이상적이라면 위를 향한 축은 +g, 아래를 향한 축은 -g, 나머지는 0입니다.
단일 축의 간단한 보정은 다음처럼 구할 수 있습니다.
G = 9.80665
def calibration(positive_face_mean, negative_face_mean):
bias = (positive_face_mean + negative_face_mean) / 2.0
scale = (2.0 * G) / (positive_face_mean - negative_face_mean)
return bias, scale
def correct(raw, bias, scale):
return (raw - bias) * scale
정밀 보정은 세 축의 비직교성까지 포함한 3×3 행렬을 사용합니다. 자기계는 로봇을 여러 방향으로 회전해 점 구름을 모은 뒤 중심이 이동하는 hard-iron 오차와 타원으로 찌그러지는 soft-iron 오차를 보정합니다. 모터 전류가 바뀔 때 자기장이 달라지면 정적 보정만으로 해결되지 않습니다.
13. 공분산을 올바르게 채우기
sensor_msgs/msg/Imu의 세 공분산은 각각 행 우선 3×3 배열입니다. 대각 원소는 각 축 분산, 비대각 원소는 축 사이 공분산입니다. 자세를 제공하지 않으면 orientation_covariance[0] = -1로 표시합니다. 모든 원소가 0인 배열은 ‘오차가 0’이 아니라 공분산을 알 수 없음을 뜻하므로, 소비 노드가 기본값을 선택할 수 있습니다.
표준편차가 σ라면 분산은 σ²입니다. 도 단위 표준편차는 라디안으로 바꾼 뒤 제곱해야 합니다.
import math
gyro_std_deg_s = 0.12
gyro_var = math.radians(gyro_std_deg_s) ** 2
msg.angular_velocity_covariance = [
gyro_var, 0.0, 0.0,
0.0, gyro_var, 0.0,
0.0, 0.0, gyro_var,
]
msg.orientation_covariance[0] = -1.0 # 자세를 제공하지 않음
필터가 IMU를 지나치게 따라가면 공분산이 너무 작은지, 거의 무시하면 너무 큰지 확인합니다. 숫자를 감으로 조정하기 전에 실제 주행 로그에서 평균과 표준편차를 측정하십시오.
14. 타임스탬프, 지연과 동기화
고속 센서 융합에서는 값만큼 시간이 중요합니다. header.stamp는 메시지를 ROS가 받은 시각이 아니라 측정이 일어난 시각이어야 합니다. 카메라가 80 ms 늦고 IMU가 5 ms 늦는데 둘을 같은 현재 시각의 값으로 합치면 회전 중에 공간 정합이 어긋납니다.
장치가 자체 하드웨어 시계를 쓴다면 ROS 시계로 변환하는 오프셋과 드리프트가 필요합니다. 여러 컴퓨터를 쓰는 로봇은 PTP 또는 NTP 상태도 확인합니다. /use_sim_time을 켠 시뮬레이션에서는 모든 노드가 /clock을 사용해야 합니다.
ros2 topic echo /imu/data_raw --field header --once
ros2 topic delay /imu/data_raw
ros2 param get /imu_driver use_sim_time
콜백에서 now()로 적분 간격을 재기보다 연속한 메시지의 header.stamp 차이를 사용해야 네트워크 지터의 영향을 줄일 수 있습니다.
15. 상보 필터와 EKF: 어떤 상황에 무엇을 쓰는가
상보 필터는 빠른 자이로 자세에 느린 중력 기준을 섞는 간단하고 해석 가능한 방법입니다. 저가형 로봇의 롤·피치 안정화나 학습용으로 좋습니다. EKF는 IMU, 바퀴 오도메트리, GPS, 비전·LiDAR 오도메트리처럼 여러 상태와 공분산을 함께 다룰 때 적합합니다.
| 상황 | 권장 출발점 | 이유 |
|---|---|---|
| 2륜 실내 로봇의 자세 안정 | 상보 필터 또는 IMU 드라이버 자세 | 구성이 단순하고 롤·피치가 핵심 |
| 바퀴 오도메트리와 IMU 결합 | robot_localization EKF |
속도·회전과 공분산을 일관되게 융합 |
| 드론 자세 제어 | 고주기 전용 자세 필터 | 낮은 지연과 높은 주기가 중요 |
| 실외 절대 위치·방위 | EKF + GNSS/절대 방위 | IMU만으로 장시간 기준을 유지할 수 없음 |
자기계나 외부 방위 관측이 없으면 요는 장기적으로 관측 불가능하고 표류합니다. EKF를 쓴다고 물리적으로 없는 정보가 생기지는 않습니다. 필터는 센서를 대체하지 않고, 서로 다른 센서의 장단점을 공분산에 따라 조합합니다.
16. 실습: IMU 상태 감시 노드 만들기
다음 노드는 단위·유한값·주기·중력 크기·포화 가능성을 검사합니다. 실제 제품에서는 진단 메시지로 연결할 수 있지만, 먼저 로그로 판단 규칙을 확인해 봅니다.
#!/usr/bin/env python3
import math
import rclpy
from rclpy.node import Node
from rclpy.qos import qos_profile_sensor_data
from sensor_msgs.msg import Imu
class ImuMonitor(Node):
def __init__(self):
super().__init__('imu_monitor')
self.last_stamp = None
self.count = 0
self.bad = 0
self.create_subscription(
Imu, '/imu/data_raw', self.on_imu, qos_profile_sensor_data)
self.create_timer(2.0, self.report)
@staticmethod
def stamp_sec(stamp):
return stamp.sec + stamp.nanosec * 1e-9
def on_imu(self, msg):
values = [msg.angular_velocity.x, msg.angular_velocity.y,
msg.angular_velocity.z, msg.linear_acceleration.x,
msg.linear_acceleration.y, msg.linear_acceleration.z]
if not all(math.isfinite(v) for v in values):
self.bad += 1
self.get_logger().error('NaN 또는 무한대 IMU 값')
return
stamp = self.stamp_sec(msg.header.stamp)
if self.last_stamp is not None:
dt = stamp - self.last_stamp
if dt <= 0.0 or dt > 0.05: # 목표가 100 Hz 이상인 예
self.get_logger().warning(f'비정상 측정 간격: {dt:.4f} s')
self.last_stamp = stamp
a = msg.linear_acceleration
magnitude = math.sqrt(a.x*a.x + a.y*a.y + a.z*a.z)
if not 7.0 < magnitude < 13.0:
self.get_logger().warning(
f'중력과 크게 다른 가속도 크기: {magnitude:.2f} m/s^2')
self.count += 1
def report(self):
self.get_logger().info(
f'최근 2초 수신={self.count}, 잘못된 값={self.bad}')
self.count = 0
self.bad = 0
def main():
rclpy.init()
node = ImuMonitor()
try:
rclpy.spin(node)
finally:
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
chmod +x imu_monitor.py
python3 imu_monitor.py
# QoS가 맞지 않아 수신되지 않으면 양쪽 설정 확인
ros2 topic info /imu/data_raw --verbose
17. 실제 로봇 장착 원칙
IMU는 가능한 한 로봇 회전 중심에 가깝고, 프레임에 단단히 고정되며, 모터·감속기·냉각팬의 고주파 진동과 자기장에서 떨어진 곳에 둡니다. 너무 부드러운 스펀지는 센서가 프레임과 따로 흔들리는 공진을 만들 수 있으므로, 완충재는 주파수 측정 후 선택해야 합니다.
전원 노이즈가 심하면 별도 레귤레이터, 디커플링, 차폐와 접지 구조를 점검합니다. I²C는 짧은 내부 배선에 적합하고, 긴 케이블과 전기적 잡음이 큰 환경에서는 CAN, RS-422/485, Ethernet 계열 산업용 모듈이 유리합니다.
장착 후에는 다음 순서로 검증합니다.
전원 켜기 전 완전 정지 → 정지 편향 측정 → 손으로 세 축 회전 → 정확한 90° 회전 → 모터만 구동 → 실제 노면 주행 → rosbag 비교 → 공분산과 필터 조정
18. 문제 해결표와 배포 체크리스트
| 증상 | 우선 확인 | 해결 방향 |
|---|---|---|
| 토픽이 수신되지 않음 | 이름, 타입, QoS 호환성 | topic info --verbose로 양끝 비교 |
| 값이 57배 차이 | degree/s와 rad/s | SI 단위로 변환 |
정지 az가 -9.81 |
장착 방향, 축 변환 | 고정 TF와 드라이버 설정 수정 |
| 각도가 계속 흐름 | 자이로 편향·온도 | 예열, 정지 보정, 외부 기준 융합 |
| 모터를 켜면 값 폭증 | 기계 진동·전원 노이즈 | 위치 변경, 필터, 전원·고정 개선 |
| 자세가 순간 뒤집힘 | 쿼터니언 정규화·축 규약 | 메시지와 변환 단계 검사 |
| 융합 결과가 느림 | 타임스탬프·지연·공분산 | 측정 시각 사용, 지연 및 분산 재측정 |
배포 전에는 frame_id, SI 단위, 축 부호, 출력 주기, 타임스탬프 단조 증가, 공분산, 포화 여유, 온도 안정 시간, 실제 주행 진동, rosbag 재현 가능성을 모두 기록합니다. 이 기록이 있어야 센서를 교체하거나 장착 위치를 바꿨을 때 같은 기준으로 비교할 수 있습니다.
- IMU관성 측정 장치
- 가속도계와 자이로스코프를 조합해 선가속도와 각속도를 측정하는 센서 장치입니다.
- Accelerometer가속도계
- 몸체에 작용하는 특정 힘을 세 축에서 측정하며 정지 상태에서는 중력의 영향을 함께 관측합니다.
- Gyroscope자이로스코프
- 세 축 주위의 각속도를 측정하는 센서로 각도는 각속도를 시간에 따라 적분해 추정합니다.
- Magnetometer자기계
- 주변 자기장 벡터를 측정해 방위 기준으로 사용할 수 있지만 모터와 철 구조물의 간섭에 민감합니다.
- MEMS미세전자기계시스템
- 반도체 공정으로 미세한 기계 구조와 전자 회로를 하나의 Chip에 구현하는 기술입니다.
- Bias편향
- 참값이 0이어야 할 때도 Sensor 출력에 일정하거나 천천히 변하며 남는 영점 오차입니다.
- Drift표류
- 편향과 잡음이 적분되면서 추정 자세·속도·위치가 시간에 따라 참값에서 멀어지는 현상입니다.
- Specific Force특정 힘
- 가속도계가 측정하는 비중력 힘으로 자유낙하 상태에서는 0에 가까워집니다.
- Saturation포화
- 실제 움직임이 Sensor 측정 범위를 넘어 출력이 최대 또는 최소값에서 잘리는 현상입니다.
- Aliasing에일리어싱
- Sampling 주파수가 부족해 높은 주파수 진동이 낮은 주파수의 가짜 Signal로 나타나는 현상입니다.
- Covariance공분산
- 측정값의 불확실성과 축 사이 관계를 나타내며 Sensor Fusion에서 각 측정을 얼마나 믿을지 결정합니다.
- Allan Deviation앨런 편차
- 여러 평균 시간에 대한 Sensor 안정도를 분석해 백색 잡음과 Bias 불안정성 등을 구분하는 지표입니다.
- Complementary Filter상보 필터
- 빠르지만 표류하는 자이로와 느리지만 절대 기준을 주는 가속도계의 주파수 특성을 결합하는 자세 Filter입니다.
- EKF확장 칼만 필터
- 비선형 System Model을 국소 선형화하고 여러 Sensor 측정과 공분산을 결합해 상태를 추정하는 Filter입니다.
- Quaternion쿼터니언
- 특이점 없이 3차원 회전을 표현하는 네 성분 표현으로 ROS 자세 Message에 사용됩니다.
- ENU동-북-상 좌표계
- East, North, Up 방향을 축으로 사용하는 오른손 좌표계이며 ROS의 지리 좌표 규약에 사용됩니다.
- NED북-동-하 좌표계
- North, East, Down 방향을 축으로 사용하는 항공·해양 분야의 좌표계입니다.
- Hard-iron Error고정 자기장 오차
- Robot의 자석이나 직류 자기장 때문에 Magnetometer 측정 중심이 원점에서 이동하는 오차입니다.
- Soft-iron Error자기장 왜곡 오차
- 주변 강자성 물질이 자기장을 방향별로 다르게 왜곡해 Magnetometer 점군이 타원형이 되는 오차입니다.
- Time Synchronization시간 동기화
- 서로 다른 Sensor의 측정 시각을 같은 시간 기준에 맞춰 움직이는 Robot에서도 올바르게 결합하는 과정입니다.
연습 문제
- 정지 상태 500개 샘플에서 자이로 편향과 표준편차를 구하십시오.
- IMU의 여섯 면을 위로 두고 가속도계 축별 편향과 배율을 계산하십시오.
- 왼쪽 90° 회전에서
z부호와 적분 각도를 확인하십시오. - 모터 끔·공회전·주행 세 조건을 rosbag으로 기록해 표준편차를 비교하십시오.
header.stamp기준 측정 주기와 콜백 도착 시각 기준 주기의 차이를 비교하십시오.- 실제 장착 위치에서
base_link → imu_link변환을 문서화하십시오. - 포화 임곗값과 누락 메시지를 감지하도록 감시 노드를 확장하십시오.
- 공분산을 10배 작게·크게 바꿔 융합 결과가 어떻게 달라지는지 관찰하십시오.
- 가속도계 범위를 바꾸고 정지 잡음과 충격 포화 빈도를 비교하십시오.
- 출력 데이터율과 저역 통과 필터 설정을 바꾸어 모터 진동 스펙트럼을 비교하십시오.
- 30분 정지 기록에서 1초·10초·60초 이동 평균의 안정도를 계산하십시오.
- 급출발 구간에서 가속도 크기 조건을 적용한 상보 필터와 적용하지 않은 결과를 비교하십시오.
- 자기계 보정 전후의 XY 점군을 그리고 원점 이동과 타원 왜곡을 설명하십시오.
- IMU와 바퀴 오도메트리의 타임스탬프를 인위적으로 50 ms 어긋나게 해 융합 오차를 관찰하십시오.
- 센서 고장·타임스탬프 역행·토픽 중단 시 감속 또는 안전 정지 정책을 설계하십시오.
참고 자료
19. 확인 퀴즈 15문항
답을 선택한 뒤 정답 확인을 누르세요. 정답과 해설은 제출 후에 표시됩니다.
1. IMU 가 절대 직접 잴 수 없는 것은?
IMU 가 재는 것은 가속도와 각속도뿐입니다. 위치는 가속도를 두 번 적분해야 얻어지는데 그 과정에서 오차가 시간의 제곱으로 커져 사실상 불가능합니다.
2. 가만히 놓아둔 가속도계가 0 이 아니라 약 9.81 을 내놓는 이유는?
이것은 결함이 아니라 오히려 쓸모입니다. 가만히 있을 때 중력이 어느 방향인지 알려 주므로, 로봇이 앞뒤와 좌우로 얼마나 기울어져 있는지를 그 값에서 계산해 낼 수 있습니다.
3. 자이로가 직접 알려 주는 것은?
각도가 아니라 각속도입니다. 각도를 얻으려면 적분해야 하는데, 편향 때문에 시간에 비례해 오차가 쌓이므로 아주 짧은 시간 동안만 그 값을 믿을 수 있습니다.
4. 자이로 편향이 초당 0.5도일 때 5분 뒤의 각도 오차는?
한 번 적분하는 값이므로 오차가 시간에 비례해 늘어납니다. 아주 좋은 센서의 편향값인데도 몇 분이면 로봇이 어디를 보고 있는지 방향을 완전히 잃게 됩니다.
5. 가속도계 편향 0.1 m/s² 로 1분간 적분했을 때의 위치 오차는?
두 번 적분하므로 오차가 시간의 제곱으로 커집니다. 10초에 5 m, 30초에 45 m 로 늘어나며 이것이 IMU 로 위치를 추정하는 것이 사실상 불가능한 이유입니다.
6. 더 비싸고 좋은 IMU 를 사면 위치 추정 문제가 해결되는가?
제곱으로 커지는 오차는 더 좋은 부품으로 해결되지 않습니다. 표류하지 않는 다른 센서와 합치는 것이 유일한 답이며 이것이 센서 융합의 출발점입니다.
7. IMU 의 편향을 재는 표준적인 방법은?
가만히 있으면 각속도의 참값이 0 이므로 평균값이 곧 편향입니다. 켤 때마다 다시 재는 것이 좋고 많은 드라이버가 시작할 때 자동으로 이것을 합니다.
8. 로봇을 들고 흔들면서 전원을 켜면 안 되는 이유는?
이후 로봇은 가만히 있어도 계속 돌고 있다고 믿게 됩니다. 많은 드라이버가 시작 직후 몇 초 동안 자동으로 편향을 재므로 그 사이에는 로봇을 건드리면 안 됩니다.
9. 편향을 잘 보정해도 몇 분 뒤 다시 어긋나는 이유는?
전자 부품이 데워지면서 특성이 바뀌고, 시간이 지나면서도 값이 천천히 흘러갑니다. 그래서 표류하지 않는 다른 센서로 계속 보정해 주는 구조가 반드시 필요합니다.
10. Imu 메시지에서 자세를 계산해 주지 않는 IMU 는 그 사실을 어떻게 표시하는가?
이 관례를 지키지 않으면 뒤의 융합 단계가 비어 있는 값을 진짜로 믿고 씁니다. 앞 화면에서 배운 분산 배열의 역할이 여기서 구체적으로 드러납니다.
11. ROS 규약에서 정지 상태의 IMU 가 내놓아야 할 Z 축 가속도는?
X 가 앞, Y 가 왼쪽, Z 가 위인 규약을 따르기 때문입니다. -9.81 이 나오면 Z 축이 뒤집힌 것이고, x 나 y 에서 9.81 이 나오면 축 자체가 바뀐 것입니다.
12. IMU 를 연결한 뒤 반드시 해야 할 가장 간단한 검증은?
값을 읽는 것만으로는 축이 뒤집힌 것을 알 수 없습니다. 이 확인 하나로 축 뒤집힘의 대부분이 걸러지며 부호가 반대면 로봇이 회전 방향을 반대로 보고하게 됩니다.
13. 가속도계만으로 알 수 없는 것은?
기울기는 중력 방향이라는 표류하지 않는 절대 기준이 있어 얻을 수 있지만, 방위는 그런 기준이 없습니다. 지자기, 바퀴, 라이다, 위성 중 하나에서 받아야 합니다.
14. 가속도계로 기울기를 계산할 때 급출발 중에는 값을 쓰지 않는 이유는?
가속도계는 중력과 운동 가속을 구분하지 못합니다. 그래서 좋은 구현은 가속도의 크기가 9.81 에서 많이 벗어나면 그 값을 기울기 계산에 쓰지 않습니다.
15. 융합 단계에 넣을 IMU 잡음값은 언제 재야 하는가?
책상 위에서 멀쩡하던 IMU 가 주행 중에는 잡음이 열 배가 되는 일이 흔합니다. 책상 값을 쓰면 필터가 IMU 를 지나치게 믿게 되어 결과가 나빠집니다.
COMMUNITY
강의 댓글
질문과 학습 경험을 함께 나눠보세요.댓글을 불러오는 중입니다.