예제 #1
0
    def controller_state_update(self):
        self.curve_roll.setData(self.imu_angle_data[0])
        self.curve_pitch.setData(self.imu_angle_data[1])
        self.curve_yaw.setData(self.imu_angle_data[2])
        self.curve_roll_v.setData(self.imu_angle_v_data[0])
        self.curve_pitch_v.setData(self.imu_angle_v_data[1])
        self.curve_yaw_v.setData(self.imu_angle_v_data[2])
        self.t_roll_angle.setText('roll: %0.1f' % (self.imu_angle_data[0][-1]))
        self.t_pitch_angle.setText('pitch: %0.1f' %
                                   (self.imu_angle_data[1][-1]))
        self.t_yaw_angle.setText('yaw: %0.1f' % (self.imu_angle_data[2][-1]))
        self.t_roll_angle_v.setText('roll: %0.1f' %
                                    (self.imu_angle_v_data[0][-1]))
        self.t_pitch_angle_v.setText('pitch: %0.1f' %
                                     (self.imu_angle_v_data[1][-1]))
        self.t_yaw_angle_v.setText('yaw: %0.1f' %
                                   (self.imu_angle_v_data[2][-1]))

        self.cube_mat = self.cube_quat.toRotationMatrix()
        self.cube_mat_data = self.cube_mat.data()
        self.cube_transform = pg.Transform3D(
            self.cube_mat_data[0], self.cube_mat_data[1],
            self.cube_mat_data[2], 0, self.cube_mat_data[3],
            self.cube_mat_data[4], self.cube_mat_data[5], 0,
            self.cube_mat_data[6], self.cube_mat_data[7],
            self.cube_mat_data[8], 0, 0, 0, 0, 1)

        self.cube.setTransform(self.cube_transform)
예제 #2
0
    def __init__(self, x=0, y=0, z=0, scale=0.1, widget=None):
        """
        If there is no widget given a new window is created and its id is accessible via self.widget.
        :param x: optional, float
        :param y: optional, float
        :param z: optional, float
        :param widget: optional, gl.GLViewWidget
        :return: None
        """
        if not widget:
            self.app = QtGui.QApplication([])
            self.widget = gl.GLViewWidget()
            self.widget.opts['distance'] = 40
            self.widget.show()
        else:
            self.app = False
            self.widget = widget

        self.scale = scale
        self.x = x
        self.y = y
        self.z = z
        self.rot0 = 0
        self.rot1 = 0
        self.rot2 = 0

        self.axis = gl.GLAxisItem()
        tr = pg.Transform3D()
        tr.scale(self.scale)
        tr.rotate(self.rot0, 1, 0, 0)
        tr.rotate(self.rot1, 0, 1, 0)
        tr.rotate(self.rot2, 0, 0, 1)
        self.axis.setTransform(tr)
        self.axis.translate(self.x, self.y, self.z)
        self.widget.addItem(self.axis)
예제 #3
0
def update():
    dataLoad()
    global data
    global pos
    #print(data[-1])
    curve1.setData(data[0])
    curve2.setData(data[1])
    temp = pg.Transform3D(tr)
    temp.rotate(data[0][-1], 0, 1, 0)
    box.setTransform(temp)
    if sys.stdin.buffer.peek() != '':
        a = input()
        s.write(a)
예제 #4
0
 def update(self, x=None, y=None, z=None, scale=None):
     if x:
         self.x = x
     if y:
         self.y = y
     if z:
         self.z = z
     if scale:
         self.scale = scale
     tr = pg.Transform3D()
     tr.scale(self.scale)
     self.grid.setTransform(tr)
     self.grid.translate(self.x, self.y, self.z)
예제 #5
0
 def _AffineTransform_to_pg(self, tr):
     import pyqtgraph
     if tr.dims == (2, 2):
         m = tr.matrix
         o = tr.offset
         ptr = pyqtgraph.QtGui.QTransform(m[0,0], m[1,0], 0.0, m[0,1], m[1,1], 0.0, o[0], o[1], 1.0)
         return ptr
     elif tr.dims == (3, 3):
         m = np.eye(4)
         m[:3, :3] = tr.matrix
         m[:3, 3] = tr.offset
         ptr = pyqtgraph.Transform3D(m)
         return ptr
     else:
         raise TypeError("Converting AffineTransform of dimension %r to pyqtgraph is not supported." % tr.dims)
