Beispiel #1
0
def scattered_obstacles(numobs, radius, sc_size):
    """Convenience function for randomly-scattered obstacles and their sprites.

    Args:
        numobs (positive int): Number of obstacles to generate.
        radius (positive float): Obstacle radius.
        obs_image (pygame.Surface): Obstacle image (shared among instances).
        sc_size (int, int): Width, height of the display area, in pixels.

    Returns:
        (list, list): First list contains the SimpleObstacle2d's; 2nd their sprites.
    Notes:
        By default, this uses the same sprite class as BasePointMass2d.
    """
    sc_width, sc_height = sc_size
    yoffset = sc_height // (numobs + 2)
    yvals = list(range(yoffset, sc_height - yoffset, yoffset))
    shuffle(yvals)
    obslist = list()
    for i in range(numobs):
        offset = (i + 1) / (numobs + 1)
        rany = yvals[i]
        new_pos = Point2d(offset * sc_width, rany)
        obs_image = obstacle_bumper(radius)
        obstacle = SimpleObstacle2d(new_pos, Point2d(0, 0), radius, obs_image)
        obslist.append(obstacle)
    obs_sprites = [obs.sprite for obs in obslist]
    return obslist, obs_sprites
Beispiel #2
0
    def __init__(self,
                 position,
                 velocity,
                 radius,
                 mass,
                 maxspeed,
                 maxforce,
                 spritedata=None):
        # Non-constant Point2d's need to be copied
        self.pos = copy.copy(position)
        self.vel = copy.copy(velocity)
        self.accumulated_force = Point2d(0, 0)
        # Additional values; these should be mostly constant
        self.radius = float(radius)
        self.mass = float(mass)
        self.maxspeed = float(maxspeed)
        self.maxforce = float(maxforce)
        # Normalized front vector in world coordinates; aligned with velocity.
        try:
            self.front = velocity.unit()
        except ZeroDivisionError:
            # If velocity is <0,0>, set facing to positive x-axis
            self.front = Point2d(1.0, 0.0)
        self.left = Point2d(-self.front[1], self.front[0])

        # Optional sprite data
        if self.__class__._spriteclass and spritedata is not None:
            self.sprite = self.__class__._spriteclass(self, spritedata)
Beispiel #3
0
 def test_vector_equals_magnitude_times_direction(self, x, y):
     vtest = Point2d(x, y)
     if vtest == Point2d(0, 0):
         self.assertRaises(ZeroDivisionError)
     elif isnan(x * x + y * y) or isinf(x * x + y * y):
         self.assertRaises(OverflowError)
     else:
         vscaled = vtest.norm() * vtest.unit()
         self.assertAlmostEqual(vtest.x, vscaled.x)
         self.assertAlmostEqual(vtest.y, vscaled.y)
Beispiel #4
0
 def test_cauchy_schwarz_inequality(self, a, b, c, d):
     if isnan(a * a + b * b) or isinf(a * a + b * b):
         self.assertRaises(OverflowError)
     elif isnan(c * c + d * d) or isinf(c * c + d * d):
         self.assertRaises(OverflowError)
     else:
         vtest = Point2d(a, b)
         wtest = Point2d(c, d)
         if isnan(vtest * wtest) or isnan(vtest.norm() * wtest.norm()):
             self.assertRaises(OverflowError)
         else:
             self.assertLessEqual(abs(vtest * wtest),
                                  vtest.norm() * wtest.norm())
Beispiel #5
0
    def move(self, delta_t=1.0, force_vector=None):
        """Updates rectilinear position, velocity, and acceleration.

        Args:
            delta_t (float): Time increment since last move.
            force_vector (Point2d, optional): Vector force to apply during this update.

        If force_vector is None (the default), we use the force accumulated by
        self.accumulate_force() since the last call to this method, and zero
        out the accumulated force. Otherwise, apply the force_vector given, and
        leave the accumulated force unaffected.

        In any case, the maximum force and resulting velocity are limited by
        maxforce and maxspeed attributes.
        """
        # Update position using current velocity
        self.pos = self.pos + delta_t * self.vel

        # If no force_vector was given, use self-accumulated force.
        if force_vector is None:
            force_vector = copy.copy(self.accumulated_force)
            self.accumulated_force.zero()
        # Don't exceed our maximum force; compute acceleration
        force_vector.truncate(self.maxforce)
        accel = (delta_t / self.mass) * force_vector
        # Compute new velocity, but don't exceed maximum speed.
        self.vel = self.vel + accel
        self.vel.truncate(self.maxspeed)

        # Align heading to match our forward velocity. Note that
        # if velocity is very small, skip this to avoid jittering.
        if self.vel.sqnorm() > SPEED_EPSILON_SQ:
            self.front = self.vel.unit()
            self.left = Point2d(-self.front.y, self.front.x)
Beispiel #6
0
 def test_rotations_are_orthogonal(self, x, y):
     from math import pi
     vtest = Point2d(x, y)
     vperp = vtest.rotated_by(pi / 2)
     vperp2 = vtest.rotated_by(-pi / 2)
     self.assertAlmostEqual(vtest * vperp, 0.0)
     self.assertAlmostEqual(vtest * vperp2, 0.0)
