所以我试图建立一个可以自主驾驶的机器人。为此,我需要机器人前进并同时检查距离。如果距离小于首选距离,则停止向前移动。到目前为止,我已经在下面编写了这段代码,但它似乎并没有同时运行,而且它们也没有进行交互。我怎样才能确保这两个函数确实相互作用。如果还有需要的信息,我很乐意为您提供。谢谢!
from multiprocessing import Process
from TestS import distance
import Robot
import time
constant1 = True
min_distance = 15
def forward():
global constant1:
robot.forward(150) #forward movement, speed 150
time.sleep(2)
def distance_check():
global constant1
while constant1:
distance() #checking distance
dist = distance()
return dist
time.sleep(0.3)
if dist < min_distance:
constant1 = False
print 'Something in the way!'
break
def autonomy(): #autonomous movement
while True:
p1 = Process(target=forward)
p2 = Process(target=distance_check)
p1.start() #start up 2 processes
p2.start()
p2.join() #wait for p2 to finish
答案 0 :(得分:2)
因此,您发布的代码存在一些严重问题。首先,您不希望distance_check
进程完成,因为它正在运行while循环。您不应该p2.join()
,也不应该在while循环中始终启动新进程。你在这里混合了太多的做事方式 - 要么两个孩子永远奔跑,要么他们每个人跑一次,而不是混合。
然而,主要问题是原始流程无法与原始流程进行通信,即使是通过global
(除非您做更多工作)。线程更适合这个问题。
您的return
函数中还有一个distance_check()
,因此该语句下方的代码无法执行(包括sleep
和constant1
的设置{1}}(应该有更好的名字)。
总之,我认为你想要这样的东西:
from threading import Thread
from TestS import distance
import Robot
import time
can_move_forward = True
min_distance = 15
def move_forward():
global can_move_forward
while can_move_forward:
robot.forward(150)
time.sleep(2)
print('Moving forward for two seconds!')
def check_distance():
global can_move_forward
while True:
if distance() < min_distance:
can_move_forward = False
print('Something in the way! Checking again in 0.3 seconds!')
time.sleep(0.3)
def move_forward_and_check_distance():
p1 = Thread(target = move_forward)
p2 = Thread(target = check_distance)
p1.start()
p2.start()
由于您在代码中指定了python-3.x,我们还更正了您的print
。
显然我无法检查这是否会按照您的意愿运行,因为我没有您的机器人,但我希望这至少对您有所帮助。
答案 1 :(得分:2)
多处理解决方案的一个问题是distance_check
返回停止
dist = distance()
return dist # <------
time.sleep(0.3)
if dist < min_distance:
....
您似乎正在尝试在流程之间交换信息:通常使用Queues or Pipes完成。
我在您的问题的行之间阅读并提出以下规范:
我认为您可以在不使用多处理的情况下实现目标。这是一个使用生成器/协同程序的解决方案。
出于测试目的,我编写了自己的机器人版本和障碍物传感器 - 试图模仿我在代码中看到的内容
class Robot:
def __init__(self, name):
self.name = name
def forward(self, speed):
print('\tRobot {} forward speed is {}'.format(self.name, speed))
if speed == 0:
print('\tRobot {} stopped'.format(speed))
def distance():
'''User input to simulate obstacle sensor.'''
d = int(input('distance? '))
return d
Decorator to start a coroutine/generator:
def consumer(func):
def wrapper(*args,**kw):
gen = func(*args, **kw)
next(gen)
return gen
wrapper.__name__ = func.__name__
wrapper.__dict__ = func.__dict__
wrapper.__doc__ = func.__doc__
return wrapper
生产者不断检查是否可以安全移动
def can_move(target, min_distance = 15):
'''Continually check for obstacles'''
while distance() > min_distance:
target.send(True)
print('check distance')
target.close()
消耗安全移动信号的生成器/协程,并根据需要更改机器人的速度。
@consumer
def forward():
try:
while True:
if (yield):
robot.forward(150)
except GeneratorExit as e:
# stop the robot
robot.forward(0)
机器人的速度应该与障碍物传感器产生距离一样快。机器人将向前移动直到它接近某个东西然后停止并且所有关闭。通过在forward
和can_move
中稍微调整逻辑,您可以更改行为,以便生成器/协同程序继续运行,但只要有一些东西在它前面就会发送零速命令走开(或机器人转动)它会再次开始移动。
用法:
>>>
>>> robot = Robot('Foo')
>>> can_move(forward())
distance? 100
Foo forward speed is 150
check distance
distance? 50
Foo forward speed is 150
check distance
distance? 30
Foo forward speed is 150
check distance
distance? 15
Foo forward speed is 0
Robot 0 stopped
>>>
虽然这在Python 3.6中有效,但它基于对生成器和协同程序的可能过时的概念/理解。使用Python 3 +的一些async
添加可能有不同的方法。