2
$\begingroup$

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)
address = "127.0.0.1"
s.bind((address, port))
print("Waiting for data...\n")
sphere = bpy.data.objects["Sphere"]
sphere.location = (0, 0, 20)

for i in range(1000):
    data, addr = s.recvfrom(1024)
    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)

Simulink model Model

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
address = "127.0.0.1"
base = 20
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((address, port))
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, addr = s.recvfrom(16)
            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
        self._timer = wm.event_timer_add(0.1, 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()

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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.