Skip to content
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

Dynamic friction fix #52

Merged
merged 8 commits into from
Aug 29, 2023
Merged

Conversation

felixbjorkeson
Copy link
Contributor

@felixbjorkeson felixbjorkeson commented Jun 27, 2023

The velocity update applying dynamic friction is probably wrong in the paper (Detailed Rigid Body Simulation with Extended Position Based Dynamics).
We had a discussion about in the "10 minutes physics" discord channel (channel created by the papers author, Matthias Müller)
Equation 30 in the paper doesn't make sense unit wise.
The equation is supposed to calculate a velocity Δv = [m/s, meter per second]
The left side in the min has unit force⋅time [ N⋅s = kg⋅m/s2 ⋅ s = kg ⋅ m / s], the right has velocity. So there is a mass discrepancy, either divide the left side in the min with mass, or instead calculate an impulse p (= force⋅time)
So instead of calculating Δv with equation 30, we calculate the impulse p, therefore the right side in the min needs to be multiplied by mass. We have p = Δv / (w1+w2), using vt as Δv also makes sense, since this is the impulse needed to counteract all relative velocity of the contact.
The new equation then becomes
p = -vt / |vt| ⋅ min(h ⋅ μ ⋅ |fn|, |vt|/(w0+w1)), then apply the p as usual according to (33)

@felixbjorkeson
Copy link
Contributor Author

Just to clarify the consequence i noticed when implementing my own xpbd physics engine.
According to coulomb friction model, two objects with different mass but same friction coefficients and initial velocity should come to rest at the same time/distance. But with the original equation, heavy objects will come to a stop much sooner than light objects.

@Jondolf Jondolf added the bugfix label Jun 27, 2023
@Jondolf
Copy link
Owner

Jondolf commented Jun 27, 2023

Thanks, the friction definitely seems to be working in a more realistic way with bodies that have different masses now. However, this does seem to increase the amount of "explosions", especially with larger dynamic friction coefficients; below is the cubes example with a coefficient of 1.0.

2023-06-27.12-28-10.mp4

This was already a problem to some extent, but not nearly as strong. I don't know what's causing it, but it probably isn't the friction in itself. One thing I've been wondering is if r1 and r2 are supposed to be the original contact positions in world space or the local contact positions rotated by the current rotations of the bodies, which would approximate the current contact positions in world space.

@Jondolf
Copy link
Owner

Jondolf commented Jun 27, 2023

Also, is the 10 minute physics Discord server private? I have tried looking for it but couldn't find it. I was thinking that it might be useful for me to be on there since I maintain this physics engine.

@felixbjorkeson
Copy link
Contributor Author

Unsure if its allowed to post links here, but the discord channel should not be private. It can be found in from the youtube channel, then community tab.
Regarding r1 and r2, they should be the local offsets. So they can be transformed to correct world coordinates with updated poses of the rigid bodies.
Very interesting behavior with jumping boxes :P I haven't really used the library (I sometimes compare specific parts to my own implementation in C#) but if I have time I can look for some errors.

@Jondolf Jondolf added the A-Dynamics Relates to rigid body dynamics: motion, mass, constraint solving, joints, CCD, and so on label Jul 16, 2023
@Jondolf
Copy link
Owner

Jondolf commented Jul 20, 2023

Hi again, the explosions were fixed by #90 for contacts between convex colliders (like the cubes), and this PR works fine now, as I'm no longer seeing any jumping cubes. For non-convex colliders like trimeshes there are still problems though, so I'll wait a little longer until I get this PR merged.

If you don't mind, I can also take over in terms of fixing merge conflicts and such. Just to be sure, I'll also compare with other engines to make sure the friction works correctly both in 2D and 3D.

@felixbjorkeson
Copy link
Contributor Author

Hi, great, i don't mind if you take over the merge conflicts.
I saw that you implemented contact manifold to solve the contact explosions. Which for me seems strange, in my implementation i only use single contact between bodies and have never encountered such issues.
I noticed that changes was made to use the local contact points but i assume the issue still remained, (before manifolds was implemented). But i suspect the issue from the beginning was that the penetration depth was not recalculated at each solve?

I quickly read the contact solve code and noticed some things that is not correct (or at least differs from my implementation)

  1. The contact normal should also be defined in local coordinates for either body 1 or body 2, the normal should then be transformed to world at every solve just like the local contact points (to have the correct direction)
  2. When calculating the static friction the corresponding normal and tangential λ should be used, not the correction magnitude (in this case penetration for the normal and relative contact point speed for the tangent)

@Jondolf
Copy link
Owner

Jondolf commented Jul 24, 2023

Thanks, the normals should probably be stored as local and transformed to world space at every solve like you mentioned, and the static friction should also be fixed. I'll fix these later.

However, neither one of these is causing the actual explosiveness. Completely removing static friction doesn't help, and the contact normal fix doesn't seem to help either, although it might reduce drifting a bit.

I'm thinking that it could somehow be caused by floating point precision problems and numerical instability, because using f64 instead of f32 removes the explosiveness. According to logs, the Lagrange multiplier update is unusually big at explosions due to a value of c (the penetration) that is nearly 10 times as large as normal, so the problem is probably somewhere in the penetration constraint. Or maybe there is occasionally an inverted normal somehow that pulls the cube deeper into the ground, which causes a much larger penetration the next frame.

@Jondolf
Copy link
Owner

Jondolf commented Jul 26, 2023

FYI the contact normal fix reduces drifting and makes cube stacking significantly more stable, see #97

@Jondolf
Copy link
Owner

Jondolf commented Aug 28, 2023

Hi, I finally revisited this PR, resolved the conflicts and made some minor improvements to naming and comments.

I also compared this against Unity just to verify, and the results look quite good if not better than Unity:

friction_comparison.mp4

The bigger boxes travel the same distance as the smaller ones, as expected. It does look like our friction might be slightly weaker than Unity's (both use coefficient of 0.3), but that could also be a setup problem or something.

I still haven't fixed all of the collision problems I mentioned earlier, but it's not worth delaying this PR more since it doesn't seem like it's causing any problems that aren't present on the main branch. I'm happy to finally get this merged tomorrow :)

@Jondolf Jondolf merged commit f102a65 into Jondolf:main Aug 29, 2023
3 checks passed
@Jondolf Jondolf added C-Bug Something isn't working and removed bugfix labels Jul 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Dynamics Relates to rigid body dynamics: motion, mass, constraint solving, joints, CCD, and so on C-Bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants