Как заставить работать несколько объектов одновременно? - PullRequest
2 голосов
/ 01 мая 2019

Я использовал Python для управления некоторыми инструментами, для которых я создал класс. У меня несколько инструментов одного типа, поэтому в моем сценарии несколько экземпляров одного и того же класса.

Скажем, класс 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 достаточно независимы и не требуют особых требований к синхронизации. Я просто не хочу тратить время на сериализацию в коде.

Я провел некоторый поиск и немного узнал о многопоточности, но я обнаружил, что в функцию Thread добавлена ​​ функция , которая на самом деле не применима к моей ситуации.

1 Ответ

1 голос
/ 01 мая 2019

Одним из способов решения этой проблемы является реализация конечного автомата .То есть вместо того, чтобы определять проблему с помощью команд, таких как move_left() и move_right(), вместо этого вы можете иметь некоторые переменные, которые представляют конечную позицию, в которой вы хотите, чтобы каждая рука заканчивалась, и второй набор переменных, которые представляют текущуюположение руки.Затем на каждом временном шаге вы просто слегка перемещаете руки в направлении их цели-цели.

Вот очень простая игрушка, демонстрирующая эту идею.Обратите внимание, что он перемещает каждую «руку» не более чем на 0,1 единицы каждые 100 мс (с шагом времени (вы, конечно, можете использовать любые значения временного шага и максимального движения):

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(), чтобы дать оружию новые / другие значения назначения, и они сразу женачать движение от (где бы они ни находились в настоящее время) к новым целевым позициям - нет необходимости ждать, пока они прибудут в старые пункты назначения первыми.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...