ODE.net - collision detection: strange error message
ODE.net - collision detection: strange error message
Ive integrated the code from the ODE.NET-Collision-Detection howto with my irrlicht-setup. Atm I only have two boxes (CubeSceneNodes), one of them with geom and body so that its affected by gravity. the other is supposed to be a static object, so it only got a geom to do collisions with. But with the collision-code from the howto (which is only for collision of body-having objects, afaik), Tao.ODE says its getting invalid parameters for dAreConnectedExcluding right on the first calculated timestep, although the objects shouldnt intersect then - complete failure information here: http://pastebin.kubuntu-de.org/5331
Ive also tried with the bleeding edge odedotnet code from the svn repository, but it doesnt change anything.
My collision code: http://pastebin.kubuntu-de.org/5336
The OnCollision method is the same as in the howto.
May someone give a hint?
Ive also tried with the bleeding edge odedotnet code from the svn repository, but it doesnt change anything.
My collision code: http://pastebin.kubuntu-de.org/5336
The OnCollision method is the same as in the howto.
May someone give a hint?
Tanuva
ConnectedToExcluding needs two bodies, as you only have one body it will fail. So do something like this:
ConnectedToExcluding is then only called when there are two bodies.
Code: Select all
if(b1 == null || b2 == null)
{
u.print("b1 oder b2 == null", true);
}
else
{
if(b1.ConnectedToExcluding(b2, JointType.Contact))
return;
}
Hmm
If it really is the exact same error as before then remove ConnectedToExcluding and see if it works...
Also, is this valid?
I haven't actually used C# but if there are no contacts then wouldn't contactgeoms.Length be zero? In which case is it valid to create a new Contact array of zero size?
If it really is the exact same error as before then remove ConnectedToExcluding and see if it works...
Also, is this valid?
Code: Select all
ContactGeom[] contactgeoms = e.Geom1.Collide(e.Geom2, 13);
Contact[] contact = new Contact[contactgeoms.Length];
Yes, its the same error.
Honestly, I don't really know what that code does, I've transcripted it from the ode.net-collision-detection-example and hoped it works out of the box. But I'm sure now the problem is caused by the supposed-to-be static object. The collision code wants to compare two bodies, but since the second object only has a geom, thats impossible. But what I dont understand then is why my "if(b1 == null || b2 == null)" isnt triggered... If I remove the static object, the code works - at least ode doesnt throw errors. So its somehow caused by the bodyless object. Having removed the code you mentioned, ode gives me this error message: http://pastebin.kubuntu-de.org/5468 - which leads me to the staticness once again as it seems to be thrown at line 16.
I basically know how collisions theoretically work in ode, but how may I get it working for such a static object, which is essential for having f.e. a ground to walk on top of...?
Honestly, I don't really know what that code does, I've transcripted it from the ode.net-collision-detection-example and hoped it works out of the box. But I'm sure now the problem is caused by the supposed-to-be static object. The collision code wants to compare two bodies, but since the second object only has a geom, thats impossible. But what I dont understand then is why my "if(b1 == null || b2 == null)" isnt triggered... If I remove the static object, the code works - at least ode doesnt throw errors. So its somehow caused by the bodyless object. Having removed the code you mentioned, ode gives me this error message: http://pastebin.kubuntu-de.org/5468 - which leads me to the staticness once again as it seems to be thrown at line 16.
I basically know how collisions theoretically work in ode, but how may I get it working for such a static object, which is essential for having f.e. a ground to walk on top of...?
Tanuva
I just downloaded the ODE.net source.
It *seems* that when for example you call
Body b1 = e.Geom1.Body;
This actually creates a Body object, so it will *never* be null.
So instead, this body object has an attribute Handle of type IntPtr. Which perhaps you can test,
e.g.
if (b1.Handle == 0 || b2.Handle == 0)
(I'm not sure how C# actually uses pointers or what IntPtr actually is though... So maybe you don't compare to 0 or you use some method or something... Who knows.)
Look in Body.cs and BaseOdeResource.cs
(It's also possible I don't know what the hell I'm talking about, not ever having used C#. Be warned )
EDIT: Seems to check the pointers is
if (b1.Handle == IntPtr.Zero || b2.Handle == IntPtr.Zero)
It *seems* that when for example you call
Body b1 = e.Geom1.Body;
This actually creates a Body object, so it will *never* be null.
So instead, this body object has an attribute Handle of type IntPtr. Which perhaps you can test,
e.g.
if (b1.Handle == 0 || b2.Handle == 0)
(I'm not sure how C# actually uses pointers or what IntPtr actually is though... So maybe you don't compare to 0 or you use some method or something... Who knows.)
Look in Body.cs and BaseOdeResource.cs
(It's also possible I don't know what the hell I'm talking about, not ever having used C#. Be warned )
EDIT: Seems to check the pointers is
if (b1.Handle == IntPtr.Zero || b2.Handle == IntPtr.Zero)
Hey, you're genious! The body.Handle is what they had mentioned about the "ID" of a body in the original ODE FAQ, I just couldnt find such a property for the .net-body. I have completely moved the body-to-body collision code into the else-thing which already contains the b1.ConnectedToExcluding(...) thing, so that its only called if the handle of one of the bodies is != IntPtr.Zero. Runs perfectly smooth now and afaik until now, I just have to modify the code for the body-to-geom collisions so that it creates joints between the body and the surrounding space (what did they call it in the faq, cant remember the english expression...) instead of another (in this case non-existent) body.
Here's the actual code: http://pastebin.kubuntu-de.org/5489
Edit: Okay, simply changing the c.Attach(...) in line 35 from (b1, b2) to (b1, null) to have it being attached to the surrounding space didnt help much - now ode tells me about a failed assertion in dCollideBoxBox (the two objects have a box-shaped geom). At least I see that ode isnt that clearly arranged as I got the impression from the first examples... How do I get the "dynamic" object to collide with the "static" object properly?
[Why isnt there some documentation of odedotnet anywhere? The c++ one doesnt help at all...]
Here's the actual code: http://pastebin.kubuntu-de.org/5489
Edit: Okay, simply changing the c.Attach(...) in line 35 from (b1, b2) to (b1, null) to have it being attached to the surrounding space didnt help much - now ode tells me about a failed assertion in dCollideBoxBox (the two objects have a box-shaped geom). At least I see that ode isnt that clearly arranged as I got the impression from the first examples... How do I get the "dynamic" object to collide with the "static" object properly?
[Why isnt there some documentation of odedotnet anywhere? The c++ one doesnt help at all...]
Tanuva
I don't think you need this. Just use c.Attach(b1, b2); as before. Bodies with IntPtr.zero handles are the same as the surrounding space...Edit: Okay, simply changing the c.Attach(...) in line 35 from (b1, b2) to (b1, null)
This is the structure of my (c++) code:
Code: Select all
dBodyID b1 = dGeomGetBody(o1);
dBodyID b2 = dGeomGetBody(o2);
// don't generate contacts if both are bodiless.
// this is mainly to prevent intersecting static geoms (e.g. scenery) from hogging resources.
// however in some cases this would be undesirable (e.g. you have non physically simulated objects
// that you still want to detect collisions with... Ghosts maybe?)
if ( !(b1 || b2) ) return;
// If both geoms have bodies, which are joined by a non contact joint, then return.
// e.g. could be useful for a ragdoll, if limbs overlap.
if (b1 && b2 && dAreConnectedExcluding(b1, b2, dJointTypeContact)) return;
// array of available contact points
const int MAX_CONTACTS = 12;
dContact contact[MAX_CONTACTS];
int numc = dCollide(o1, o2, MAX_CONTACTS, &contact[0].geom, sizeof(dContact));
// No contacts
if (numc == 0) return;
// ignore ray collisions
if ( (dGeomGetClass(o1) == dRayClass) || (dGeomGetClass(o2) == dRayClass))
{
return;
}
// for each contact, create an actual contact joint between two bodies
// these will be removed after simulation stepping
for (int i = 0; i < numc; i++)
{
contact[i].surface.mode = dContactBounce | dContactSoftCFM;
contact[i].surface.mu = 100;
contact[i].surface.bounce = 0;
contact[i].surface.bounce_vel = 0;
contact[i].surface.soft_cfm = 0;
dJointID c = dJointCreateContact(dWorld, dPerStepContactJointGroup, contact+i);
dJointAttach(c, b1, b2);
}
Ha! That must be the cause of the errors. Im using odedotnet with the tao.ode binaries that came with it, but with ode 0.8 from cvs. Likely they changed the API since 0.5... Gonna have a look at ODE.net, thanks for the tip!
Im rewriting the relevant code parts to match the original ode.net structure. Itsa pity that it doesnt have such a nice OO-architecture, but one cant have it all.
Im rewriting the relevant code parts to match the original ode.net structure. Itsa pity that it doesnt have such a nice OO-architecture, but one cant have it all.
Tanuva
Now, here I come again.
First, the code: http://pastebin.kubuntu-de.org/5922
I've ported all of it to ode.net and after some trying (and unsuccessful searching for documentation or examples...), its running - except collision detection. There are various tutorials on that on the net, but they're all cpp and I have tried to port it to c#, with limited success. I cant really figure out what d.Collide expects as parameters. Because nearly everything is an IntPtr now, theres no data type checking anymore and I have to stick to ODE's error messages, which are (what have you expected?) not that helpful.
This is the actual error, referring to line 26 of my code:
In the syntax-completion-help it says d.Collide wants these parameters:
And what should I use for skip?
Very confused (but wishing for the final enlightenment),
First, the code: http://pastebin.kubuntu-de.org/5922
I've ported all of it to ode.net and after some trying (and unsuccessful searching for documentation or examples...), its running - except collision detection. There are various tutorials on that on the net, but they're all cpp and I have tried to port it to c#, with limited success. I cant really figure out what d.Collide expects as parameters. Because nearly everything is an IntPtr now, theres no data type checking anymore and I have to stick to ODE's error messages, which are (what have you expected?) not that helpful.
This is the actual error, referring to line 26 of my code:
I know that in the cpp-version the last parameter of dCollide is sizeof(*contactgeomarray*). Now I tried to imitate this value by using contactgeomarray.Length, but that doesnt do the job.ODE INTERNAL ERROR 1: assertion "skip >= (int)sizeof(dContactGeom)" failed in dCollideBoxBox()
In the syntax-completion-help it says d.Collide wants these parameters:
As you can see, I have filled an array of ContactGeoms with the ones of the contact-array and it at least doesnt provoke an error... Or is it supposed to be something else?IntPtr o1,
IntPtr o2,
int flags,
d.ContactGeom[] contact,
int skip
And what should I use for skip?
Very confused (but wishing for the final enlightenment),
Tanuva
I translated one of the box stack demos in the ode source, and this was how I did my collision testing, maybe it'll help you out:
MAX_CONTACTS is a int constant, contacts is a d.ContactGeom[], and contact is a d.Contact for the contact joint params. Your parameters should be correct.
Here's the complete translated demo source btw. I'm still trying to learn ODE by translating more C++ demos but I'm waiting for the next release of ODE.NET first; there's a [well, some] missing feature.
Code: Select all
static void near(IntPtr space, IntPtr g1, IntPtr g2)
{
IntPtr b1 = d.GeomGetBody(g1);
IntPtr b2 = d.GeomGetBody(g2);
if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
return;
int count = d.Collide(g1, g2, MAX_CONTACTS, contacts, d.ContactGeom.SizeOf);
for (int i = 0; i < count; ++i)
{
contact.geom = contacts[i];
IntPtr joint = d.JointCreateContact(world, contactgroup, ref contact);
d.JointAttach(joint, b1, b2);
}
}
Here's the complete translated demo source btw. I'm still trying to learn ODE by translating more C++ demos but I'm waiting for the next release of ODE.NET first; there's a [well, some] missing feature.
YEAH!
Finally, I found what was wrong:
(where geoms[] is the contactgeom[])
Was missing in the second for-loop, where the joints are created. Now the blocks collide with each other. Not that nice yet, but Im working on it.
Thanks you two!
Finally, I found what was wrong:
Code: Select all
contact[i].geom = geoms[i];
Was missing in the second for-loop, where the joints are created. Now the blocks collide with each other. Not that nice yet, but Im working on it.
Thanks you two!
Tanuva