소스 뷰어
print( "Hello ...", flush=1 )
print( "Initiating MPU6050 ...", flush=1 )

from MPU6050 import init_mpu6050
from time import sleep 
import math, time
import numpy as np
from scipy.signal import butter, filtfilt

mpu, packet_size, fifo_buffer = init_mpu6050()

print( "Done.\n" )

g = 9.8 # gravity acceleration (m/s^2)

accel_coeff = g/(2**14)
admp_coeff = accel_coeff*2
gyro_coeff = 250 / 2**15
g_cali_coeff = 1 # 중력 가속도 보정 계수

cali_start = -1
cali_end = -1
cali_duration = 20 # 캘리브레이션 시간
g_cali = 0
g_cali_diff = g # 캘리브레이션 차이

then = time.time()

velocity = np.array( [0, 0, 0], float )
position = np.array( [0, 0, 0], float )

duration = 0.01
count = 0

# 캘리브레이션 가속도 데이터 (X, Y, Z 축 가속도)
accel_cali_data = []

# 저주파 필터를 사용하여 중력 성분 추출
def low_pass_filter(data, cutoff=0.1, fs=50, order=4):
    nyquist = 0.5 * fs
    normal_cutoff = cutoff / nyquist
    b, a = butter(order, normal_cutoff, btype='low', analog=False)
    return filtfilt(b, a, data, axis=0)
pass

while 1 :
    if not mpu.isreadyFIFO(packet_size):
        # Check if FIFO data are ready to use...
        continue
    pass

    sleep( duration )

    count += 1
        
    FIFO_buffer = mpu.get_FIFO_bytes(packet_size)

    now = time.time()
    elapsed = now - then
    then = now

    # raw acceleration
    accel = mpu.get_acceleration()
    accel.x = accel.x * accel_coeff
    accel.y = accel.y * accel_coeff
    accel.z = accel.z * accel_coeff
    
    # quaternion
    q = mpu.DMP_get_quaternion_int16(FIFO_buffer)
    q.normalize()

    # world-frame acceleration vectors (practical for INS)
    accel_linear = mpu.get_linear_accel(accel, q)
    ax = accel_linear.x 
    ay = accel_linear.y 
    az = accel_linear.z

    if cali_start < 0 :
        print( f"Calibrating gravity coefficients for {cali_duration} seconds ...." )
        print( "Please place the IMU on a flat, horizontal surface.", flush=1)
        input( "Enter to continue, please ... ")
        cali_start = time.time()
        count = 0 
    elif g_cali_diff > 0.01 : # 캘리브레이션
        g_measure = math.sqrt( ax*ax + ay*ay + az*az )

        if len( accel_cali_data ) > 1_000 :
            accel_cali_data.pop( 0 )
        pass
    
        accel_cali_data.append( [ax, ay, az] )

        if len( accel_cali_data ) < 20 :
            count = 0 
            continue 
        pass

        # X, Y, Z 축에 대해 필터 적용
        # 중력 벡터의 크기를 통해 중력 가속도 계산
        
        gravity = low_pass_filter( np.array( accel_cali_data) )
        gravity_magnitude = np.linalg.norm(gravity, axis=1)
        gravity_average = np.mean(gravity_magnitude)

        g_cali_coeff = g/gravity_average
        g_cali = g_measure*(g_cali_coeff)
        g_cali_diff = abs( g_cali - g )

        print( f"[{count:4d}] [{(now - cali_start):4.1f} sec. ] Gravity:", end="")
        print( f" avg = {gravity_average:6.3f}", end="")
        print( f", measure = {g_measure:6.3f}", end="")
        print( f", cali = {g_cali:6.3f} m/s2", end="" )
        print()
    elif cali_start > 0 and cali_end < 0 :
        count = 0 
        cali_end = time.time()
        print( "Success calibrating IMU.")
        print()
        input( "Enter to continue, please ... ")
    pass

    if cali_end < 0 :
        continue
    pass

    dt = elapsed

    accel = np.array( [ax, ay, az], float )
    
    # accelation calibrqation
    accel_cali = accel*g_cali_coeff
    accel_cali[2] -= g # 중력 가속도 감쇠

    velocity += accel_cali*dt 
    position += velocity*dt
    
    print( f'[{count:4d}] World Gravity     ', end="" )
    print( f'  x: {ax:13.5f}', end="" )
    print( f', y: {ay:13.5f}', end="" )
    print( f', z: {az:13.5f} m/s2' )

    print( f'[{count:4d}] World G calibrated', end="" )
    print( f'  x: {accel[0]*g_cali_coeff:13.5f}', end="" )
    print( f', y: {accel[1]*g_cali_coeff:13.5f}', end="" )
    print( f', z: {accel[2]*g_cali_coeff:13.5f} m/s2' )

    print( f'[{count:4d}] World Accelration ', end="" )
    print( f'  x: {accel_cali[0]:13.5f}', end="" )
    print( f', y: {accel_cali[1]:13.5f}', end="" )
    print( f', z: {accel_cali[2]:13.5f} m/s2' )

    print( f'[{count:4d}] World Velocity    ', end="" )
    print( f'  x: {velocity[0]:13.5f}', end="" )
    print( f', y: {velocity[1]:13.5f}', end="" )
    print( f', z: {velocity[2]:13.5f} m/s' )

    print( f'[{count:4d}] World Position    ', end="" )
    print( f'  x: {position[0]:13.5f}', end="" )
    print( f', y: {position[1]:13.5f}', end="" )
    print( f', z: {position[2]:13.5f} m' )

    print( "-"*86 )

pass