I'm looking for workflows to rotate an object in Blender in real-time with a stream of quaternion data from an inertial measurement unit (IMU). The quaternion data can be provided in whatever way or form is neccessary, so it will suit a proposed Blender workflow.
-
https://blender.stackexchange.com/questions/153079/object-controlling-using-arduino https://blender.stackexchange.com/questions/27959/controlling-drivers-with-data-received-via-tcp-udp/27960 https://blender.stackexchange.com/questions/27959/controlling-drivers-with-data-received-via-tcp-udp – Duarte Farrajota Ramos Jun 08 '22 at 08:47
-
1This will highly depend on how you are getting the data from the IMU, whether the process is supposed to be automated and whether you know how to implement scripts with Python? – Robert Gützkow Jun 09 '22 at 17:04
-
Dear Robert, I don't understand why you closed my question. Would you care to elaborate? I don't see why it matters how I aquire the data or if I know how to implement scripts with Python. The question is about the workflow and pointers to relevant documentation. Point is that I have quaternions and I'd like to feed them into Blender, so the cube rotates when I rotate the IMU. Kind regards – babe.schnitzel Jun 09 '22 at 21:48
-
1The approach and necessary steps highly depend on how you intend to get the quaternions from the IMU into Blender due to the requirement of updates happening in real time (IMU reports an update and the object is supposed to update the rotation). Generally, this could be done by implementing a Python add-on in Blender through its Python API. However, Blender does not provide support for IMUs out of the box. – Robert Gützkow Jun 10 '22 at 08:25
-
1I would suggest you try to break your question down into separate problems for which we could provide a precise answer to or point you to an existing answer that was previously asked (e.g. how to change the rotation of an object, how to continously run an operator, how to communicate over the network, ...). Depending on the context you are trying to use this for, there may be software other than Blender that is more suitable for this task though, for instance game engines (UPBGE, Godot, Unity, Unreal, ...). – Robert Gützkow Jun 10 '22 at 08:30
-
@babe.schnitzel Thanks for the update. While answering your own question is entirely possible and even encouraged when find a solution, it should be done respecting the site structure. Could you break this up into two posts so the solution to the issue is displayed as separate answer in the proper answer section below, while keeping it distinct from the enquiry in the question section above? Perhaps add a few images illustrating the workflow and final results. See https://blender.stackexchange.com/help/how-to-answer – Duarte Farrajota Ramos Jun 13 '22 at 12:04
1 Answers
I learned from the comments and references here that the quaternion data could be provided to Blender via an UDP socket. Then a modal operator could be used to manipulate the properties of the object, which has to be written in Python, using the Blender Python API.
Unfortunately the approach given in Object Controlling using Arduino, which is using a modal operator, did not work for me. I adapted the script to process the rotational data but my version of the script failed because it tried to open the socket multiple times.
Later I came across a very nice blog post by Michał Ciesielski about using sockets in Blender. Instead of a modal operator he is using an application timer. I adapted his code a little to suit my needs.
Here's how I ran the code (on Linux) to make the little cube rotating, which sits there when you start a new project:
Create or open the Blender script in the 'Scripting' workspace.
import bpy import socketHOST = '127.0.0.1' PORT = 65432
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.bind((HOST, PORT))
data = None bpy.data.objects['Cube'].rotation_mode = 'QUATERNION'
def handle_data(): interval = 0.33 try: data, addr = s.recvfrom(128) if data.decode('utf-8') == 'quit': interval = None s.close() else: bpy.data.objects['Cube'].rotation_quaternion = list(map(float, data.decode('utf-8')[1:-1].split(','))) except Exception as e: print(e)
return intervalbpy.app.timers.register(handle_data)
Run the Blender script by pressing the 'Run script' button (triangle).
Run the client script from the command line. This script simulates the quaternion data which would come from the IMU.
#!/usr/bin/env python3 import time import socket import numpy as npHOST = "127.0.0.1" PORT = 65432
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.connect((HOST, PORT))
try: while True: time.sleep(0.33) random_quaternion = list(np.random.uniform(-1, 1, size=(1, 4))[0]) data = str(random_quaternion) sock.send(data.encode()) print(data) except KeyboardInterrupt: # Stop with Ctrl-C sock.send(str('quit').encode())
Now you should see the little cube rotating. If you don't, check the error messages. To see the error message that the Blender script creates, start Blender from the command line and redo the above steps.
When I used an actual IMU I noticed that the latency, between rotating the IMU and the cube rotating on the screen, was rather big. I wonder why?! Will the latency shrink when I run Blender on more powerful hardware? Or is the approach to use an application handler very slow?
I'd like to leave the question open and would like to accept an answer that gives a better overview of all the possible workflows to get external (real-time) data into Blender to manipulate objects in real-time.
- 41
- 5