我一直在使用Python控制一些乐器,为此我创建了一个Class。我有多种同一种乐器,所以我的脚本具有同一个类的多个实例。
让我们说该类为Arm
,它具有方法move_left
,move_right
和reset
。现在我有这样的脚本:
arm1 = Arm()
arm2 = Arm()
arm1.move_left()
arm2.move_left()
arm1.move_right()
arm2.move_right()
arm1.reset()
arm2.reset()
它完全是串行的。我必须等待arm1
完成move_left
,然后从arm2
到move_left
。这是非常低效的。我希望arm1
和arm2
同时移动。它们不必完全相同,因为arm1
和arm2
是非常独立的,并且没有太多同步要求。我只是不想在代码的序列化中浪费时间。
我已经进行了一些搜索并且对线程有了一些了解,但是我发现的全部是关于将 function 放入Thread目标中的,这实际上不适用于我的情况。
答案 0 :(得分:1)
解决该问题的一种方法是实现状态机。也就是说,与其通过move_left()
和move_right()
之类的命令来定义问题,不如使用一些变量来表示希望每个手臂最终到达的最终位置,并使用第二组变量代表手臂的当前位置。然后,在每个时间步上,您只需将手臂向目标位置移动少量。
这是一个非常简单的玩具程序来演示这个想法。请注意,它每100mS时间步长将每个“手臂”移动不超过0.1个单位(当然,您可以使用所需的任何时间步长和最大运动值):
import time
class Robot:
def __init__(self):
self._leftArmCurrentPos = 0.0
self._leftArmTargetPos = 0.0
self._rightArmCurrentPos = 0.0
self._rightArmTargetPos = 0.0
def setLeftArmTargetPos(self, newPos):
self._leftArmTargetPos = newPos
def setRightArmTargetPos(self, newPos):
self._rightArmTargetPos = newPos
# Returns the closest value to (deltaVal) in the range [-0.1, +0.1]
def clamp(self, deltaVal):
aLittleBit = 0.1 # or however much you want
if (deltaVal > aLittleBit):
return aLittleBit
elif (deltaVal < -aLittleBit):
return -aLittleBit
else:
return deltaVal
def moveArmsTowardsTargetPositions(self):
leftArmDelta = self.clamp(self._leftArmTargetPos - self._leftArmCurrentPos)
if (leftArmDelta != 0.0):
self._leftArmCurrentPos += leftArmDelta
print("Moved left arm by %f towards %f, new left arm pos is %f" % (leftArmDelta, self._leftArmTargetPos, self._leftArmCurrentPos))
rightArmDelta = self.clamp(self._rightArmTargetPos - self._rightArmCurrentPos)
if (rightArmDelta != 0.0):
self._rightArmCurrentPos += rightArmDelta
print("Moved right arm by %f towards %f, new right arm pos is %f" % (rightArmDelta, self._rightArmTargetPos, self._rightArmCurrentPos))
if __name__ == "__main__":
r = Robot()
r.setLeftArmTargetPos(10.0)
r.setRightArmTargetPos(-3.0)
while True:
r.moveArmsTowardsTargetPositions()
time.sleep(0.1)
此方法的一个很好的副作用是,如果您在任何时候想要改变手臂的位置时都改变了主意,则可以简单地致电setLeftArmTargetPos()
或setRightArmTargetPos()
来赋予手臂新的手臂/不同的目标值,它们将立即开始(从当前位置)移动到新的目标位置-无需等待它们首先到达旧目标。