oscillation caused by soft objects

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
yanbo2u
Posts: 21
Joined: Sun Oct 04, 2015 4:41 pm

oscillation caused by soft objects

Post by yanbo2u »

i have a link made by Boxes. they are connected by revolute joints.

the problem is that the link oscillates by itself, and eventually disconnected like explosion all over the world.

I tried to increase the update rate. It does get better, but still oscillates given enough time.

I think it is caused by the softness of the Box entities (for collision checking and dynamics).

Is there any solution?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: oscillation caused by soft objects

Post by Norbo »

Oscillation and instability are typically caused by a system of constraints being too hard to solve. Softness generally makes the system easier to solve, so I don't think softness is a cause.

It sounds like the constraints may be configured in a way that causes them to 'fight' each other. There may also be other issues, like extremely long lever arms relative to object inertia.

I would recommend reproducing the issue in a BEPUphysicsDemos demo and then copying the resulting code for me to look at.
yanbo2u
Posts: 21
Joined: Sun Oct 04, 2015 4:41 pm

Re: oscillation caused by soft objects

Post by yanbo2u »

Sorry, I should have been more clear. Here is a sample of code of my object system. It spontaneously oscillates.

Code: Select all

            float L = 0.5f;
            float H = 0.1f;
            float W = 0.1f;
            float mass = 0.1f;

            Vector3 center = new Vector3(0,5,0);
            Box box0 = new Box(center, L, H, W, mass);
            AttachWithSkin(game, box0, CubeModel);
            space.Add(box0);

            Vector3 v_1 = new Vector3(0, - H, 0);
            Box box1 = new Box(center + v_1, L, H, W, mass);
            AttachWithSkin(game, box1, CubeModel);
            space.Add(box1);

            Vector3 v_2 = new Vector3(0, -H - H, 0);
            Box box2 = new Box(center + v_2, L, H, W, mass);
            AttachWithSkin(game, box2, CubeModel);
            space.Add(box2);

            Vector3 v_3 = new Vector3(0, -H - H - H, 0);
            Box box3 = new Box(center + v_3, L, H, W, mass);
            AttachWithSkin(game, box3, CubeModel);
            space.Add(box3);

            RevoluteJoint j0 = new RevoluteJoint(ground, box0, center, Vector3.UnitX);
            space.Add(j0);
            Vector3 v_j1 = new Vector3(L/2, -H/2, 0);
            RevoluteJoint j1 = new RevoluteJoint(box0, box1, center + v_j1, Vector3.UnitZ);
            space.Add(j1);
            Vector3 v_j2 = new Vector3(-L, -H, 0);
            RevoluteJoint j2 = new RevoluteJoint(box1, box2, center + v_j1 + v_j2, Vector3.UnitZ);
            space.Add(j2);
            Vector3 v_j3 = new Vector3(L, -H, 0);
            RevoluteJoint j3 = new RevoluteJoint(box2, box3, center + v_j1 + v_j2 + v_j3, Vector3.UnitZ);
            space.Add(j3);

            RevoluteMotor m0 = new RevoluteMotor(ground, box0, Vector3.UnitX);
            m0.Settings.Mode = MotorMode.Servomechanism;
            space.Add(m0);
yanbo2u
Posts: 21
Joined: Sun Oct 04, 2015 4:41 pm

Re: oscillation caused by soft objects

Post by yanbo2u »

in fact, I found a temporary solution to my case. But it is not general.

If I simply increase W to be 10 times as before, there is little oscillation.

This gives me an idea. I add 4 additional Boxes. Each of them is 10 times wide as before. And I weld each of the new box to the corresponding old box. Collision is ignored between each pair of new and old boxes. However, I also have to ignore collisions between additional boxes and every other object is the world. This a pain in the eye.

So my new question is that is there any way of introducing a group of entities such that collision only happens within this group? In other words, no collision happens between an object in the group and an object outside this group.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: oscillation caused by soft objects

Post by Norbo »

Here's a few options (including a couple I believe you already tried for completeness):
1) Constraints currently early-out on low impulses as an optimization. Very light objects early out in the solver faster. Disable this behavior by setting SolverSettings.DefaultMinimumImpulse = 0 or work around it by increasing object mass. (This 'feature' is going away in v2.0.0.)

2) This constraint system is pretty hard to solve. Softening the involved angular constraints should make it easier. Reduce the stiffness more than the damping to make it less prone to oscillation.

3) Instead of actually increasing the size of the chain elements, increase their inertia tensor directly along certain axes by scaling up the desired rows of the box.LocalInertiaTensor. In this case, scaling up Right and Up would help.

4) The longer a chain of objects is, the more difficult it is to solve. If you know that one end will typically be the 'root' of the chain, you can increase the mass of the boxes near the root. This is related to the 'mass ratio' problem- a very heavy object sitting on top of a light object will tend to be unstable, but a light object sitting on a heavy object is perfectly stable.

5) Increase the Space.Solver.IterationLimit.

6) Decrease the Space.TimeStepSettings.TimeStepDuration and update more frequently.

Here's an example using all of the above:

Code: Select all

            float L = 0.5f;
            float H = 0.1f;
            float W = 0.1f;
            float mass = .1f;

            //Disable the solver short circuiting. It does not play well with low mass objects.
            SolverSettings.DefaultMinimumImpulse = 0;

            //Increase the iteration limit.
            Space.Solver.IterationLimit = 20;

            List<Box> boxes = new List<Box>();
            var center = new Vector3(0, 5, 0);
            int boxCount = 10;
            for (int i = 0; i < boxCount; ++i)
            {
                //Note the mass; objects near the root are much heavier.
                Box box = new Box(center + new Vector3(0, -H * i, 0), L, H, W, mass * (boxCount - i));
                boxes.Add(box);
                Space.Add(box);

                //Scale up the inertia of the constrained axes.
                const float inertiaMultiplier = 2f;
                var localInertia = box.LocalInertiaTensor;
                localInertia.Right *= inertiaMultiplier;
                localInertia.Up *= inertiaMultiplier;
                box.LocalInertiaTensor = localInertia;

            }

            var j0 = new WeldJoint(null, boxes[0], boxes[0].Position);
            j0.NoRotationJoint.SpringSettings.Stiffness *= 0.01f;
            j0.NoRotationJoint.SpringSettings.Damping *= 0.05f;
            Space.Add(j0);
            for (int i = 0; i < boxes.Count - 1; ++i)
            {
                var offset = new Vector3(L * ((i & 1) == 0 ? 0.5f : -0.5f), -H / 2, 0);
                var joint = new RevoluteJoint(boxes[i], boxes[i + 1], boxes[i].Position + offset, Vector3.UnitZ);

                //Reduce constraint stiffness more than damping to help avoid oscillation.
                joint.AngularJoint.SpringSettings.Stiffness *= 0.003f;
                joint.AngularJoint.SpringSettings.Damping *= 0.01f;

                Space.Add(joint);
            }

            //Reduce the duration of the time step (and update more frequently to compensate).
            Space.TimeStepSettings.TimeStepDuration = 1 / 120f;
Generally, you won't need to use all of these at once. For example, pushing the iteration limit up or the time step duration down can eliminate the need for some of the other options.
So my new question is that is there any way of introducing a group of entities such that collision only happens within this group? In other words, no collision happens between an object in the group and an object outside this group.
Yup, CollisionGroups. Check the documentation for more information and the CollisionFilteringDemo for an example.
Post Reply