#
# Wandering behavior.
# This wanderer has the robot move backwards (i.e. the laptop faces the user as the
# user walks behind the robot). The servo should be pointed with its cord pointing
# towards the laptop. The camera is not used.
#
# This wandering behavior follows the left-hand rule.
#
#
#
#
# Required libraries
# socket is needed to connect to the sonar server and the ER1 server
# string is needed to send commands to the servers
#
import socket
import string
import msvcrt
#
# Hard-coded variables
# sonar variables are definitions of distances on the sonar
# velocity variables are definitions of speeds for the robot to move at
# Servo variable are positions
# maxloop is the biggest number of times to do one behavior before returning to the main loop
# also the biggest number of times to run the main loop before asking if should do more
#
sonarTooClose = 20
sonarClose = 50
sonarHallWidth = 130
sonarMaxTrust = 150 # Max value the sonar will accept without double-checking
sonarTolerance = 10 # Error tolerance of the sonar
sonarNumTries = 3
velocitySlow = 10
velocityNormal = 20
maxloop = 50
servoCenter = 125
servoLeft = 240
servoRight = 30
#
# Initialize the TCP connections to the sonar and the robot
#
HOST = '127.0.0.1' # localhost
SONARPORT = 5010 # The port used by the sonar server
ER1PORT = 5001 # The port used by the ER1 server
# Here is the sonar connection
sonarSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # python is cool
sonarSocket.connect((HOST, SONARPORT)) # ditto
# Here is the ER1 connection
er1Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # python is cool
er1Socket.connect((HOST, ER1PORT)) # ditto
#
# Definitions of useful functions:
# Send a command to the socket
# Send a command to the sonar
#
def sendSonar(command):
global sonarSocket
command += "\r\n"
sonarSocket.send(command) # send it off to the server
if command == "q": # if we want to quit
return ""
data = sonarSocket.recv(128) # the server always responds!!
lineReceived = data # gratuitous name change
return lineReceived
def getSonar():
global sonarMaxTrust
global sonarNumTries
avg = 0
tries = 0
while tries < sonarNumTries:
val = int(sendSonar("1"))
if val > sonarMaxTrust:
val = int(sendSonar("1"))
avg += val
tries += 1
avg /= sonarNumTries
return avg
def sendRobot(command):
global er1Socket
er1Socket.send(command) # send it off to the server
if command == "q": # if we want to quit
return ""
data = er1Socket.recv(128) # the server always responds!!
lineReceived = data # gratuitous name change
return lineReceived
#
# Here is a function to move the servo to a position.
# It takes an int as input.
#
def moveServo(amount):
sonarString = "BD1SV2M" + str(amount)
sendSonar(sonarString)
sendSonar("1") # Must throw out first sonar reading after move
#
# The emergency behavior
# Stop
# Play emergency sound (not done yet)
# Turn until you can move back (not done yet)
# Move back until you are not in range
#
def emergency():
global maxloop
global sonarTooClose
global velocitySlow
loopvar = 0
print sendRobot("v f 0 10 0"); # stop
while not msvcrt.kbhit():
sonarVal = getSonar()
print "Sonar distance:", sonarVal
if sonarVal < sonarTooClose:
lineToSend = "v f " + str(velocitySlow) + " 10 0"
print sendRobot(lineToSend)
else:
print sendRobot("v f 0 10 0");
break
loopvar += 1
if loopvar > maxloop:
print sendRobot("v f 0 10 0")
break;
sendRobot("v f 0 10 0");
#
# Wall chase
# Move the robot forward until it is within a range of the wall
# Add a little safety margin
# This will also move the robot back if it is too close
#
def gotoWall(dist):
global velocityNormal
global velocitySlow
global sonarTooClose
global sonarTolerance
minDist = sonarTooClose
if minDist < dist - 2*sonarTolerance:
minDist = dist - 2*sonarTolerance
maxDist = dist - sonarTolerance
if maxDist < sonarTooClose:
maxDist = sonarTooClose
moveServo(servoCenter)
while not msvcrt.kbhit():
wall = getSonar()
if wall > maxDist:
sendRobot("v b " + str(velocitySlow) + " 10 0")
elif wall < minDist:
sendRobot("v f " + str(velocitySlow) + " 10 0")
else:
print "Got the wall!"
break
sendRobot("v f 0 10 0")
return 1
#
# Forward motion until the sonar detects some obstacle to the forward
#
def longForward():
global velocityNormal
global sonarHallWidth
global sonarClose
global sonarTolerance
moveServo(servoCenter)
print "Going forward"
sendRobot("v b " + str(velocityNormal) + " 10 0")
while not msvcrt.kbhit():
lastWall = getSonar()
if lastWall < sonarHallWidth: # there HAS to be an obstacle
print "1 FOUND A WALL at dist", lastWall
gotoWall(sonarClose)
sendRobot("h") # stop the robot
return 1 # Later this should return odometry
nextWall = getSonar()
if nextWall < lastWall - sonarTolerance or nextWall < sonarHallWidth:
print "2 FOUND A WALL at dist", nextWall
gotoWall(sonarClose)
sendRobot("h")
return 1
def turnTo(dir):
global servoCenter
moveServo(servoCenter)
currWall = getSonar()
while not msvcrt.kbhit():
sendRobot("v t" + dir + " 0.5 0.5 0.3")
nextWall = getSonar()
if nextWall > currWall + 50:
break
#
# Initialization
#
#
# Main loop
#
while 1:
moveServo(servoCenter)
sonarVal = getSonar()
if sonarVal < sonarTooClose:
print "Emergency", sonarVal
emergency()
print "Commands: ";
print " w - Forward";
print " s - Back";
print "Space bar - stop";
print " a - Turn left";
print " d - Turn right";
print " q - Quit";
c = msvcrt.getch(); # get a keypress (no enter needed)
if c == ' ':
print "STOPPING"
sendRobot("h");
if c == 'w':
print "GOING FORWARD"
longForward()
print "DONE"
if c == 's':
print "GOING BACK... HIT SPACE TO STOP"
sendRobot("v f 10 10 1");
if c == 'a':
print "TURNING LEFT"
turnTo("l")
print "DONE"
if c == 'd':
print "TURNING RIGHT"
turnTo("r")
print "DONE"
if c == 'q':
break
moveServo(servoCenter)
sendRobot("h");
sendRobot("q")
sendSonar("q")
er1Socket.close()
sonarSocket.close()
print "Done"
syntax highlighted by Code2HTML, v. 0.9.1