向目标扔球的遗传算法

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

我想用Pymunk产生一种遗传算法,其目的是将球扔向目标。

我知道如何完成大多数遗传算法的工作,但是Pymunk对我来说是新手。这个想法是,球将从一个固定的位置开始,例如距地面1.5m,距篮筐水平20m。假设球重1公斤。然后,球将以一定的力以一定的角度发射。适应度将是它在飞行过程中最接近目标中心的位置。

因此,例如,总体中的某个人看起来像[10.0, 5.0],其中10.0表示水平应用10N,5.0表示垂直应用5N。

我不希望它在我能看到的窗口中运行每个模拟,但是我希望能够将其打开,以便在一定数量的代之后或一旦达到一定的代数就可以为最适合的个体运行它。一定的健身水平。这是我的意思https://prnt.sc/pn1hoc的直观表示。

我已经尽力使用pymunk文档来解决这个问题,但是我发现它不是很有帮助,所以我很困惑。

我知道我需要启动一个空格

space = pymunk.Space()
space.gravity = (0.0, -900.0)  # not sure what this means?

然后在该空间中创建一个球

def add_ball(space):
    mass = 1
    radius = 14
    moment = pymunk.moment_for_circle(mass, 0, radius)
    body = pymunk.Body(mass, moment)
    body.position = 100, 150
    shape = pymunk.Circle(body, radius)
    space.add(body, shape)
    return shape

尽管此球将开始掉落,但不确定如何使其静态开始。

然后生成目标,我应该做类似的事情

def add_target(space):
    body = pymunk.Body(body_type = pymunk.Body.STATIC)
    body.position = (500, 300)
    target = pymunk.Segment(body, (-150, 0), (-150, 50), 5)
    space.add(target)
    return target

我真的很感谢将这些拼接在一起的一些帮助,这样我可以在我的遗传算法中运行模拟,也可以将其切换为在窗口中运行。

谢谢。

编辑:

我已经研究出如何设置地板,这是到目前为止的所有代码

import sys, random
import pygame
from pygame.locals import *
import pymunk
import pymunk.pygame_util


def add_ball(space):
    mass = 1
    radius = 14
    moment = pymunk.moment_for_circle(mass, 0, radius)
    body = pymunk.Body(mass, moment)
    body.position = (50, 150)
    shape = pymunk.Circle(body, radius)
    space.add(body, shape)
    return shape


def add_floor(space):
    body = pymunk.Body(body_type = pymunk.Body.STATIC)
    body.position = (0, 0)
    target = pymunk.Segment(body, (0, 5), (600, 5), 5)
    space.add(target)
    return target


def add_target(space):
    body = pymunk.Body(body_type = pymunk.Body.STATIC)
    body.position = (700, 300)
    target = pymunk.Segment(body, (-150, 0), (-150, 50), 5)
    space.add(target)
    return target


def main():
    pygame.init()
    screen = pygame.display.set_mode((600, 600))
    clock = pygame.time.Clock()

    space = pymunk.Space()
    space.gravity = (0.0, -900.0)

    target = add_target(space)
    floor = add_floor(space)
    balls = []
    draw_options = pymunk.pygame_util.DrawOptions(screen)

    ball_count = 0
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                sys.exit(0)
            elif event.type == KEYDOWN and event.key == K_ESCAPE:
                sys.exit(0)

        if ball_count < 1:
            ball_shape = add_ball(space)
            balls.append(ball_shape)
            ball_count += 1

        space.step(1/50.0)

        screen.fill((255,255,255))
        space.debug_draw(draw_options)

        pygame.display.flip()
        clock.tick(50)

if __name__ == '__main__':
    main()
python genetic-algorithm physics-engine pymunk
1个回答
1
投票

我认为这个问题有几个部分。我的第一建议是从最小的东西开始,然后从那里开始扩展。当有多个部分令人困惑或您不知道如何解决时,此方法非常适合各种问题。

这里有一些指针:

您需要精确地确定测量健身的方式。一些示例:

  1. 在一定时间后测量球到目标的距离。这应该非常容易实现,因为当仿真结束时,您只需要测量一次即可。但是,可能很难决定应该几点。

  2. 测量一次“掷”中球到目标的最小距离。我想这要好于1,但要取决于您要培训的内容。在这种情况下,您可以在每次调用step函数时测量距离,并跟踪其最小值。我认为我会从这种适合度的测量方法开始,因为它相当容易,但仍然感觉还不错。

[您可能想将模拟与其显示分开。因此,您应该尝试编写执行一圈/“掷”的功能并将其模拟到最后。

例如,这是一个简单的示例,我将do_one_throw方法与投掷脉冲作为输入并通过1000个模拟步骤返回到目标的最小距离结合在一起:

def add_ball(space):
    mass = 1
    radius = 14
    moment = pymunk.moment_for_circle(mass, 0, radius)
    body = pymunk.Body(mass, moment)
    body.position = (50, 150)
    shape = pymunk.Circle(body, radius)
    space.add(body, shape)
    return shape


def add_floor(space):
    body = pymunk.Body(body_type = pymunk.Body.STATIC)
    body.position = (0, 0)
    target = pymunk.Segment(body, (0, 5), (600, 5), 5)
    space.add(target)
    return target


def add_target(space):
    body = pymunk.Body(body_type = pymunk.Body.STATIC)
    body.position = (700, 300)
    target = pymunk.Segment(body, (-150, 0), (-150, 50), 5)
    space.add(target)
    return target

def do_one_throw(impulse):
    space = pymunk.Space()
    space.gravity = (0.0, -900.0)

    ball_shape = add_ball(space)
    add_floor(space)
    target_shape = add_target(space)

    ball_shape.body.apply_impulse_at_local_point(impulse)

    min_distance_to_target = 1000000
    steps = 1000
    for _ in range(steps):
        space.step(1/50.0)
        distance_to_target = target_shape.body.position.get_distance(ball_shape.body.position)
        if distance_to_target < min_distance_to_target:
            min_distance_to_target = distance_to_target
    return min_distance_to_target

一旦掌握了这些基本知识,就可以添加更多漂亮的功能

  • 例如,您可以简单地通过使用打印来打印出模拟中发生的事情来开始。
  • 您在空间上设置的重力是重力矢量。请注意,pymunk是独立于单位的,因此只要您传入的所有内容都一致,就可以正确解决:http://www.pymunk.org/en/latest/overview.html#mass-weight-and-units
  • 例如,您可以通过一些更聪明的逻辑来决定何时结束模拟,从而优化我的快速代码和肮脏代码,因此,如果球已经过去而又没有机会回来,则无需运行所有1000步。] >
  • 您可以添加pygame绘图代码,看起来您已经在这里取得了很大的进步
  • 改进了到目标的距离的测量,现在我通过测量物体之间的距离来获得最简单的解决方案,但是您可能想要形状之间的距离,因此如果形状发生碰撞,则距离为0。
© www.soinside.com 2019 - 2024. All rights reserved.