Rotating one object at the expense of the second

Post Reply
leusd1000
Posts: 5
Joined: Tue Nov 03, 2020 6:00 pm

Rotating one object at the expense of the second

Post by leusd1000 »

I'm new to Bullet physics I have a problem. My task is related to the rotation of two objects. The task is to rotate the lower object and the upper object would rotate due to friction. At this point, the bottom object rotates as needed, but it doesn't affect the top object in any way. I tried to change different friction values, but it didn't work. I will be grateful for any help.

Best regards, Dmitry.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Rotating one object at the expense of the second

Post by drleviathan »

If I understand what you're asking (correct me if I'm wrong): you want to have a dynamic object dragged around when it sits on a rotating kinematic "floor".

The trick is: not only do you have to rotate the kinematic floor but you must also set its velocities to agree with its movement.

There is one other gotcha: don't forget to activate the kinematic object when you start rotating it. That will guarantee the dynamic object will also be activated and will be moved during the "integration" portion of Bullet's btDynamicsWorld::stepSimulation().
leusd1000
Posts: 5
Joined: Tue Nov 03, 2020 6:00 pm

Re: Rotating one object at the expense of the second

Post by leusd1000 »

Thanks for the quick response. Your advice really helped me, but there are still some problems. The problem was that I did not activate the kinematic object, but now there is a new problem. When trying to put a dynamic object
to kinematic, then a bounce of a dynamic object occurs (from which you need to get rid). I also added a setRestitution (0.0) property for both objects, but that didn't fix the problem (getting rid of the bounce). Here is I rotate kinematic object(body->object) on simulation step:

Code: Select all

//rotation
btQuaternion m_lastRot;
btTransform tranf = body->object->getWorldTransform();
tranf.getBasis().getRotation(m_lastRot);
btQuaternion qx(btVector3(1, 0, 0), 1);
const btScalar RADIANS_PER_DEGREE = 3.14159 / btScalar(180.0);
btQuaternion q = btQuaternion(0.0f, 0.0f, 1.0f * RADIANS_PER_DEGREE);
tranf.setRotation(q * m_lastRot);

body->object->setWorldTransform(tranf);

body->object->setCollisionFlags(body->object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
body->object->activate(true);			
body->object->setRestitution(btScalar(0.0));
And also setting restitution for dynamic object on simulation step:

Code: Select all

body->object->setRestitution(btScalar(0.0));
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Rotating one object at the expense of the second

Post by drleviathan »

Dunno what is causing your "bounce". Does the dynamic object fall onto the kinematic floor and bounce only when it first touches? Or does it bounce constantly as the simulation continues? Perhaps it is a tunneling penetration resolution glitch: what are your steps, substeps, and min_num_substeps? what are your object sizes? What shape types are you using for dynamic object and kinematic floor?

You don't need to: setCollisionFlags(), activate(), or setRestitution() constantly after every step. Those can be done just once.

BTW, there is a nice trick you can use for kinematic objects: if the floor doesn't need to visually rotate but you want the dynamic object to move as if the floor were spinning, then you can just set the angularVelocity of the floor once (don't forget to activate it) and then don't bother to update the floor's transform. The dynamic object's contact points will detect the floor's angularVelocity and move accordingly. You can do this with linearVelocity to make "conveyor belts" which don't actually move, but do move the dynamic objects that touch them. One gotcha here: the velocities you use must be larger than the sleeping thresholds, else the kinematic conveyor will be deactivated after 2 seconds, and probably also the dynamic objects that touch them.

A nice way to animate a kinematic object is to derive a CustomAction from btActionInterface and then add the action to the World. So for a spinning kinematic object the CustomAction might look like this:

Code: Select all

// dunno if this works or even compiles (I did not test)

constexpr btScalar MIN_ANGULAR_SPEED = 1.0e-4;

class KinematicSpinnerAction : public btActionInterface {
public:
    KinematicSpinnerAction(btRigidBody* body)
        : m_body(body), m_axis(0.0, 0.0, 0.0), m_angularSpeed(0.0)
    {
        assert(m_body != nullptr);
    }

    void setAngularVelocity(const btVector3& angularVelocity) {
        m_angularSpeed = angularVelocity.length();
        if (m_angularSpeed > MIN_ANGULAR_SPEED) {
            m_axis = (1.0 / m_angularSpeed) * angularVelocity;
            m_body->setAngularVelocity(angularVelocity);
        } else {
            m_body->setAngularVelocity(btVector3(0.0, 0.0, 0.0));
        }
    }

    void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) final override {
        if (m_angularSpeed > MIN_ANGULAR_SPEED) {
            // always activate if necessary
            if (!m_body->isActive()) {
                m_body->activate();
            }
            // compute and set new transform
            btTransform t = m_body->getTransform();
            btScalar angle = deltaTimestep * m_angularSpeed;
            btQuaternion dq(m_axis, angle);
            t.setRotation(dq * t.getRotation());
            m_body->setTransform(t);
        }
    }

    void debugDraw(btIDebugDraw* debugDrawer) final override { }

private:
    btRigidBody* m_body;
    btVector3 m_axis; // normalized axis
    btScalar m_angularSpeed; // radians/sec
};
leusd1000
Posts: 5
Joined: Tue Nov 03, 2020 6:00 pm

Re: Rotating one object at the expense of the second

Post by leusd1000 »

Thanks for the helpful tips, but the problem was different. I first build a hard case with default settings, and then use the setWorldTransform function to place this body where I need it. So, after the first step, the speed of the body becomes higher, and because of this (as I understand it) there was a ricochet. Now I set the conversion with btDefaultMotionState at build time and it works.
But now I have another problem... During rotation, objects begin to slide from the rotating object by centrifugal force(as I understand). This is normal, this is how physics works, but even when the rotation velocity is very low and the force should not be enough to move objects, the second ones still slip. So how can I handle (reduce or turn off) that force or could it be the problem with something else?
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Rotating one object at the expense of the second

Post by drleviathan »

I have two ideas:

(1) Increase the friction coefficient on one or both objects? I believe friction > 1.0 is ok.

(2) Increase the substep frequency (e.g. reduce the substep duration) toward 240 Hz if you aren't already there yet.
leusd1000
Posts: 5
Joined: Tue Nov 03, 2020 6:00 pm

Re: Rotating one object at the expense of the second

Post by leusd1000 »

(1) I tried different values for friction (0, 10] for both objects but that doesn't helped, still slips.
(2) I didn't get how it could helps, but it looks like this value is already set

Code: Select all

 stepSimulation(0.1f, 10000, 1.0f / 2400.0f);
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Rotating one object at the expense of the second

Post by drleviathan »

You're calling stepSimulation(timeStep, maxSubSteps, subStep) with:

Code: Select all

fixed timesStep = 0.1f
maxSubSteps = 1000
fixed subStep = 1.0f / 2400.0f
I haven't explored it myself, but there have been reports of strange stuff happening at subSteps smaller than 1/1000. Meanwhile, if you don't have objects moving at "unreasonably high speeds" then such a short subStep is probably not necessary, maybe even wasteful (in terms of CPU cycles spent for simulation results).

If you don't expect tunneling at subStep= 1/240 I would suggest trying it just to see what happens. If that doesn't solve your problems then well... I might be out of ideas without either: (a) more info (*) or (b) debugging a running example.

(*) When it comes to more info, these questions come to mind:

(1) You're using convex shapes for things that move, right?
(2) What are you really trying to do? Are you making a game (which just needs to be fun and might benefit from non-physical hacks) or are you trying to provide a physically accurate simulation?
Post Reply