Rotating a GLMeshItem Box

397 views
Skip to first unread message

Brandon

unread,
Jul 12, 2017, 3:50:54 PM7/12/17
to pyqtgraph
I'd like to show a rotating cube in 3D reflecting roll/pitch/yaw updates from my IMU.
I've developed the code to display the box using GLMeshItem, now I'd like to add an update function that rotates it based on a rotation matrix derived from the IMU data.

I'm new to Qt, so please feel free to suggest an alternate methods.  I may be barking up the wrong tree.  I searched the docs and web a bit and tried a few things which didn't work.
Any suggestions will be appreciated.

When I run the code below "box3d.py" (derived from GLVolumeItem.py) I get the following exception in my update function.  My update function blows:
Error while drawing item <pyqtgraph.opengl.items.GLMeshItem.GLMeshItem object at 0x7f4bdf664478>.
[14:34:24]  

    |==============================>>
    |  Traceback (most recent call last):
    |    File "box3d.py", line 105, in <module>
    |      if __name__ == '__main__':
    |    File "/usr/lib/python2.7/bdb.py", line 49, in trace_dispatch
    |      return self.dispatch_line(frame)
    |    File "/usr/lib/python2.7/bdb.py", line 67, in dispatch_line
    |      self.user_line(frame)
    |    File "/usr/lib/python2.7/pdb.py", line 158, in user_line
    |      self.interaction(frame, None)
    |    File "/usr/lib/python2.7/pdb.py", line 210, in interaction
    |      self.cmdloop()
    |    File "/usr/lib/python2.7/cmd.py", line 130, in cmdloop
    |      line = raw_input(self.prompt)
    |    File "/usr/lib/python2.7/dist-packages/pyqtgraph/opengl/GLViewWidget.py", line 179, in paintGL
    |      self.drawItemTree(useItemNames=useItemNames)
    |    File "/usr/lib/python2.7/dist-packages/pyqtgraph/opengl/GLViewWidget.py", line 219, in drawItemTree
    |      self.drawItemTree(i, useItemNames=useItemNames)
    |    File "/usr/lib/python2.7/dist-packages/pyqtgraph/opengl/GLViewWidget.py", line 200, in drawItemTree
    |      debug.printExc()
    |    --- exception caught here ---
    |    File "/usr/lib/python2.7/dist-packages/pyqtgraph/opengl/GLViewWidget.py", line 197, in drawItemTree
    |      i.paint()
    |    File "/usr/lib/python2.7/dist-packages/pyqtgraph/opengl/items/GLMeshItem.py", line 167, in paint
    |      self.parseMeshData()
    |    File "/usr/lib/python2.7/dist-packages/pyqtgraph/opengl/items/GLMeshItem.py", line 148, in parseMeshData
    |      self.normals = md.faceNormals(indexed='faces')
    |    File "/usr/lib/python2.7/dist-packages/pyqtgraph/opengl/MeshData.py", line 188, in faceNormals
    |      self._faceNormals = np.cross(v[:,1]-v[:,0], v[:,2]-v[:,0])
    |    File "/usr/lib/python2.7/dist-packages/numpy/core/numeric.py", line 1682, in cross
    |      raise ValueError(msg)
    |  ValueError: incompatible dimensions for cross product
    |  (dimension must be 2 or 3)
    |==============================<<

Test code is here, in its entirety:
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
import pyqtgraph.opengl as gl
import numpy as np
import math
import pdb

app = QtGui.QApplication([])
w = gl.GLViewWidget()
w.show()
w.setWindowTitle('3D Box')
w.setCameraPosition(distance=10, elevation=30, azimuth=90)

g = gl.GLGridItem()
g.scale(1,1,1)
w.addItem(g)

# Box vertices, faces, and face colors
verts_box = np.array([
   [ 0,  0,  0],
   [ 1,  0,  0],
   [ 1,  1,  0],
   [ 0,  1,  0],
   [ 0,  0,  1],
   [ 1,  0,  1],
   [ 1,  1,  1],
   [ 0,  1,  1]],
   dtype=float)

faces_box = np.array([
    [0, 1, 2],
    [0, 2, 3],
    [0, 1, 4],
    [1, 5, 4],
    [1, 2, 5],
    [2, 5, 6],
    [2, 3, 6],
    [3, 6, 7],
    [0, 3, 7],
    [0, 4, 7],
    [4, 5, 7],
    [5, 6, 7],
])

colors_box = np.array([
    [1, 1, 0, 0.5],
    [1, 1, 0, 0.5],
    [1, 0, 1, 0.5],
    [1, 0, 1, 0.5],
    [0, 1, 1, 0.5],
    [0, 1, 1, 0.5],
    [1, 0, 0, 0.5],
    [1, 0, 0, 0.5],
    [0, 1, 0, 0.5],
    [0, 1, 0, 0.5],
    [0, 0, 1, 0.5],
    [0, 0, 1, 0.5],
])

## Mesh item will automatically compute face normals.
#m1 = gl.GLMeshItem(vertexes=verts, faces=faces, faceColors=colors, smooth=False)
m1 = gl.GLMeshItem(vertexes=verts_box, faces=faces_box, faceColors=colors_box, smooth=False)

m1.translate(0, 0, 0)
#m1.setGLOptions('additive')
w.addItem(m1)

def rotation_matrix(axis, theta):
    """
    Return the rotation matrix associated with counterclockwise rotation about
    the given axis by theta radians.
    """
    axis = np.asarray(axis)
    axis = axis/math.sqrt(np.dot(axis, axis))
    a = math.cos(theta/2.0)
    b, c, d = -axis*math.sin(theta/2.0)
    aa, bb, cc, dd = a*a, b*b, c*c, d*d
    bc, ad, ac, ab, bd, cd = b*c, a*d, a*c, a*b, b*d, c*d
    return np.array([[aa+bb-cc-dd, 2*(bc+ad), 2*(bd-ac)],
                     [2*(bc-ad), aa+cc-bb-dd, 2*(cd+ab)],
                     [2*(bd+ac), 2*(cd-ab), aa+dd-bb-cc]])
R2 = rotation_matrix([0,0,1],np.pi/180.)

def update() :
    global verts_box, m1, R2
    verts_box = np.dot(verts_box,R2)
    m1.setMeshData(vertexes=verts_box)

t = QtCore.QTimer()
t.timeout.connect(update)
t.start(500)

pdb.set_trace()



## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()
Reply all
Reply to author
Forward
0 new messages