Volocopter

Source code for obstacle

"""
Implementation of the polygonal obstacles as well as of the walls
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as pat

from shapely.geometry import Polygon, Point

[docs]class Obstacle: """ Class implementing simple 2D polygonal obstacles. Attributes ---------- points : list List of (x, y) coordinates in the frame of the environnement representing the obstacle. bounding_box : 4-tuple Coordinates of the lower left and upper right corners of the bounding box containing the obstacle. center : tuple Coordinates of the center of the bounding box. polygon : shapely.geometry.Polygon The polygon representing the obstacle. Methods ------- plot Displays the polygon on screen. """ def __init__(self, map_dimensions, size, nb_pts): self.center = np.array([np.random.rand()*map_dimensions[0], np.random.rand()*map_dimensions[1]]) # We use very simple convex polygons, generated with a radius # and randomly selected angles. angles = sorted((np.random.rand()*2*np.pi for _ in range(nb_pts))) self.points = \ np.array([self.center +\ np.array([size*np.cos(angle), size*np.sin(angle)])\ for angle in angles]) self.bounding_box = (min(self.points, key=lambda x: x[0])[0], min(self.points, key=lambda x: x[1])[1], max(self.points, key=lambda x: x[0])[0], max(self.points, key=lambda x: x[1])[1]) self.polygon = Polygon(self.points)
[docs] def colides(self, x, y): """ Checks if the given point is in the obstacle or not. """ return self.polygon.contains(Point(x, y))
[docs] def plot(self): """ Draws the polygon on screen. """ plt.gca().add_patch(pat.Polygon(self.points, color='black', fill=True))
[docs]class Wall: """ Class implementing a wall with a moving hole in it Attributes ---------- width : float The total width of the wall. bottom_y : float The position of the bottom of the wall. hole : float The position of the hole in the wall. thickness : float The thickness of the wall. speed : float The speed of the hole, if the obstacles are choosen to be dynamic. Methods ------- colides Checks if a point is in the wall or not. plot Draws the wall on screen. visible Checks if the wall is in the field of view """ def __init__(self, width, bottom_y, thickness, moving=False): self.width = width self.bottom_y = bottom_y self.hole = width*np.random.rand() self.thickness = thickness self.speed = (np.random.rand()-1/2)*2 if moving else 0
[docs] def colides(self, x, y, time=0): """ Checks if the given point is in the obstacle or not. """ if time == 0: return (x < self.hole - self.width*.05 \ or x > self.hole + self.width*.05) \ and (self.bottom_y <= y <= self.bottom_y + self.thickness) hole = (self.hole + self.speed*time)%(self.width) return (x < hole - self.width*.05 or x > hole + self.width*.05)\ and (self.bottom_y <= y <= self.bottom_y + self.thickness)
[docs] def plot(self, time=0, x_scale=1, y_scale=1): """ Draws the wall on screen. """ hole = (self.hole+self.speed*time)%(self.width) plt.gca().add_patch( pat.Rectangle((0, self.bottom_y*y_scale), hole-0.05*self.width, self.thickness*y_scale, color='grey', fill=True)) plt.gca().add_patch( pat.Rectangle(((hole+self.width*.05)*x_scale, self.bottom_y*y_scale), self.width*x_scale, self.thickness*y_scale, color='grey', fill=True)) plt.gca().add_patch( pat.Rectangle((0, (self.bottom_y+self.thickness*.4)*y_scale), hole - self.width*.1, self.thickness*.2*y_scale, color='black', fill=True)) plt.gca().add_patch( pat.Rectangle(((hole+self.width*.1)*x_scale, (self.bottom_y+self.thickness*.4)*y_scale), (self.width)*x_scale, self.thickness*.2*y_scale, color='black', fill=True))
[docs] def visible(self, view_top, view_bottom): """ Checks if the wall is in the field of view """ return self.bottom_y <= view_top \ and self.bottom_y + self.thickness >= view_bottom