Beispiel #1
0
    def __init__(self, x0, target, render):
        self.render = render
        if self.render:
            super(CarWorld, self).__init__()
        else:
            self.world = b2.b2World(gravity=(0, 0), doSleep=True)

        self.world.gravity = (0.0, 0.0)
        self.initial_position = (x0[0], x0[1])
        self.initial_angle = 0

        ground = self.world.CreateBody(position=(0, 20))
        ground.CreateEdgeChain(
            [(-10, -30),
             (-10, 5),
             (-30, 30),]
            )
	    
        ground.CreateEdgeChain(
            [(10, -30),
             (10, 5),
             (-10, 30),]
            )
	    
        xf1 = b2.b2Transform()
        xf1.angle = 0.3524 * b2.b2_pi
        xf1.position = b2.b2Mul(xf1.R, (1.0, 0.0))

        xf2 = b2.b2Transform()
        xf2.angle = -0.3524 * b2.b2_pi
        xf2.position = b2.b2Mul(xf2.R, (-1.0, 0.0))

        self.car = TDCar(self.world, position=self.initial_position, angle=self.initial_angle)

        self.target = self.world.CreateStaticBody(
            position=target[:2],
            angle=self.initial_angle,
            shapes=[b2.b2PolygonShape(vertices=[xf1*(-1, 0), xf1*(1, 0),
                                                xf1*(0, .5)]),
                    b2.b2PolygonShape(vertices=[xf2*(-1, 0), xf2*(1, 0),
                                                xf2*(0, .5)])],
        )
        self.target.active = False


        self.start = self.world.CreateStaticBody(
            position=self.initial_position,
            angle=self.initial_angle,
            shapes=[b2.b2PolygonShape(vertices=[xf1*(-1, 0), xf1*(1, 0),
                                                xf1*(0, .5)]),
                    b2.b2PolygonShape(vertices=[xf2*(-1, 0), xf2*(1, 0),
                                                xf2*(0, .5)])],
        )
        self.start.active = False
