Visualize object rotations in real time

Hey all!

I want to preface this by saying I’m fairly new to VTK. For some background, I’m sending gyro and accelerometer data over serial from an Arduino. I’m then passing it through an IMU data fusion algorithm, and finally visualizing the object virtually with a cube.

My application would take place in the last step as I want to be able to pass the roll, pitch, and yaw parameters to an STL object with VTK to visualize the orientation in real time.

I would greatly appreciate any clarifying questions, example code, or other information.

Thank you in advance!

Here I think you need to make a rotation matrix from euler rotation data, i.e. yaw, pitch and roll data and apply it to the actor.

For this the function euler2rotation_matrix(z, y, x) should do the trick.
z=yaw
y=pitch
x=roll

The vtkMatrix must be in 4x4 format.

def euler2rotation_matrix(z, y, x):
    sz = np.sin(z)
    cz = np.cos(z)
    sy = np.sin(y)
    cy = np.cos(y)
    sx = np.sin(x)
    cx = np.cos(x)

    a11 = cz * cy
    a12 = cz * sy * sx - cx * sz
    a13 = sz * sx + cz * cx * sy
    a21 = cy * sz
    a22 = cz * cx + sz * sy * sx
    a23 = cx * sz * sy - cz * sx
    a31 = -sy
    a32 = cy * sx
    a33 = cy * cx

    R = np.asarray([[a11, a12, a13, 0], [a21, a22, a23, 0], [a31, a32, a33, 0], [0, 0, 0, 1]])

    return R
def rotation_matrix_to_vtk(matrix):
    vtk_matrix = vtkMatrix4x4()
    for i in range(4):
        for j in range(4):
            vtk_matrix.SetElement(i, j, matrix[i][j])
    return vtk_matrix

and final apply

yaw = 30
pitch = 20
roll = 10
rotation_matrix = euler2rotation_matrix(np.radians(roll), np.radians(pitch), np.radians(yaw))
vtk_matrix = rotation_matrix_to_vtk(rotation_matrix)
actor.SetUserMatrix(vtk_matrix)

If you save it continuously after this stage, it will work.

How should I continuously update the view? Should I use the .AddObserver method to run the function on a timer?

# prints and resets to initial orientation
def print_camera_orientation_callback(obj, event):
    print(camera.GetOrientation())
    set_orientation(renderer, {'position': (0.0, 0.0, 200.0), 'focal point': (0.0, 0.0, 0.0), 'view up': (1.0, 0.0, 0.0), 'distance': 200.0, 'clipping range': (0.01, 1000.01), 'orientation': (0.0, -0.0, 0.0)})

    render_window.Render()

# adds interactor on keypress
timer_id = render_window_interactor.CreateRepeatingTimer(10)
render_window_interactor.AddObserver('TimerEvent', print_camera_orientation_callback, 1.0)

# render scene
render_window.Render()

# start interactor
render_window_interactor.Start()

This is what I currently have and it’s not able to continuously repeat.

I see, you can add

render_window_interactactor.Render()

since what you are doing is in the interactor, you need to constantly update it as well.

I see. This is what I currently have. read_data() is a function that simply reads data from serial.

  1. I have an issue where the rendered window will freeze after a period of time (~5 - 30 seconds), but the while loop doesn’t (tested by printing a counter).
  2. I have another issue where the matrix transformation occurs about the edge of my object rather than the center. I’ve referenced this math stack exchange page to try to fix the matrix transform issue, but haven’t had any luck.

If you’re able to help with any of these issues, it would be greatly appreciated!

# prints and resets to initial orientation
def print_camera_orientation_callback(obj, event):
    while True:
        _, _, _, gx, gy, gz = read_data()

        rotation_matrix = euler2rotation_matrix(np.radians(gx), np.radians(gz), np.radians(gy))

        vtk_matrix = rotation_matrix_to_vtk(rotation_matrix)

        actor.SetUserMatrix(vtk_matrix)

        render_window.Render()
        render_window_interactor.Render()

# adds interactor on keypress
render_window_interactor.AddObserver('KeyPressEvent', print_camera_orientation_callback, 1.0)

# render scene
render_window.Render()

# start interactor
render_window_interactor.Start()

Have you solved the problem?

I have been able to solve this for the most part. I have a very basic implementation by integrating a gyro, but I want a quaternion based visual as it helps to eliminate gyro drift, as well as gimble lock. If you have any ideas to implement this, it would be appreciated.

As for my current set up, I can post some sample code later.

I see,

for quaternion this code helps you i think

transform = vtkTransform()
quat = vtkQuaterniond()
radian_angle = np.deg2rad(angle)
if axis == "x":
    quat.SetRotationAngleAndAxis(radian_angle, [1, 0, 0])
if axis == "y":
    quat.SetRotationAngleAndAxis(radian_angle, [0, 1, 0])
if axis == "z":
    quat.SetRotationAngleAndAxis(radian_angle, [0, 0, 1])

mtxRot = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
vtkMath().QuaternionToMatrix3x3(quat, mtxRot)
# Rotation: convert 3x3 to 4x4 matrix
mtxTr2 = vtkMatrix4x4()  # identity mtx
 for i in range(3):
      for j in range(3):
          mtxTr2.SetElement(i, j, mtxRot[i][j])
transform.SetMatrix(mtxTr2)
transform_filter = vtkTransformFilter()
transform_filter.SetTransform(transform)
transform_filter.SetInputData(actor.GetMapper().GetInput())
transform_filter.Update()

transformed_data = transform_filter.GetOutput()

transformed_mapper = vtkDataSetMapper()
transformed_mapper.SetInputData(transformed_data)

actor.SetMapper(transformed_mapper)