Assert in ndIntersections.h

Report any bugs here and we'll post fixes

Moderators: Sascha Willems, Thomas

Assert in ndIntersections.h

Postby Esharc » Mon Feb 14, 2022 8:28 am

Hello Julio,

In this function of ndIntersections.h
Code: Select all
inline ndFloat32 dBoxDistanceToOrigin2 (const ndVector& minBox, const ndVector& maxBox)
{
   dAssert(maxBox.m_x >= minBox.m_x);
   dAssert(maxBox.m_y >= minBox.m_y);
   dAssert(maxBox.m_z >= minBox.m_z);
   const ndVector mask (((minBox * maxBox) > ndVector::m_zero) & ndVector::m_triplexMask);
   const ndVector dist (maxBox.Abs().GetMin (minBox.Abs()) & mask);
   return dist.DotProduct(dist).GetScalar();
}


We hit those assert every time that we spawn AI vehicles to new locations in the world. What we do is we have a spawn area around the human operated vehicle and spawn AI vehicles in the area to keep that area full of traffic. When the AI reaches the limit of the spawn area, they are moved to a new location somewhere in the spawn area again. There is a height field that is connected to the AI vehicle that moves around on the terrain as the vehicle moves around. We have had a long thread on the height field bumps in a previous thread.

Should we be doing something different when moving the rigid bodies? Or is it safe to comment out those asserts? When I run our application in release (which will ignore those asserts) then everything still works as expected.
Esharc
 
Posts: 120
Joined: Tue Jan 10, 2017 5:23 am
Location: South Africa

Re: Assert in ndIntersections.h

Postby Julio Jerez » Mon Feb 14, 2022 9:50 am

Not that assert is serious. It means some where an aabb is flipped. The min point es bigger that the max, that will cause bad problems with negative surface areas and volumes.
Where it is called from?
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Assert in ndIntersections.h

Postby Esharc » Mon Feb 14, 2022 10:43 am

The call stack for the assert is:
NewtonAssert.png
NewtonAssert.png (153.57 KiB) Viewed 10932 times

NewtonAssert(Watches).png
NewtonAssert(Watches).png (147.21 KiB) Viewed 10932 times


I think what might be happening is that when we move the AI vehicle the height grid position has not updated yet, so the AI body is not in the same position as the height grid anymore for that one frame, or maybe more than just one frame. So perhaps I just have to paused the updated of the engine whilst moving the vehicle. But that won't be so easy as there are many other objects in the world as well. Otherwise I might have to do something in my OnAabbOverlap callback?
Esharc
 
Posts: 120
Joined: Tue Jan 10, 2017 5:23 am
Location: South Africa

Re: Assert in ndIntersections.h

Postby Julio Jerez » Mon Feb 14, 2022 11:37 am

Why don't you just kept a vector of the objects tha need update, an issue the change in a post update?

The is a method that is called after the physics is all done.
It is use in the demos for moving the camera.
Also in the destruction demos.

You just add them to the list, the in the post update, apply the change and clear the vector.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Assert in ndIntersections.h

Postby Julio Jerez » Mon Feb 14, 2022 2:53 pm