Beispiel #2
0
    def __init__(self, x0, target, render):
        self.render = render
        if self.render:
            super(PointMassWorld, self).__init__()
        else:
            self.world = b2.b2World(gravity=(0, -10), doSleep=True)

        x0 = np.asfarray(x0)
        target = np.asfarray(target)

        self.world.gravity = (0.0, 0.0)
        self.initial_position = (x0[0], x0[1])
        self.initial_angle = b2.b2_pi
        self.initial_linear_velocity = (x0[2], x0[3])
        self.initial_angular_velocity = 0

        ground = self.world.CreateBody(position=(0, 20))
        ground.CreateEdgeChain([(-20, -20), (-20, 20), (20, 20), (20, -20),
                                (-20, -20)])

        xf1 = b2.b2Transform()
        xf1.angle = 0.3524 * b2.b2_pi
        xf1.position = b2.b2Mul(xf1.R, (1.0, 0.0))

        xf2 = b2.b2Transform()
        xf2.angle = -0.3524 * b2.b2_pi
        xf2.position = b2.b2Mul(xf2.R, (-1.0, 0.0))
        self.body = self.world.CreateDynamicBody(
            position=self.initial_position,
            angle=self.initial_angle,
            linearVelocity=self.initial_linear_velocity,
            angularVelocity=self.initial_angular_velocity,
            angularDamping=5,
            linearDamping=0.1,
            shapes=[
                b2.b2PolygonShape(
                    vertices=[xf1 * (-1, 0), xf1 * (1, 0), xf1 * (0, .5)]),
                b2.b2PolygonShape(
                    vertices=[xf2 * (-1, 0), xf2 * (1, 0), xf2 * (0, .5)])
            ],
            shapeFixture=b2.b2FixtureDef(density=1.0),
        )
        self.target = self.world.CreateStaticBody(
            position=target[:2],
            angle=self.initial_angle,
            shapes=[
                b2.b2PolygonShape(
                    vertices=[xf1 * (-1, 0), xf1 * (1, 0), xf1 * (0, .5)]),
                b2.b2PolygonShape(
                    vertices=[xf2 * (-1, 0), xf2 * (1, 0), xf2 * (0, .5)])
            ],
        )
        self.target.active = False
    def draw_for_pygame(self, screen, W_W, W_H, global_playground, world_size, world_scale, draw_particles=True,
                        offset=(0, 0), angle=0, scale=1,
                        color=(0.8 * 255, 0, 0), mode=None, main_car_color=False, width=5):
        if mode == "image":
            tmp = Box2D.b2Transform()
            tmp.position = (0, 0)
            tmp.angle = -angle
            image = self.image
            image = pygame.transform.rotate(image, 57.295779513 * (-self.hull.angle + angle))
            pos = self.hull.position
            center = image.get_rect().center
            draw_pos = scale * (tmp * (Box2D.b2Vec2(offset) - pos))
            screen.blit(image, (draw_pos[0] - center[0] + W_W / 2, draw_pos[1] + W_H / 2 - center[1]))
            return
        tmp = Box2D.b2Transform()
        tmp.position = (0, 0)
        tmp.angle = -angle
        if draw_particles:
            for p in self.particles:
                pygame.draw.lines(global_playground, 255 * np.array(p.color), False,
                                  -world_scale * np.array(p.poly) + np.array(world_size) / 2, width)

        # Following code for generating observation
        NON_MAIN_CAR_COLOR = (0, 0, 255)
        for obj in self.drawlist:
            for f in obj.fixtures:
                trans = f.body.transform

                path = [-scale * (tmp * ((trans * v) - offset)) + (W_W / 2, W_H / 2) for v in f.shape.vertices]
                if "phase" not in obj.__dict__:
                    if not main_car_color:
                        pygame.draw.polygon(screen, NON_MAIN_CAR_COLOR, path)
                    else:
                        pygame.draw.polygon(screen, color, path)
                else:
                    pygame.draw.polygon(screen, [255 * i for i in obj.color], path)
                # object_to_draw.append(([255 * i for i in obj.color], path))
                if "phase" not in obj.__dict__: continue
                a1 = obj.phase
                a2 = obj.phase + 1.2  # radians
                s1 = math.sin(a1)
                s2 = math.sin(a2)
                c1 = math.cos(a1)
                c2 = math.cos(a2)
                if s1 > 0 and s2 > 0: continue
                if s1 > 0: c1 = np.sign(c1)
                if s2 > 0: c2 = np.sign(c2)
                white_poly = [
                    (-WHEEL_W * SIZE, +WHEEL_R * c1 * SIZE), (+WHEEL_W * SIZE, +WHEEL_R * c1 * SIZE),
                    (+WHEEL_W * SIZE, +WHEEL_R * c2 * SIZE), (-WHEEL_W * SIZE, +WHEEL_R * c2 * SIZE)
                ]
                white_poly_path = [-scale * (tmp * ((trans * v) - offset)) + (W_W / 2, W_H / 2) for v in white_poly]
                pygame.draw.polygon(screen, 255 * np.array(WHEEL_WHITE), white_poly_path)
