Search code examples
pythonudpportblendersimulink

Read an array from a UDP port in Python


I have the following Simulink model: Simulink Model with UDP

With this model and a joystick I want to provide inputs to the UDP port which I will read from another application; in my case Blender.

So at Blender I have the following code that works perfectly for 1 provided input from Simulink.

import bpy
import math
import socket
import struct

port = 12009
address = "127.0.0.1"
base = 0
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((address, port))
cube = bpy.data.objects['Cube']
cube.location = (base, 0, 0)

class ModalTimerOperator(bpy.types.Operator):
    """Operator which runs its self from a timer"""
    bl_idname = "wm.modal_timer_operator"
    bl_label = "Modal Timer Operator"

    _timer = None

    def modal(self, context, event):
        if event.type in {'RIGHTMOUSE', 'ESC'}:
            self.cancel(context)
            s.close()
            cube.location = (base, 0, 0)
            return {'CANCELLED'}

        if event.type == 'TIMER':
            data, addr = s.recvfrom(1024)
            data = struct.unpack('!d', data)
            x = data[0]
            print(data)
            cube.location = (x, 0, 0)
            print("X:", x)

        return {'PASS_THROUGH'}

    def execute(self, context):
        wm = context.window_manager
        self._timer = wm.event_timer_add(0.001, window = context.window)
        wm.modal_handler_add(self)
        return {'RUNNING_MODAL'}

    def cancel(self, context):
        wm = context.window_manager
        wm.event_timer_remove(self._timer)


def register():
    bpy.utils.register_class(ModalTimerOperator)


def unregister():
    bpy.utils.unregister_class(ModalTimerOperator)


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.wm.modal_timer_operator()

When I try to run this, I get the following error:

struct.error: unpack requires a buffer of 8 bytes

How can I unpack an array instead of just a double using struct.unpack? What changes should I make in the code to achieve this?


Solution

  • I found the answer myself. There is no need to use matrix concatenation; just simply connect the mux singal of your desired sent signals via UDP. Then in the code just change the line of the struct.unpack to the following (if you have 3 signals):

        data = struct.unpack('!ddd', data)
        x = data[0]*100
        y = data[1]*100
        z = data[2]*100