computing work done by a btGeneric6DofConstraint?

mepster
Posts: 5
Joined: Fri Dec 17, 2010 12:26 am

computing work done by a btGeneric6DofConstraint?

Post by mepster »

I'm trying to compute the total work done by a btGeneric6DofConstraint in the last timestep. Has anyone figured out how to do this?

I am using Bullet to evolve neural controllers for simulated robots. The robot legs are powered by btGeneric6DofConstraint joints (I'm only using the btRotationalLimitMotor part). I will make the evolutionary fitness consider the total work done by all the legs. (This will make the running more natural.)

I think I would understand how to do this with btRotationalLimitMotor::solveAngularLimits(). (There you can get the impulse that is actually applied. So if you just get the angle it's applied over, I think you can compute the work.)

However, looks like solveAngularLimits() is now obsolete - it is not called anywhere in the bullet libraries. There is a function btTypedConstraint::getAppliedImpulse(), but this returns a scalar. Work = distance * impulse (both are vectors) / time, so a scalar is not enough.

Has anybody else computed total work done by a rotational motor, or have any tips where I should try to get the work, or the impulse & angle traveled? E.g., a hint like "the best place to get both is after the total impulse is computed in function XYZ".

Thanks!


P.S. Here are some videos of the evolved robots, you may recognize the body model from one of the Bullet demos called MotorDemo. http://youtube.com/geccospider
kloplop321
Posts: 55
Joined: Sun Jan 01, 2012 7:37 pm

Re: computing work done by a btGeneric6DofConstraint?

Post by kloplop321 »

Wait, are you doing evolutionary neural networks that are connected to sensors and emitters?

:shock:

This is really cool
mepster
Posts: 5
Joined: Fri Dec 17, 2010 12:26 am

Re: computing work done by a btGeneric6DofConstraint?

Post by mepster »

Sensors and effectors, yeah... thanks! Bullet is very good for evolutionary robotics.

Wonder if anyone else has some tips on computing the total work done by a rotational motor. I set the m_targetVelocity of the rotational motor, and at some point this gets converted to a torque, can anyone explain how/where? (That's the point where I might be able to put a callback or something to accumulate the total work.)

I believe the next place the m_targetVelocity pops up is in btGeneric6DofConstraint::get_limit_motor_info2(). Here an m_constraintError is computed from it... but at that point I lose it. Where does the m_constraintError get converted into an actual torque that is applied? I imagine somewhere the constraint errors are all resolved...?

Thanks for any explanation or help!

Cheers,

Mike
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: computing work done by a btGeneric6DofConstraint?

Post by Erwin Coumans »

The constraint solver internally updates the m_accumulatedImpulse for each constraint row.

This is not properly updated in this function:
btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish( ... )
So perhaps there is a better way to provide the constraint feedback.

You might be able to run the 'obsolete' code path (check out m_useSolveConstraintObsolete) and use the applied impulses as part of each limit/motor.

Hope this helps,
Erwin
anyway
Posts: 2
Joined: Mon Apr 23, 2012 2:57 pm

Re: computing work done by a btGeneric6DofConstraint?

Post by anyway »

Hi,

I am also interested in this topic. I tried to implement a torque sensor on a hinge constraint and a generic 6 dof constraint. I tried to get the obsolete code path to work on a generic 6 dof constraint as proposed by Erwin. I set the flag D6_USE_OBSOLETE_METHOD in btGeneric6DofConstraint.cpp with is used to initialize m_useSolveConstraintObsolete. But if I run my code now, there is an other problem: The first segment of my robot arm is attached to the world frame

Code: Select all

hingeGen1 = new btGeneric6DofConstraint(*upperArmRB, trans, false);
hingeGen1->setAngularLowerLimit(btVector3(0,0,-3.14));
hingeGen1->setAngularUpperLimit(btVector3(0,0,3.14));
hingeGen1->setLinearLowerLimit(btVector3(0,0,0));
hingeGen1->setLinearUpperLimit(btVector3(0,0,0));
hingeGen1->enableFeedback(true);
mot1 = hingeGen1->getRotationalLimitMotor(2);
dynamicsWorld->addConstraint(hingeGen1, true);
The second constraint is set up between this segment and the other segment

Code: Select all

hingeGen2 = new btGeneric6DofConstraint(*upperArmRB, *lowerArmRB, transA, transB, true);
hingeGen2->setAngularLowerLimit(btVector3(0,0,-3.14));
hingeGen2->setAngularUpperLimit(btVector3(0,0,3.14));
hingeGen2->setLinearLowerLimit(btVector3(0,0,0));
hingeGen2->setLinearUpperLimit(btVector3(0,0,0));
hingeGen2->enableFeedback(true);
mot2 = hingeGen2->getRotationalLimitMotor(2);
dynamicsWorld->addConstraint(hingeGen2, true);
But unfortunately the the second constraint seems to be ignored by the solver. The second segment starts to move down (due to gravity) immediately. This does only happen if the obsolete code path is used. I checked the enabled-flag and the constraint seems not to be disabled or broken.

Does the obsolete code path still works in Bullet? What can I do to get this to work and obtain correct values for torques / impulse applied by one rotational motor only? Currently I am using Bullet 2.79.

Please help, I'm really in trouble here.

Greetings,
anyway