Beispiel #4
0
    def draw_for_pygame(self,
                        screen,
                        W_W,
                        W_H,
                        draw_particles=True,
                        offset=(0, 0),
                        angle=0,
                        scale=1,
                        color=(0.8 * 255, 0, 0),
                        mode=None,
                        main_car_color=False):
        if mode == "human":
            tmp = Box2D.b2Transform()
            tmp.position = (0, 0)
            tmp.angle = -angle

            if main_car_color:
                image = self.image
            else:
                image = self.image2

            image = pygame.transform.rotate(
                image, 57.295779513 * (-self.hull.angle + angle))
            pos = self.hull.position
            center = image.get_rect().center
            draw_pos = scale * (tmp * (Box2D.b2Vec2(offset) - pos))
            screen.blit(image, (draw_pos[0] - center[0] + W_W / 2,
                                draw_pos[1] + W_H / 2 - center[1]))
            return
        '''if draw_particles:
            for p in self.particles:
                viewer.draw_polyline(p.poly, color=p.color, linewidth=5)'''
        # Following code for generating observation
        NON_MAIN_CAR_COLOR = (0, 0, 255)
        for obj in self.drawlist:
            for f in obj.fixtures:
                trans = f.body.transform
                tmp = Box2D.b2Transform()
                tmp.position = (0, 0)
                tmp.angle = -angle
                path = [
                    -scale * (tmp * ((trans * v) - offset)) +
                    (W_W / 2, W_H / 2) for v in f.shape.vertices
                ]
                if "phase" not in obj.__dict__:
                    if not main_car_color:
                        pygame.draw.polygon(screen, NON_MAIN_CAR_COLOR, path)
                    else:
                        pygame.draw.polygon(screen, color, path)
                else:
                    pygame.draw.polygon(screen, self.drawlist_colors[obj],
                                        path)
	def dist_rod(self, rod_fix, rod_body):
		shape1 = self.fixtures[0].shape
		shape2 = rod_fix.shape
		transform1 = Box2D.b2Transform()
		pos1 = self.body.position
		angle1 = self.body.angle
		transform1.Set(pos1, angle1)
		transform2 = Box2D.b2Transform()
		pos2 = rod_body.position
		angle2 = rod_body.angle
		transform2.Set(pos2, angle2)
		pointA, pointB, distance, iterations = Box2D.b2Distance(shapeA=shape1, shapeB=shape2, transformA=transform1, transformB=transform2)
		# print(distance)
		return distance
	def dist(self, other_polygon):
		"""do not work on a polygon and a rod"""
		shape1 = self.fixtures[0].shape
		shape2 = other_polygon.fixtures[0].shape
		transform1 = Box2D.b2Transform()
		pos1 = self.body.position
		angle1 = self.body.angle
		transform1.Set(pos1, angle1)
		transform2 = Box2D.b2Transform()
		pos2 = other_polygon.body.position
		angle2 = other_polygon.body.angle
		transform2.Set(pos2, angle2)
		pointA, pointB, distance, iterations = Box2D.b2Distance(shapeA=shape1, shapeB=shape2, transformA=transform1, transformB=transform2)
		return distance
    def draw_for_world_map(self, surface, world_scale, world_width, world_height):
        for obj in self.drawlist:
            for f in obj.fixtures:
                trans = f.body.transform
                tmp = Box2D.b2Transform()
                tmp.position = (0, 0)
                tmp.angle = -self.hull.angle
                # trans = Box2D.b2Transform()

                path = [-world_scale * (((trans * v))) + (world_width / 2, world_height / 2) for v in f.shape.vertices]
                '''if "phase" not in obj.__dict__:
                    pygame.draw.polygon(surface, color, path)
                else:'''
                pygame.draw.polygon(surface, self.drawlist_colors[obj], path)
                # object_to_draw.append(([255 * i for i in obj.color], path))
                if "phase" not in obj.__dict__: continue
                a1 = obj.phase
                a2 = obj.phase + 1.2  # radians
                s1 = math.sin(a1)
                s2 = math.sin(a2)
                c1 = math.cos(a1)
                c2 = math.cos(a2)
                if s1 > 0 and s2 > 0: continue
                if s1 > 0: c1 = np.sign(c1)
                if s2 > 0: c2 = np.sign(c2)
                white_poly = [
                    (-WHEEL_W * SIZE, +WHEEL_R * c1 * SIZE), (+WHEEL_W * SIZE, +WHEEL_R * c1 * SIZE),
                    (+WHEEL_W * SIZE, +WHEEL_R * c2 * SIZE), (-WHEEL_W * SIZE, +WHEEL_R * c2 * SIZE)
                ]
                white_poly_path = [-world_scale * (((trans * v))) + (world_width / 2, world_height / 2) for v in
                                   white_poly]
                pygame.draw.polygon(surface, WHEEL_WHITE, white_poly_path)
