Improving collision between dynamic and kinematic entities

Discuss any questions about BEPUphysics or problems encountered.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Improving collision between dynamic and kinematic entities

Post by snoozbuster »

So, the only dynamic objects in my game are the boxes that you move through the level, and the rest of the objects are kinematic. Unfortunately, this means the boxes have a tendancy to clip through the kinematics, especially when the kinematics are moving the boxes through pushing them (which is almost all of them). I tried increased the boxes' mass to an ungodly huge number (int.MaxValue - 1, to be exact) because I remember you saying an object with a large mass depending on one with a small mass makes collision squishy, but it only slightly improved the issue. Is there something else I could use besides kinematic enities? For example, could I make them dynamic but not affected by gravity and still have them not move when colliding with boxes (either without extra code or perhaps with a very rigid constraint)? Then I could set their mass to, like, ten, and the boxes to one, and that wouldn't be squishy (I might have to do some things with collision groups to keep them from responding from unlikely collision with each other, though). Anyways, any other ideas? Thanks!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Improving collision between dynamic and kinematic entiti

Post by Norbo »

So, the only dynamic objects in my game are the boxes that you move through the level, and the rest of the objects are kinematic. Unfortunately, this means the boxes have a tendancy to clip through the kinematics, especially when the kinematics are moving the boxes through pushing them (which is almost all of them). I tried increased the boxes' mass to an ungodly huge number (int.MaxValue - 1, to be exact) because I remember you saying an object with a large mass depending on one with a small mass makes collision squishy, but it only slightly improved the issue.
The issue of mass ratios comes into play when a heavy dynamic object is dependent upon a light dynamic object. This is a difficult situation for the solver to handle, but given enough time (Space.Solver.IterationLimit), it will improve. The problem is, the number of iterations needed to improve a big ratio like 100:1 might be prohibitively expensive.

However, the issue of kinematics crushing dynamic objects is different. Kinematic objects have effectively infinite mass. There's no real-world analog for them. Kinematics simply cannot be pushed back by any amount of force. Increasing a dynamic object's mass or increasing the number of solver iterations may alter the termination state of the involved constraints, but it can't address the core problem. A finite mass is still less than infinite mass and nothing can push back against that infinite mass. It's easy enough to create a completely unsolvable system with moving kinematics. This means that no matter how many iterations are run, it cannot converge to a solution because no solution exists. In these situations, the dynamic body gets 'crushed' and wiggles around helplessly, usually getting launched or squeezed out at some point.
Is there something else I could use besides kinematic enities? For example, could I make them dynamic but not affected by gravity and still have them not move when colliding with boxes (either without extra code or perhaps with a very rigid constraint)? Then I could set their mass to, like, ten, and the boxes to one, and that wouldn't be squishy (I might have to do some things with collision groups to keep them from responding from unlikely collision with each other, though). Anyways, any other ideas? Thanks!
Making the machinery dynamic and weak enough to avoid crushing the boxes would do the trick. Since the boxes can fight back against the machinery (making it a solvable system), they won't get completely crushed.

There are a variety of ways to make the machinery dynamic. The most obvious and direct option is to actually make them real contraptions bound together with motors and other constraints with specific motor strengths. Collision rules would indeed be useful for managing interactions. The RobotArmDemo shows the configuration of a complex articulated structure with constraints and collision rules.

The simplest type of machines, like rollers (if you decide to switch them to dynamic from kinematic as well), would likely make use of things like the SingleEntityLinear/AngularMotors. Simple moving platforms could also get away with just those motors, though for things where you don't need or desire physical weakness, kinematics are still a good thing to use. Faking things may also be useful sometimes (e.g. a 'pushing volume' as opposed to 100 individually rotating, motor-controlled rollers).

Finally, an important note to remember: a 'very rigid constraint' can crush a light dynamic object almost as effectively as a moving kinematic entity. Dynamic objects aren't a magic bullet; the value of dynamic machinery is that it can be weakened away from infinite forces so that the solver can actually figure out a solution.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

Norbo wrote: However, the issue of kinematics crushing dynamic objects is different.
Alright, that's a fantastic explanation.
Norbo wrote: There are a variety of ways to make the machinery dynamic. The most obvious and direct option is to actually make them real contraptions bound together with motors and other constraints with specific motor strengths. Collision rules would indeed be useful for managing interactions. The RobotArmDemo shows the configuration of a complex articulated structure with constraints and collision rules.
That doesn't seem like it would be too hard, being that most of my machines are only one or two meshs... Although it might be more difficult to add in rollers.
Norbo wrote:for things where you don't need or desire physical weakness, kinematics are still a good thing to use. Faking things may also be useful sometimes (e.g. a 'pushing volume' as opposed to 100 individually rotating, motor-controlled rollers).
Well, the problem is that I don't need nor desire physical weakness, but not infinite mass. I'm not sure what you mean by "pushing volume," is it, like, an invisible entity that pushes the objects in lieu of rotating rollers?