예제 #6
0
    def updateMeshTransform(self, q, t=[0, 0, 1]):
        v = numpy.array(q[1:])
        vnorm = numpy.linalg.norm(v)
        v = v * 1 / vnorm
        angle = 2 * math.atan2(vnorm, q[0])
        # print('3d', angle, v)
        tr = pg.Transform3D()
        tr.translate(*t)
        tr.rotate(rad2deg(angle), *v)

        tr.rotate(90, 1, 0, 0)
        # tr.translate(0, 0, -0.5)
        tr.scale(0.015, 0.015, 0.015)

        self.mesh_item.setTransform(tr)
예제 #7
0
    def update(self, x=None, y=None, z=None, rot0=None, rot1=None, rot2=None):
        if x:
            self.x = x
        if y:
            self.y = y
        if z:
            self.z = z
        if rot0:
            self.rot0 = rot0
        if rot1:
            self.rot1 = rot1
        if rot2:
            self.rot2 = rot2

        tr = pg.Transform3D()
        tr.scale(self.scale)
        tr.rotate(self.rot0, 1, 0, 0)
        tr.rotate(self.rot1, 0, 1, 0)
        tr.rotate(self.rot2, 0, 0, 1)
        self.axis.setTransform(tr)
        self.axis.translate(self.x, self.y, self.z)
예제 #8
0
def testMatrix():
    """
    SRTTransform3D => Transform3D => SRTTransform3D
    """
    tr = pg.SRTTransform3D()
    tr.setRotate(45, (0, 0, 1))
    tr.setScale(0.2, 0.4, 1)
    tr.setTranslate(10, 20, 40)
    assert tr.getRotation() == (45, QtGui.QVector3D(0, 0, 1))
    assert tr.getScale() == QtGui.QVector3D(0.2, 0.4, 1)
    assert tr.getTranslation() == QtGui.QVector3D(10, 20, 40)

    tr2 = pg.Transform3D(tr)
    assert np.all(tr.matrix() == tr2.matrix())
    
    # This is the most important test:
    # The transition from Transform3D to SRTTransform3D is a tricky one.
    tr3 = pg.SRTTransform3D(tr2)
    assert_array_almost_equal(tr.matrix(), tr3.matrix())
    assert_almost_equal(tr3.getRotation()[0], tr.getRotation()[0])
    assert_array_almost_equal(tr3.getRotation()[1], tr.getRotation()[1])
    assert_array_almost_equal(tr3.getScale(), tr.getScale())
    assert_array_almost_equal(tr3.getTranslation(), tr.getTranslation())
예제 #9
0
    def test_pyqtgraph_conversion(self):
        if not HAVE_PYQTGRAPH:
            self.skipTest("pyqtgraph could not be imported")

        pts2 = np.random.normal(size=(100, 2))

        qtr1 = pyqtgraph.QtGui.QTransform()
        qtr1.scale(1.1, -9)
        qtr1.translate(3, -30)
        qtr1.rotate(32)
        t_atr = linear.STTransform.convert_from(qtr1, 'pyqtgraph')
        qtr2 = t_atr.convert_to('pyqtgraph')

        assert np.allclose(
            pyqtgraph.transformCoordinates(qtr1, pts2, transpose=True),
            t_atr.map(pts2))
        assert np.allclose(
            pyqtgraph.transformCoordinates(qtr2, pts2, transpose=True),
            t_atr.map(pts2))

        pts3 = np.random.normal(size=(100, 3))

        qtr1 = pyqtgraph.Transform3D()
        qtr1.scale(1.1, -9, 1e4)
        qtr1.translate(3, -30, 0)
        qtr1.rotate(32, 0, 1, 2)
        t_atr = linear.AffineTransform.convert_from(qtr1, 'pyqtgraph')
        print(t_atr)
        qtr2 = t_atr.convert_to('pyqtgraph')

        assert np.allclose(
            pyqtgraph.transformCoordinates(qtr1, pts3, transpose=True),
            t_atr.map(pts3))
        assert np.allclose(
            pyqtgraph.transformCoordinates(qtr2, pts3, transpose=True),
            t_atr.map(pts3))
