Collision response filtering

Post Reply
forsslund
Posts: 2
Joined: Mon Dec 11, 2017 3:19 pm

Collision response filtering

Post by forsslund »

Hello,
I am making an application where the user control a sphere, moving it freely in a confined space with a 3D haptic device (a kind of joystick) using a generic 6dof constraint. In the space there a number of boxes the user can pick up with the sphere (using additional 6dof constraints) and move about. However, as a first step, I would like the other boxes to remain static visavi the picked up box. Any other motion is ok, like gravity, affecting all boxes.

I have tried with collision filtering, but obviously then there is no collision response at all. I would still like collision response but only one-way, that is my picked up box should be constrained from moving into the other boxes in the environment, but the boxes should otherwise be free to move. I have tried setting mass to 0 when in contact and then back to some non-zero mass after release but some energy is still added. Is there a proper way to handle this scenario?
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA
Contact:

Re: Collision response filtering

Post by Erwin Coumans »

There is no such thing as one-way collision response, since Newton laws action force = - reaction force.

It is not clear what you try to achieve, and why this requires a non-physical interaction. Usually you let the user control some object (sphere) using some constraint that follows the user intention (such as a VR gripper etc).
forsslund
Posts: 2
Joined: Mon Dec 11, 2017 3:19 pm

Re: Collision response filtering

Post by forsslund »

Thanks for the quick reply! I will try to explain better. Here is a screenshot of the full environment, showing our avatar (green sphere) which is indeed controlled by a btGeneric6DofConstraint, whose A frame offset is updated with the device position at each step.
all.PNG
all.PNG (105.48 KiB) Viewed 3720 times
push.PNG
push.PNG (36.93 KiB) Viewed 3720 times
Here box A is picked up with another btGeneric6DofConstraint and both avatar and box A can be moved about, however A very easily pushes box B. In reality we would at least have friction. I assume that the constraint simply has higher priority(?), making both boxes move without effort. (I have tried various friction values)
push2.PNG
push2.PNG (34.96 KiB) Viewed 3720 times
If we push B to the static wall the "spring" of the btGeneric6DofConstraint is enlarged, illustrated by showing the device position (user intent) in yellow vs the avatar (green). I would like something similar, as a way to model friction, for situations above as well. If friction is set very high, I think it would make boxes semi-static without breaking newtons laws..(?)

To clarify further, I am using the difference between the device position and avatar position as the real force feedback to be output to the haptic device. This way the user would be able to feel objects before they are pushed away, and feel if box B is pushed by the held Box A.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Collision response filtering

Post by drleviathan »

I think maybe the strengths (max force/torque?) of btGenetic6DofConstraint can be tuned to make the constraint "weaker". Even if that works you wouldn't be able to make one setting to get the gradual increase of pressure it sounds like you want, unless you dynamically update the constraint's parameters. Also, the parameters of the constraint are many and not necessarily intuitive.

There is another way to do what you want. This article talks about it:

http://www.vrinflux.com/newton-vr-physi ... -the-vive/

In short: you slam the velocity of boxA toward its target position and allow that push boxB. You may need to tweak the mass of boxA (make it less massive) while it is pushing to get the exact feel that you want.

In Bullet you would do this by deriving an Action from btActionInterface. Something like this "critically damped spring with zero history" that can be tuned with a simple "timescale". To tune: figure out how fast you want the spring to be able to move the object to its target position when unimpeded. 1 second? 2 seconds? half a second? Whatever, the longer the time the weaker the spring, the shorter the timescale the stronger. Once you know how much time for the spring to be able to reposition the object, divide that number by about three and use that as the action's "timescale". Why 3? Because the action will reduce the object's offset by about 1/e every substep and e^-3 is a pretty small number.

Code: Select all

class TractorAction : public btActionInterface {
public:
    TractorAction(btRigidBody* body, btScalar timescalel) : m_timescale(timescale), m_body(body) {
        m_targetPosition = body->getPosition();
    }

    void setTargetPosition(const btVector3& position) { m_targetPosition = position; };

    void setTimescale(btScalar) {
        // DANGER: timescale should NEVER be smaller than the largest possible substep, else instability
        const btScalar MIN_TRACTOR_TIMESCALE(2 * MAX_SUBSTEP_PERIOD);
        m_timescale = btMax(timescale, MIN_TRACTOR_TIMESCALE);
    }

    void updateAction(btCollisionWorld* world, btScalar timeStep) {
        // this is a "critically damped spring with zero history":
        // every frame it slams the velocity of m_body to approach m_targetPosition with exponential decay
        const btScalar MIN_ACTIVATION_OFFSET_SQUARED = 0.0001f; // 1cm^2
        btVector3 offset = m_targetPosition - m_body->getPosition();
        if (m_body->isActive()) {
            m_body->setLinearVelocity((timeStep / m_timescale) * offset);
        } else if (offset.length2() > MIN_ACTIVATION_OFFSET_SQUARED) {
            m_body->activate();
            m_body->setLinearVelocity((timeStep / m_timescale) * offset);
        }
    }

private:
    btVector3 m_targetPosition;
    btScalar m_timescale;
    btRigidBody* m_body;
};
Some notes:

I'm typing this example code from scratch and memory. Dunno if this actually compiles or is bug-free.

This action doesn't care about the object's mass. It just computes a velocity that always pushes the object toward its target. When the object gets close to its target it will set the velocity to a small value (the object will come to a stop).

You might want to temporarily reduce the sprung object's mass to tune how hard it "hits" any dynamic obstacles as it moves toward its target. When the sprung object is light it will tend to be stopped by the obstacle: it makes the "friction" effect you're looking for more noticeable. That is, you could keep the action responsive by setting its timescale small (1/10 a second for example) but make its strength weak by setting the sprung object's mass artificially small.

You might also want to temporarily reduce the sprung object's restitution so that it doesn't "bounce" off of heavy obstacles and static objects.

You might also want to temporarily increase the sprung object's angular damping (or to modulate its angular velocity inside the updateAction()) to prevent it from swinging about fast when clipping an obstacle.
Post Reply