Homepage GitHub

Threading and nodes limitations

I’m using the legacy Python Library ‘uavcan’.

My setup: I’m connecting two CAN-Beds to a Raspberry-Pi that talk via SLCAN. One is ‘ttyACM0’ and the other ‘ttyACM1’

I have a Battery connected to one of the CAN-Beds.

I am able to spin a node and receive battery info. So far so good. Now since I’m building a GUI with PyQt I spin the node into its own QThread and still everything works.

Now, I want to scale my system to two nodes, each in its own QThread. This is where things don’t work anymore.

I connect the battery to both CAN-Beds.

I start each node and I’m expecting to receive data from both nodes but only one receives data. I know both are running because I put some print statements on the infinite loop that runs the spin method.

Something else that I noticed is that I get info for a second from one node and then it stops and the other node is now the only receiving. This is related to the order I start the nodes so maybe there is some resource that can’t be shared.

The only thing that occurs to me is that I’m doing something that wasn’t even supposed to be a use case of the library but

I don’t know enough to know what I don’t know.

Any insights on running parallel nodes are welcome!

Are you sure this is not caused by Python’s GIL? Threading is kinda broken in Python.

So after a long session of debugging thru print statements. I found where things stop working. I cannot explain the cause because I stopped searching but in the node.py there is a method

def call_handlers(self, transfer):
        for uavcan_type, wrapper in self._handlers:
            if uavcan_type == get_uavcan_data_type(transfer.payload):
                try:
                    wrapper(transfer)
                # noinspection PyBroadException
                except Exception as e:
                    logger.error("Transfer handler exception", exc_info=True)
                    if not self._catch_exceptions:
                        raise e

I know both my threads are running but one is never passing the check

      if uavcan_type == get_uavcan_data_type(transfer.payload):

So I printed uavcan_type and the value from get_uavcan_data_type() and if they were equal
and saw this in the log

/dev/ttyACM2: 
uavcan_type = uavcan.equipment.power.BatteryInfo, 
get_uavcan_data_type() = uavcan.equipment.power.BatteryInfo
Are they equal: False

/dev/ttyACM1: 
uavcan_type = uavcan.equipment.power.BatteryInfo, 
get_uavcan_data_type() = uavcan.equipment.power.BatteryInfo
Are they equal: True

So I tried converting the values to strings before the comparison and now both threads are sending the data that I need.
Too bad I can’t explain why is that ‘If’ failing when it shouldn’t.