import math


G = 9.80665


def mat_vec_mul(R, v):
    return [
        R[0][0] * v[0] + R[0][1] * v[1] + R[0][2] * v[2],
        R[1][0] * v[0] + R[1][1] * v[1] + R[1][2] * v[2],
        R[2][0] * v[0] + R[2][1] * v[1] + R[2][2] * v[2],
    ]


def mat_transpose(R):
    return [
        [R[0][0], R[1][0], R[2][0]],
        [R[0][1], R[1][1], R[2][1]],
        [R[0][2], R[1][2], R[2][2]],
    ]


def rotation_matrix_body_to_world(rpy_deg):
    """
    rpy_deg = [roll, pitch, yaw], degree

    Convention:
        roll  around X
        pitch around Y
        yaw   around Z

    R_body_to_world = Rz(yaw) @ Ry(pitch) @ Rx(roll)
    """

    roll = math.radians(rpy_deg[0])
    pitch = math.radians(rpy_deg[1])
    yaw = math.radians(rpy_deg[2])

    cr, sr = math.cos(roll), math.sin(roll)
    cp, sp = math.cos(pitch), math.sin(pitch)
    cy, sy = math.cos(yaw), math.sin(yaw)

    return [
        [cy * cp, cy * sp * sr - sy * cr, cy * sp * cr + sy * sr],
        [sy * cp, sy * sp * sr + cy * cr, sy * sp * cr - cy * sr],
        [-sp,     cp * sr,                  cp * cr],
    ]

#####################################################################

dt = 0.02

rpy_deg = [10, 20, 30]

linear_acc_ms2 = [3.2, 5.5 , 7.7]           #   linear acc in imu body frame

vel_world = [0.0, 0.0, 0.0]                 #   linear vel in world frame


#   get direction cosine matrix
R_bw = rotation_matrix_body_to_world(rpy_deg)
R_wb = mat_transpose(R_bw)


#   Convert acceleration body -> world
acc_world_mps2 = mat_vec_mul(R_bw, linear_acc_ms2)

#   Integrate velocity in world frame
vel_world[0] += acc_world_mps2[0] * dt
vel_world[1] += acc_world_mps2[1] * dt
vel_world[2] += acc_world_mps2[2] * dt

#   Convert velocity world -> current body
vel_body = mat_vec_mul(R_wb, vel_world)

