Rotating parts of compound body

Discuss any questions about BEPUphysics or problems encountered.
tomweiland
Posts: 99
Joined: Wed May 08, 2019 12:17 am

Re: Rotating parts of compound body

Post by tomweiland » Tue Jan 14, 2020 9:56 pm

Norbo wrote:
Tue Jan 14, 2020 9:38 pm
It could also be that the goal position of the capstan is partially embedded in the ship.
I've double checked, and based on the capstan's position and dimensions, it shouldn't be embedded in the ship...it should actually be hovering about 0.1 units above the deck :?

tomweiland
Posts: 99
Joined: Wed May 08, 2019 12:17 am

Re: Rotating parts of compound body

Post by tomweiland » Tue Jan 14, 2020 11:25 pm

I just implemented the inertia scaling like you said, with my target mass being 500. Unfortunately, the ship is still spinning...

Code: Select all

compoundBuilder.BuildDynamicCompound(out Buffer<CompoundChild> _colliderChildren, out BodyInertia _shipInertia);
float _inverseInertiaScale = 1f / (500f * _shipInertia.InverseMass);
_shipInertia.InverseMass *= _inverseInertiaScale;
Symmetric3x3.Scale(_shipInertia.InverseInertiaTensor, _inverseInertiaScale, out _shipInertia.InverseInertiaTensor);
ship.inertia = _shipInertia;
ship.shape = World.physics.Simulation.Shapes.Add(new BigCompound(_colliderChildren, compoundBuilder.Shapes, World.physics.BufferPool));

Norbo
Site Admin
Posts: 4903
Joined: Tue Jul 04, 2006 4:45 am

Re: Rotating parts of compound body

Post by Norbo » Tue Jan 14, 2020 11:37 pm

Are the child shape weights fairly uniform, so that the inertia tensor is reasonable for the actual size of the boat?

As always, the quickest way for me to figure out this kind of issue would be to reproduce it in the demos with a stripped down example for me to look at.

tomweiland
Posts: 99
Joined: Wed May 08, 2019 12:17 am

Re: Rotating parts of compound body

Post by tomweiland » Wed Jan 15, 2020 12:49 am

Norbo wrote:
Tue Jan 14, 2020 11:37 pm
Are the child shape weights fairly uniform, so that the inertia tensor is reasonable for the actual size of the boat?
I haven't changed the weights, so that could be the issue. Just to clarify, do the weights actually affect the final mass of the compound (if I'm scaling the inertia), or do they only make a difference relative to each other? Basically, can I just give each child shape a weight of 1 and then scale the inertia to give the compound a mass of 500, even if the child shape weights don't add up to 500?

tomweiland
Posts: 99
Joined: Wed May 08, 2019 12:17 am

Re: Rotating parts of compound body

Post by tomweiland » Wed Jan 15, 2020 1:42 am

So I've adjusted the weights—each child shape now has a weight of 1, with the inertia still being scaled as before. The spinning has stopped, and the ship still seems to behave as if it had a mass of 500.

The capstan is now held in place in the desired position, however, I can simply walk through it as if it weren't there. The character controller seems to just not collide with it...any idea what might be causing this?

I'm also a little concerned about gravity in this situation—since the constraint is holding the capstan collider in position slightly above the deck, is it possible for the force of gravity to accumulate (because the capstan is technically always falling) to a point where the constraint won't be strong enough anymore—or maybe the ship will start getting pushed around, despite its much larger mass?

Norbo
Site Admin
Posts: 4903
Joined: Tue Jul 04, 2006 4:45 am

Re: Rotating parts of compound body

Post by Norbo » Wed Jan 15, 2020 10:46 pm

