Assertion failed: bd->position.IsValid()

I’m getting this error occasionally:

Assertion failed: bd->position.IsValid(), file …\src\box2d\Box2D\Dynamics\b2Body.cpp, line 27

Context is that I apply_force to a lot of bodies to emulate the shockwave from explosion.

Could it be that you are normalising a vector of zero length somewhere?

Also, what is the magnitude of the impulse you pass into apply_force ?

Hmm… Funny thing, turns out I’m not actually apply_force, because things I work are kinematic bodies that I calculate physics for by myself. I use dynamic bodies only for projectiles. Maybe it happens when body flies away too far?

Code that emulates shockwave is like this, if it matters

for k, ghost in pairs(collidersById) do
local r = ghost:world_position() - self:world_position()
local d = vmath.length(r)
if ghost.tree then
	ghost.tree:push(vmath.normalize(r) * pow2(30000 / (d + 60)) * last_dt, ghost:world_position())
end			
end

As Ragnar mentioned, normalization of zero length vectors will produce bad results that can easily spread. Check if the length of r is very close to zero, and check the result from vmath.normalize(r) so that it seems like an actual direction vector (and doesn’t contain NaN’s)

Ok, so based on Ragnar’s answer it could be that the vector r is of 0 length. Could you please print it to make sure this isn’t the case?

Yes, it’s possible that it’s zero length occasionally. Maybe it’s the problem.

Ok, so maybe you could change your code to also check that the length of r is greater than 0 before trying to normalize it?

local d = vmath.length(r)
if ghost.tree and d > 0 then
	ghost.tree:push(vmath.normalize(r) * pow2(30000 / (d + 60)) * last_dt, ghost:world_position())
end			

On the other hand, I think it looks bad that we show that kind of engine error in the console. Can this be improved @Ragnar_Svensson or @Mathias_Westerdahl?

Yes, we should probably check for it in the lua layer. A slightly more stable method is to pick a hard-coded direction whenever the distance goes below a certain threshold:

if ghost.tree then
    local dir = r
    if vmath.length_sqr(dir) < 0.01 then -- means 0.1 units threshold
        dir = vmath.vector3(0, 1, 0) -- any direction that makes the most sense (if any)
    else
        dir = vmath.normalize(dir)
    end
    ghost.tree:push(dir * pow2(30000 / (d + 60)) * last_dt, ghost:world_position())
end
1 Like

Actually, I have fixed my code by simply changing the string order, so exploded ball (“ghost”) is removed from the list before I pass over this list for the shockwaving.

But I would really appreciate if engine would do what Ragnar suggests. Or any other solution that does not involve cryptic error messages.