[ODE] Trouble balancing "hover" rays over very short distances

Megan Fox shalinor at gmail.com
Fri Feb 4 12:09:51 MST 2005


My system is thus - every "walking" entity has a hover sensor cast
directly down from their torso.  This provides a convinient way of
allowing walking over uneven surfaces without collision geometry
snagging on every little thing along the way.

The problem, however, is that when this repulsor line gets very short
(below about 0.5 units), it ceases to function properly.  As far as
can tell, this is due to my force limiting code, which is there to
make sure the forces marshalled don't send the character sailing off
at high speeds whenever the penetration of the ray is finally
resolved.

It's sort of like trying to balance the forces of a harmonic system
where you can only apply forces on the negative half of the swing. 
Not something I've ever done.


If I work the system out with the math I've been using over the last
year (college physics with calculus focus, woo haw), all I seem to get
is my characters rocketting off into the stratasphere, so I've
resorted to physics black magic coding.  Except my black magic has
failed to handle the case of VERY small penetration distances, and
further black magic to fix that case has negative effects on the
(right now excellent!) balance of the rest of the system.


The current code is as follows:

// Grab out the data for the sensor
vector3 sensorPos, pushDir;
sensorList->Get(sensorPos, pushDir);

// Rotate the vector to be in world-space
quaternion curOrientation = this->targetEntity->GetRot();
pushDir = curOrientation.rotate(pushDir);

// Flip the vector (sensors always point in the "down" direction, we
want the "up" direction)
pushDir = -pushDir;

// Grab the relevant portion of the current velocity
vector3 curVelocity = nOpende::BodyGetLinearVel(this->tempBodyID);
vector3 velDir = curVelocity;
velDir.norm();
float relevantVel = curVelocity.len() * (velDir.dot(pushDir));

vector3 forceToApply;

// Now apply whatever up-force is necessary to fix the height of the
repulsor to desired levels
if (relevantVel < sensorList->repulsorUpForce *
(sensorList->repulsorHeight - sensorList->collisionDepth))
forceToApply = pushDir * (sensorList->repulsorUpForce *
(sensorList->repulsorHeight - sensorList->collisionDepth) -
relevantVel) / deltaTime;
else if (relevantVel < (sensorList->repulsorHeight -
sensorList->collisionDepth))
forceToApply = pushDir * ((sensorList->repulsorHeight -
sensorList->collisionDepth) - relevantVel) / deltaTime;
this->AddImpulseAtRelPos(forceToApply, sensorPos);

// If the collided-with geom has a body, apply the equal and opposite
counter-force
if (sensorList->collidedWith)
{
    nOpende::BodyEnable(sensorList->collidedWith);
    nOpende::BodyAddForceAtPos(sensorList->collidedWith,
-forceToApply, sensorList->collisionPos);
}



... the code is more complex than it need be for a simple up-push
because the same sensor code works for any respulsor in the system
(think hemispherically-mobile hover pads on the bottom of a hover
tank, that sort of thing).

Any suggestions are welcome.  The best idea I've got at the moment is
to decide that repulsors at that distance are pretty useless anyways
(they don't provide enough distance between the ground and character
to allow significantly more mobility than if the character's geom were
just dragging on the ground), and just not use them at distances below
0.5.

-Megan Fox


More information about the ODE mailing list