Beispiel #8
0
 def draw_for_pygame(self, screen, W_W,W_H, draw_particles=True,  offset=(0,0), angle=0, scale=1):
     #if draw_particles:
         #for p in self.particles:
             #viewer.draw_polyline(p.poly, color=p.color, linewidth=5)
     for obj in self.drawlist:
         for f in obj.fixtures:
             trans = f.body.transform
             tmp = Box2D.b2Transform()
             tmp.position = (0, 0)
             tmp.angle = -angle
             #trans = Box2D.b2Transform()
             path = [-scale*(tmp*((trans*v)-offset)) + (W_W/2, W_H/2) for v in f.shape.vertices]
             pygame.draw.polygon(screen, [255 * i for i in obj.color], path)
             if "phase" not in obj.__dict__: continue
             a1 = obj.phase
             a2 = obj.phase + 1.2  # radians
             s1 = math.sin(a1)
             s2 = math.sin(a2)
             c1 = math.cos(a1)
             c2 = math.cos(a2)
             if s1 > 0 and s2 > 0: continue
             if s1 > 0: c1 = np.sign(c1)
             if s2 > 0: c2 = np.sign(c2)
             white_poly = [
                 (-WHEEL_W*SIZE, +WHEEL_R*c1*SIZE), (+WHEEL_W*SIZE, +WHEEL_R*c1*SIZE),
                 (+WHEEL_W*SIZE, +WHEEL_R*c2*SIZE), (-WHEEL_W*SIZE, +WHEEL_R*c2*SIZE)
                 ]
             white_poly_path = [-scale*(tmp*((trans*v)-offset)) + (W_W/2, W_H/2) for v in white_poly]
             pygame.draw.polygon(screen, WHEEL_WHITE, white_poly_path)
    def render_road_for_pygame(self, screen, width=width, height=height):
        screen.fill((0.4 * 255, 0.8 * 255, 0.4 * 255))
        tmp = Box2D.b2Transform()
        tmp.position = (0, 0)
        tmp.angle = -self.camera_angle
        k = PLAYFIELD / 20.0
        square_to_draw = []
        for x in range(-20, 20, 2):
            for y in range(-20, 20, 2):
                square_to_draw.append([(k * x + k, k * y + 0),
                                       (k * x + 0, k * y + 0),
                                       (k * x + 0, k * y + k),
                                       (k * x + k, k * y + k)])

        for square in square_to_draw:
            path = [self.camera_scale * (tmp * (-v[0] + self.camera_offset[0], -v[1] + self.camera_offset[1])) + (
                width / 2, height / 2) for v in square]
            to_print = False
            for pos in path:
                if pos[0] > -0 and pos[0] < width and pos[1] > -0 and pos[1] < height:
                    to_print = True
            if to_print:
                pygame.draw.polygon(screen, (0.4 * 255, 0.9 * 255, 0.4 * 255), path)

        for poly, color in self.road_poly:
            # path_tmp = [(-v[0] + self.camera_offset[0], -v[1] + self.camera_offset[1]) for v in poly]
            path = [self.camera_scale * (tmp * (-v[0] + self.camera_offset[0], -v[1] + self.camera_offset[1])) + (
                width / 2, height / 2) for v in poly]
            to_print = False
            for pos in path:
                if pos[0] > -0 and pos[0] < width and pos[1] > -0 and pos[1] < height:
                    to_print = True
            if to_print:
                pygame.draw.polygon(screen, [255 * i for i in color], path)
