如何使多个对象同时工作?

时间:2019-04-30 23:27:25

标签: python-3.x multithreading oop

我一直在使用Python控制一些乐器,为此我创建了一个Class。我有多种同一种乐器,所以我的脚本具有同一个类的多个实例。

让我们说该类为Arm,它具有方法move_leftmove_rightreset。现在我有这样的脚本:

arm1 = Arm()
arm2 = Arm()
arm1.move_left()
arm2.move_left()
arm1.move_right()
arm2.move_right()
arm1.reset()
arm2.reset()

它完全是串行的。我必须等待arm1完成move_left,然后从arm2move_left。这是非常低效的。我希望arm1arm2同时移动。它们不必完全相同,因为arm1arm2是非常独立的,并且没有太多同步要求。我只是不想在代码的序列化中浪费时间。

我已经进行了一些搜索并且对线程有了一些了解,但是我发现的全部是关于将 function 放入Thread目标中的,这实际上不适用于我的情况。

1 个答案:

答案 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()来赋予手臂新的手臂/不同的目标值,它们将立即开始(从当前位置)移动到新的目标位置-无需等待它们首先到达旧目标。