예제 #10
0
    def make_volume_data(self, resolution=1.0, max_size=500e6):
        """
        Using the current state of vertexes, edges, generates a scalar field
        useful for building isosurface or volumetric renderings.
        
        Parameters
        ----------
        resolution: float, default=1.0 microns
            width (um) of a single voxel in the scalar field.
        max_size: int
            maximum allowed scalar field size (bytes).
        Returns
        -------
            * 3D scalar field indicating distance from nearest membrane,
            * 3D field indicating section IDs of nearest membrane,
            * QTransform that maps from 3D array indexes to original vertex 
                coordinates.
        """
        vertexes, lines = self.get_geometry()
        
        maxdia = vertexes['dia'].max() # maximum diameter (defines shape of kernel)
        kernel_size = int(maxdia/resolution) + 3 # width of kernel
        
        
        # read vertex data
        pos = vertexes['pos']
        d = vertexes['dia']
        sec_id = vertexes['sec_index']
        
        # decide on dimensions of scalar field
        mx = pos.max(axis=0)
        mn = pos.min(axis=0)
        diff = mx - mn
        shape = tuple((diff / resolution + kernel_size).astype(int))

        # prepare blank scalar field for drawing
        size = np.dtype(np.float32).itemsize * shape[0] * shape[1] * shape[2]
        if size > max_size:
            raise Exception("Scalar field would be larger than max_size (%dMB > %dMB), resolution is%f" % (size/1e6, max_size/1e6, resolution))
        scfield = np.zeros(shape, dtype=np.float32)
        scfield[:] = -1000
        
        # array for holding IDs of sections that contribute to each area
        idfield = np.empty(shape, dtype=int)
        idfield[:] = -1
        
        # map vertex locations to voxels
        vox_pos = pos.copy()
        vox_pos -= mn.reshape((1,3))
        vox_pos *= 1./resolution

        # Define kernel used to draw scalar field along dendrites
        def cone(i,j,k):
            # value decreases linearly with distance from center of kernel.
            w = kernel_size / 2
            return w - ((i-w)**2 + (j-w)**2 + (k-w)**2)**0.5
        kernel = resolution * np.fromfunction(cone, (kernel_size,)*3)
        kernel -= kernel.max()

        def array_intersection(arr1, arr2, pos):
            """
            Return slices used to access the overlapping area between two 
            arrays that are offset such that the origin of *arr2* is a *pos* 
            relative to *arr1*.            
            """
            s1 = [0]*3
            s2 = [0]*3
            t1 = [0]*3
            t2 = [0]*3
            pos = map(int, pos)
            for axis in range(3):
                s1[axis] = max(0, -pos[axis])
                s2[axis] = min(arr2.shape[axis], arr1.shape[axis]-pos[axis])
                t1[axis] = max(0, pos[axis])
                t2[axis] = min(arr1.shape[axis], pos[axis]+arr2.shape[axis])
            slice1 = (slice(t1[0],t2[0]), slice(t1[1],t2[1]), slice(t1[2],t2[2]))
            slice2 = (slice(s1[0],s2[0]), slice(s1[1],s2[1]), slice(s1[2],s2[2]))
            return slice1, slice2            

        # Draw lines into volume using *kernel* as the brush
        vox_pos[:,0] = np.clip(vox_pos[:,0], 0, scfield.shape[0]-1)
        vox_pos[:,1] = np.clip(vox_pos[:,1], 0, scfield.shape[1]-1)
        vox_pos[:,2] = np.clip(vox_pos[:,2], 0, scfield.shape[2]-1)
        for c in range(lines.shape[0]):
            i = lines[c, 0]
            j = lines[c, 1]
            p1 = vox_pos[i].copy()
            p2 = vox_pos[j].copy()
            diff = p2-p1
            axis = np.argmax(np.abs(diff))
            dia = d[i]
            nvoxels = abs(int(diff[axis]))+1
            for k in range(nvoxels):
                kern = kernel + (dia/2.0)
                sl1, sl2 = array_intersection(scfield, kern, p1) # find the overlapping area between the field and the kernel
                idfield[sl1] = np.where(scfield[sl1] > kern[sl2], idfield[sl1], sec_id[i])
                scfield[sl1] = np.where(scfield[sl1] > kern[sl2], scfield[sl1], kern[sl2])
                dia += (d[j]-d[i]) / nvoxels
                p1 += diff / nvoxels
                
        # return transform relating volume data to original vertex data
        transform = pg.Transform3D()
        w = resolution * kernel_size / 2 # offset introduced due to kernel
        transform.translate(*(mn-w))
        transform.scale(resolution, resolution, resolution)
        transform.translate(1, 1, 1)
        return scfield, idfield, transform
