Blender Robotic control Python code giving wrong angles?

I made a code for my ESP32 to control my robotic arm ( 5 Axes ; 5 steppermotors ) when it gets coordinates through the serialport like e.g.: “1000, 1000, 1000, 1000, 1000.
Then, I have code in Blender witch should read the angles from the Bones of the 3d Moddel of the Arm witch I rigged up.
Somehow, only the first Coordinate seems to be right.
When the Arm is in its zeroposition, it gives me these coordinates: Sending angles: 0,0,0,29947,-29947 (these are wrong)
When I play the animation a little bit further, it gives me numbers, that are way to high, still zero and i’m not shure if it is correct that some are negative…
: 22874,0,-29947,0,-632

I don’t fully understand how and why it is reading the angles like this and I,m still very new.
I hope that somebody can help me out 😉

Blender Python Script:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>import bpy
import math
import serial
import time
import threading
port = 'COM3'
# Thread lock for serial writing
serial_lock = threading.Lock()
# Connect to the serial port
try:
ser = serial.Serial(port, 9600)
print("Connected to: " + ser.portstr)
except serial.SerialException as e:
print(f"Could not open port {port}: {e}")
raise
armature_name = 'Armature'
# Function to get the armature object safely
def get_armature():
try:
ob = bpy.data.objects[armature_name]
bpy.context.view_layer.objects.active = ob
bpy.ops.object.mode_set(mode='POSE')
return ob
except KeyError:
print(f"Armature '{armature_name}' not found in the current scene")
return None
except ReferenceError:
print(f"ReferenceError: Armature '{armature_name}' has been removed")
return None
ob = get_armature()
if ob is None:
raise KeyError(f"Failed to initialize armature '{armature_name}'")
# Adding appropriate offsets for all 5 motors
offsets = [0, 0, 0, 0, 0]
gear_ratio = 5.5 * 5.5 * 5.5 #Planetary gearbox in the robotic arm
def get_local_orientation(pose_bone):
local_orientation = pose_bone.matrix.to_euler()
if pose_bone.parent is None:
return local_orientation
else:
x = local_orientation.x - pose_bone.parent.matrix.to_euler().x
y = local_orientation.y - pose_bone.parent.matrix.to_euler().y
z = local_orientation.z - pose_bone.parent.matrix.to_euler().z
return (x, y, z)
def sendAngles():
ob = get_armature()
if ob is None:
return
bones = [
'Dreinen', # first Bone
'LowerArm', # second bone
'UpperArm', # ...
'UpperArm2',
'UpperArm3'
]
if len(bones) != len(offsets):
raise ValueError("The number of bones does not match the number of offsets")
angles = []
for i, bone_name in enumerate(bones):
try:
bone = ob.pose.bones[bone_name]
except KeyError:
print(f"Bone '{bone_name}' not found in armature '{armature_name}'")
continue
angle = math.degrees(get_local_orientation(bone)[2]) + offsets[i]
# Convert angle to steps considering the gear ratio
steps = int(angle * gear_ratio)
angles.append(str(steps))
angle_str = ','.join(angles)
print("Sending angles:", angle_str) # Debug print
with serial_lock:
try:
if ser.is_open:
ser.write(angle_str.encode('UTF-8'))
time.sleep(0.1) # Add delay between writes
else:
print("Serial port is not open")
except serial.SerialException as e:
print(f"Serial write error: {e}")
def frameChange(passedScene):
try:
sendAngles()
except Exception as e:
print(f"Error in frameChange handler: {e}")
bpy.app.handlers.frame_change_pre.append(frameChange)
# Additional setup verification prints
print("Script started.")
print(f"Armature name: {armature_name}")
print(f"Connected to: {ser.portstr}")
print(f"Offsets: {offsets}")
print(f"Gear ratio: {gear_ratio}")
# Print bone names to verify they are correct
for bone_name in ['Dreinen', 'LowerArm', 'UpperArm', 'UpperArm2', 'UpperArm3']:
if bone_name in ob.pose.bones:
print(f"{bone_name} found.")
else:
print(f"Bone '{bone_name}' not found in armature '{armature_name}'.")
# End the serial connection properly when done
import atexit
def close_serial():
if ser.is_open:
ser.close()
print("Closed serial connection.")
atexit.register(close_serial)
</code>
<code>import bpy import math import serial import time import threading port = 'COM3' # Thread lock for serial writing serial_lock = threading.Lock() # Connect to the serial port try: ser = serial.Serial(port, 9600) print("Connected to: " + ser.portstr) except serial.SerialException as e: print(f"Could not open port {port}: {e}") raise armature_name = 'Armature' # Function to get the armature object safely def get_armature(): try: ob = bpy.data.objects[armature_name] bpy.context.view_layer.objects.active = ob bpy.ops.object.mode_set(mode='POSE') return ob except KeyError: print(f"Armature '{armature_name}' not found in the current scene") return None except ReferenceError: print(f"ReferenceError: Armature '{armature_name}' has been removed") return None ob = get_armature() if ob is None: raise KeyError(f"Failed to initialize armature '{armature_name}'") # Adding appropriate offsets for all 5 motors offsets = [0, 0, 0, 0, 0] gear_ratio = 5.5 * 5.5 * 5.5 #Planetary gearbox in the robotic arm def get_local_orientation(pose_bone): local_orientation = pose_bone.matrix.to_euler() if pose_bone.parent is None: return local_orientation else: x = local_orientation.x - pose_bone.parent.matrix.to_euler().x y = local_orientation.y - pose_bone.parent.matrix.to_euler().y z = local_orientation.z - pose_bone.parent.matrix.to_euler().z return (x, y, z) def sendAngles(): ob = get_armature() if ob is None: return bones = [ 'Dreinen', # first Bone 'LowerArm', # second bone 'UpperArm', # ... 'UpperArm2', 'UpperArm3' ] if len(bones) != len(offsets): raise ValueError("The number of bones does not match the number of offsets") angles = [] for i, bone_name in enumerate(bones): try: bone = ob.pose.bones[bone_name] except KeyError: print(f"Bone '{bone_name}' not found in armature '{armature_name}'") continue angle = math.degrees(get_local_orientation(bone)[2]) + offsets[i] # Convert angle to steps considering the gear ratio steps = int(angle * gear_ratio) angles.append(str(steps)) angle_str = ','.join(angles) print("Sending angles:", angle_str) # Debug print with serial_lock: try: if ser.is_open: ser.write(angle_str.encode('UTF-8')) time.sleep(0.1) # Add delay between writes else: print("Serial port is not open") except serial.SerialException as e: print(f"Serial write error: {e}") def frameChange(passedScene): try: sendAngles() except Exception as e: print(f"Error in frameChange handler: {e}") bpy.app.handlers.frame_change_pre.append(frameChange) # Additional setup verification prints print("Script started.") print(f"Armature name: {armature_name}") print(f"Connected to: {ser.portstr}") print(f"Offsets: {offsets}") print(f"Gear ratio: {gear_ratio}") # Print bone names to verify they are correct for bone_name in ['Dreinen', 'LowerArm', 'UpperArm', 'UpperArm2', 'UpperArm3']: if bone_name in ob.pose.bones: print(f"{bone_name} found.") else: print(f"Bone '{bone_name}' not found in armature '{armature_name}'.") # End the serial connection properly when done import atexit def close_serial(): if ser.is_open: ser.close() print("Closed serial connection.") atexit.register(close_serial) </code>
import bpy
import math
import serial
import time
import threading