Just to clarify, do the weights actually affect the final mass of the compound (if I'm scaling the inertia), or do they only make a difference relative to each other? Basically, can I just give each child shape a weight of 1 and then scale the inertia to give the compound a mass of 500, even if the child shape weights don't add up to 500?
Yup, if the final inertia gets scaled to match a target mass, then the weights are only meaningful in a relative sense.
The capstan is now held in place in the desired position, however, I can simply walk through it as if it weren't there. The character controller seems to just not collide with it...any idea what might be causing this?
First guess would be some kind of collision filter going haywire.

If it's the demos dynamic character controller, it may be worth confirming that its mass/maximum horizontal force aren't so huge that it can just shove the capstan around at the hinge's current stiffness settings. I'd be a little surprised if that was it, since it probably would have caused issues with the boat before.

Could happen if the capstan was just extremely light compared to the character, too.
I'm also a little concerned about gravity in this situation—since the constraint is holding the capstan collider in position slightly above the deck, is it possible for the force of gravity to accumulate (because the capstan is technically always falling) to a point where the constraint won't be strong enough anymore—or maybe the ship will start getting pushed around, despite its much larger mass?
Naw, it'll be fine- if the constraint wasn't strong to resist gravity, it'd be immediately visible. Constraints don't just force bodies into position, they actually solve for the required impulses necessary to reach the constraint goal and apply those impulses to the connected bodies continuously. In other words, there's no hidden state accumulating in the background.

tomweiland
Posts: 99
Joined: Wed May 08, 2019 12:17 am

Re: Rotating parts of compound body

Post by tomweiland » Thu Jan 16, 2020 12:33 am

Norbo wrote:
Wed Jan 15, 2020 10:46 pm
First guess would be some kind of collision filter going haywire.
I haven't set anything up with collision filtering (besides removing cannonballs from the simulation when they hit another body)—how can I find out if this is the culprit?
Norbo wrote:
Wed Jan 15, 2020 10:46 pm
If it's the demos dynamic character controller, it may be worth confirming that its mass/maximum horizontal force aren't so huge that it can just shove the capstan around at the hinge's current stiffness settings. I'd be a little surprised if that was it, since it probably would have caused issues with the boat before.
It is the demos controller, but I don't think this is the issue because the capstan appears to stay in the correct position. Unless the controller is somehow walking into the capstan body and therefore doesn't collide...
Norbo wrote:
Wed Jan 15, 2020 10:46 pm
Could happen if the capstan was just extremely light compared to the character, too.
The capstan has a mass of 1 while the player has a mass of 10.

Norbo
Site Admin
Posts: 4903
Joined: Tue Jul 04, 2006 4:45 am

Re: Rotating parts of compound body

Post by Norbo » Thu Jan 16, 2020 12:50 am

I haven't set anything up with collision filtering (besides removing cannonballs from the simulation when they hit another body)—how can I find out if this is the culprit?
You would have had to implement some form of collision filtering in the INarrowphaseCallbacks by returning false from the relevant callbacks. There's nothing built in.
It is the demos controller, but I don't think this is the issue because the capstan appears to stay in the correct position. Unless the controller is somehow walking into the capstan body and therefore doesn't collide...
If the capstan is represented by a convex primitive, being inside will still generate contacts.
The capstan has a mass of 1 while the player has a mass of 10.
Depending on the hinge stiffness and the character's movement force, it's conceivable that it could shove the capstan a bit, but this isn't a good explanation if the capstan isn't actually getting shoved.

tomweiland
Posts: 99
Joined: Wed May 08, 2019 12:17 am

Re: Rotating parts of compound body

Post by tomweiland » Thu Jan 16, 2020 2:24 am

Norbo wrote:
Thu Jan 16, 2020 12:50 am
You would have had to implement some form of collision filtering in the INarrowphaseCallbacks by returning false from the relevant callbacks. There's nothing built in.
I guess I should clarify: I haven't done anything custom—I simply copied the NarrowphaseCallbacks from one of the demos (can't remember which one though). Considering I haven't added anything, could this still be the issue? It doesn't make sense to me that collisions would work, except for this particular collision...
Norbo wrote:
Thu Jan 16, 2020 12:50 am
If the capstan is represented by a convex primitive, being inside will still generate contacts.
It's a cylinder.

Norbo
Site Admin
Posts: 4903
Joined: Tue Jul 04, 2006 4:45 am

Re: Rotating parts of compound body

Post by Norbo » Thu Jan 16, 2020 10:23 pm

Considering I haven't added anything, could this still be the issue? It doesn't make sense to me that collisions would work, except for this particular collision...
Some demos callbacks have collision filtering, some don't. If the callbacks all return only true, you can be sure that it's unrelated.

Not much to go on right now- standard recommendation would be to try to reproduce the behavior in the demos so I can look at it.

tomweiland
Posts: 99
Joined: Wed May 08, 2019 12:17 am

Re: Rotating parts of compound body

Post by tomweiland » Fri Jan 17, 2020 12:09 am

Norbo wrote:
Thu Jan 16, 2020 10:23 pm
Some demos callbacks have collision filtering, some don't. If the callbacks all return only true, you can be sure that it's unrelated.
I just checked and I'm using the NarrowPhaseCallbacks from the character demo—the only method that doesn't return true is this one:

Code: Select all

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool AllowContactGeneration(int workerIndex, CollidableReference a, CollidableReference b)
{
    if (b.Mobility != CollidableMobility.Static)
    {
        return SubgroupCollisionFilter.AllowCollision(properties[a.Handle].filter, properties[b.Handle].filter);
    }
    return a.Mobility == CollidableMobility.Dynamic || b.Mobility == CollidableMobility.Dynamic;
}
I'll do some more poking around and see if I can figure anything else out...if not, I'll try and reproduce it in a bare-bones project.