looking at the stack trace, the call come from here.
Code: Select all
   ndFloat32 CalculateDistance2(const ndVector& localOrigin0, const ndVector& size0, const ndVector& localOrigin1, const ndVector& size1) const
   {
      ndFloat32 separatingDistance2 = CalculateBox0Distance2(localOrigin0, size0, localOrigin1, size1);
      if (separatingDistance2 == ndFloat32(0.0f))
      {
         separatingDistance2 = CalculateBox1Distance2(localOrigin0, size0, localOrigin1, size1);


what that function does, is that is calculate the minimum distance between two boxes.
the two boxes are parametric with an origin and a size, so there is no way neither of the can be
flipped. the only way this could happen is if matrix is wrong, or of somehow some illegal floats where produce at some point.
one transforms the other to it local space and build an aabb on that space. the other does the opposite.
for that CalculateBox0Distance2 uses m_localMatrix0 and
for that CalculateBox1Distance2 uses m_localMatrix1 and

when is happen see if m_localMatrix0 and m_localMatrix1 or m_localMatrixAbs0 and m_localMatrixAbs1are valid.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Assert in ndIntersections.h

Postby Esharc » Wed Feb 16, 2022 4:20 am

Hi Julio,

Sorry I got sidetracked with other work. A quick check of those local matrices seemed to look fine to me, but I will take a couple of screen shots today and post them here, maybe you spot something else. It did not work to have the AI vehicle spawning in a post update, the asserts still happened.

I noticed that in CalculateContactsDiscrete you have an assert check for separationDistance of less than 100.
Code: Select all
ndInt32 ndContactSolver::CalculateContactsDiscrete()
{
   ndInt32 count = 0;
   if (m_instance0.GetShape()->GetAsShapeCompound() || m_instance1.GetShape()->GetAsShapeCompound())
   {
      count = CompoundContactsDiscrete();
   }
   else if (m_instance0.GetShape()->GetAsShapeConvex())
   {
      count = ConvexContactsDiscrete();
   }
   else
   {
      dTrace(("Fix compound contact for pair: %s %s\n", m_instance0.GetShape()->SubClassName(), m_instance1.GetShape()->SubClassName()));
      dAssert(0);
   }

   m_contact->m_timeOfImpact = m_timestep;
   m_contact->m_separatingVector = m_separatingVector;
   dAssert(m_separationDistance < ndFloat32(100.0f));
   m_contact->m_separationDistance = m_separationDistance;
   return count;
}

I am getting that assert, but the count value is zero. Can you maybe only assert of the count is greater than zero?
Esharc
 
Posts: 120
Joined: Tue Jan 10, 2017 5:23 am
Location: South Africa

Re: Assert in ndIntersections.h

Postby Esharc » Wed Feb 16, 2022 5:14 am

So I notice that the size1 is always negative when the assert happens when moving the AI vehicles.
NewtonAssert(Watches)_1.png
NewtonAssert(Watches)_1.png (156.6 KiB) Viewed 10906 times


And the size is calculated in ndShapeHeightField::GetLocalAabb
NewtonAssert_2.png
NewtonAssert_2.png (185.55 KiB) Viewed 10906 times
Esharc
 
Posts: 120
Joined: Tue Jan 10, 2017 5:23 am
Location: South Africa

Re: Assert in ndIntersections.h

Postby Julio Jerez » Wed Feb 16, 2022 6:38 am

Ah, that must be the problem.

If size is negative then I will cause the box to be flipped.

It seem there is a bug in CalculateLocal aabb. That some how can produce a negative aabb.

What the funtion does is that given two points, I round them to the points on the height field and ge the lelvation at those points.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Assert in ndIntersections.h

Postby Julio Jerez » Wed Feb 16, 2022 10:54 am

I can't see by inspection why the aabb can become flipped. I added these checks

dAssert(boxP0.m_x <= boxP1.m_x);
dAssert(boxP0.m_y <= boxP1.m_y);
dAssert(boxP0.m_z <= boxP1.m_z);

please sync and try again maybe that can assert when an that time, and we can see why this happens.
for what I can see there is no way the aabb will be negative.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Assert in ndIntersections.h

Postby Julio Jerez » Wed Feb 16, 2022 1:46 pm

oh check out this thread.
viewtopic.php?f=12&t=9763&p=66837#p66837

you are changing a static body matrix, and it seems that the aabb in some case was not updated.
please sync just to make sure the aabb of the heightfield is up to date after you set the matrix.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Assert in ndIntersections.h

Postby Esharc » Thu Feb 17, 2022 1:51 am

I synced this morning, and I am now getting the asserts at the checks that you added. Here is a screenshot of it.
NewtonAssert_3.png
NewtonAssert_3.png (156.35 KiB) Viewed 10881 times

I noticed that when the assert happens, sometimes boxP0 is greater than m_maxBox, and sometime boxP1 is smaller than m_minBox.

If I add
Code: Select all
boxP0 = boxP0.Select(boxP0.GetMax(m_minBox), m_yMask);
boxP0 = boxP0.Select(boxP0.GetMin(m_maxBox), m_yMask);
boxP1 = boxP1.Select(boxP1.GetMax(m_minBox), m_yMask);
boxP1 = boxP1.Select(boxP1.GetMin(m_maxBox), m_yMask);

then I get the assert that I mentioned earlier in ndContactSolver.cpp CalculateContactsDiscrete()
Code: Select all
dAssert(m_separationDistance < ndFloat32(100.0f));
Esharc
 
Posts: 120
Joined: Tue Jan 10, 2017 5:23 am
Location: South Africa

Re: Assert in ndIntersections.h

Postby Julio Jerez » Thu Feb 17, 2022 10:16 am

oh I see, yes you are right is not enough to just check if the box extremes are outsize the terrain,
I added that check.
Code: Select all
boxP0 = boxP0.Select(boxP0.GetMax(m_minBox), m_yMask);
boxP0 = boxP0.Select(boxP0.GetMin(m_maxBox), m_yMask);
boxP1 = boxP1.Select(boxP1.GetMax(m_minBox), m_yMask);
boxP1 = boxP1.Select(boxP1.GetMin(m_maxBox), m_yMask);


now what you are getting is that the spawn vehicles and the terrain tile are too away,
which should never happens,
Code: Select all
   m_contact->m_timeOfImpact = m_timestep;
   m_contact->m_separatingVector = m_separatingVector;
   dAssert(m_separationDistance < ndFloat32(100.0f));
   m_contact->m_separationDistance = m_separationDistance;


my guess is that what you spawn the vehicle you also move the terrain, but the update will not happen until the next frame, the terrain will still have the old aabb.

this is the skeleton of an update
Code: Select all
      m_scene->Begin();
      m_collisionUpdate = true;
      m_scene->BalanceScene();

      ndInt32 const steps = m_subSteps;
      ndFloat32 timestep = m_timestep / steps;
      for (ndInt32 i = 0; i < steps; i++)
      {
         SubStepUpdate(timestep);
      }

      m_scene->SetTimestep(m_timestep);
      
      ParticleUpdate(m_timestep);
      UpdateTransformsLock();
      UpdateTransforms();
      PostModelTransform();
      m_inUpdate = false;
      PostUpdate(m_timestep);
      UpdateTransformsUnlock();

      m_scene->End();


if you make your scene changes in any of the call backs called from SubStepUpdate,
they will not take place until the next update.

you should make your scene changes in function PostUpdate,
What I do is that I make a deferred queue vector that collect the objects that represent changes, them in Post update you iterate over that queue, and you issue all the pending changes and clean the queue. this is similar to how people do stuff using openGL.

I am pretty sure this is the problem now, because the broad phase will not allow to calculate contact point for two aabb that are farther away that few units. and that what the distance check is telling us.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Assert in ndIntersections.h

Postby Esharc » Thu Feb 17, 2022 10:26 am

Hmmm, that is strange because I have been getting those same distance asserts with our human controllable vehicle on a ndShapeStatic_bvh as well. And in that instance the mesh is not moved at all.

I will implement the SetMatrix calls to be in a post update and see if it solves the issue and get back to you.
Esharc
 
Posts: 120
Joined: Tue Jan 10, 2017 5:23 am
Location: South Africa

Re: Assert in ndIntersections.h

Postby Julio Jerez » Thu Feb 17, 2022 10:43 am

there are other reasons for that function to issue a warning.

for example if for some reason a huge force is generated that cause an explosion, is a body is teleported, them the two bodies could be in close distance and after one sub step they flight away.

in the case for a huge impulse of force there are warning on the integrator that will say of that was the case. In this case we can consider it a teleporting of a static mesh.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Assert in ndIntersections.h

Postby Esharc » Fri Feb 18, 2022 8:23 am

Hi Julio,

I have tried adding the teleporting to a post update, but it still did not work, so to simplify the problem for myself, I used a simple vehicle on a terrain that I know I get the assert.

The assert happens between the terrain and a body that is attached to the main body via a hinge joint.
Here is a screen shot of the place where the assertion happens with the stack
NewtonAssertSeperationDist_1.png
NewtonAssertSeperationDist_1.png (150.99 KiB) Viewed 10858 times


I then stepped back into the function where the separation distance gets calculated and stepped through the while loop iterating over the stack. I then noticed that at a point it goes into the if statement checking if the dist2 > 0.0. At which point it breaks out of the while loop.
NewtonAssertSeperationDist_4.png
NewtonAssertSeperationDist_4.png (149.75 KiB) Viewed 10858 times


Here I added a watch for what the closestDist value is, which is greater than 100.
NewtonAssertSeperationDist_5.png
NewtonAssertSeperationDist_5.png (126.46 KiB) Viewed 10858 times


What would limit the closest distance to 100 of even 1000 as is the case with the assert in the last image? And shouldn't the asserts be the same distance for both the CompoundToShapeStaticBvhContactsDiscrete and CalculateContactsDiscrete functions?
Esharc
 
Posts: 120
Joined: Tue Jan 10, 2017 5:23 am
Location: South Africa


Return to Bugs and Fixes

Who is online

Users browsing this forum: No registered users and 15 guests