使用pygame渲染自上而下护理模拟的自定义openAI健身房环境,其中相机跟随汽车

问题描述 投票:0回答:0

我正在尝试构建自定义 OpenAI Gym 环境。为此,我正在使用 Pygame 编写渲染函数。在我的环境中,我想想象一辆由强化学习代理通过赛道控制的汽车。我想让相机跟随汽车穿过赛道。因此,当赛道在移动时,汽车在 pygame 窗口内保持固定位置。汽车仅围绕其上轴(偏航)旋转。 汽车的位置和偏航由强化学习代理实时确定。赛道的形状是事先知道的。

我是 pygame 的超级新手。我遇到了很多问题。我无法让轨道越过汽车。汽车的旋转似乎有效,但我什至看不到轨道。

我真的迷路了,希望能得到一些指导和具体的例子来说明如何实现我想要的结果。

我尝试了很多不同的方法。这就是我现在所拥有的。我评论了代码并在评论中包含了问题。汽车的旋转现在似乎可以正常工作,但是,我看不到赛道,我也不知道为什么。我也完全不确定我的方法是否正确。

  def render(self):
    VIEWPORT_W = 1000
    VIEWPORT_H = 800
    SCALE = 30
    veh_length, veh_width = self.sim_model.params.veh_length, self.sim_model.params.veh_width
    if self.render_mode is None:
        gym.logger.warn(
            "You are calling render method without specifying any render mode. "
            "You can specify the render_mode at initialization, "
            f'e.g. gym("{self.spec.id}", render_mode="rgb_array")'
        )
        return

    if self.screen is None and self.render_mode == "human":
        pygame.init()
        pygame.display.init()
        self.screen = pygame.display.set_mode((VIEWPORT_W, VIEWPORT_H))
    if self.clock is None:
        self.clock = pygame.time.Clock()

    self.screen.fill(0)

    # ROTATING THE CAR
    # define a surface (RECTANGLE), with SRCALPHA for transparency during rotation
    # I use SCALE to make the car bigger, else it is super tiny
    car = pygame.Surface((veh_width*SCALE, veh_length*SCALE), pygame.SRCALPHA)
    # fill the rectangle / surface with green color
    car.fill((0, 255, 0))
    # creating a copy of orignal image for smooth rotation
    car_copy = car.copy()
    car_copy.set_colorkey((0, 0, 0))
    # define rect for placing the rectangle at the desired position
    rect_around_car = car_copy.get_rect()
    rect_around_car.center = (VIEWPORT_W // 2, (2 * VIEWPORT_H) // 3)

    old_car_center = rect_around_car.center
    rot = self.current_sim_state[2] * 180 / np.pi  # the RL agent returns a yaw in radians
    rotated_car = pygame.transform.rotate(car, -rot)  # pygame has opposite rotation direction... so I need a -
    rotated_rect_around_car = rotated_car.get_rect()
    rotated_rect_around_car.center = old_car_center

    # HERE I WANT TO PLOT THE RACE TRACK ON A SURFACE AND MOVE THAT SURFACE IN OPPOSITE DIRECTION OF THE CAR
    x_c = self.track["X"]  # list of x coordinates of time optimal race line
    x_i = self.track["X_i"]  # list of x coordinates of inner boundary of the track
    x_o = self.track["X_o"]  # list of x coordinates of outer boundary of the track
    # corresponding y coordinates
    y_c = self.track["Y"]
    y_i = self.track["Y_i"]
    y_o = self.track["Y_o"]

    # Draw all lines on the track surface. Then move the entire surface
    track = pygame.Surface((VIEWPORT_W, VIEWPORT_H), pygame.SRCALPHA)

    # some data processing to be able to draw lines
    center_line_points = list(zip(x_c, y_c))
    inner_line_points = list(zip(x_i, y_i))
    outer_line_points = list(zip(x_o, y_o))
    # drawing all lines on the track surface
    # How can I use SCALE here, so that the track is proportional to the rectangle representing the car?
    pygame.draw.aalines(track, "white", closed=False, points=center_line_points)
    pygame.draw.aalines(track, "white", closed=False, points=inner_line_points)
    pygame.draw.aalines(track, "white", closed=False, points=outer_line_points)
    # that is the x and y position of the current x and y coordinate of the car this coordinate is calculated
    # outside the render function and is set to a new value every time before I call render()
    # I have no idea how to go about the coordinate systems. The calculation of the position of the car
    # is completely independent of the coordinate system in pygame.
    car_x = self.current_sim_state[0]
    car_y = self.current_sim_state[1]


    if self.render_mode == "human":
        assert self.screen is not None
        # here I blit the surfaces. No idea if this is how you are supposed to do it
        self.screen.blit(rotated_car, rotated_rect_around_car)
        self.screen.blit(track, (-car_x, -car_y))
        pygame.event.pump()
        self.clock.tick(self.metadata["render_fps"])
        pygame.display.flip()
    elif self.render_mode == "rgb_array":
        # here I want to output a np.array with the rgb matrix of the current frame
        # so I can render the frames to a mp4 once the simulation is over
        return np.transpose(
            np.array(pygame.surfarray.pixels3d(rotated_car)), axes=(1, 0, 2)
        )

  return
python pygame openai-gym pygame-surface
© www.soinside.com 2019 - 2024. All rights reserved.