port = 'COM3'  

# Thread lock for serial writing
serial_lock = threading.Lock()

# Connect to the serial port
try:
    ser = serial.Serial(port, 9600)
    print("Connected to: " + ser.portstr)
except serial.SerialException as e:
    print(f"Could not open port {port}: {e}")
    raise

armature_name = 'Armature'  

# Function to get the armature object safely
def get_armature():
    try:
        ob = bpy.data.objects[armature_name]
        bpy.context.view_layer.objects.active = ob
        bpy.ops.object.mode_set(mode='POSE')
        return ob
    except KeyError:
        print(f"Armature '{armature_name}' not found in the current scene")
        return None
    except ReferenceError:
        print(f"ReferenceError: Armature '{armature_name}' has been removed")
        return None

ob = get_armature()
if ob is None:
    raise KeyError(f"Failed to initialize armature '{armature_name}'")

# Adding appropriate offsets for all 5 motors
offsets = [0, 0, 0, 0, 0]
gear_ratio = 5.5 * 5.5 * 5.5  #Planetary gearbox in the robotic arm

def get_local_orientation(pose_bone):
    local_orientation = pose_bone.matrix.to_euler()
    if pose_bone.parent is None:
        return local_orientation
    else:
        x = local_orientation.x - pose_bone.parent.matrix.to_euler().x
        y = local_orientation.y - pose_bone.parent.matrix.to_euler().y
        z = local_orientation.z - pose_bone.parent.matrix.to_euler().z
        return (x, y, z)

