OpenIGTLink event in case of a new incoming MRML node

Hi,
I’m coding a scripted module that handles an OpenIGTLink connection to a tracker and I experience some delay between the call to start the connection and when the incoming data is actually streamed.
I have tried using the solution proposed here by @lassoan but it seems the ConnectedEvent is still sent prior to the actual streaming. With the code below, I still get 0 incoming MRML node at run time, but shortly after I can definitely see the incoming node in the Data tree of Slicer.

self.cnode = slicer.vtkMRMLIGTLConnectorNode()
self.cnode.SetName('PointerConnector')
slicer.mrmlScene.AddNode(self.cnode)
self.addObserver(self.cnode, slicer.vtkMRMLIGTLConnectorNode.ConnectedEvent, self.onConnected)
if self.cnode.Start() != 1:
   slicer.util.errorDisplay("Cannot connect to openIGTLink")

def onConnected(self, caller, event):
  if self.cnode.GetNumberOfIncomingMRMLNodes() == 0:
    slicer.util.errorDisplay("No data streamed")
  elif cnode.GetIncomingMRMLNode(0).GetClassName() != 'vtkMRMLLinearTransformNode':
    slicer.util.errorDisplay("Streamed data not a linear transform")
  else:
    self.pointerTransform = cnode.GetIncomingMRMLNode(0)

Thank you for any help,
S.

Establishing a connection and receiving messages are independent events. You can receive messages anytime after the connection is established. The server may send new transform names, images, etc. anytime, even several hours after the connection is established (whenever the server wants to send them).

If you want to get notified about a new node then you can add an observer to the MRML scene. See an example here.

Thank you for your response.
If I understand correctly, I should have in my module widget class:

class MyModuleWidget(ScriptedLoadableModuleWidget, VTKObservationMixin):
  ...
  def setup(self):
    ...
    slicer.mrmlScene.AddObserver(slicer.vtkMRMLScene.NodeAddedEvent, self.onNodeAdded)
    self.cnode = slicer.vtkMRMLIGTLConnectorNode()
    self.cnode.SetName('PointerConnector')
    slicer.mrmlScene.AddNode(self.cnode)
    self.cnode.Start()

  def onNodeAdded(self, caller, event, calldata):
    calledNode = calldata
    if isinstance(calledNode, slicer.vtkMRMLLinearTransformNode): # check new node class
      if self.cnode.GetNumberOfIncomingMRMLNodes() > 0: # connection has at least one node
        if self.cnode.GetIncomingMRMLNode(0).GetID() == calledNode.GetID(): # check if nodes identical
          self.logic.process(self.phantomModel, self.pointerModel, calledNode)

However, by doing so I get an error on my callback:

TypeError: onNodeAdded() missing 1 required positional argument: 'calldata'

Is it possible to have a callback with calldata and as a member function of the widget class (using self to get cnode) ?

You need to add the @vtk.calldata_type(vtk.VTK_OBJECT) decorator as it is shown in the example I referenced in my previous post.

1 Like