Столкновения объектов в pybox2d

пытаюсь сделать модель некого устройства (как у OpenAI Gymnasium) для дальнейшего обучения модели PPO. Никак не могу понять, почему отсутствуют столкновения в модели, которую я пытаюсь сделать. Объекты просто проходя сквозь друг друга, хотя я сделал им всем фикстуры.

import pygame as pg
from pygame.locals import *
from pygame.color import *

import Box2D
from Box2D import *
import random
from math import cos, sin, radians, atan


FPS = 60
WIN_WIDTH = 900
WIN_HEIGHT = 750
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (125, 125, 125)
LIGHT_BLUE = (64, 128, 255)
GREEN = (0, 200, 64)
YELLOW = (225, 225, 0)
PINK = (230, 50, 230)
RED = (255, 0, 0)

clock = pg.time.Clock()
sc = pg.display.set_mode((WIN_WIDTH, WIN_HEIGHT))

pg.init()
# Создаем мир Box2D
gravity = 50
world = b2World(gravity=(0, gravity), doSleep=False)

# Создаем рамку
top = world.CreateStaticBody(position=(1, 1), shapes=b2PolygonShape(box=(WIN_WIDTH, 1)))
bot = world.CreateStaticBody(
    position=(WIN_WIDTH - 1, WIN_HEIGHT - 1), shapes=b2PolygonShape(box=(WIN_WIDTH, 1))
)
left = world.CreateStaticBody(
    position=(0, 0), shapes=b2PolygonShape(box=(1, WIN_HEIGHT))
)
right = world.CreateStaticBody(
    position=(WIN_WIDTH, WIN_HEIGHT), shapes=b2PolygonShape(box=(1, WIN_HEIGHT))
)

# Бараанный сбрасыватель (Параметры)
angle = 0
angle_spd = 0
r1 = 140
r2 = 100
x0 = WIN_WIDTH - (r1 + 10)
y0 = WIN_HEIGHT // 2
teeth_num = 12
phase = 360 / (teeth_num * 5)
drum_density = 10000
drum_friction = 1

# Винтовой холодильник (Параметры)
screw_left = 180
screw_right = 670
screw_top = 540 + 7.5
screw_bot = 540 - 7.5
x1 = 620
x2 = 640
y1 = 560
y2 = 520
a = x1
b = y1
step = 30
line_acc = 0
line_spd = 0
line_spd = 0.8
lines = []
for i in range(15):
    lines.append([[x1 - step * i, y1], [x2 - step * i, y2]])
restart_line = False
line_ind = 0

# Создание барабанного сбрасываетля
drum = world.CreateDynamicBody(position=(x0, y0))

for i in range(1, teeth_num + 1):
    # Первые пол паза
    drum_fixture_points = []
    drum_fixture_points.append((0, 0))
    x = r2 * cos(radians(angle + phase * 0))
    y = -r2 * sin(radians(angle + phase * 0))
    drum_fixture_points.append((x, y))
    x = r2 * cos(radians(angle + phase * 1))
    y = -r2 * sin(radians(angle + phase * 1))
    drum_fixture_points.append((x, y))
    fixture = b2FixtureDef(
        shape=b2PolygonShape(vertices=drum_fixture_points),
        density=drum_density,
        friction=drum_friction,
    )
    drum.CreateFixture(fixture)

    # Зубец
    drum_fixture_points = []
    drum_fixture_points.append((0, 0))
    x = r2 * cos(radians(angle + phase * 1))
    y = -r2 * sin(radians(angle + phase * 1))
    drum_fixture_points.append((x, y))
    x = r1 * cos(radians(angle + phase * 2))
    y = -r1 * sin(radians(angle + phase * 2))
    drum_fixture_points.append((x, y))
    x = r1 * cos(radians(angle + phase * 3))
    y = -r1 * sin(radians(angle + phase * 3))
    drum_fixture_points.append((x, y))
    x = r2 * cos(radians(angle + phase * 4))
    y = -r2 * sin(radians(angle + phase * 4))
    drum_fixture_points.append((x, y))
    fixture = b2FixtureDef(
        shape=b2PolygonShape(vertices=drum_fixture_points),
        density=drum_density,
        friction=drum_friction,
    )
    drum.CreateFixture(fixture)

    # Вторые пол паза
    drum_fixture_points = []
    drum_fixture_points.append((0, 0))
    x = r2 * cos(radians(angle + phase * 4))
    y = -r2 * sin(radians(angle + phase * 4))
    drum_fixture_points.append((x, y))
    x = r2 * cos(radians(angle + phase * 5))
    y = -r2 * sin(radians(angle + phase * 5))
    drum_fixture_points.append((x, y))
    fixture = b2FixtureDef(
        shape=b2PolygonShape(vertices=drum_fixture_points),
        density=drum_density,
        friction=drum_friction,
    )
    drum.CreateFixture(fixture)
    angle += phase * 5
    angle %= 360