def sendAngles():
    ob = get_armature()
    if ob is None:
        return

    bones = [
        'Dreinen',  # first Bone 
        'LowerArm',  # second bone
        'UpperArm',  # ...
        'UpperArm2', 
        'UpperArm3'  
    ]

    if len(bones) != len(offsets):
        raise ValueError("The number of bones does not match the number of offsets")

    angles = []
    for i, bone_name in enumerate(bones):
        try:
            bone = ob.pose.bones[bone_name]
        except KeyError:
            print(f"Bone '{bone_name}' not found in armature '{armature_name}'")
            continue
        angle = math.degrees(get_local_orientation(bone)[2]) + offsets[i]
        # Convert angle to steps considering the gear ratio
        steps = int(angle * gear_ratio)
        angles.append(str(steps))

    angle_str = ','.join(angles)
    print("Sending angles:", angle_str)  # Debug print

    with serial_lock:
        try:
            if ser.is_open:
                ser.write(angle_str.encode('UTF-8'))
                time.sleep(0.1)  # Add delay between writes
            else:
                print("Serial port is not open")
        except serial.SerialException as e:
            print(f"Serial write error: {e}")

def frameChange(passedScene):
    try:
        sendAngles()
    except Exception as e:
        print(f"Error in frameChange handler: {e}")

bpy.app.handlers.frame_change_pre.append(frameChange)

# Additional setup verification prints
print("Script started.")
print(f"Armature name: {armature_name}")
print(f"Connected to: {ser.portstr}")
print(f"Offsets: {offsets}")
print(f"Gear ratio: {gear_ratio}")

# Print bone names to verify they are correct
for bone_name in ['Dreinen', 'LowerArm', 'UpperArm', 'UpperArm2', 'UpperArm3']:
    if bone_name in ob.pose.bones:
        print(f"{bone_name} found.")
    else:
        print(f"Bone '{bone_name}' not found in armature '{armature_name}'.")

# End the serial connection properly when done
import atexit
def close_serial():
    if ser.is_open:
        ser.close()
        print("Closed serial connection.")
atexit.register(close_serial)

Example in the console:

Connected to: COM3
Script started.
Armature name: Armature
Connected to: COM3
Offsets: [0, 0, 0, 0, 0]
Gear ratio: 166.375
Dreinen found.
LowerArm found.
UpperArm found.
UpperArm2 found.
UpperArm3 found.
Sending angles: 0,0,0,29947,-29947
Sending angles: 0,0,0,29947,-29947
Sending angles: 255,0,0,-29947,29913
Sending angles: 1114,0,0,-29947,29806
Sending angles: 7286,0,0,-29947,29418
Sending angles: 13887,0,0,-29947,29346
Sending angles: 18548,0,0,-29947,-527
Sending angles: 20776,0,0,-29947,-463
Sending angles: 18548,0,0,-29947,-527
Sending angles: 20776,0,0,-29947,-463
Sending angles: 20776,0,0,-29947,-463
Sending angles: 21885,0,0,-29947,-468
Sending angles: 22778,0,-29947,0,-599
Sending angles: 22874,0,-29947,0,-632
Sending angles: 22874,0,-29947,0,-632

I tried giving the ESP32 the Coordinates manually through the serialmonitor in arduinoIDE. That worked perfectly.
I also tried giving the code to chatgpt but this didn’t really help…

New contributor

Mr. Sunny is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật