# Update object with Simulink data

I'm trying to simulate a simple dynamic system with Simulink (a bouncing ball) but the Simulink's 3D really sucks (because I'm on Linux and don't have the V-Realm Builder) so I was thinking to use Blender as a 3D world. I made a ball above a floor and I was thinking to change the ball's position using the data generated from a Simulink model. I'm using UDP to exchange data (and it works fine) but I can't achieve to update the scene in real-time because the refresh is really really slow. I'd like to move on the next step using data from an IMU and update the scene in real-time but I'm stuck on that.

I'd like to achieve something like this

How can I obtain a decent refresh rate?

Python code

import socket
import struct
import bpy

port = 8888
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print("Waiting for data...\n")
sphere = bpy.data.objects["Sphere"]
sphere.location = (0, 0, 20)

for i in range(1000):
data = struct.unpack('!d', data)
z = data[0]
sphere.location = (0, 0, z)
print("Location:", sphere.location)
bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1)


EDIT

Solution #1

I found a possible solution in this related question, which says that you'll have to edit the template. In my case, it will be something like this (and it works fine; now the only problem is that I have got some delay, maybe because of the UDP)

import bpy
import math
import socket
import struct

port = 8888
base = 20
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sphere = bpy.data.objects['Sphere']
sphere.location = (0, 0, base)

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()
sphere.location = (0, 0, base)
return {'CANCELLED'}

if event.type == 'TIMER':
data = struct.unpack('!d', data)
z = data[0]
sphere.location = (0, 0, z)
print("Z:", z)

return {'PASS_THROUGH'}

def execute(self, context):
wm = context.window_manager
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()


(I'm confident that there is a simpler way to achieve that)