Beispiel #10
0
    def __init__(self, x0, target):
        super(PointMassWorld, self).__init__()
        self.world.gravity = (0.0, 0.0)
        self.initial_position = (x0[0], x0[1])
        self.initial_angle = b2.b2_pi
        self.initial_linear_velocity = (x0[2], x0[3])
        self.initial_angular_velocity = 0

        ground = self.world.CreateBody(position=(0, 20))
        ground.CreateEdgeChain(
            [(-20, -20),
             (-20, 20),
             (20, 20),
             (20, -20),
             (-20, -20)]
            )

        xf1 = b2.b2Transform()
        xf1.angle = 0.3524 * b2.b2_pi
        xf1.position = b2.b2Mul(xf1.R, (1.0, 0.0))

        xf2 = b2.b2Transform()
        xf2.angle = -0.3524 * b2.b2_pi
        xf2.position = b2.b2Mul(xf2.R, (-1.0, 0.0))
        self.body = self.world.CreateDynamicBody(
            position=self.initial_position,
            angle=self.initial_angle,
            linearVelocity=self.initial_linear_velocity,
            angularVelocity=self.initial_angular_velocity,
            angularDamping=5,
            linearDamping=0.1,
            shapes=[b2.b2PolygonShape(vertices=[xf1*(-1, 0),
                                                xf1*(1, 0), xf1*(0, .5)]),
                    b2.b2PolygonShape(vertices=[xf2*(-1, 0),
                                                xf2*(1, 0), xf2*(0, .5)])],
            shapeFixture=b2.b2FixtureDef(density=1.0),
        )
        self.target = self.world.CreateStaticBody(
            position=target,
            angle=self.initial_angle,
            shapes=[b2.b2PolygonShape(vertices=[xf1*(-1, 0), xf1*(1, 0),
                                                xf1*(0, .5)]),
                    b2.b2PolygonShape(vertices=[xf2*(-1, 0), xf2*(1, 0),
                                                xf2*(0, .5)])],
        )
        self.target.active = False
	def min_geometry(self):
		min_dist = 1e2
		for i in range(len(self.objs) - 1):
			for j in range(i+1, len(self.objs)):
				if i != j:
					shape1 = self.objs[i].fixtures[0].shape
					shape2 = self.objs[j].fixtures[0].shape
					transform1 = Box2D.b2Transform()
					pos1 = self.objs[i].body.position
					angle1 = self.objs[i].body.angle
					transform1.Set(pos1, angle1)
					transform2 = Box2D.b2Transform()
					pos2 = self.objs[j].body.position
					angle2 = self.objs[j].body.angle
					transform2.Set(pos2, angle2)
					pointA, pointB, distance, iterations = Box2D.b2Distance(shapeA=shape1, shapeB=shape2, transformA=transform1, transformB=transform2)
					if distance < min_dist:
						min_dist = distance
		return min_dist
	def avg_geometry(self):
		total_separation = 0.0
		for i in range(len(self.objs) - 1):
			for j in range(i+1, len(self.objs)):
				if i != j:
					shape1 = self.objs[i].fixtures[0].shape
					shape2 = self.objs[j].fixtures[0].shape
					transform1 = Box2D.b2Transform()
					pos1 = self.objs[i].body.position
					angle1 = self.objs[i].body.angle
					transform1.Set(pos1, angle1)
					transform2 = Box2D.b2Transform()
					pos2 = self.objs[j].body.position
					angle2 = self.objs[j].body.angle
					transform2.Set(pos2, angle2)
					pointA, pointB, distance, iterations = Box2D.b2Distance(shapeA=shape1, shapeB=shape2, transformA=transform1, transformB=transform2)
					# print(pointA, pointB, distance, iterations)
					total_separation += distance
		return total_separation * 2/(len(self.objs) * (len(self.objs) - 1))
	def count_soft_threshold(self):
		count = 0.0
		for i in range(len(self.objs)):
			min_dist = 1e2
			for j in range(len(self.objs)):
				if i != j:
					shape1 = self.objs[i].fixtures[0].shape
					shape2 = self.objs[j].fixtures[0].shape
					transform1 = Box2D.b2Transform()
					pos1 = self.objs[i].body.position
					angle1 = self.objs[i].body.angle
					transform1.Set(pos1, angle1)
					transform2 = Box2D.b2Transform()
					pos2 = self.objs[j].body.position
					angle2 = self.objs[j].body.angle
					transform2.Set(pos2, angle2)
					pointA, pointB, distance, iterations = Box2D.b2Distance(shapeA=shape1, shapeB=shape2, transformA=transform1, transformB=transform2)
					if distance < min_dist:
						min_dist = distance
			# print(min_dist, (sigmoid(min_dist*10) - 0.5) * 2)
			count += (sigmoid(min_dist*10) - 0.5) * 2
		return count
	def count_threshold(self, threshold=0.3):
		count = 0
		for i in range(len(self.objs)):
			isolated = True
			for j in range(len(self.objs)):
				if i != j:
					shape1 = self.objs[i].fixtures[0].shape
					shape2 = self.objs[j].fixtures[0].shape
					transform1 = Box2D.b2Transform()
					pos1 = self.objs[i].body.position
					angle1 = self.objs[i].body.angle
					transform1.Set(pos1, angle1)
					transform2 = Box2D.b2Transform()
					pos2 = self.objs[j].body.position
					angle2 = self.objs[j].body.angle
					transform2.Set(pos2, angle2)
					pointA, pointB, distance, iterations = Box2D.b2Distance(shapeA=shape1, shapeB=shape2, transformA=transform1, transformB=transform2)
					if distance < threshold:
						isolated = False
			if isolated:
				count += 1
		return count
