Is my project better suited for the game engine? (Simulink -> Blender)

I’m merely interested in visualizing simulated values. No fancy material rendering or anything (At least yet). Frame rate is not really an issue either, but I’d like to avoid bottlenecks (hence my question). Just position some objects when my external program (Simulink) has calculated their positions and rotations.

Im toying around with a Python UDP server that reads a Simulink stream and positions a cube from simulated data. Unfortunately, the constant loop of repositioning the cube does not go much faster than roughly 13FPS (Considerably slower than the Simulink UDP client). I think this is because the 3D view-port is not really meant for this sort of thing (passed data is not more than 16 bytes per packet so that’s not a reason for sluggishness).

Im wondering if the game engine might be better suited for running a UDP script that constantly repositions some meshes from the data stream. In that case, where should I start? What do I need to learn?

For those interested, here is the code Im using. It is from http://blender.stackexchange.com/questions/7885/how-to-run-a-python-script-at-regular-intervals/7887#7887, with the main function instead being to read UDP and reposition cube z-pos and z-rot.


import bpy, socket, struct

# open network socket
port = 20001
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("127.0.0.1", port))
print("Run
")
s.settimeout(1) # Caught in exception to not lock program

ob = bpy.data.objects.get('Cube')

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 == 'ESC':
            s.close() # If this is not reached, the socket will be open and unable to run
            return self.cancel(context)

        if event.type == 'TIMER':
            try:
                
                data, addr = s.recvfrom(16) # 'bufsize' bytes
                if data:
                    unp = struct.unpack('!2d', data)
                    print('%.2f, %.2f' % (unp[0], unp[1]))
                    ob.rotation_euler = 0, 0, unp[0]
                    ob.location = 0, 0, unp[1]
            except socket.timeout:
                print('Simulink packet timeout.')
                #continue
        return {'PASS_THROUGH'}
    def execute(self, context):
        self._timer = context.window_manager.event_timer_add(0.1, context.window)
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}
    def cancel(self, context):
        context.window_manager.event_timer_remove(self._timer)
        return {'CANCELLED'}

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()

So, I sort of answered my own question. Getting a simple UDP server running in the game engine gives much better results for real time implementations. Makes sense, I guess.

The basic parts of the game engine turned out to be quite easy (That is, I’m not sure of my code is nice or not, but it gives me what I want for now), so I’ll likely continue this in the game engine forum.

For anyone googling ‘Simulink + Blender’, this is what I wrote, for a sensor of the ‘always’ type.


import bpy, socket, struct, math

# Setup objects
cont = bge.logic.getCurrentController()
player = cont.owner

if not 'init' in player:
    player['init'] = 1
    # open network socket
    port = 20001
    player['socket'] = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    player['socket'].bind(("127.0.0.1", port))
    print("Run
")
    player['socket'].settimeout(.1) # Caught in exception to not lock program


def main():
    try:
        data, addr = player['socket'].recvfrom(16) # 'bufsize' bytes
        if data:
            unp = struct.unpack('!2d', data)
            player.localPosition.z = unp[1]    
            player.localOrientation = (0, 0, unp[0])
    except socket.timeout:
        print('Simulink packet timeout.')

main()