tomweiland
Posts: 99
Joined: Wed May 08, 2019 12:17 am

Re: Rotating parts of compound body

Post by tomweiland » Wed Jan 22, 2020 6:37 am

So after some more investigating, I've finally decided to give up and just try and reproduce it. Here's the reproduction in a relatively bare bones console app.

I did however notice that if I increase the capstan's mass from 1 to something like 10, the tornadoship makes a reappearance. I'm guessing that simply means more force is being applied to the ship in order to hold the capstan in place compared to when it had less mass. Since the waves cause the boat to tilt, the capstan moves out of place, and the correctional forces result in angular momentum.

To counter that I can obviously reduce the mass of the capstan (or increase ship mass...is there any sort of limit I shouldn't go above?), but once the player can actually collide with it, he'll be able to push it around much easier than if it had more mass, which in turn could also cause wonky/undesirable physics behavior, couldn't it? I'm picturing a sort of scenario where the player can walk into the capstan and that consequentially pulls the boat around in some way, sort of like making yourself fly/levitate by pulling up on the hem of your own shirt or something, just horizontally. Is this at all a possibility (does what I'm trying to say even make sense)?

Norbo
Site Admin
Posts: 4903
Joined: Tue Jul 04, 2006 4:45 am

Re: Rotating parts of compound body

Post by Norbo » Wed Jan 22, 2020 11:36 pm

Here's the reproduction in a relatively bare bones console app.
The collision is being filtered out. SubgroupCollisionFilters are being used in AllowContactGeneration, but the filters are never assigned to anything. The value they happen to have causes the callback to return false.
I did however notice that if I increase the capstan's mass from 1 to something like 10, the tornadoship makes a reappearance.
I don't see that happening when I increase the mass in the repro, regardless of how much violence I subject it to (I pulled it into the demos for a visual). Even scaling the inertia down by a factor of 100 (inverse up by 100) doesn't cause any tornadoship-like behavior, just the expected wonkiness of a tank with the inertia of a shrew. Even setting the hinge offset such that the capstan is forced inside the box doesn't cause it in this case.
I'm picturing a sort of scenario where the player can walk into the capstan and that consequentially pulls the boat around in some way, sort of like making yourself fly/levitate by pulling up on the hem of your own shirt or something, just horizontally. Is this at all a possibility (does what I'm trying to say even make sense)?
The solver tries to conserve momentum; every force has an equal and opposite reaction. Provided the solver has time to find a reasonably good solution, it will not introduce extra momentum. In order to go tornadoship or fly into the sky or anything like that, extra nonphysical momentum is required.

So no, that kind of thing will not happen- so long as the solver has time to work. And in this case, provided a configuration similar to the repro you gave, it looks like it works fine.

For what it's worth, a timestep duration of 1/40f is a bit long for difficult simulations (though it works fine in the repro). You may want to try stepping the simulation more frequently with a shorter duration, or just using solver substepping:

Code: Select all

Simulation = Simulation.Create(BufferPool, new ReproNarrowphaseCallbacks() { characters = Characters, properties = BodyProperties }, new PoseIntegratorCallback(gravity), timestepper: new SubsteppingTimestepper(2), solverIterationCount: 4);
When using substepping, you can usually use lower solver iteration counts, hence 4 instead of the default of 8. More information about substepping can be found in the stability tips documentation: https://github.com/bepu/bepuphysics2/bl ... ityTips.md

But again, the repro as-is appears to work fine. There might be something else wonky going on in the main project causing tornadoship or other instability.

tomweiland
Posts: 99
Joined: Wed May 08, 2019 12:17 am

Re: Rotating parts of compound body

Post by tomweiland » Fri Jan 24, 2020 12:01 am

Norbo wrote:
Wed Jan 22, 2020 11:36 pm
The collision is being filtered out. SubgroupCollisionFilters are being used in AllowContactGeneration, but the filters are never assigned to anything. The value they happen to have causes the callback to return false.
So how can I fix this? Is there a demo I can look at to see what I should be assigning the filters to?
Norbo wrote:
Wed Jan 22, 2020 11:36 pm
I don't see that happening when I increase the mass in the repro, regardless of how much violence I subject it to (I pulled it into the demos for a visual). Even scaling the inertia down by a factor of 100 (inverse up by 100) doesn't cause any tornadoship-like behavior, just the expected wonkiness of a tank with the inertia of a shrew. Even setting the hinge offset such that the capstan is forced inside the box doesn't cause it in this case.
That's really strange...so there's no way tornadoship should or could be occurring? I figured it might have something to do with the boat getting pulled into the side of a wave by the constraint—then the buoyancy force increases due to it being further underwater, causing rotational acceleration. Now I'm not so sure about that :?
Norbo wrote:
Wed Jan 22, 2020 11:36 pm
For what it's worth, a timestep duration of 1/40f is a bit long for difficult simulations (though it works fine in the repro). You may want to try stepping the simulation more frequently with a shorter duration, or just using solver substepping:
What would be a timestep duration of ideal length? I'm a little hesitant to (at least substantially) increase this as I want to keep it consistent with my server's tickrate, and more importantly, the effect on CPU usage would be a lot bigger than what's initially obvious because my server is constantly rewinding to the oldest unaccounted-for input and resimulating to the present—meaning there'd be more ticks for the server to resimulate each time.

If I were to use substepping, how would that fit into the whole rewinding part? Would there be extra stuff I'd need to set up & watch out for, or would it work as is?
Norbo wrote:
Wed Jan 22, 2020 11:36 pm
But again, the repro as-is appears to work fine. There might be something else wonky going on in the main project causing tornadoship or other instability.
This really concerns me...the only (intentional) physics differences between the main project's and the repro's ships is that the main project's ship isn't a box, isn't affected by gravity, and has my buoyancy code on it (which handles gravity).

My buoyancy system works by checking 6 points throughout the ship to see whether they're above or below the water surface, and then applying either an upward or downward force to the ship at that point, which ends up rotating and positioning the ship in a way where it looks like it's floating.

Norbo
Site Admin
Posts: 4903
Joined: Tue Jul 04, 2006 4:45 am

Re: Rotating parts of compound body

Post by Norbo » Fri Jan 24, 2020 12:39 am

So how can I fix this? Is there a demo I can look at to see what I should be assigning the filters to?
The CarDemo (through the SimpleCar), RagdollDemo, and TankDemo (through the Tank) all make use of SubgroupCollisionFilter.

The idea is that a body can belong to a group, and within the context of that group, there is a 'subgroup membership' mask and 'collides with' mask. If two bodies are in the same group and the 'membership mask' of one body overlaps with the 'collides with' mask of the other body, then they'll collide. They'll also collide if they are in different groups.

It's not intended to be a fully general solution to all collision filtering needs- the demos just use it to stop car wheels from colliding with the car body, or connected body parts in a ragdoll from colliding with each other and such. It's assumed that the user will create whatever custom filtering is needed for their own application, if any.

If you don't need that kind of functionality, you can just remove the filters and the relevant part of the callback that uses them.
That's really strange...so there's no way tornadoship should or could be occurring?
Under normal circumstances, it shouldn't happen, right.

If a constraint configuration is sufficiently difficult that the solver can't reach a satisfactory solution, surplus momentum can appear and can cause things like tornadoship, but I couldn't get such behavior to happen in the repro with any reasonable configuration. That makes sense- usually those sorts of convergence failures require a significantly more complex (or ill-conditioned) constraint system, or extremely restricted solver time (very few iterations, very long timestep duration).
What would be a timestep duration of ideal length?
Infinitesimal! :P Alas, computers aren't infinitely fast.

There's no ideal for all simulation, other than 'the shortest you can afford'. A rule of thumb is that you shouldn't give a constraint a frequency higher than about half your update rate. In other words, at 40hz, the frequency passed to SpringSettings shouldn't be higher than 20. Sometimes it's okay to go higher, especially if there are no feedback loops, and sometimes you have to go lower (very strong feedback loops). The frequency of a constraint is how fast it will try to oscillate in isolation, so frequencies that are high relative to the update rate can become impossible to represent by the integrator and things have a tendency to become unstable. (academic sidenote: implicit integrators can handle higher stiffnesses without exploding, although they do so by effectively damping away all the unrepresentable motion.)
If I were to use substepping, how would that fit into the whole rewinding part? Would there be extra stuff I'd need to set up & watch out for, or would it work as is?
Almost no changes- if you wanted to use the brute force 'call timestep more often, with shorter timestep duration', you can just replace the single call with multiple and you're done. Similarly, for substepping, you just call Create with the appropriate parameters and you're done. Don't have to step other game logic more frequently or anything.

The only subtlety is that any custom logic you want to run on a per-physics-step or per-substep basis would need to be scooted around accordingly. The timesteppers expose callbacks for that. For stuff like buoyancy, you can almost certainly ignore this and just apply it at the external tick frequency.
This really concerns me...the only (intentional) physics differences between the main project's and the repro's ships is that the main project's ship isn't a box, isn't affected by gravity, and has my buoyancy code on it (which handles gravity).
As always, if you can reproduce the behavior in a minimal repro, I can take a look and probably diagnose it immediately.

Post Reply