Thanks for the input. I'm gonna try just making dynamic entities that aren't affected by gravity but have a 20:1 mass ratio or so (cause that's how real-life machines work, but with a far higher ratio), and if that doesn't work I'll start playing with motors and constraints. Being that machines are activated fairly often and have a rather specific path to adhere to, I'm thinking even if they are displaced by a few tenths, they'll correct themselves next time they're activated, but we'll see. It could be kind of interesting to apply some springs or something to make buckets and other machinery bounce slightly as if they were absorbing shock. Either way, I think I've got enough to go on, and I'll be sure to ask if I have questions about motors and constraints. Thanks!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Improving collision between dynamic and kinematic entiti

Post by Norbo »

Well, the problem is that I don't need nor desire physical weakness, but not infinite mass.
Be careful here- anything which does not have the necessary weakness will run into the exact same issues as infinite mass. The problem is that the solver cannot find a solution in the time allowed. Kinematics in an impossible configuration are the worst case, but an extremely strong machine can have a similar effect (since you probably don't want to run the needed number of iterations to solve it fully).

For example, imagine a door which opens and closes to let boxes pass through. If it closes and there's a box in the way, both a kinematic door and an extremely forceful dynamic door (either extremely high mass or controlled by a very strong motor) will crush the obstructing box. The desired result in that case is to instead behave like a reasonable door in real life which stops when it hits an obstruction. That's the kind of 'weakness' I mean; not a soggy waffle. Imagine the difference in strength between an automatic door to a store (appropriately 'weak' constraint) and a pneumatic metal-shaping press (rigid constraints/kinematics).
I'm not sure what you mean by "pushing volume," is it, like, an invisible entity that pushes the objects in lieu of rotating rollers?
By pushing volume, I mean anything which pushes objects directly rather than using actual entities to do the job. Like picking all objects within a bounding box and pushing them to the right. This type of thing could replace individual rollers and a few other simple machines.

A literal 'pushing volume' could be made with the space.BroadPhase.QueryAccelerator.GetEntries method to find nearby boxes. Another option would be to push all objects that are touching an object, causing a conveyor belt effect. Both of these, and many other options accomplishing similar effects, would be faster than a bunch of individually motorized rollers.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

Alright, thanks.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

I've been working on this for a few days now, and I can't get it to work right. At first I was thinking I'd attach a SingleEntityLinearMotor and a SingleEntityAngularMotor to each entity I needed to move, and then set the goals of them based on my needs. Unfortunately, transitioning from QuaternionSlerpCurves to motors isn't easy, so I thought I'd keep things as they were and instead just make motors that constrict the entities when they're stationary. This, however, causes problems with setting and unsetting the activity of the motors at the right times. Can you recommend anything? I have machines that specifically translate, ones that rotate (sometimes with an offset), and then various machines based on the concept of keyframes that are a combination of the two. Pretty much it boils down to not being able to figure out a good way to determine when the machine is at its endpoint. Using motors exclusively as a movement device, the machine slows down as it reaches the goal and never exactly gets there. Using velocity as a movement device and motors as a constriction device runs into the problem of not always going far enough (and it doesn't quite work as well as the other method). Also, I can't find a way to make the motors strong enough to resist pushing by the boxes but not strong enough to crush them... What was the mass ratio at which collision becomes squishy?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Improving collision between dynamic and kinematic entiti

Post by Norbo »

Unfortunately, transitioning from QuaternionSlerpCurves to motors isn't easy, so I thought I'd keep things as they were and instead just make motors that constrict the entities when they're stationary. This, however, causes problems with setting and unsetting the activity of the motors at the right times. Can you recommend anything?
Note that the EntityRotator and EntityMover use motors internally when controlling dynamic entities. If you'd like to use curves with them, they will handle the motors for you. There doesn't need to be a transition once an endpoint is reached.

Using motors exclusively as a movement device, the machine slows down as it reaches the goal and never exactly gets there.
This sounds like the motor is overdamped. Pushing the motor closer to critical damping may help.

It is true that the motor may not achieve the final goal due to numerical differences, though. However, the difference will very rapidly drop to inconsequential levels in a well-tuned motor.
Also, I can't find a way to make the motors strong enough to resist pushing by the boxes but not strong enough to crush them... What was the mass ratio at which collision becomes squishy?
It is not strictly a mass ratio issue. Mass ratios are just one case where the core issue becomes noticeable. Giant forces being pushed through insubstantial nodes will make solving difficult regardless of the cause. So, an extremely strong motor acting upon two similarly light objects can still cause crushing.

So, here's an example:

Code: Select all

            //Make an immobile barrier for a platform to rise into, attempting to crush a poor box.
            Box ceiling = new Box(new Vector3(0, 20, 0), 50, 1, 50);
            Space.Add(ceiling);

            //Create a platform to drop another box onto.  This platform will move up, eventually smashing into the ceiling.
            Box movingPlatform = new Box(new Vector3(0, 0, 0), 5, 1, 5, 10);
            Space.Add(movingPlatform);

            var angularMotor = new SingleEntityAngularMotor(movingPlatform);
            //This defaults to velocity motor.  Switch it to servo to keep the orientation steady.
            //(Could also set the inertia tensor inverse to zeros for the purposes of this demo.)
            angularMotor.Settings.Mode = MotorMode.Servomechanism;
            Space.Add(angularMotor);

            var linearMotor = new SingleEntityLinearMotor(movingPlatform, movingPlatform.Position);
            //This motor propels the moving platform ceilingward.
            linearMotor.Settings.VelocityMotor.GoalVelocity = new Vector3(0, 2, 0);
            Space.Add(linearMotor);


            //Drop this box onto the moving platform.
            Box freeBox = new Box(new Vector3(0, 10, 0), 1, 1, 1, 10);
            Space.Add(freeBox);
In the above, the box will fall on the platform and the platform will hardly register the event thanks to its near-rigid control (the platform is very capable of resisting the motion). Despite that rigidty, the box does not get crushed.

However, if the freeBox's mass is changed to 0.1f instead of 10, it will get completely crushed. It is a 'weak link' in the conceptual dependency graph- an extremely light object between a completely immobile object and a tightly controlled, heavier object. This is nearly the worst case (second only to being crushed by a second kinematic entity).

Now, if you also change the platform's mass to 0.1f so that both the free box and the constrained platform have the same mass, you'll notice the the box does not get crushed so completely, but it's still struggling. So it's not just mass ratios at play here. What did change is the mass relative to the strength of the constraint. The constraint is 100x stronger relative to the mass of the objects, in other words.

So, a final change- what if the free box and the moving platform both have 0.1f mass as before, but now the linear constraint is weakened by 100x?

Code: Select all

            //Make an immobile barrier for a platform to rise into, attempting to crush a poor box.
            Box ceiling = new Box(new Vector3(0, 20, 0), 50, 1, 50);
            Space.Add(ceiling);

            //Create a platform to drop another box onto.  This platform will move up, eventually smashing into the ceiling.
            //Note the low mass.
            Box movingPlatform = new Box(new Vector3(0, 0, 0), 5, 1, 5, .1f);
            Space.Add(movingPlatform);

            var angularMotor = new SingleEntityAngularMotor(movingPlatform);
            //This defaults to velocity motor.  Switch it to servo to keep the orientation steady.
            //(Could also set the inertia tensor inverse to zeros for the purposes of this demo.)
            angularMotor.Settings.Mode = MotorMode.Servomechanism;
            Space.Add(angularMotor);

            var linearMotor = new SingleEntityLinearMotor(movingPlatform, movingPlatform.Position);
            //This motor propels the moving platform ceilingward.
            linearMotor.Settings.VelocityMotor.GoalVelocity = new Vector3(0, 2, 0);
            //Weaken the constraint.
            linearMotor.Settings.VelocityMotor.Softness *= 100;
            Space.Add(linearMotor);


            //Drop this box onto the moving platform.
            //Note the low mass.
            Box freeBox = new Box(new Vector3(0, 10, 0), 1, 1, 1, .1f);
            Space.Add(freeBox);
Suddenly, it's back to being very similar to the original setup. The platform is quite capable of resisting the motion without crushing the object.

For servo constraints which target a specific goal, the equivalent to increasing the softness would be decreasing the stiffness and damping coefficients. (In fact, the softness of a velocity constraint is directly equal 1 / damping constant.)

Given a good configuration of these stiffness and damping coefficients, the objects should resist motion without crushing anything.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Improving collision between dynamic and kinematic entiti

Post by Norbo »

I should also mention that servo-mode constraints have a motor.Settings.Servo.BaseCorrectiveVelocity in addition to the usual spring-like behaviors that you can use to specify an arbitrary base speed of correction. This is another way to mitigate convergence times.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

Mkay. I'll take note of this and see if I can't get it to work... I'll also look at EntityMover and EntityRotator again and see if I can't get it to work.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

So, I got the rotation to work except for one thing... The bucket I was using as an example earlier is the one I'm using for testing, and the base part rotates fine but the glass part just goes beserk when I activate the machine. They use the same code... They just set the goal of their SingleEntityAngularMotors to curve.Evaluate(pathTime). Got any idea why this would produce such wildly different behavior?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Improving collision between dynamic and kinematic entiti

Post by Norbo »

Nothing jumps to mind, sorry. The usual recommendations about isolation and reproduction apply.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

Alright. Must be something obvious, then.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

By the way, Entity.AngularDamping has a typo... Says "continuong" if I'm not mistaken.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Improving collision between dynamic and kinematic entiti

Post by Norbo »

Noted and fixed for the next versiong. :)
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

Norbo wrote:Noted and fixed for the next versiong. :)
You're a funny man.

Anyway, I pretty much got everything to work, but I need some help tweaking the SingleEntityLinearMotors. They tend to fling boxes, because they move very rapidly. I've come to the conclusion the stiffness and damping have some sort of ratio, so I tried dividing each constant by an arbitrary number (up to 30), but it didn't seem to help. I set the MaxCorrectiveVelocity to distance.Length() / time, but that didn't really help either. I think the mass of my boxes is 1, and the machines are 10, or something like that... What would be good numbers for the stiffness and damping?
Post Reply