Webots中KUKA机器人多轴同步运动问题求助(4ms时间步长)
问题:Webots中KUKA机器人多轴同步运动异常
我用Webots模拟6轴KUKA机器人,当前仅启用3轴,控制器每4ms接收一次位置指令。调用axis.setPosition()时,仅第1轴运动,其余轴无响应且仿真画面无变化。尝试用多线程实现同步运动,问题仍未解决。求问如何在4ms时间步长下实现所有轴的同步运动?
初始代码
from bs4 import BeautifulSoup import socket import math import time from controller import Robot robot = Robot() timestep = int(robot.getBasicTimeStep()) serverIP = "127.0.0.1" serverPort = 59152 bufferSize = 1024 # Create a datagram socket print("DataParser started") UDPServerSocket = socket.socket( family=socket.AF_INET, type=socket.SOCK_DGRAM) print("Datagram socket created") UDPServerSocket.bind((serverIP, serverPort)) print("Address and IP binded") # Listen for incoming datagrams port_input = "2345" robotName = "kr10r1420" shadowName = "kr10r1420_shadow" print("Connected to dataParser") axe1 = robot.getDevice("1_axis_motor_rot") axe2 = robot.getDevice("2_axis_motor_rot") axe3 = robot.getDevice("3_axis_motor_rot") axe4 = robot.getDevice("4_axis_motor_rot") axe5 = robot.getDevice("5_axis_motor_rot") axe6 = robot.getDevice("6_axis_motor_rot") UDPServerSocket.settimeout(600.0) try: while robot.step(4) != -1: # print("Waiting for message") bytesAddressPair = UDPServerSocket.recvfrom(bufferSize) # f.write(str(time.time()) + '\n') print(str(time.time()) + " Timestep: " + str(timestep) + " " + str(axe1.getAcceleration())) message = bytesAddressPair[0] address = bytesAddressPair[1] # print(message.decode()) # motor.setPosition(position) # motor.setPosition(1) tag = BeautifulSoup(message.decode(), 'html.parser') # ------------------ Robot --------------------- aipos = tag.find_all('aipos')[0] a1 = math.radians(float(aipos['a1']) + 90) # axis z -> axis x axe1.setPosition(a1) # robot.step(4) # a2 = math.radians(float(aipos['a2']) + 90) # axis z -> axis x # axe2.setPosition(a2) a3 = math.radians(float(aipos['a3']) - 90) # axis x -> axis z axe3.setPosition(a3) # robot.step(4) # a4 = math.radians(float(aipos['a4'])) # It's not really defined, how it should be # axe4.setPosition(a4) # a5 = math.radians(float(aipos['a5'])) # It's not really defined, how it should be # axe5.setPosition(a5) a6 = math.radians(float(aipos['a6'])) # It's not really defined, how it should be axe6.setPosition(4) # print("axe1 " + str(a1) + " axe2 " + str(a2) + " axe3 " + str(a3) + " axe4 " + str(a4) + " axe5 " + str(a5) + " axe6 " + str(a6)) finally: print("File closed") # f.close()
多线程代码
from bs4 import BeautifulSoup import socket import math import time from controller import Robot import threading robot = Robot() timestep = int(robot.getBasicTimeStep()) serverIP = "127.0.0.1" serverPort = 59152 bufferSize = 1024 # Create a datagram socket print("DataParser started") UDPServerSocket = socket.socket( family=socket.AF_INET, type=socket.SOCK_DGRAM) print("Datagram socket created") UDPServerSocket.bind((serverIP, serverPort)) print("Address and IP binded") # Listen for incoming datagrams port_input = "2345" robotName = "kr10r1420" shadowName = "kr10r1420_shadow" print("Connected to dataParser") axe1 = robot.getDevice("1_axis_motor_rot") axe2 = robot.getDevice("2_axis_motor_rot") axe3 = robot.getDevice("3_axis_motor_rot") axe4 = robot.getDevice("4_axis_motor_rot") axe5 = robot.getDevice("5_axis_motor_rot") axe6 = robot.getDevice("6_axis_motor_rot") UDPServerSocket.settimeout(600.0) a1 = 0 a3 = 0 a6 = 0 def update_motor1(): while robot.step(timestep) != -1: axe1.setPosition(a1) def update_motor3(): while robot.step(timestep) != -1: axe3.setPosition(a3) def update_motor6(): while robot.step(timestep) != -1: axe6.setPosition(a6) thread1 = threading.Thread(target=update_motor1) thread3 = threading.Thread(target=update_motor3) thread6 = threading.Thread(target=update_motor6) thread1.start() thread3.start() thread6.start() try: while robot.step(timestep) != -1: # print("Waiting for message") bytesAddressPair = UDPServerSocket.recvfrom(bufferSize) # f.write(str(time.time()) + '\n') # print(str(time.time()) + " Timestep: " + str(timestep) + " " + str(axe1.getAcceleration())) message = bytesAddressPair[0] address = bytesAddressPair[1] # print(message.decode()) # motor.setPosition(position) # motor.setPosition(1) tag = BeautifulSoup(message.decode(), 'html.parser') # ------------------ Robot --------------------- aipos = tag.find_all('aipos')[0] a1 = math.radians(float(aipos['a1']) + 90) # axis z -> axis x # axe1.setPosition(a1) # robot.step(4) # a2 = math.radians(float(aipos['a2']) + 90) # axis z -> axis x # axe2.setPosition(a2) a3 = math.radians(float(aipos['a3']) - 90) # axis x -> axis z # axe3.setPosition(a3) # robot.step(4) # a4 = math.radians(float(aipos['a4'])) # It's not really defined, how it should be # axe4.setPosition(a4) # a5 = math.radians(float(aipos['a5'])) # It's not really defined, how it should be # axe5.setPosition(a5) a6 = math.radians(float(aipos['a6'])) # It's not really defined, how it should be # axe6.setPosition(4) # print("axe1 " + str(a1) + " axe2 " + str(a2) + " axe3 " + str(a3) + " axe4 " + str(a4) + " axe5 " + str(a5) + " axe6 " + str(a6)) finally: print("File closed") thread1.join() thread2.join() thread3.join()
解决方案
Webots的仿真依赖单线程核心循环驱动,多线程会破坏其同步机制(robot.step()不能在多个线程中调用),这是问题的核心原因。以下是正确实现方式:
1. 核心原则
所有控制逻辑必须放在同一个robot.step()循环内,每个时间步内完成所有轴的位置更新,Webots会在该步结束后统一刷新所有关节状态,实现同步运动。
2. 修复步骤
- 移除多线程:放弃多线程方案,回归单循环模式
- 初始化电机参数:确保每个电机设置了合理的速度、加速度(默认值为0时电机无法运动)
- 统一更新位置:在同一个时间步内完成所有轴的
setPosition()调用,不要插入额外的robot.step() - 修正代码错误:比如多线程代码中
thread2.join()的无效调用、初始代码中axe6.setPosition(4)的硬编码值
3. 修正后的完整代码
from bs4 import BeautifulSoup import socket import math from controller import Robot robot = Robot() timestep = 4 # 直接指定4ms时间步,匹配需求 serverIP = "127.0.0.1" serverPort = 59152 bufferSize = 1024 # 初始化UDP套接字 print("DataParser started") UDPServerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) UDPServerSocket.bind((serverIP, serverPort)) print("Address and IP binded") # 获取目标电机设备 axe1 = robot.getDevice("1_axis_motor_rot") axe3 = robot.getDevice("3_axis_motor_rot") axe6 = robot.getDevice("6_axis_motor_rot") # 初始化电机运动参数 for motor in [axe1, axe3, axe6]: motor.setVelocity(motor.getMaxVelocity()) # 使用最大速度,可按需调整 motor.setAcceleration(10) # 设置加速度,避免卡顿 UDPServerSocket.settimeout(600.0) try: while robot.step(timestep) != -1: # 接收UDP位置指令 bytesAddressPair = UDPServerSocket.recvfrom(bufferSize) message = bytesAddressPair[0] # 解析指令 tag = BeautifulSoup(message.decode(), 'html.parser') aipos = tag.find_all('aipos')[0] # 计算各轴目标位置(坐标系转换) a1 = math.radians(float(aipos['a1']) + 90) a3 = math.radians(float(aipos['a3']) - 90) a6 = math.radians(float(aipos['a6'])) # 统一设置所有轴位置,Webots自动同步执行 axe1.setPosition(a1) axe3.setPosition(a3) axe6.setPosition(a6) finally: print("File closed") UDPServerSocket.close()
关键注意事项
robot.step()是仿真的核心心跳,所有控制逻辑必须在两次step之间完成- 若电机速度/加速度设为0,即使调用
setPosition()也不会运动,必须初始化合理参数 recvfrom()是阻塞调用,若UDP指令发送间隔超时会导致控制器停止,可调整timeout或改用非阻塞模式
内容的提问来源于stack exchange,提问作者cedrik
相关产品推荐
相关产品推荐