예제 #11
0
    def __init__(self):
        self.width = 1000
        self.high = 1000
        self.console_high = 150
        self.plot_high = self.high - self.console_high
        self.console_size = (self.width, self.console_high)
        self.plot_size = (self.width, self.plot_high)
        self.app = QtGui.QApplication([])
        self.win = QtGui.QMainWindow()
        self.area = DockArea()
        self.win.setCentralWidget(self.area)
        self.win.resize(self.width, self.high)
        self.win.setWindowTitle('Gimbal Monitor')
        self.timer_dt = 50

        pg.setConfigOptions(antialias=True)
        pg.setConfigOption('background', [0, 0, 0])
        pg.setConfigOption('foreground', [255, 255, 255, 100])

        # Dock
        self.d_console = self.dock4console('Console')
        self.d_controller_state = self.dock4plot('Controller State')
        self.d_motors_state = self.dock4plot('Motors State')
        self.d_controller_config = self.dock4plot('Controller Config')
        self.d_motors_config = self.dock4plot('Motor Config')
        self.d_imu_attitude = Dock('IMU Attitude',
                                   size=(1000, self.plot_high),
                                   closable=True)
        #self.d_imu_attitude.show()
        self.area.addDock(self.d_console, 'bottom')
        self.area.addDock(self.d_controller_state, 'top')
        self.area.addDock(self.d_motors_state, 'top')
        self.area.addDock(self.d_controller_config, 'top')
        self.area.addDock(self.d_motors_config, 'top')
        self.area.addDock(self.d_imu_attitude, 'top')

        self.area.moveDock(self.d_motors_state, 'above',
                           self.d_controller_state)
        self.area.moveDock(self.d_controller_config, 'above',
                           self.d_motors_state)
        self.area.moveDock(self.d_motors_config, 'above',
                           self.d_controller_config)
        self.area.moveDock(self.d_imu_attitude, 'right',
                           self.d_controller_state)

        # Controller State Layout
        self.pen_width = 2
        self.fill_beta = 70
        self.pen_red = pg.mkPen('F00', width=self.pen_width)
        self.pen_green = pg.mkPen('0F0', width=self.pen_width)
        self.pen_blue = pg.mkPen('0AF', width=self.pen_width)
        self.fill_red = [255, 0, 0, self.fill_beta]
        self.fill_green = [0, 255, 0, self.fill_beta]
        self.fill_blue = [0, 200, 255, self.fill_beta]

        self.imu_angle_time_len = 200
        self.imu_angle_data = np.zeros((3, self.imu_angle_time_len))
        self.imu_angle_v_data = np.zeros((3, self.imu_angle_time_len))
        self.w_controller_state = pg.LayoutWidget()
        self.p_attitude = pg.PlotWidget(title="Camera Attitude")
        self.p_angle_v = pg.PlotWidget(title="Angle Velocity")
        self.p_attitude.showGrid(x=True, y=True)
        self.p_angle_v.showGrid(x=True, y=True)
        self.curve_roll = self.p_attitude.plot(self.imu_angle_data[0],
                                               pen=self.pen_red,
                                               fillLevel=0,
                                               brush=self.fill_red)
        self.curve_pitch = self.p_attitude.plot(self.imu_angle_data[1],
                                                pen=self.pen_green,
                                                fillLevel=0,
                                                brush=self.fill_green)
        self.curve_yaw = self.p_attitude.plot(self.imu_angle_data[2],
                                              pen=self.pen_blue,
                                              fillLevel=0,
                                              brush=self.fill_blue)
        self.curve_roll_v = self.p_angle_v.plot(self.imu_angle_v_data[0],
                                                pen=self.pen_red,
                                                fillLevel=0,
                                                brush=self.fill_red)
        self.curve_pitch_v = self.p_angle_v.plot(self.imu_angle_v_data[1],
                                                 pen=self.pen_green,
                                                 fillLevel=0,
                                                 brush=self.fill_green)
        self.curve_yaw_v = self.p_angle_v.plot(self.imu_angle_v_data[2],
                                               pen=self.pen_blue,
                                               fillLevel=0,
                                               brush=self.fill_blue)
        self.time_remain = 6
        self.angle_max = 100
        self.angle_v_max = 1000
        self.text_interval = self.angle_max * 0.12
        self.text_interval_v = self.angle_v_max * 0.12
        self.angle_text_max_y = self.angle_max * 1.12
        self.angle_v_text_max_y = self.angle_v_max * 1.12
        self.p_attitude.setXRange(0 - self.time_remain,
                                  self.imu_angle_time_len + self.time_remain)
        self.p_attitude.setYRange(-100, 100)
        self.p_angle_v.setXRange(0 - self.time_remain,
                                 self.imu_angle_time_len + self.time_remain)
        self.p_angle_v.setYRange(-1000, 1000)

        self.t_roll_angle = pg.TextItem()
        self.t_roll_angle.setText('roll: %0.1f' % (0), [255, 0, 0, 200])
        self.t_roll_angle.setPos(0, self.angle_text_max_y)
        self.p_attitude.addItem(self.t_roll_angle)

        self.t_pitch_angle = pg.TextItem()
        self.t_pitch_angle.setText('pitch: %0.1f' % (0), [0, 255, 0, 200])
        self.t_pitch_angle.setPos(0,
                                  self.angle_text_max_y - self.text_interval)
        self.p_attitude.addItem(self.t_pitch_angle)

        self.t_yaw_angle = pg.TextItem()
        self.t_yaw_angle.setText('yaw: %0.1f' % (0), [0, 200, 255, 230])
        self.t_yaw_angle.setPos(0,
                                self.angle_text_max_y - 2 * self.text_interval)
        self.p_attitude.addItem(self.t_yaw_angle)

        self.t_roll_angle_v = pg.TextItem()
        self.t_roll_angle_v.setText('roll: %0.1f' % (0), [255, 0, 0, 200])
        self.t_roll_angle_v.setPos(0, self.angle_v_text_max_y)
        self.p_angle_v.addItem(self.t_roll_angle_v)

        self.t_pitch_angle_v = pg.TextItem()
        self.t_pitch_angle_v.setText('pitch: %0.1f' % (0), [0, 255, 0, 200])
        self.t_pitch_angle_v.setPos(
            0, self.angle_v_text_max_y - self.text_interval_v)
        self.p_angle_v.addItem(self.t_pitch_angle_v)

        self.t_yaw_angle_v = pg.TextItem()
        self.t_yaw_angle_v.setText('yaw: %0.1f' % (0), [0, 200, 255, 230])
        self.t_yaw_angle_v.setPos(
            0, self.angle_v_text_max_y - 2 * self.text_interval_v)
        self.p_angle_v.addItem(self.t_yaw_angle_v)

        self.w_controller_state.addWidget(self.p_attitude, row=0, col=0)
        self.w_controller_state.addWidget(self.p_angle_v, row=1, col=0)
        self.d_controller_state.addWidget(self.w_controller_state,
                                          row=0,
                                          col=1)

        self.timer_controller_state = QtCore.QTimer()
        self.timer_controller_state.timeout.connect(
            self.controller_state_update)

        # Motors State Layout
        self.motors_state_time_len = 200
        self.ntc_tempre_data = np.zeros((3, self.motors_state_time_len))
        self.input_current_data = np.zeros((3, self.motors_state_time_len))
        self.motor_current_data = np.zeros((3, self.motors_state_time_len))
        self.input_v_data = np.zeros((3, self.motors_state_time_len))
        self.duty_cycle_now_data = np.zeros((3, self.motors_state_time_len))
        self.rpm_data = np.zeros((3, self.motors_state_time_len))
        self.tacho_data = np.zeros((3, self.motors_state_time_len))
        self.tacho_abs_data = np.zeros((3, self.motors_state_time_len))

        self.w_motors_state = pg.LayoutWidget()
        self.p_ntc_tempre = pg.PlotWidget()
        self.p_current = pg.PlotWidget()
        self.p_input_v = pg.PlotWidget()
        self.p_duty_cycle_now = pg.PlotWidget()
        self.p_rpm = pg.PlotWidget()
        self.p_tacho = pg.PlotWidget()
        self.p_tach_abs = pg.PlotWidget()
        self.p_ntc_tempre.showGrid(True)
        self.p_current.showGrid(True)
        self.p_input_v.showGrid(True)
        self.p_duty_cycle_now.showGrid(True)
        self.p_rpm.showGrid(True)
        self.p_tacho.showGrid(True)
        self.p_tach_abs.showGrid(True)
        self.curve_ntc_tempre = self.p_ntc_tempre.plot(self.ntc_tempre_data[0],
                                                       pen=self.pen_blue,
                                                       fillLevel=0,
                                                       brush=self.fill_blue)
        self.curve_input_current = self.p_current.plot(
            self.input_current_data[0], pen=self.pen_)

        # IMU Attitude OpenGL Layout

        self.vr_layout = pg.LayoutWidget()

        self.w_vr = gl.GLViewWidget()
        glEnable(GL_LINE_SMOOTH)
        glShadeModel(GL_SMOOTH)
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_CULL_FACE)
        glCullFace(GL_BACK)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC1_ALPHA)
        self.light()
        glMatrixMode(GL_PROJECTION)
        glMatrixMode(GL_MODELVIEW)
        gluPerspective(40., 1., 1., 40.)
        self.w_vr.opts['distance'] = 40
        self.w_vr.opts['azimuth'] = -10
        print(self.w_vr.opts)
        self.w_vr.setWindowTitle('IMU Attitude')
        #self.w_vr.setCameraPosition(pos=[0, 0, 50],)

        self.w_vr.show()
        self.vr_ground = gl.GLGridItem()
        self.vr_ground.scale(10, 10, 1)
        self.w_vr.addItem(self.vr_ground)

        self.cube_width = 20
        self.cube_high = self.cube_width * (1 - 0.618)
        self.verts = np.array([
            [self.cube_width / 2, self.cube_width / 2, self.cube_high / 2],
            [-self.cube_width / 2, self.cube_width / 2, self.cube_high / 2],
            [-self.cube_width / 2, -self.cube_width / 2, self.cube_high / 2],
            [self.cube_width / 2, -self.cube_width / 2, self.cube_high / 2],
            [self.cube_width / 2, self.cube_width / 2, -self.cube_high / 2],
            [-self.cube_width / 2, self.cube_width / 2, -self.cube_high / 2],
            [-self.cube_width / 2, -self.cube_width / 2, -self.cube_high / 2],
            [self.cube_width / 2, -self.cube_width / 2, -self.cube_high / 2],
        ])
        self.face = np.array([
            [0, 1, 2],  # up
            [0, 2, 3],
            [4, 6, 5],  # down
            [4, 7, 6],
            [0, 3, 7],  # front
            [0, 7, 4],
            [1, 6, 2],  # back
            [1, 5, 6],
            [0, 4, 5],  # left
            [0, 5, 1],
            [2, 6, 7],  # right
            [2, 7, 3],
        ])
        self.alpha = 1
        self.c_red = [1, 0, 0, self.alpha]
        self.c_greed = [0, 1, 0, self.alpha]
        self.c_blue = [0, 0, 1, self.alpha]
        self.gray_scale = 0.8
        self.c_gray = [
            self.gray_scale, self.gray_scale, self.gray_scale, self.alpha
        ]
        self.colors = np.array([
            self.c_gray,
            self.c_gray,
            self.c_gray,
            self.c_gray,
            self.c_gray,
            self.c_gray,
            self.c_gray,
            self.c_gray,
            self.c_gray,
            self.c_gray,
            self.c_gray,
            self.c_gray,
        ])
        self.cube = gl.GLMeshItem(vertexes=self.verts,
                                  faces=self.face,
                                  faceColors=self.colors,
                                  shader='shaded',
                                  drawEdges=True,
                                  edgeColor=(1, 1, 1, 1),
                                  smooth=False)
        self.cube.translate(0, 0, 3)
        self.cube_quat = QQuaternion(1.0, 0.0, 0.0, 0.0)
        self.cube_mat = self.cube_quat.toRotationMatrix()
        self.cube_mat_data = self.cube_mat.data()
        self.cube_transform = pg.Transform3D(
            self.cube_mat_data[0], self.cube_mat_data[1],
            self.cube_mat_data[2], 0, self.cube_mat_data[3],
            self.cube_mat_data[4], self.cube_mat_data[5], 0,
            self.cube_mat_data[6], self.cube_mat_data[7],
            self.cube_mat_data[8], 0, 0, 0, 0, 1)

        self.cube.setTransform(self.cube_transform)
        self.w_vr.addItem(self.cube)
        self.d_imu_attitude.addWidget(self.w_vr)