Beispiel #15
0
 def __init__(self, shape=None):
     self._basic_shape = shape
     self.transform = B2D.b2Transform()
     self.transform.SetIdentity()
     if isinstance(shape, B2D.b2PolygonShape):
         self._poly_collide = _collide_poly
         self._circle_collide = _collide_poly_circle
     elif isinstance(shape, B2D.b2CircleShape):
         self._poly_collide = _collide_circle_poly
         self._circle_collide = _collide_circle
     else:
         msg = 'Expected b2PolygonShape or b2CircleShape, got %s'
         raise TypeError(msg % type(shape).__name__)
     self._old_scale = (1.0, 1.0)
     self.rescaled_shape = None
Beispiel #16
0
 def render_road_for_pygame(self,
                            screen,
                            W_W,
                            W_H,
                            offset=(0, 0),
                            angle=0,
                            scale=1):
     screen.fill((0.4 * 255, 0.8 * 255, 0.4 * 255))
     for poly, color in self.road_poly:
         tmp = Box2D.b2Transform()
         tmp.position = (0, 0)
         tmp.angle = -angle
         # trans = Box2D.b2Transform()
         path_tmp = [(-v[0] + offset[0], -v[1] + offset[1]) for v in poly]
         path = [scale * (tmp * v) + (W_W / 2, W_H / 2) for v in path_tmp]
         pygame.draw.polygon(screen, [255 * i for i in color], path)
    def camera_update(self, mode="human"):
        if (self.camera_follow != -1):
            angle = self.cars[self.camera_follow].hull.angle
            vel = self.cars[self.camera_follow].hull.linearVelocity
            if vel[0] ** 2 + vel[1] ** 2 > 0.5 ** 2:
                angle = math.atan2(-vel[0], +vel[1])

            tmp = Box2D.b2Transform()
            tmp.position = (0, 0)
            tmp.angle = angle
            if mode == "rgb_array":
                self.camera_offset = self.cars[self.camera_follow].hull.position + tmp * (0, 16)
                self.camera_angle = angle
                self.camera_scale = self.obs_scale
            elif mode == "human":
                self.camera_offset = self.cars[self.camera_follow].hull.position + tmp * (0, height / 54)
                self.camera_angle = angle
                self.camera_scale = self.world_scale
        else:
            self.camera_offset = initial_camera_offset
            self.camera_angle = initial_camera_angle
            self.camera_scale = initial_camera_scale
