-
Notifications
You must be signed in to change notification settings - Fork 191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The collision between two segments #240
Comments
Take a look at this example and check what might be different from your setup. If you want you can also set b1.position to something else as I have commented out, its just that then it will keep collide with impulse & ke > 0 for more frames so I left it out to easily see the result. import math
import pygame
import pymunk
import pymunk.pygame_util
pygame.init()
screen = pygame.display.set_mode((800, 800))
draw_options = pymunk.pygame_util.DrawOptions(screen)
clock = pygame.time.Clock()
space = pymunk.Space()
b1 = pymunk.Body()
s1 = pymunk.Segment(b1, (-25, 0), (25, 0), 5)
s1.mass = 1
#b1.position = 300, 125
b1.position = 300, 100
b1.angle = math.pi / 2
b2 = pymunk.Body()
s2 = pymunk.Segment(b2, (-25, 0), (25, 0), 5)
s2.mass = 1
b2.position = 400, 100
space.static_body.position = 250, 100
s3 = pymunk.Circle(space.static_body, 25)
space.add(s3)
space.add(b1, s1, b2, s2)
b2.apply_impulse_at_local_point((-10, 0))
def post_solve(arbiter: pymunk.Arbiter, space, data):
if arbiter.total_ke == 0:
return
print("post_solve")
print(f"total_impulse: {arbiter.total_impulse}, total_ke {arbiter.total_ke}")
handler = space.add_default_collision_handler()
handler.post_solve = post_solve
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
screen.fill((0, 0, 0))
space.debug_draw(draw_options)
space.step(1 / 50)
pygame.display.update()
clock.tick(50) |
Ah, now I understand the issue. Something is broken with the segment/segment collision I think. When playing around with it I also noticed that there are two different errors possible: This arrangement will not create a collision at all until they intersect "without" radius: b1 = pymunk.Body()
s1 = pymunk.Segment(b1, (-80, 0), (80, 0), 80)
s1.mass = 1
b1.angle = math.pi / 2
b1.position = 200, 200
b2 = pymunk.Body()
s2 = pymunk.Segment(b2, (-80, 0), (80, 0), 80)
s2.mass = 1
b2.position = 500, 280 While this one will create a collision, but no impulse to resolve it etc until the meet at the "no radius" point : b1 = pymunk.Body()
s1 = pymunk.Segment(b1, (-80, 0), (80, 0), 80)
s1.mass = 1
b1.angle = math.pi / 2
# b1.position = 300, 125
b1.position = 200, 200
b2 = pymunk.Body()
s2 = pymunk.Segment(b2, (-80, 0), (80, 0), 80)
s2.mass = 1
b2.position = 500, 120 (I increased the size of the segments to better see the collision drawing) The code for the segment collisions is here in case you are interested: https://github.com/viblo/Chipmunk2D/blob/2e8d4104b7e2380d1a73f5363a931b3eb3de8d07/src/cpCollision.c#L573 I suspect I wont be able to solve this quickly.. Anyway, I saw you sent me an email as well, and I think the idea you had of a workaround with two circles and a box all attached to the same body should work. Something like this, but maybe with some more consideration of the mass in case its important since now its not exactly the same. b1 = pymunk.Body()
s1 = pymunk.Segment(b1, (-80, 0), (80, 0), 80)
s1.mass = 1
b1.angle = math.pi / 2
# b1.position = 300, 125
b1.position = 200, 200
b2 = pymunk.Body()
s2a = pymunk.Circle(b2, 80, (-80, 0))
s2b = pymunk.Circle(b2, 80, (80, 0))
s2c = pymunk.Poly.create_box(b2, (160, 160))
# s2 = pymunk.Segment(b2, (-80, 0), (80, 0), 80)
s2c.mass = 1
b2.position = 500, 120
space.add(b1, s1, b2, s2a, s2b, s2c) |
Hi, thank you for your reply. I tested the code you provided, and the collision detection works well. I also have two questions about pymunk. The first one is, why should we consider the mass more in the previous example? In the example, the mass center of body 2 is at the center of the box. Could this cause errors when calculating the energy loss during collision? The second question is about the collision_type in the callback function, which seems to change its order when two bodies collide over many steps. I will describe this second question further.
"When I use body2 to collide with body1 continuously, I check the collision_type in the post_solve function. At first, it will return [1, 2]. Then, after some steps, it will return [2, 1]. Why does this happen? |
So, to answer your first question about the mass: The moment of the body ( For the second case I believe you have a small bug, at least in the code you pasted here. The collision type should be set on the shape and not body. If I change it to do that the ordering is consistent all the time for me. |
Oh, I see. Thank you for your information. |
Hi,
I'm trying to simulate the collision between two segments, s1 and s2, which have the same shape. The initial positions of s1 and s2 are p1 = Vec2d(100, 100) and p2 = Vec2d(150, 92), respectively. Their initial angles are a1 = np.pi / 2 for s1 and a2 = -np.pi for s2. The elasticity and gravity for both segments are set to 0. The initial scenario is shown below.
s2 approaches s1 using two methods. The first method involves setting the velocity of s2 (v2) to Vec2d(-0.5, 0) at the first step (
agents[1].body.velocity = Vec2d(-0.5, 0.)
). The second method involves applying an impulse to s2 with the codeagents[1].body.apply_impulse_at_world_point(Vec2d(-1.0, 0), agents[1].body.position)
at the first step.After a few steps, the segments collide. Initially, when s1 and s2 collide, I check the total_impulse and total_ke of the system, which are (0, 0) and 0, respectively. These values remain unchanged until the positions of the two segments are as shown in the following figure.
At this step, the two contact points obtained from the collide_handler are [100.0, 100.0] and [101.5, 100.0]. Subsequently, the segments separate from each other, resulting in the final scenario depicted below.
I wonder why this happen? Do you have any pointers for me?
Thank you!
The text was updated successfully, but these errors were encountered: