I want to use Blender gaming engine to display the position of objects that I get from UDP. The UDP contains the datas (X) for Object A, and (X) for object B I also need to use bge to compute some distances and send this over udp
I did some tests, and I succeed in using Python to read the data from UDP. for object A
Python Script
import bge
import math
import socket
import struct
#socket for receiving position
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((address, port))
#socket for sending information
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s2.bind((address, port2))
def setPosition():
if not allSensorsArePositive():
return
data, addr = s.recvfrom(16)
data = struct.unpack('dd', data)
objA_x = data[0]
owner = bge.logic.getCurrentController().owner
owner.localPosition.x = objA_x
owner.localPosition.y = 0
for object B
import bge
import math
import socket
import struct
#socket for receiving position
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((address, port))
def setPosition():
if not allSensorsArePositive():
return
data, addr = s.recvfrom(16)
data = struct.unpack('dd', data)
objB_x = data[1]
owner = bge.logic.getCurrentController().owner
owner.localPosition.x = objB_x
owner.localPosition.y = 0
But i don't like the idea of "deserializing" the data twice. And I get an error at execution :
OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
Python module can't be imported - object 'ObjB', controller 'Python':
Also, I would like to know if there a place, where I can execute once :
data, addr = s.recvfrom(16)
data = struct.unpack('dd', data)
# some stuff
objA_x = data[0]
objB_x = data[1]
and then store and objA_x, objB_x variables so that they can be used by scripts for each object.
Note : I know one can do it with BPY, but I need a real time environment and computation done by bge (get distances), so I prefer to stick with bge.
#Example with bpy
import bge
import math
import socket
import struct
port = 25001
port2 = 25002
address = "127.0.0.1"
base = 20
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((address, port))
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s2.bind((address, port2))
objA = bge.data.objects['objA']
objA.location = (500, 0, 0)
objB = bge.data.objects['objB']
objB.location = (0, 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 {'ESC'}:
self.cancel(context)
s.close()
objA.location = (0, 0, 0)
objB.location = (0, 0, 0)
return {'CANCELLED'}
if event.type == 'TIMER':
data, addr = s.recvfrom(16)
data = struct.unpack('dd', data)
objA_x = data[0]
objB_x = data[1]
objA.location = (objA_x, 0, 0)
objB.location = (objB_x, 0, 0)
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()
EDIT : As suggested by @Strapicarus
I edited the 2 scripts :
Object A
import bge
import random
import socket
import struct
import math
port = 25001
port2 = 25002
address = "127.0.0.1"
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setblocking(0)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((address, port))
#s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#s2.bind((address, port2))
def setPosition():
if not allSensorsArePositive():
return
data_bytes, addr = s.recvfrom(16)
data = struct.unpack('dd', data_bytes)
obj_x = data[0]
owner = bge.logic.getCurrentController().owner
owner.localPosition.x = obj_x
owner.localPosition.y = 0
def allSensorsArePositive():
for sensor in bge.logic.getCurrentController().sensors:
if not sensor.positive:
return False
return True
Object B
import bge
import random
import socket
import struct
import math
port = 25001
address = "127.0.0.1"
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setblocking(0)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((address, port))
def setPosition():
if not allSensorsArePositive():
return
data_bytes, addr = s.recvfrom(16)
data = struct.unpack('dd', data_bytes)
obj_x= data[1]
owner = bge.logic.getCurrentController().owner
owner.localPosition.x = obj_x
owner.localPosition.y = 0
def allSensorsArePositive():
for sensor in bge.logic.getCurrentController().sensors:
if not sensor.positive:
return False
return True
but I still have an error at Execution:
Blender Game Engine Started
Python module can't be imported - object 'ObjA', controller 'Python':
Traceback (most recent call last):
File "D:\~\blender\Env3D.blend\pos_obj_A.py", line 12, in <module>
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
Python module can't be imported - object 'ObjB', controller 'Python':
Traceback (most recent call last):
File "D:\~\blender\Env3D.blend\pos_obj_B.py", line 12, in <module>
s.bind((address, port))
OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
Blender Game Engine Finished
Ressources:
Controlling drivers with data received via TCP/UDP
data
for multiple things (bytes from the socket, as well as the result fromstruct.unpack()
). Furthermore, your question subject and tags indicates the BGE, but your code doesn't use the BGE at all. All in all it's rather confusing. $\endgroup$self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.socket.setblocking(0) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.socket.bind((host,port))
i think the problem is the socket blocking a left this here, sorry dont have time to elaborate a proper answer. $\endgroup$