Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collision Detection Problems with b2ContactEdge and b2Distance #766

Open
nocholasrift opened this issue May 22, 2024 · 4 comments
Open

Collision Detection Problems with b2ContactEdge and b2Distance #766

nocholasrift opened this issue May 22, 2024 · 4 comments

Comments

@nocholasrift
Copy link

nocholasrift commented May 22, 2024

Hi there! I am currently working with the author of mvsim: https://github.com/MRPT/mvsim, which is a robot simulator which uses Box2D for collision detection. Box2D works great for preventing objects from penetrating each other. However, when we try to set a flag to true to expose this collision to the user, the behavior is inconsistent. Specifically, the problem seems to happen mostly when two edges are face to face (parallel), but occasionally happens for corner edges.

Current there are two techniques used to detect collision:

  1. b2ContactEdge->contact->isTouching()
  2. b2Distance() with the fixtures -- it works great sometimes, others it returns a large distance, even if the two bodies are face to face with two edges colliding.

Here is a link to the issue in which we are discussing this problem: MRPT/mvsim#42

Any help would be greatly appreciated! Is there a better way to detect collisions than this method?

Attached below is the dump file as requested as a follow up from my Discord post, where the robot crashed head on into an obstacle, and using both 1 and 2 failed to detect the collision:
box2d_dump.zip

@erincatto
Copy link
Owner

Are calling b2Distance directly? I need the data you are sending to that specific function. The world dump doesn't give me the data you send to that function. You'll have to print the input yourself somehow.

I'm guessing you increased b2_maxPolygonVertices? But looking at your geometry it doesn't seem necessary. Also you are creating 514 joints between static bodies.

image

@nocholasrift
Copy link
Author

Is there some cleaner way to accomplish this printout of the data other than going through the docs and printing every member of every struct and class used? This is the code being used to try and detect the collisions, would I be trying to print all the fields relevant to dO, dc, and di?

// Instantaneous collision flag:
isInCollision_ = false;
if (b2ContactEdge* cl = b2dBody_->GetContactList(); cl != nullptr)
{
	for (auto contact = cl->contact; contact != nullptr;
		 contact = contact->GetNext())
	{
		// We may store with which other bodies it's in collision?
		const auto shA = cl->contact->GetFixtureA()->GetShape();
		const auto shB = cl->contact->GetFixtureB()->GetShape();
		if (cl->contact->GetFixtureA()->IsSensor()) continue;
		if (cl->contact->GetFixtureB()->IsSensor()) continue;

		b2DistanceInput di;
		di.proxyA.Set(shA, 0 /*index for chains*/);
		di.proxyB.Set(shB, 0 /*index for chains*/);
		di.transformA =
			cl->contact->GetFixtureA()->GetBody()->GetTransform();
		di.transformB =
			cl->contact->GetFixtureB()->GetBody()->GetTransform();
		di.useRadii = true;

		b2SimplexCache dc;
		dc.count = 0;
		b2DistanceOutput dO;
		b2Distance(&dO, &dc, &di);

		if (dO.distance < simulable_parent_->collisionThreshold() ||
			cl->contact->IsTouching())
			isInCollision_ = true;
	}
}

@erincatto
Copy link
Owner

Set a breakpoint before the call to b2Distance, then in the watch window put in di, expand it and then copy the values. You should also list the proxy vertices.

Here is some example data I captured in Visual Studio.

-		distanceInput	{proxyA={m_buffer=0x000000eb168fee90 {{...}, {...}} m_vertices=0x000000eb168ff1d0 {x=-4.00000000 y=1.00000000 } ...} ...}	b2DistanceInput
-		proxyA	{m_buffer=0x000000eb168fee90 {{x=-4.00000000 y=1.00000000 }, {x=-5.00000000 y=5.00000000 }} m_vertices=...}	b2DistanceProxy
+		m_buffer	0x000000eb168fee90 {{x=-4.00000000 y=1.00000000 }, {x=-5.00000000 y=5.00000000 }}	b2Vec2[2]
+		m_vertices	0x000000eb168ff1d0 {x=-4.00000000 y=1.00000000 }	const b2Vec2 *
		m_count	2	int
		m_radius	0.00999999978	float
