Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # 6.00.2x Problem Set 2: Simulating robots
- import math
- import random
- import ps2_visualize
- import pylab
- # For Python 2.7:
- from ps2_verify_movement27 import testRobotMovement
- # If you get a "Bad magic number" ImportError, you are not using
- # Python 2.7 and using most likely Python 2.6:
- # === Provided class Position
- class Position(object):
- """
- A Position represents a location in a two-dimensional room.
- """
- def __init__(self, x, y):
- """
- Initializes a position with coordinates (x, y).
- """
- self.x = x
- self.y = y
- def getX(self):
- return self.x
- def getY(self):
- return self.y
- def getNewPosition(self, angle, speed):
- """
- Computes and returns the new Position after a single clock-tick has
- passed, with this object as the current position, and with the
- specified angle and speed.
- Does NOT test whether the returned position fits inside the room.
- angle: number representing angle in degrees, 0 <= angle < 360
- speed: positive float representing speed
- Returns: a Position object representing the new position.
- """
- old_x, old_y = self.getX(), self.getY()
- angle = float(angle)
- # Compute the change in position
- delta_y = speed * math.cos(math.radians(angle))
- delta_x = speed * math.sin(math.radians(angle))
- # Add that to the existing position
- new_x = old_x + delta_x
- new_y = old_y + delta_y
- return Position(new_x, new_y)
- def __str__(self):
- return "(%0.2f, %0.2f)" % (self.x, self.y)
- # === Problem 1
- class RectangularRoom(object):
- """
- A RectangularRoom represents a rectangular region containing clean or dirty
- tiles.
- A room has a width and a height and contains (width * height) tiles. At any
- particular time, each of these tiles is either clean or dirty.
- """
- def __init__(self, width, height):
- """
- Initializes a rectangular room with the specified width and height.
- Initially, no tiles in the room have been cleaned.
- width: an integer > 0
- height: an integer > 0
- """
- self.width = width
- self.height = height
- self.room = []
- for i in range(height):
- self.room.append([])
- for j in range(width):
- self.room[i].append(False)
- def cleanTileAtPosition(self, pos):
- """
- Mark the tile under the position POS as cleaned.
- Assumes that POS represents a valid position inside this room.
- pos: a Position
- """
- self.room[int(pos.getY())][int(pos.getX())] = True
- def isTileCleaned(self, m, n):
- """
- Return True if the tile (m, n) has been cleaned.
- Assumes that (m, n) represents a valid tile inside the room.
- m: an integer
- n: an integer
- returns: True if (m, n) is cleaned, False otherwise
- """
- return self.room[n][m]
- def getNumTiles(self):
- """
- Return the total number of tiles in the room.
- returns: an integer
- """
- return self.width * self.height
- def getNumCleanedTiles(self):
- """
- Return the total number of clean tiles in the room.
- returns: an integer
- """
- tot = 0
- for i in range(self.height):
- for j in range(self.width):
- if self.room[i][j] == True:
- tot += 1
- return tot
- def getRandomPosition(self):
- """
- Return a random position inside the room.
- returns: a Position object.
- """
- rand_y = random.randrange(0, self.height)
- rand_x = random.randrange(0, self.width)
- p = Position(rand_x, rand_y)
- return p
- def isPositionInRoom(self, pos):
- """
- Return True if pos is inside the room.
- pos: a Position object.
- returns: True if pos is in the room, False otherwise.
- """
- return (pos.getY() < self.height and pos.getY() >= 0) and (pos.getX() < self.width and pos.getX() >= 0)
- class Robot(object):
- """
- Represents a robot cleaning a particular room.
- At all times the robot has a particular position and direction in the room.
- The robot also has a fixed speed.
- Subclasses of Robot should provide movement strategies by implementing
- updatePositionAndClean(), which simulates a single time-step.
- """
- def __init__(self, room, speed):
- """
- Initializes a Robot with the given speed in the specified room. The
- robot initially has a random direction and a random position in the
- room. The robot cleans the tile it is on.
- room: a RectangularRoom object.
- speed: a float (speed > 0)
- """
- self.room = room
- self.speed = speed
- self.direction = random.randrange(0, 360)
- self.position = self.room.getRandomPosition()
- self.room.cleanTileAtPosition(self.position)
- def getRobotPosition(self):
- """
- Return the position of the robot.
- returns: a Position object giving the robot's position.
- """
- return self.position
- def getRobotDirection(self):
- """
- Return the direction of the robot.
- returns: an integer d giving the direction of the robot as an angle in
- degrees, 0 <= d < 360.
- """
- return self.direction
- def setRobotPosition(self, position):
- """
- Set the position of the robot to POSITION.
- position: a Position object.
- """
- self.position = position
- def setRobotDirection(self, direction):
- """
- Set the direction of the robot to DIRECTION.
- direction: integer representing an angle in degrees
- """
- self.direction = direction
- def updatePositionAndClean(self):
- """
- Simulate the raise passage of a single time-step.
- Move the robot to a new position and mark the tile it is on as having
- been cleaned.
- """
- raise NotImplementedError # don't change this!
- # === Problem 2
- class StandardRobot(Robot):
- """
- A StandardRobot is a Robot with the standard movement strategy.
- At each time-step, a StandardRobot attempts to move in its current
- direction; when it would hit a wall, it *instead* chooses a new direction
- randomly.
- """
- def updatePositionAndClean(self):
- """
- Simulate the raise passage of a single time-step.
- Move the robot to a new position and mark the tile it is on as having
- been cleaned.
- """
- current_position = self.getRobotPosition()
- new_position = current_position.getNewPosition(self.direction, self.speed)
- while self.room.isPositionInRoom(new_position) == False:
- self.direction = random.randrange(0, 360)
- new_position = current_position.getNewPosition(self.direction, self.speed)
- self.position = new_position
- self.room.cleanTileAtPosition(new_position)
- # Uncomment this line to see your implementation of StandardRobot in action!
- #testRobotMovement(StandardRobot, RectangularRoom)
- # === Problem 3
- def generateMove(robot):
- # this function gets a robot and moves him based on this direction and speed. If it moved him to a valid position in the room, it cleans it. If not, it spends that time step
- # setting him a new random direction
- current_position = robot.getRobotPosition()
- new_position = current_position.getNewPosition(robot.direction, robot.speed)
- if robot.room.isPositionInRoom(new_position) == True:
- robot.setRobotPosition(new_position)
- robot.room.cleanTileAtPosition(robot.position)
- else:
- robot.setRobotDirection(random.randrange(0, 360))
- def runSimulation(num_robots, speed, width, height, min_coverage, num_trials,
- robot_type):
- """
- Runs NUM_TRIALS trials of the simulation and returns the mean number of
- time-steps needed to clean the fraction MIN_COVERAGE of the room.
- The simulation is run with NUM_ROBOTS robots of type ROBOT_TYPE, each with
- speed SPEED, in a room of dimensions WIDTH x HEIGHT.
- num_robots: an int (num_robots > 0)
- speed: a float (speed > 0)
- width: an int (width > 0)
- height: an int (height > 0)
- min_coverage: a float (0 <= min_coverage <= 1.0)
- num_trials: an int (num_trials > 0)
- robot_type: class of robot to be instantiated (e.g. StandardRobot or
- RandomWalkRobot)
- """
- results = []
- # for numTrials
- for i in range(num_trials):
- # create room and robots
- room = RectangularRoom(width, height)
- robots = []
- for i in range(num_robots):
- robot = robot_type(room, speed)
- robots.append(robot)
- # calculate current coverage
- current_coverage = room.getNumCleanedTiles() / float(room.getNumTiles())
- steps = 0
- # until min_coverage is satisfied
- while current_coverage < min_coverage:
- # move every robot. add one time-step to counter. recalculate current coverage of room.
- for robot in robots:
- generateMove(robot)
- steps += 1
- current_coverage = room.getNumCleanedTiles() / float(room.getNumTiles())
- # append result of this trial
- results.append(steps)
- # return average of time steps taken by the robots in all the simulations
- return sum(results) / float(len(results))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement