Stability problem

Discuss any questions about BEPUphysics or problems encountered.
Cunick
Posts: 9
Joined: Tue Nov 20, 2007 9:33 pm

Stability problem

Post by Cunick »

Hello! I 've just started using your library and i am quite impressed with it. It is simple & powerful.

But i have trouble - the lot 'o cubes sample is freezing, and my simple program which physics is:

Code: Select all

 space = new Space();

            space.addEntity(PrimitiveToolbox.constructCubePhysConvexPolyhedron(1, new Vector3(5f, 5f, 5f), 1));
            space.addEntity(PrimitiveToolbox.constructCubePhysConvexPolyhedron(1, new Vector3(5f, 8f, 5f), 1));
           space.addEntity(PrimitiveToolbox.constructCubePhysConvexPolyhedron(1, new Vector3(5f, 47f, 5f), 1));
        //    space.addEntity(PrimitiveToolbox.constructCubePhysConvexPolyhedron(1, new Vector3(5f, 21f, 5f), 1));
           
                
            for (int i = 0; i <= 10; i++)
                for(int j = 0; j <= 10; j++)
            {
                     space.addEntity(PrimitiveToolbox.constructCubeStaticConvexPolyhedron(1, new Vector3( i, 0,  j)));

            }

            space.gravity = new Vector3(0, -9.81f, 0f); //Ileft unset, the default value is (0,0,0).
            space.timeScale = 0.5f; //If left unset, the default value is 1.
            space.iterations = 5; //If left unset, the default value is 5. 
It freezes when the third cube lands on two previous. Can you help me to solve this problem?
Cunick
Posts: 9
Joined: Tue Nov 20, 2007 9:33 pm

Get full body position

Post by Cunick »

A have a function for drawing model and using it with you library so:

Code: Select all

           DrawModel(cubeModel, Matrix.CreateScale(2f) * Matrix.CreateTranslation(space.entities[0].getPosition()) * Matrix.CreateTranslation(new Vector3(0f, -0.5f, 0f)), view, projection, true);
But the model is just moving, not rotating and understand why - because it gets only information from position vector. So, how can i get a rotation?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Post by Norbo »

I ran the sample code provided, but I was unable to replicate a freeze. Are there any other adjustments to the simulation settings (gravity, timescale, external forces and such) outside of the code sample? Right now, my best guess as to why you might see a freeze is that the bottom cube gets wedged into a crevice between two static cubes composing the ground when the third cube slams into the top of the stack.

If it got wedged in this manner, it's possible that it would choose poor deseperation directions and continually jiggle back and forth. While the engine prevents infinite loops, this could cause a severe drop in FPS on a slower computer in the worst conditions, though not a freeze. Additionally, this kind of behavior should be replicable (albeit extremely rare).

Does the problem still occur if you use a ground which is a single large hexahedron, similar to the original simulation?

Code: Select all

space.addEntity(PrimitiveToolbox.constructHexahedronStaticConvexPolyhedron(10f, 1f, 10, new Vector3(0, -.5f, 0)));
The rotation of an entity can be obtained by using the (Entity).rotationMatrix field. Additionally, a quaternion which is used to calculate the rotationMatrix is accessible through the (Entity).rotation field.


Edit:
Come to think of it, is it possible that something outside of the physics is causing the freeze? Perhaps the custom display interacting with the engine?
Cunick
Posts: 9
Joined: Tue Nov 20, 2007 9:33 pm

Post by Cunick »

Thanks for fast reply :)
1)When a set
space.addEntity(PrimitiveToolbox.constructCubePhysConvexPolyhedron(1, new Vector3(5f, 30f, 5f), 1));
i.e. y parameter 30 instead of 47 it becomes working fine. If you want i can publish full code of my program.

2)Ok, big thanks.
Cunick
Posts: 9
Joined: Tue Nov 20, 2007 9:33 pm

Post by Cunick »

And i found that if i ran pfrogram in debug mode(f5) - the everything is ok, and else (ctl-f5) freezes occurs;
Cunick
Posts: 9
Joined: Tue Nov 20, 2007 9:33 pm

Post by Cunick »

#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using BEPUphysics;
#endregion

namespace WindowsGame1
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
ContentManager content;
//variables for counting fps
private float fpscounter;
private float updateIntervalTime = 1.0f;
private float timeFromLastUpdate = 0.0f;
private float framecounter = 0;
List<DisplayObject> displayObjects = new List<DisplayObject>();
Space space;
private Matrix projection;
private Matrix view;