Beispiel #18
0
    def __init__(self,
                 num_player=1,
                 verbose=1,
                 seed=8367813160709901366,
                 window_size=WINDOW_SIZE,
                 action_repeat=None):
        EzPickle.__init__(self)
        self.seed(seed=seed)
        self.contactListener_keepref = FrictionDetector(self)
        self.world = Box2D.b2World(
            (0, 0), contactListener=self.contactListener_keepref)
        self.viewer = None
        pygame.init()
        pygame.font.init()
        self.window_size = window_size

        # For rendering purpose. Lazy initialize.
        self.screen = None
        self.playground_surface = None
        self.playground = None

        self._viewer = None
        # self.screen = pygame.display.set_mode(window_size)
        # self.playground_surface = pygame.display.set_mode(window_size)
        self.invisible_state_window = None
        self.invisible_video_window = None
        self.road = None
        self.cars = {}
        self.rewards = {i: 0 for i in range(num_player)}
        self.prev_rewards = {i: 0 for i in range(num_player)}
        self.verbose = verbose
        self.num_player = num_player
        self.track = None
        self.done = {}
        self.background = None
        self.road_poly = None
        self.action_repeat = action_repeat if action_repeat is not None else 1

        self.camera_offset = None
        self.camera_scale = None
        self.camera_no_follow_scale = None
        self.car_scale = None
        self.camera_angle = None
        self.camera_follow = -1

        self.show_all_car_obs = False
        self.ontrack_count = 0
        self.tile_visited_count = None
        self.idle_count = None
        self.step_count = None

        self.isopen = True

        # self.world_map = None
        self.world_scale = 10
        self.obs_scale = (self.world_scale / (100 / math.sqrt(96))) * 1.8
        self.world_size = self.world_scale * 500 + window_size[
            0] * 2, self.world_scale * 400 + window_size[1] * 2
        # self.world_size = 6000,6000
        self.obs_size = (self.world_size[0] / (100 / math.sqrt(96))) * 1.8, (
            self.world_size[1] / (100 / math.sqrt(96))) * 1.8
        # self.obs_size = 5000,5000
        self.initial_camera_scale = self.obs_scale
        tmp = Box2D.b2Transform()
        tmp.position = (self.obs_size[0] / 2, self.obs_size[1] / 2)
        self.initial_camera_offset = tmp
        self.initial_camera_angle = 0

        self.obs = {}
        self.info = {}

        self.observation_playground = pygame.Surface(self.obs_size)
        self.observation_screens = [pygame.Surface(
            (STATE_W, STATE_H))] * self.num_player
        # self.world_map = pygame.Surface(self.world_size)

        self.fonts = {
            5: pygame.font.SysFont('Comic Sans MS', 5),
            30: pygame.font.SysFont('Comic Sans MS', 30)
        }

        self.fd_tile = None

        # self.action_space = spaces.Box(np.array([-1, 0, 0]),  # We will rescale acceleration and brake.
        #                                np.array([+1, +1, +1]),
        #                                dtype=np.float32)  # steer, gas, brake

        self.action_space = spaces.Box(np.array([-1, -1]),
                                       np.array([+1, +1]),
                                       dtype=np.float32)
        self.observation_space = spaces.Box(low=0,
                                            high=255,
                                            shape=(STATE_W, STATE_H, 1),
                                            dtype=np.uint8)
        if num_player > 1:
            self.action_space = spaces.Dict(
                {i: self.action_space
                 for i in range(num_player)})
    def __init__(self, x0, world_info, target, render):
        self.render = render
        if self.render:
            super(PointMassWorldObstacle, self).__init__()
        else:
            self.world = b2.b2World(gravity=(0, -10), doSleep=True)
        self.world.gravity = (0.0, 0.0)
        self.initial_position = (x0[0], x0[1])
        self.initial_angle = b2.b2_pi
        self.initial_linear_velocity = (x0[2], x0[3])
        self.initial_angular_velocity = 0

        ground = self.world.CreateBody(position=(0, 20))
        ground.CreateEdgeChain([(-20, -20), (-20, 20), (20, 20), (20, -20),
                                (-20, -20)])

        xf1 = b2.b2Transform()
        xf1.angle = 0.3524 * b2.b2_pi
        xf1.position = b2.b2Mul(xf1.R, (1.0, 0.0))

        xf2 = b2.b2Transform()
        xf2.angle = -0.3524 * b2.b2_pi
        xf2.position = b2.b2Mul(xf2.R, (-1.0, 0.0))
        """
        self.body_shape = [b2.b2PolygonShape(vertices=[xf1*(-1, 0),
                                                xf1*(1, 0), xf1*(0, .5)]),
                    b2.b2PolygonShape(vertices=[xf2*(-1, 0),
                                                xf2*(1, 0), xf2*(0, .5)])]
        """
        self.body_shape = [b2.b2PolygonShape(box=(1, 1))]
        self.body = self.world.CreateDynamicBody(
            position=self.initial_position,
            angle=self.initial_angle,
            linearVelocity=self.initial_linear_velocity,
            angularVelocity=self.initial_angular_velocity,
            angularDamping=5,
            linearDamping=0.1,
            shapes=self.body_shape,
            shapeFixture=b2.b2FixtureDef(density=1.0),
        )
        self.initial_pos = self.world.CreateStaticBody(
            position=self.initial_position,
            angle=self.initial_angle,
            shapes=self.body_shape,
        )
        self.target = self.world.CreateStaticBody(
            position=target[:2],
            angle=self.initial_angle,
            shapes=[
                b2.b2PolygonShape(
                    vertices=[xf1 * (-1, 0), xf1 * (1, 0), xf1 * (0, .5)]),
                b2.b2PolygonShape(
                    vertices=[xf2 * (-1, 0), xf2 * (1, 0), xf2 * (0, .5)])
            ],
        )

        self.obstacle_post = []
        self.obstacle_shape = []
        self.obstacle = []
        obstacles = world_info['obstacles']
        self.n_obs = len(obstacles)
        for i in range(self.n_obs):
            self.obstacle_post.append(obstacles[i][:2])
            self.obstacle_shape.append(
                [b2.b2PolygonShape(box=tuple(obstacles[i][2:]))])
            self.obstacle.append(
                self.world.CreateStaticBody(position=self.obstacle_post[i],
                                            angle=self.initial_angle,
                                            shapes=self.obstacle_shape[i]))

        self.initial_pos.active = False
        self.target.active = False
FPS = 50  # Frames per second
ZOOM = 2.7  # Camera zoom
ZOOM_FOLLOW = True  # Set to False for fixed view (don't use zoom)

TRACK_DETAIL_STEP = 21 / SCALE
TRACK_TURN_RATE = 0.31
TRACK_WIDTH = 40 / SCALE
BORDER = 8 / SCALE
BORDER_MIN_COUNT = 4

ROAD_COLOR = [0.4, 0.4, 0.4]

WINDOW_SIZE = width, height = 1000, 800
white = 255, 255, 255
initial_camera_scale = 1
tmp = Box2D.b2Transform()
tmp.position = (0, 0)
initial_camera_offset = tmp
initial_camera_angle = 0
car_scale = 15
# num_player = 1

DARK_COLOR = (0, 0, 51)
MID_COLOR = (0, 40, 100)
LIGHT_COLOR = (16, 87, 100)
TILE_COLOR = (80, 80, 80)


class FrictionDetector(contactListener):
    def __init__(self, env):
        contactListener.__init__(self)