Realtime point cloud visualization

I tried a realtime point cloud visualization code with vtk 8.1.2. This is the reference link:

I tried the code with vtk 8.1.2 and vtk 6.3.0 and it only works for vtk 6.3.0. I checked multiple times and could not figure out what is the problem between the two version. I have a few question:
0. The code tried vtk 8.1.2 only show the rendered scene but the object is not moving. The vtk 6.3.0 works fine that the object is moving as expected in near-realtime 20 fps.

  1. Is there a better way for realtime point cloud udpating with numpy array. This code is the best one I found but it seems not working with VTK 8.1.2 and I could not figure out the problem after multiple tries.
  2. Is there a good way to add the colorized vector on the point cloud along with this program?

Here is the code:

import vtk
import numpy as np
import time
import threading
import vtk.util.numpy_support as vtk_np

class VTKActorWrapper(object):

def __init__(self, nparray):

    super(VTKActorWrapper, self).__init__()

    self.nparray = nparray

    nCoords = nparray.shape[0]
    nElem = nparray.shape[1]

    self.verts = vtk.vtkPoints()
    self.cells = vtk.vtkCellArray()
    self.scalars = None

    self.pd = vtk.vtkPolyData()

    self.verts.SetData(vtk_np.numpy_to_vtk(nparray))
    self.cells_npy = np.vstack([np.ones(nCoords, dtype = np.int64),
                                np.arange(nCoords, dtype = np.int64)]).T.flatten()
    self.cells.SetCells(nCoords, vtk_np.numpy_to_vtkIdTypeArray(self.cells_npy))
    self.pd.SetPoints(self.verts)
    self.pd.SetVerts(self.cells)

    self.mapper = vtk.vtkPolyDataMapper()
    self.mapper.SetInputDataObject(self.pd)

    self.actor = vtk.vtkActor()
    self.actor.SetMapper(self.mapper)
    self.actor.GetProperty().SetRepresentationToPoints()
    self.actor.GetProperty().SetColor(0.0, 1.0, 0.0)

def update(self, threadLock, update_on):
    thread = threading.Thread(target = self.update_actor, args = (threadLock, update_on))
    thread.start()

def update_actor(self, threadLock, update_on):

    pc = np.asarray(np.load('pts.npy'))
    count = 0

    while (update_on.is_set()):
        start_time = time.time()
        count += 1
        time.sleep(0.01)
        threadLock.acquire()
        pc = pc + 0.01
        self.nparray[:] = np.ascontiguousarray(pc)
        self.pd.Modified()
        threadLock.release()
        print(time.time() - start_time)

class VTKVisualisation(object):

def __init__(self, threadLock, actorWrapper, axis = True, ):

    super(VTKVisualisation, self).__init__()

    self.threadLock = threadLock

    self.ren = vtk.vtkRenderer()
    self.ren.AddActor(actorWrapper.actor)

    self.axesActor = vtk.vtkAxesActor()
    self.axesActor.AxisLabelsOff()
    self.axesActor.SetTotalLength(1, 1, 1)
    self.ren.AddActor(self.axesActor)

    self.renWin = vtk.vtkRenderWindow()
    self.renWin.AddRenderer(self.ren)

    ## IREN
    self.iren = vtk.vtkRenderWindowInteractor()
    self.iren.SetRenderWindow(self.renWin)
    self.iren.Initialize()

    self.style = vtk.vtkInteractorStyleTrackballCamera()
    self.iren.SetInteractorStyle(self.style)

    self.iren.AddObserver("TimerEvent", self.update_visualisation)
    dt = 30  # ms
    timer_id = self.iren.CreateRepeatingTimer(dt)

def update_visualisation(self, obj = None, event = None):
    time.sleep(0.01)
    self.threadLock.acquire()
    self.ren.GetRenderWindow().Render()
    self.threadLock.release()

def main():

update_on = threading.Event()
update_on.set()

threadLock = threading.Lock()

pc = np.ascontiguousarray(np.asarray(np.load('pts.npy')))
# pc = np.zeros(pc.shape)
actorWrapper = VTKActorWrapper(pc)
actorWrapper.update(threadLock, update_on)

viz = VTKVisualisation(threadLock, actorWrapper)
viz.iren.Start()
update_on.clear()

main()

Thanks.

I found that with the version 8.1.2, we need to update the self.verts = vtk.vtkPoints() object and it works.

So we have:

self.nparray[:] = self.pc
self.verts.Modified()
self.cells.Modified()
self.pd.Modified()