public Game1()
{
graphics = new GraphicsDeviceManager(this);
content = new ContentManager(Services);
}
private void DrawModel(Model model, Matrix world, Matrix view, Matrix projection, bool light)
{
Matrix[] transforms_parts_model = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms_parts_model);
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
if (light)
{
effect.LightingEnabled = true;
effect.EnableDefaultLighting();
effect.TextureEnabled = true;
effect.DiffuseColor = new Vector3(1, 1, 1);
effect.DirectionalLight0.Enabled = true;
effect.DirectionalLight1.Enabled = true;
effect.DirectionalLight2.Enabled = true;
}
else
{
effect.LightingEnabled = false;
effect.DiffuseColor = Vector3.Zero;
effect.DirectionalLight0.Enabled = false;
effect.DirectionalLight1.Enabled = false;
effect.DirectionalLight2.Enabled = false;
effect.TextureEnabled = false;
}
effect.View = view;
effect.Projection = projection;
effect.World = transforms_parts_model[mesh.ParentBone.Index] * world;
effect.CommitChanges();
}
mesh.Draw();
}
}
void DrawModelWithPhysics(Entity physObject, Model model, Matrix world, Matrix view, Matrix projection, bool light)
{
Matrix temp;
temp = Matrix.Transform(Matrix.CreateScale(2f), physObject.rotation) * Matrix.CreateTranslation(physObject.getPosition()) * Matrix.CreateTranslation(new Vector3(0f, -0.5f, 0f));
Matrix[] transforms_parts_model = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms_parts_model);
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
if (light)
{
effect.LightingEnabled = true;
effect.EnableDefaultLighting();
effect.TextureEnabled = true;
effect.DiffuseColor = new Vector3(1, 1, 1);
effect.DirectionalLight0.Enabled = true;
effect.DirectionalLight1.Enabled = true;
effect.DirectionalLight2.Enabled = true;
}
else
{
effect.LightingEnabled = false;
effect.DiffuseColor = Vector3.Zero;
effect.DirectionalLight0.Enabled = false;
effect.DirectionalLight1.Enabled = false;
effect.DirectionalLight2.Enabled = false;
effect.TextureEnabled = false;
}
effect.View = view;
effect.Projection = projection;
effect.World = transforms_parts_model[mesh.ParentBone.Index] * world * temp; ;
effect.CommitChanges();
}
mesh.Draw();
}
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
space = new Space();

space.addEntity(PrimitiveToolbox.constructCubePhysConvexPolyhedron(1, new Vector3(5f, 10f, 5f), 1));
space.addEntity(PrimitiveToolbox.constructCubePhysConvexPolyhedron(1, new Vector3(5f, 13f, 5f), 1));
space.addEntity(PrimitiveToolbox.constructCubePhysConvexPolyhedron(1, new Vector3(5f, 5f, 5f), 1));
space.addEntity(PrimitiveToolbox.constructCubeStaticConvexPolyhedron(15, new Vector3(7f, -7f, 7f)));
foreach (Entity e in space.entities)
{
if (e is ConvexPolyhedron)
{

}
}
space.gravity = new Vector3(0, -9.81f, 0f);
foreach (Entity e in space.entities)
{
if (e is ConvexPolyhedron)
displayObjects.Add(new DisplayPolyhedron((ConvexPolyhedron)e, graphics));
else if (e is Sphere)
displayObjects.Add(new DisplaySphere((Sphere)e, graphics));
else if (e is Cylinder)
displayObjects.Add(new DisplayCylinder((Cylinder)e, graphics));
else if (e is Cone)
displayObjects.Add(new DisplayCone((Cone)e, graphics));
else if (e is Triangle)
displayObjects.Add(new DisplayTriangle((Triangle)e, graphics));
}
base.Initialize();
}


/// <summary>
/// Load your graphics content. If loadAllContent is true, you should
/// load content from both ResourceManagementMode pools. Otherwise, just
/// load ResourceManagementMode.Manual content.
/// </summary>
/// <param name="loadAllContent">Which type of content to load.</param>
protected override void LoadGraphicsContent(bool loadAllContent)
{
if (loadAllContent)
{
// TODO: Load any ResourceManagementMode.Automatic content
}

// TODO: Load any ResourceManagementMode.Manual content
}


/// <summary>
/// Unload your graphics content. If unloadAllContent is true, you should
/// unload content from both ResourceManagementMode pools. Otherwise, just
/// unload ResourceManagementMode.Manual content. Manual content will get
/// Disposed by the GraphicsDevice during a Reset.
/// </summary>
/// <param name="unloadAllContent">Which type of content to unload.</param>
protected override void UnloadGraphicsContent(bool unloadAllContent)
{
if (unloadAllContent)
{
// TODO: Unload any ResourceManagementMode.Automatic content
content.Unload();
}

// TODO: Unload any ResourceManagementMode.Manual content
}


/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();

// TODO: Add your update logic here
space.update(gameTime);
base.Update(gameTime);
}


/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), (float)graphics.GraphicsDevice.Viewport.Width / (float)graphics.GraphicsDevice.Viewport.Height, .1f, 10000.0f);
view = Matrix.CreateLookAt(new Vector3(0, 2, 20), new Vector3(0, 2, 0), Vector3.Up);

graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
for (int k = 0; k < displayObjects.Count; k++)
{
displayObjects[k].draw(view, projection);
}
// TODO: Add your drawing code here
float elapsed_time = (float)gameTime.ElapsedRealTime.TotalSeconds;
framecounter++;
timeFromLastUpdate += elapsed_time;
if (timeFromLastUpdate > updateIntervalTime)
{
fpscounter = framecounter / timeFromLastUpdate;
Window.Title = "FPS: " + fpscounter.ToString();
framecounter = 0;
timeFromLastUpdate -= updateIntervalTime;
}
base.Draw(gameTime);
}
}
}
Cunick
Posts: 9
Joined: Tue Nov 20, 2007 9:33 pm

Post by Cunick »

I 've got a freezing problem on such sample. And in Debug mode it works brilliamt(but a bit laggy)
Cunick
Posts: 9
Joined: Tue Nov 20, 2007 9:33 pm

Post by Cunick »

And one more question - how can i get spheres stopped rolling on static cube (they are falling on it)? They have some rolling friction or not?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Post by Norbo »

Alright, I've gotten it to freeze with that set up and in non-debug mode. I'll try to figure out what's going on. Though with that one giant cube, it's apparent its not the wedging problem, and it isn't an infinite loop within the controller handling. This might take a bit of time. I can't think off the top of my head what would cause it to freeze in a release build but not in a debug build.

Because it acts like it's going through an infinite loop (CPU usage and such) I'm going through all the collision related functions and testing for excessive recursion. Maybe some initialization values are not set in the same manner under release mode, but I'm not sure about the specifics. It is apparently unrelated to the rendering code.

After further testing, I'm a little more worried. I can't find the cause after going through essentially every loop associated with the collision system, including those involved in the deep contact resolution system. None of them are executing according to my tests, nor are any updates occurring (after the freeze). I'm going to keep looking for anything I've missed, but right now what I'm seeing implies something a little more tricky.

I ran another test (the stress test demo, cut down to a 5-block base pyramid), and it doesn't even make it past initialization under the release/nondebug mode. There are no potentially infinite loops under these circumstances, leading me to believe it is something to do with the way it's being built and run.

For now, I've posted a question on MSDN about some possibilities with the build configuration, but I'll keep going through the engine code to see if I can identify a precise location where it is failing.

As for the spheres, you can add damping to the entity (linearDamping and angularDamping), but essentially the sphere is 'falling' onto the next contact point. I'll try to see what else I can do to prevent improper accelerations. You can also mess with the velocityClamping value of the space the objects reside in. This can lead to some ugly problems where the object stops moving during otherwise normal simulation, though.
Cunick
Posts: 9
Joined: Tue Nov 20, 2007 9:33 pm

Post by Cunick »

And i have found a new bug - sometimes csharp throws an exception with space.update() method - it says that it doesn't support nan(not a number parameter).

The saddest part of all of it story, that i need physics engine for program, that i need for course in my university, and deadline for submitting this program - is 27 november. Task is very simple - you have a plane and a hole near it. When you press key, some spheres, cubes etc. falls on a plane, and then some special object (bulldozer - i imitated it with rolling cylinder :) ) begin moving automatically and sweeps that objects in a hole. As you see, physics is very simple, but your engine is not working stable with cubes (when i replaced cubes with cylinders there are no more freezes). Can you any ideas of describing stable physiscs for such task?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Post by Norbo »

Under what conditions does the space.update() method throw a NaN exception?

Is there a stability issue (excessive jitter, falling through objects, etc) besides the fact that cubes freeze under a release build in certain circumstances? If not, using a debug build configuration should help- I cannot reproduce the freeze with the debug build.

That bit about the cylinders not freezing is interesting though. I'm going to start looking around to see if there are any variables in the PhysConvexPolyhedron that might be left uninstantiated or with different values in a start without debugging mode that aren't in a cylinder.
Cunick
Posts: 9
Joined: Tue Nov 20, 2007 9:33 pm

Post by Cunick »

1)It is hard to say, usually when rolling cylinder collides with three or four objects or when it have excesive speed. I 'll try to post some code tomorrow.
2)No, it is so random - sometimes cube is just in the air and system freezes.
And:
If not, using a debug build configuration should help- I cannot reproduce the freeze with the debug build.
i don't understand you because code that i've posted freezes in all build modes in XNA Game Studio Express, except usual debugging(f5). So you-ve really got .exe file from code that i've posted without freezing?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Post by Norbo »

Yes and no, it seems. I went back and re-tried the full code sample you posted; it does indeed freeze under non-debug mode with both configurations.

However, using only the original snippet placed into the original demos source code, it works fine in Debug configuration under both debug and start without debugging, but froze with the Release/Start without debugging combo.

This actually helps to some extent- at least now I know that it isn't necessarily directly related to the Release build optimizations, but more likely directly related to the debugging settings. I wish I had a better lead than this, or at least knew that it was something obviously wrong in my code.

I'll try to replicate the NaN for now, who knows, maybe that will point to a related error.

Alright, I've got a setup where a large cylinder slams into 9 assorted cones and cubes at 100 meters per second. Then, another cylinder falls from the sky and impacts the ground at over 250 meters per second. While running without debugging still sometimes freezes, I don't observe a NaN exception. I'll take a look at your sample code when you post it later, I suppose.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Post by Norbo »

This extreme weirdness deserves a post of its own over a simple edit.

I am encountering what appear to be logical impossibilities- in my experience, computers don't take too kindly to logical impossibilities.

While everything works happy dandy in debug mode, the freezes that occur under "start without debugging" apparently occur somewhere in the decision that chooses whether or not to go with a deep contact resolution or a shallow contact generation path. Instead of choosing either of these options, it does nothing and freezes.

Essentially,

Code: Select all

if it is colliding 
{
    if it is shallow
    { 
          Add contact and go on your merry way.
     }
     else
     {
          It is deeply colliding, deseparate.
     } 
}
else
{
      It's not colliding.
}
becomes...

Code: Select all

if it is colliding 
{
     Succeed at some calculations to determine shallow/deep penetration state.
     Analyze the calculation results: WAAAAARGH I DON'T WANT TO TAKE EITHER PATH
}

The only evaluation done at what appears to be the time of the freeze is a very simple Vector3 equality check. Nothing special. Note that no freeze occurs at the time of the calculations- it makes it through it unscathed. Only when the values are checked does it explode. Since it's not throwing any exceptions, it doesn't appear to be a NaN or null issue.


So, it seems the point of the freeze has been found, or at least narrowed down- but has it really??

During my attempts at debugging the non-debug mode execution, I noticed something peculiar and disturbing.

A piece of debug code references a static boolean value named CHECK which starts as false. testCount() is a simple helper method that, currently, just throws a generic exception to crash the program before the freeze (it technically throws an exception if the method has been called over a given threshold; in the following, that threshold is zero). CHECK and testCount() are not referenced in any other locations.

Code: Select all

if (updateIterations > 1)
{
      CHECK = true;
      if (CHECK)
          Toolbox.testCount();
}
This doesn't seem too useful, but it gets nice and strange pretty quick. Notably, the exception is never thrown, and the program freezes in what seems like an infinite loop. This lack of an exception would be fine if updateIterations < 2 at all times, but it is not. In fact, if I change the code to:

Code: Select all

if (updateIterations > 1)
{
      CHECK = true;
}
if (CHECK)
      Toolbox.testCount();
the exception gets thrown. This proves that the updateIterations has to be greater than 1 at some point, but it begs the question- why didn't the previous code throw an exception?

Not only that, but earlier, the same setup- all other code equal- produced two different, separate results. I can't explain how or why this is this case, other than some sort of memory corruption.

This throws the entire debug process I used to determine the freeze's location into question. I have no idea what is going on.

I'm currently waiting for my post to be approved on the XNA boards (taking quite a while), but until then I'm just going to keep trying to add features/randomly stumble upon a fix to the horrible catastrophic error.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Post by Norbo »

After quite a bit more searching, I've finally got it to freeze while I have a profiler running, and it is showing a very specific location for the problem. It's seperate from where my previous tests indicated, though very loosely related. This is much more definitive than my exception tests, so I hope it pans out...

Edit: It worked! The crash is gone.. as far as I can tell anyway, plus the profiler helped me find a few troublesome spots so it should run marginally faster too. I'll get this packed up and shipped out as fast as I can, hopefully I can get compound objects running by tomorrow if I'm lucky.
Post Reply