# Создание винтового холодильника
screw = world.CreateStaticBody(
    position=((screw_left + screw_right) / 2, (screw_top + screw_bot) / 2)
)
screw.CreateFixture(
    b2FixtureDef(
        shape=b2PolygonShape(
            box=((screw_right - screw_left) / 2, (screw_bot - screw_top) / 2)
        ),
        density=100000000000,
        restitution=0,
    )
)
screw_lines = []
for line in lines:
    pos = (line[0][0] / 2 + line[1][0] / 2, line[0][1] / 2 + line[1][1] / 2)
    screw_line = world.CreateDynamicBody(
        position=pos,
        shapes=b2EdgeShape(vertices=[line[0], line[1]]),
    )
    screw_lines.append(screw_line)

# Создаём первую трубу
pipe = world.CreateDynamicBody(position=(x0 - 500, y0 - r2 - 40))
pipe.CreateFixture(
    b2FixtureDef(shape=b2CircleShape(radius=1.2), density=3, friction=0.3)
)

# Запускаем цикл симуляции
running = True
while running:
    for event in pg.event.get():
        if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
            running = False

    # Шаг симуляции
    world.Step(1.0 / 60, 40, 40)

    # Управление барабаном
    angle_acc = random.random() * 0.1 - 0.05
    angle_spd += angle_acc
    if angle_spd < 0:
        angle_spd = 0
    if angle_spd > 0.5:
        angle_spd = 0.5

    # drum.ApplyForce(b2Vec2(x0, y0), b2Vec2(0, -gravity), True)
    drum.position.Set(x0, y0)

    drum.angularVelocity = -angle_spd

    # Отрисовка
    sc.fill((0, 0, 0))
    for body in world.bodies:
        for fixture in body.fixtures:
            shape = fixture.shape
            if isinstance(shape, b2PolygonShape):
                vertices = [(body.transform * v) for v in shape.vertices]
                pg.draw.polygon(sc, (255, 255, 255), [v for v in vertices])
            elif isinstance(shape, b2CircleShape):
                center = body.transform * shape.pos
                radius = shape.radius
                pg.draw.circle(sc, (255, 255, 255), center, int(radius * 10))

    # Управление винтом
    for (i, line), screw_line in zip(enumerate(lines), screw_lines):
        line[0][0] -= line_spd
        line[1][0] -= line_spd
        if line[0][0] < 200:
            x_dif = 200 - line[0][0]
            y_dif = x_dif / (abs(x1 - x2) / abs(y1 - y2))

            a -= x_dif
            b -= y_dif
            pg.draw.line(sc, WHITE, [a + step, y1], [x1 + step, b], 3)

            line[0][0] += x_dif
            line[0][1] -= y_dif

            screw_line.position.Set(
                (line[0][0] + line[1][0]) / 2, (line[0][1] + line[1][1]) / 2
            )

            if line[0][0] >= line[1][0] and line[0][1] <= line[1][1]:
                restart_line = True
                line_ind = i
        pg.draw.line(sc, WHITE, line[0], line[1], 3)

    if restart_line:
        restart_line = False
        lines.pop(line_ind)
        lines.append([[a + step, y1], [x1 + step, b]])
        a = x1
        b = y1
    # pg.display.flip()
    # pg.time.wait(10)
    pg.display.update()
    clock.tick(FPS)

pg.quit()

Ответы (0 шт):