-		proxyB	{m_buffer=0x000000eb168feeb0 {{x=-107374176. y=-107374176. }, {x=-107374176. y=-107374176. }} m_vertices=...}	b2DistanceProxy
+		m_buffer	0x000000eb168feeb0 {{x=-107374176. y=-107374176. }, {x=-107374176. y=-107374176. }}	b2Vec2[2]
+		m_vertices	0x000002a0fdb64c70 {x=0.00000000 y=0.00000000 }	const b2Vec2 *
		m_count	1	int
		m_radius	1.00000000	float
-		transformA	{p={x=0.00000000 y=0.00000000 } q={s=0.00000000 c=1.00000000 } }	b2Transform
+		p	{x=0.00000000 y=0.00000000 }	b2Vec2
+		q	{s=0.00000000 c=1.00000000 }	b2Rot
-		transformB	{p={x=-3.27151895 y=6.73861551 } q={s=0.00000000 c=1.00000000 } }	b2Transform
+		p	{x=-3.27151895 y=6.73861551 }	b2Vec2
+		q	{s=0.00000000 c=1.00000000 }	b2Rot
		useRadii	false	bool
-		distanceInput.proxyA.m_vertices,2	0x000000eb168ff1d0 {{x=-4.00000000 y=1.00000000 }, {x=-5.00000000 y=5.00000000 }}	const b2Vec2[2]
+		[0]	{x=-4.00000000 y=1.00000000 }	const b2Vec2
+		[1]	{x=-5.00000000 y=5.00000000 }	const b2Vec2
-		distanceInput.proxyB.m_vertices,1	0x000002a0fdb64c70 {{x=0.00000000 y=0.00000000 }}	const b2Vec2[1]
+		[0]	{x=0.00000000 y=0.00000000 }	const b2Vec2

@nocholasrift
Copy link
Author

nocholasrift commented Jul 2, 2024

@erincatto Apologies for the delay, here is a a dump of what was contained in di right before the function call. Is the nan value I'm seeing in the proxyA m_buffer to blame? The setup is same as before, there is a head on collision between the robot and the obstacle, but the current way the box2D api is being used isn't detecting any collision (last if statement in code provided above is false).

	Locals		
		angle	0	float
		cl	@0x555555c7f8e0	b2ContactEdge
		contact	@0x555555c7f8a0	b2Contact
		context	@0x7fffffffdf60	mvsim::TSimulContext &
		dO	@0x7fffffffddd0	b2DistanceOutput
		dc	@0x7fffffffddf4	b2SimplexCache
		di	@0x7fffffffde00	b2DistanceInput
			proxyA	@0x7fffffffde00	b2DistanceProxy
				m_buffer	@0x7fffffffde00	b2Vec2[2]
					[0]	@0x7fffffffde00	b2Vec2
						x	nan	float
						y	4.591634678053128e-41	float
					[1]	@0x7fffffffde08	b2Vec2
						x	34816179306496.0	float
						y	3.061136495317563e-41	float
				m_count	4	int32
				m_radius	0.00999999978	float
				m_vertices	@0x555555d56b08	b2Vec2
					x	0.0299999937	float
					y	0.144999996	float
			proxyB	@0x7fffffffde20	b2DistanceProxy
				m_buffer	@0x7fffffffde20	b2Vec2[2]
					[0]	@0x7fffffffde20	b2Vec2
					[1]	@0x7fffffffde28	b2Vec2
				m_count	14	int32
				m_radius	0.00249999994	float
				m_vertices	@0x555555fb9938	b2Vec2
					x	0.0769287646	float
					y	0	float
			transformA	@0x7fffffffde40	b2Transform
				p	@0x7fffffffde40	b2Vec2
					x	-3.195467	float
					y	5.40175343	float
				q	@0x7fffffffde48	b2Rot
					c	-0.851679325	float
					s	0.524063289	float
			transformB	@0x7fffffffde50	b2Transform
				p	@0x7fffffffde50	b2Vec2
					x	-3.67499995	float
					y	5.4749999	float
				q	@0x7fffffffde58	b2Rot
					c	1	float
					s	0	float
			useRadii	true	bool
		lck	@0x7fffffffdd80	std::unique_lock<std::shared_mutex>
		pos	@0x555555f45f2c	b2Vec2 &
		shA	@0x555555d56af0	b2Shape
		shB	@0x555555fb9920	b2Shape
		this	@0x555555fd76d0	mvsim::Block
		vel	@0x555555f45f60	b2Vec2 &
		w	0	float
	Inspector		
	Expressions		
	Return Value		
	Tooltip		

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants