Python 用遗传算法对目标进行投球

Python 用遗传算法对目标进行投球,python,genetic-algorithm,physics-engine,pymunk,Python,Genetic Algorithm,Physics Engine,Pymunk,我想用Pymunk生成一个遗传算法,其目标是向目标投掷一个球 我知道如何做大多数遗传算法的东西,但Pymunk对我来说是新的。这个想法是,球将从一个固定的位置开始,比如离地1.5米,水平距离篮圈20米。假设这个球重1公斤。然后,球将以一定的力以一定的角度发射。健身将是它在飞行中距离目标中心最近的一次 因此,例如,群体中的个体可能看起来像[10.0,5.0],其中10.0表示水平施加10N,5.0表示垂直施加5N 我不想让它在我能看到的窗口中运行每一个模拟,但我希望能够打开它,以便在经过一定数量的

我想用Pymunk生成一个遗传算法,其目标是向目标投掷一个球

我知道如何做大多数遗传算法的东西,但Pymunk对我来说是新的。这个想法是,球将从一个固定的位置开始,比如离地1.5米,水平距离篮圈20米。假设这个球重1公斤。然后,球将以一定的力以一定的角度发射。健身将是它在飞行中距离目标中心最近的一次

因此,例如,群体中的个体可能看起来像
[10.0,5.0]
,其中10.0表示水平施加10N,5.0表示垂直施加5N

我不想让它在我能看到的窗口中运行每一个模拟,但我希望能够打开它,以便在经过一定数量的世代或达到一定的适应水平后,为最适合的个体运行它。这是我的意思的视觉表现

我已经尽力使用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()
导入系统,随机
导入pygame
从pygame.locals导入*
进口皮芒克
导入pymunk.pygame_util
def添加球(空格):
质量=1
半径=14
力矩=pymunk。圆的力矩(质量,0,半径)
主体=pymunk.主体(质量、力矩)
body.position=(50150)
形状=pymunk.圆(主体,半径)
添加(主体、形状)
返回形状
def添加_楼层(空间):
body=pymunk.body(body_type=pymunk.body.STATIC)
body.position=(0,0)
目标=pymunk.段(主体,(0,5),(600,5),5)
space.add(目标)
返回目标
def添加_目标(空格):
body=pymunk.body(body_type=pymunk.body.STATIC)
body.position=(700300)
目标=pymunk.段(体,(-150,0),(-150,50),5)
space.add(目标)
返回目标
def main():
pygame.init()
screen=pygame.display.set_模式((600600))
clock=pygame.time.clock()
space=pymunk.space()
空间重力=(0.0,-900.0)
目标=添加_目标(空格)
楼层=添加楼层(空间)
球=[]
draw\u options=pymunk.pygame\u util.DrawOptions(屏幕)
球数=0
尽管如此:
对于pygame.event.get()中的事件:
如果event.type==退出:
系统出口(0)
elif event.type==KEYDOWN和event.key==K_转义:
系统出口(0)
如果球数<1:
球形=添加球形(空间)
balls.append(ball\u形状)
球数+=1
空间步长(1/50.0)
屏幕填充((255255))
space.debug\u draw(draw\u选项)
pygame.display.flip()
时钟滴答(50)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
main()

我认为这个问题有几个部分。我的第一条建议是从尽可能小的事情开始,然后从那里扩展。当有几个部分令人困惑或者你不知道如何解决时,这种方法非常适用于各种各样的问题

以下是一些要点:

您需要准确了解您想要如何衡量健康状况。一些示例:

  • 测量一段时间后球到目标的距离。这应该很容易实现,因为您只需要在模拟结束时测量一次距离。然而,可能很难决定应该是什么时间

  • 在一次“投掷”中测量球到目标的最小距离。我想这比1强,但这取决于你想训练什么。在这种情况下,您可以在每次调用步长函数时测量距离,并跟踪其最小值。我想我会从这种测量健康的方法开始,因为它相当简单,但感觉还不错

  • 您可能希望将模拟与其显示分开。因此您应该尝试编写执行一轮/“抛出”的函数,并将其模拟到底

    例如,这里有一个简单的例子,我用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
    
    def添加球(空格):
    质量=1
    半径=14
    力矩=pymunk。圆的力矩(质量,0,半径)
    主体=pymunk.主体(质量、力矩)
    body.position=(50150)
    形状=pymunk.圆(主体,半径)
    添加(主体、形状)
    返回形状
    def添加_楼层(空间):
    body=pymunk.body(body_type=pymunk.body.STATIC)
    body.position=(0,0)
    目标=pymunk.段(主体,(0,5),(600,5),5)
    space.add(目标)
    返回目标
    def添加_目标(空格):
    body=pymunk.body(body_type=pymunk.body.STATIC)
    body.position=(700300)
    目标=pymunk.段(体,(-150,0),(-150,50),5)
    space.add(目标)
    返回目标
    def do_单掷(脉冲):
    space=pymunk.space()
    空间重力=(0.0,-900.0)
    球形=添加球形(空间)
    添加楼层(空间)
    目标形状=添加目标(空间)
    球形。主体。在局部点(脉冲)施加脉冲
    到目标的最小距离=1000000
    步数=1000
    对于范围内的uu(步):
    空间步长(1/50.0)
    距离目标=目标形状。身体。位置。获取距离(球形状。身体。位置)
    如果到目标的距离小于到目标的最小距离:
    到目标的最小距离=到目标的距离