Beispiel #7
0
 def test_length_of_unit_vectors(self, x, y):
     assume(x * x + y * y != 0)
     if isnan(x * x + y * y) or isinf(x * x + y * y):
         self.assertRaises(OverflowError)
     else:
         vtest = Point2d(x, y)
         u = vtest.unit()
         vtest.normalize()
         self.assertAlmostEqual(u.norm(), 1.0)
         self.assertAlmostEqual(vtest.norm(), 1.0)
Beispiel #8
0
 def __init__(self, center, length, thick, f_normal, spritedata=None):
     # Positional data
     self.pos = Point2d(center[0], center[1])
     self.front = f_normal.unit()
     self.left = self.front.left_normal()
     self.rsq = (length / 2)**2
     # Structural data
     self.length = length
     self.thick = thick
     # Wall sprite
     if self.__class__._spriteclass and spritedata is not None:
         self.sprite = self.__class__._spriteclass(self, *spritedata)
Beispiel #9
0
def boundary_walls(sc_size, thick=10):
    """Convenience function to generate walls/sprites near the screen border.

    Args:
        sc_size (int, int): Width, height of the display area, in pixels.
        thick (int, optional): Thickness of walls, in pixels.

    Returns:
        (list, list): List of BaseWall2d, List of BaseWall2dSprite.
    """
    sc_width, sc_height = sc_size
    wall_list = [
        BaseWall2d((sc_width // 2, thick), sc_width, thick, Point2d(0, 1),
                   WALL_DATA),
        BaseWall2d((sc_width // 2, sc_height - thick), sc_width, thick,
                   Point2d(0, -1), WALL_DATA),
        BaseWall2d((thick, sc_height // 2), sc_height, thick, Point2d(1, 0),
                   WALL_DATA),
        BaseWall2d((sc_width - thick, sc_height // 2), sc_height, thick,
                   Point2d(-1, 0), WALL_DATA)
    ]
    wall_sprites = [wall.sprite for wall in wall_list]
    return wall_list, wall_sprites
Beispiel #10
0
 def test_xy_coords(self, x, y):
     vtest = Point2d(x, y)
     self.assertEqual(vtest.x, x)
     self.assertEqual(vtest.y, y)
Beispiel #11
0
 def test_negation_subtraction_inverses(self, x, y):
     from aiboids.point2d import ZERO_VECTOR
     vtest = Point2d(x, y)
     self.assertEqual(vtest + (-vtest), ZERO_VECTOR)
     self.assertEqual(vtest - vtest, ZERO_VECTOR)
Beispiel #12
0
 def test_coordinate_addition(self, a, b, c, d):
     vtest = Point2d(a, b) + Point2d(c, d)
     self.assertEqual(vtest, Point2d(a + c, b + d))
Beispiel #13
0
sys.path.append(mypar)

from aiboids.point2d import Point2d
from aiboids.vehicle2d import SimpleVehicle2d
from aiboids import pgrender

if __name__ == "__main__":
    # Display set-up
    SCREEN_SIZE = (1024, 768)
    SCREEN, BGCOLOR = pgrender.setup(SCREEN_SIZE,
                                     'FLOCKING/EVADE steering demo.')
    UPDATE_SPEED = 0.5
    BORDER = 30

    # Used to generate random positions for vehicles
    randpoint = lambda: Point2d(randint(BORDER, SCREEN_SIZE[0] - BORDER),
                                randint(BORDER, SCREEN_SIZE[1] - BORDER))

    # Vehicles (sheep/dog) and obstacle information
    NUMSHEEP = 29
    SHEEP_RADIUS = 20
    DOG_RADIUS = 20
    WHISKER_FRONT = SHEEP_RADIUS * 1.25
    WHISKER_SIDES = SHEEP_RADIUS * 1.1
    WALL_WHISKERS = [
        WHISKER_FRONT * Point2d(1, 0), WHISKER_SIDES * Point2d(1, 1).unit(),
        WHISKER_SIDES * Point2d(1, -1).unit()
    ]
    NUMVEHICLES = NUMSHEEP + 1
    NUMOBSTACLES = 12

    # Amount of time spent flocking
Beispiel #14
0
 def test_vector_norms(self, x, y):
     if isnan(x * x + y * y) or isinf(x * x + y * y):
         self.assertRaises(OverflowError)
     else:
         vtest = Point2d(x, y)
         self.assertAlmostEqual(vtest.norm()**2, vtest.sqnorm())
Beispiel #15
0
 def test_promote_integer_coords(self, x, y):
     vtest = Point2d(x, y)
     self.assertEqual(vtest.x, float(x))
     self.assertEqual(vtest.y, float(y))
Beispiel #16
0
 def test_zero_inplace(self, x, y):
     vtest = Point2d(x, y)
     vtest.zero()
     self.assertEqual(vtest, Point2d(0, 0))
Beispiel #17
0
from aiboids.point2d import Point2d
from aiboids.vehicle2d import SimpleVehicle2d
from aiboids.steering import WaypointPath

from aiboids import pgrender

if __name__ == "__main__":
    # Display set-up
    SCREEN_SIZE = (800, 640)
    screen, bgcolor = pgrender.setup(SCREEN_SIZE, 'Waypoints steering demo.')
    UPDATE_SPEED = 1.0
    BORDER = 30

    # Used to generate random positions and velocities for vehicles
    randpoint = lambda: Point2d(randint(BORDER, SCREEN_SIZE[0] - BORDER),
                                randint(BORDER, SCREEN_SIZE[1] - BORDER))

    # Number of vehicles and obstacles
    numveh = 2
    numobs = 8
    total = numveh + numobs

    # Waypoint/path information
    pathlen = 6
    min_dist_sq = 80**2

    # Load images
    images = dict()
    images['green'] = pgrender.boid_chevron(20, (0, 222, 0), (0, 0, 0))
    images['yellow'] = pgrender.boid_chevron(20, (222, 222, 0), (0, 0, 0))
Beispiel #18
0
 def test_rotations_are_orthogonal_in_degrees(self, x, y):
     vtest = Point2d(x, y)
     vperp = vtest.rotated_by(90, True)
     vperp2 = vtest.rotated_by(-90, True)
     self.assertAlmostEqual(vtest * vperp, 0.0)
     self.assertAlmostEqual(vtest * vperp2, 0.0)
Beispiel #19
0
 def test_orthogonal_dot_product(self, x, y):
     if isnan(x * y) or isinf(x * y):
         self.assertRaises(OverflowError)
     else:
         self.assertEqual(Point2d(x, y) * Point2d(y, -x), 0.0)
         self.assertEqual(Point2d(x, y) * Point2d(-y, x), 0.0)
Beispiel #20
0
 def negative_rotation_is_inverse(self, x, y, theta):
     vtest = Point2d(x, y)
     vrot = vtest.rotated_by(theta)
     self.assertEqual(vtest, vrot.rotated_by(-theta))
Beispiel #21
0
 def test_doubling_vs_addition(self, x, y):
     vtest = Point2d(x, y)
     self.assertEqual(2 * vtest, vtest + vtest)
Beispiel #22
0
 def test_tuple_vs_coords(self, x, y):
     vtest = Point2d(x, y)
     self.assertEqual(vtest.ntuple, (vtest.x, vtest.y))
Beispiel #23
0
 def test_for_zero_vector(self):
     from aiboids.point2d import ZERO_VECTOR
     self.assertEqual(ZERO_VECTOR, Point2d(0, 0))
     self.assertIsNot(ZERO_VECTOR, Point2d(0, 0))
Beispiel #24
0
sys.path.append(mypar)

from aiboids.point2d import Point2d
from aiboids.vehicle2d import SimpleVehicle2d
from aiboids import pgrender

if __name__ == "__main__":
    # Display set-up
    SCREEN_SIZE = (1024, 768)
    screen, bgcolor = pgrender.setup(SCREEN_SIZE,
                                     'TAKECOVER/STALKING steering demo.')
    BORDER = 30
    UPDATE_SPEED = 0.5

    # Used to generate random positions and velocities for vehicles
    randpoint = lambda: Point2d(randint(BORDER, SCREEN_SIZE[0] - BORDER),
                                randint(BORDER, SCREEN_SIZE[1] - BORDER))

    # Number of vehicles and obstacles
    numveh = 3
    numobs = 20
    total = numveh + numobs
    VEH_RADIUS = 20
    WHISKER_FRONT = VEH_RADIUS * 1.25
    WHISKER_SIDES = WHISKER_FRONT * 1.1
    WALL_WHISKERS = [
        WHISKER_FRONT * Point2d(1, 0), WHISKER_SIDES * Point2d(1, 1).unit(),
        WHISKER_SIDES * Point2d(1, -1).unit()
    ]
    OBS_RADIUS = 12

    # Load images
Beispiel #25
0
mypar = os.path.abspath(os.path.join(mydir, os.pardir))
sys.path.append(mypar)

from aiboids.point2d import Point2d, ZERO_VECTOR
from aiboids.vehicle2d import BasePointMass2d, SimpleVehicle2d
from aiboids import pgrender

if __name__ == "__main__":
    # Display set-up
    SCREEN_SIZE = (800, 640)
    screen, bgcolor = pgrender.setup(SCREEN_SIZE, 'SEEK/ARRIVE steering demo.')
    UPDATE_SPEED = 1.0
    BORDER = 30

    # Used to generate random positions and velocities for vehicles
    randpoint = lambda: Point2d(randint(BORDER, SCREEN_SIZE[0] - BORDER),
                                randint(BORDER, SCREEN_SIZE[1] - BORDER))

    # Number of vehicles and obstacles
    numveh = 3
    numtargs = numveh
    total = numveh + numtargs

    # Images for pygame sprites
    images = dict()
    images['green'] = pgrender.boid_chevron(20, (0, 222, 0))
    images['yellow'] = pgrender.boid_chevron(20, (222, 222, 0))
    images['red'] = pgrender.boid_chevron(25, (222, 0, 0))

    # Steering behaviour target images (generated here)
    img_targ = pygame.Surface((5, 5))
    img_targ.fill((0, 0, 0))