[ODE] Inconsistent depth return for dGeomRay
Shamyl Zakariya
zakariya at earthlink.net
Tue Jan 13 01:35:29 MST 2004
For reference, I'm on the default ODE 0.39, NOT from CVS. Compiled with
GCC 3.3 on Mac OS X 10.3
Shamyl Zakariya
"this is, after all, one of those movies where people spend a great
deal of time looking at things and pointing."
From a review of _Fantastic Voyage_
On Jan 13, 2004, at 12:29 AM, Shamyl Zakariya wrote:
> All
>
> I've been trying to implement a kind of range finder class using
> dGeomRay -- as part of a feedback system for my robotics simulations.
>
> I'm having trouble with the depth returned by dCollide, however --
> it's inconsistent, or rather, it seems to sometimes skip geoms in my
> simulation completely; other times it sees the same geom just fine.
> It's repeatable, but doesn't follow any pattern I can detect.
>
> The screenshots I'm linking to may clarify what I'm getting at here:
>
> http://home.earthlink.net/~zakariya/ray/0.png
> http://home.earthlink.net/~zakariya/ray/1.png
> http://home.earthlink.net/~zakariya/ray/2.png
> http://home.earthlink.net/~zakariya/ray/3.png
>
> The pink line is the ray, being emitted from the tower on the dark
> square in the middle; the small pink sphere/lumpy thing is the contact
> point as reported by dCollide. In some circumstances it collides
> correctly, in others is passes through and collides with an object
> behind. For reference, I'm fairly certain the objects in question
> really are where they're supposed to be, as my robot successfully
> bumps into them when walking around.
>
> Now, in case I've missed something obvious I'm attaching some code.
>
> Here's the relevant part of my collision callback function:
>
> static void nearCallback (void *data, dGeomID o1, dGeomID o2)
> {
> /*
> Check to see if this is a ray collision
> RangeSensor class's static method SensorForRay
> returns a pointer to any RangeSensor implementation
> which uses that geom.
> */
>
> if ( dGeomGetClass( o1 ) == dRayClass || dGeomGetClass( o2 ) ==
> dRayClass )
> {
> RangeSensor *rangeSensor = NULL;
> if ( rangeSensor = RangeSensor::SensorForRay( o1 ) )
> {
> rangeSensor->measure( o2 );
> }
> else if ( rangeSensor = RangeSensor::SensorForRay( o2 ) )
> {
> rangeSensor->measure( o1 );
> }
>
> //don't let rays be processed by default code
> return;
> }
>
> //the rest is irrelevant here
> }
>
> The RangeSensor::measure function is below, it calls dCollide with one
> contact. I checked to see if using multiple contacts made any
> difference, but as per the documentation, it always finds only one
> contact point. Here's the method:
>
> void RangeSensor::measure( dGeomID geom )
> {
> dContactGeom contact;
> if ( dCollide( _rayGeom, geom, 1, &contact, sizeof(dContactGeom)) > 0
> )
> {
> _contactPos[0] = contact.pos[0];
> _contactPos[1] = contact.pos[1];
> _contactPos[2] = contact.pos[2];
> _contactPos[3] = contact.pos[3];
>
> _distance = contact.depth;
> }
> }
>
> And, my drawing and stepping methods. For reference, RangeSensor is
> has step() called on it right before the simulation is stepped.
>
> void RangeSensor::draw( void )
> {
> // get the ray's origin and direction
> dVector3 start, dir, endpoint;
> dGeomRayGet( _rayGeom, start, dir );
>
> // crop the distance to either the max length or what was
> // calculated in ::measure()
> dReal distance = _distance < _maxLength ? _distance : _maxLength;
>
> // static int count = 0;
> // if ( !( count++ % 10 ))
> // {
> // printf("RangeSensor::draw() ray depth: %f\n", distance );
> // }
>
> // project endpoint of ray
> endpoint[0] = start[0] + distance * dir[0];
> endpoint[1] = start[1] + distance * dir[1];
> endpoint[2] = start[2] + distance * dir[2];
>
> GLVisualization *graphics = GLVisualization::instance();
> graphics->setColor( _color[0], _color[1], _color[2] );
> graphics->drawLine( start, endpoint );
>
> if ( !_contactVisual )
> {
> // 2 refers to the radius
> _contactVisual = graphics->buildSphere( 2 );
> }
>
> // draw contact point, if ray intersects something
> if ( _distance < _maxLength )
> {
> dMatrix3 R;
> dRSetIdentity( R ); // we don't need to orient the contact point
> graphics->drawObject( _contactVisual, _contactPos, R );
> }
>
> }
>
> void RangeSensor::step( void )
> {
>
> /*
> The anchor and direction vector are in
> coordinates relative to _attachedTo, so we've got
> to convert them into world coordinates and update
> our ray accordingly.
> */
>
> dVector3 anchor, direction;
>
> for (int i = 0; i < 3; i++ )
> {
> anchor[i] = _anchor[i];
> direction[i] = _direction[i];
> }
>
> // these functions convert the point and vector
> // from values relative to _attachedTo, to
> // world coordinates. I know they work correctly.
> // _attachedTo is just a class with a geom
> getRelPoint( _attachedTo, anchor );
> getRelAxis( _attachedTo, direction );
>
> // update the ray
> dGeomRaySet( _rayGeom, anchor[0], anchor[1], anchor[2],
> direction[0], direction[1], direction[2] );
>
> //reset distance measurement, it will be properly measure
> //soon when collision detection is performed
> _distance = _maxLength;
> }
>
> I hope somebody can help me here -- this is very frustrating.
>
> Shamyl Zakariya
> "this is, after all, one of those movies where people spend a great
> deal of time looking at things and pointing."
> From a review of _Fantastic Voyage_
>
> _______________________________________________
> ODE mailing list
> ODE at q12.org
> http://q12.org/mailman/listinfo/ode
>
More information about the ODE
mailing list