So I'm trying to build a robot that can drive autonomously. For that I need the robot to drive forward and check distance at the same time. And if distance is less than preferred distance, stop forward movement. By now I've written this code below, but it doesn't seem to run simultaneously and they also don't interact. How can I make it that these two functions do indeed interact. If there's anymore information needed I'm happy to supply you. Thanks!
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
So, there's some serious problems with the code you posted. First, , because it's running a while loop. ,因为它正在运行while循环。 You should not do p2.join()
, nor should you be starting new processes all the time in your while loop. You're mixing too many ways of doing things here - either the two children run forever, or they each run once, not a mix.
However, the main problem is that (unless you do some more work). (除非您做更多工作)。 Threads are much more suited to this problem.
You also have a return
inside your distance_check()
function, so (including the sleep
, and the setting of constant1
(which should really have a better name). (包括sleep
,以及constant1
的设置(应该有更好的名字)。
In summary, I think you want something like this:
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()
Since you specified python-3.x in your tags, I've also corrected your print
.
Obviously I can't check that this will work as you want it to because I don't have your robot, but I hope that this is at least somewhat helpful.
One issue with your multiprocessing solution is that distance_check
returns and stops
dist = distance()
return dist # <------
time.sleep(0.3)
if dist < min_distance:
....
It seems like you are trying to exchange information between the processes: which is typically done using Queues or Pipes .
I read between the lines of your question and came up with the following specs:
I think you can achieve your goal without using multiprocessing. Here is a solution that uses generators/coroutines.
For testing purposes, I have written my own versions of a robot and an obstacle sensor - trying to mimic what I see in your code
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
A producer to continually check to see if it is safe to move
def can_move(target, min_distance = 15):
'''Continually check for obstacles'''
while distance() > min_distance:
target.send(True)
print('check distance')
target.close()
A generator/coroutine that consumes safe-to-move signals and changes the robot's speed as needed.
@consumer
def forward():
try:
while True:
if (yield):
robot.forward(150)
except GeneratorExit as e:
# stop the robot
robot.forward(0)
The robot's speed should change as fast as the obstacle sensor can produce distances. The robot will move forward till it gets close to something and just stop and it all shuts down . By tweaking the logic a bit in forward
and can_move
you could change the behaviour so that the generators/coroutines keep running but send a zero speed command as long as something is in front of it then when the thing gets out of the way (or the robot turns) it will start moving again.
Usage:
>>>
>>> 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
>>>
While this works in Python 3.6, it is based on a possibly outdated notion/understanding of generators and coroutines. There may be a different way to do this with some of the async
additions to Python 3+.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.