How to make a correct limbo-hinge? ( door-wall example )

User avatar
Dragonlord
Posts: 198
Joined: Mon Sep 04, 2006 5:31 pm
Location: Switzerland

How to make a correct limbo-hinge? ( door-wall example )

Post by Dragonlord »

I've got a simple setup where a door ( a box ) is connected to a static wall ( hence a static hinge ). I'm using a hinge constraint. So far this works but I want to restrict the door from moving uncontrollable. Hence if the door is shut the angle is 0 and if the door is open it is something like 90° for example. Hence I want to limit the door to swing only from 0° to 90°. I tried doing it the following way:

Code: Select all

const btVector3 btPivotA( pivot.x, pivot.y, pivot.z ); // right next to the door slightly outside
btVector3 btAxisA( 0.0f, 1.0f, 0.0f ); // pointing upwards, aka Y-axis

hinge = new btHingeConstraint( *phyBody, btPivotA, btAxisA );

hinge->setLimit( 0.0f * ONE_PI, 90.0f * ONE_PI );
The door though still swings without any limit. How am I supposed to get this simple setup working? Or can the hinge not be limited?
User avatar
Dragonlord
Posts: 198
Joined: Mon Sep 04, 2006 5:31 pm
Location: Switzerland

Re: How to make a correct limbo-hinge? ( door-wall example )

Post by Dragonlord »

Managed to get this one working but it required a hack on the sources. First I noticed that there is a constructor version which uses an entire coordinate system instead of only an axis. Using this one enabled the limits and they worked... just not as expected. After some fiddling around I noticed that the case rigidBody<->staticWorld has a short sight in the constructor not transforming back the axis only the position ( which works for the case you only and ever want to rotate around the Z-Axis ). This had though not been enough. The hinge behaves badly if the limits are either both positive or both negative. For this I recalculated on the fly the limits and centered them so the hinge should work optimally. The given constructor though is not able to cope this change since it works only on the rbAFrame and calculates rbBFrame by back-projecting. The solution had been to hack in a new constructor where I can specify both coordinate systems for the case of a single body.

BulletDynamics/ConstraintSolver/btHingeConstraint.h, line 72ff

Code: Select all

	btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, const btTransform& rbBFrame);

BulletDynamics/ConstraintSolver/btHingeConstraint.cpp, line 167ff

Code: Select all

btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, const btTransform& rbBFrame)
:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame),
m_angularOnly(false),
m_enableAngularMotor(false)
{
	// flip axis
	m_rbBFrame.getBasis()[0][2] *= btScalar(-1.);
	m_rbBFrame.getBasis()[1][2] *= btScalar(-1.);
	m_rbBFrame.getBasis()[2][2] *= btScalar(-1.);
	
	//start with free
	m_lowerLimit = btScalar(1e30);
	m_upperLimit = btScalar(-1e30);	
	m_biasFactor = 0.3f;
	m_relaxationFactor = 1.0f;
	m_limitSoftness = 0.9f;
	m_solveLimit = false;
}
Requires now some code to transform the coordinate systems ( since Bullet seems to expect hinges to always rotate around the Z-Axis ) and applying a correction matrix for the rbBFrame only and it works.

The only problem I noticed so far is that the hinge is a bit... relaxing. Hence if I lean some object against the door it pushes the door slightly ( maybe 0.1° or so ) into the door frame ( hence below the allowed swing range ). It stays there but maybe there is a way to prevent this from happening ( hence a strong constraint that never allows the door to swing past a certain angle ). Apart from this it's now working. Just have to add some dampening so the door does not swing that freely.
mhx
Posts: 6
Joined: Wed Apr 18, 2007 8:12 pm

Re: How to make a correct limbo-hinge? ( door-wall example )

Post by mhx »

Dragonlord,

Since this is an open-source project you are more than welcome to contribute. These are obviously missing features/bugs and your points are very valid. I assume you already noticed that 90.0f*PI doesn't make any sense for the joint limits.
Either one adds a constructor which takes the B-frame as well, or maybe one can rotate the b frame around the axis of revolution when setting the joint limits, i.e do exactly what you do and calculate the center angle and rotate the frame the corresponding degrees around the z-axis and store the equal offset internally.

One could also let the user specify which axis to rotate around instead of having to rotate the frame yourself, I just assumed that would be fine since you typically have to specify a frame for your joints in your game engine. As for the "soft" limits, this is a deliberate design decision that damps the angular velocity before reaching the actual limit in an effort to reduce jitter and also to get a more natural behaviour for ragdolls. Try fiddling to with the limit softness parameter and see if you can get things to behave like you want, otherwise I can try to rework it a bit.

If you already have for fixes for these issues I suggest you send them to Erwin, I won't have time to fix this for a while now since things are a bit crazy at work, but later on I can have a whack at it.

Cheers and good luck,
Marcus (who added the joint limits).
User avatar
Dragonlord
Posts: 198
Joined: Mon Sep 04, 2006 5:31 pm
Location: Switzerland

Re: How to make a correct limbo-hinge? ( door-wall example )

Post by Dragonlord »

mhx wrote:I assume you already noticed that 90.0f*PI doesn't make any sense for the joint limits.
Can't follow you there right now. What's the problem with a 90° angle? With my setup this worked out as expected.
Either one adds a constructor which takes the B-frame as well, or maybe one can rotate the b frame around the axis of revolution when setting the joint limits, i.e do exactly what you do and calculate the center angle and rotate the frame the corresponding degrees around the z-axis and store the equal offset internally.
Not sure exactly if you talk now about the construtor (ribigBodyA,rbFrameA). This one works but misses a call to also rotate the angle. The following line fixed this problem:

BulletDynamics/ConstraintSolver/btHingeConstraint.cpp, line 148ff:

Code: Select all

	m_rbBFrame.setBasis( m_rbA.getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis() );[/quote]

This way specifying any coordinate frame for rbAFrame produces the correct rbBFrame in world space. In my specific case this didn't work though since I adjusted the hinge. Lemme explain a bit what I mean here. I have for example a hinge where a user wants to set the limits (10°->160°) [ sort of cranked up door that can not close fully anymore ). In certain situations ( especially under the influence of gravity ) this can cause the object to jitter around 10° never coming to rest. What I did now is centering the hinge by calculating the center ( here 85° ) and equal swing in both directions ( here 75° ). This way I had a hinge with the limits ( -75° -> 75° ) which works optimal. The problem now is that the axis has to be rotated by 75° along the rotation axis to compensate for this centering but this fix goes [i]only[/i] to rbBFrame and not rbAFrame or else it won't work. This specific situation can only be fixed with the new constructor I mentioned above taking both frames. I hope I could explain a bit what I'm messing around with :D

[quote]As for the "soft" limits, this is a deliberate design decision that damps the angular velocity before reaching the actual limit in an effort to reduce jitter and also to get a more natural behaviour for ragdolls. Try fiddling to with the limit softness parameter and see if you can get things to behave like you want, otherwise I can try to rework it a bit.[/quote]
I tried already with softness=1.0, relaxing=1.0 and various values for the bias parameter. So far nothing changed the behavior. Chances are though I misunderstood what the parameters are doing, which is very well possible.

[quote]If you already have for fixes for these issues I suggest you send them to Erwin, I won't have time to fix this for a while now since things are a bit crazy at work, but later on I can have a whack at it.[/quote]
He should be frequenting this board so if he considers it important he takes a stab at it. After all he's a busy man too ( who is not :( )

Cheers and good luck,
Marcus (who added the joint limits).[/quote]
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: How to make a correct limbo-hinge? ( door-wall example )

Post by Erwin Coumans »

The btHinge::setLimit only accepts radians, not degrees. So instead of 90*PI (which mixes degrees and radians), you should use SIMD_HALF_PI (as defined in LinearMath/btScalar.h), or multiply degrees by SIMD_RADS_PER_DEG to get radians:

Code: Select all

hinge->setLimit( 0.0f, SIMD_HALF_PI );
//or equivalent
hinge->setLimit( 0.0f, 90 * SIMD_RADS_PER_DEG );
This specific situation can only be fixed with the new constructor I mentioned above taking both frames.
Or, as Marcus mentioned, we can also center the b frame around the axis of revolution inside the hinge->setLimit(...) implementation.
He should be frequenting this board so if he considers it important he takes a stab at it.
I'm indeed too busy to process each patch/comment straight away, even though a few other developers are helping with develpment now. We recently started using Google Code, including the issue tracker, and you issue is here:
http://code.google.com/p/bullet/issues/detail?id=41

Can you try to create a new fix and submit a patch/code snippet for btHinge::setLimit to that issue, that rotates the frame B?
On the softness/relaxation tuning, please experiment a bit more, and otherwise hopefully Marcus can help out.

Thanks for the feedback/fixes!
Erwin
User avatar
Dragonlord
Posts: 198
Joined: Mon Sep 04, 2006 5:31 pm
Location: Switzerland

Re: How to make a correct limbo-hinge? ( door-wall example )

Post by Dragonlord »

Erwin Coumans wrote:The btHinge::setLimit only accepts radians, not degrees.
Ah he meant this. My engine runs internally on radians too so that's no problem. The user can just enter the limits in degrees since that's more natural for a designer than dealing with radians himself ;)
Or, as Marcus mentioned, we can also center the b frame around the axis of revolution inside the hinge->setLimit(...) implementation.
That's correct. In fact the fix would be not that difficult if I get this right. After all the equation just has to first subtract the center value from the current angle, then do equation as it is, and then then adding the center value again. In this situation no tampering with the rbBFrame would be required at all and the existing constructor ( with the axis fix ) would work.
We recently started using Google Code, including the issue tracker, and you issue is here:
http://code.google.com/p/bullet/issues/detail?id=41

Can you try to create a new fix and submit a patch/code snippet for btHinge::setLimit to that issue, that rotates the frame B?
On the softness/relaxation tuning, please experiment a bit more, and otherwise hopefully Marcus can help out.
Uhm... Google hates me. But I can try if I get there. Otherwise I just post here.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: How to make a correct limbo-hinge? ( door-wall example )

Post by Erwin Coumans »

Dragonlord wrote: But I can try if I get there. Otherwise I just post here.
If you have issues with Google Code issue tracker, you can zip the modified btHingeConstraint.cpp/h source code and attached it to this forum thread.

Thanks,
Erwin
bindumol
Posts: 15
Joined: Thu May 08, 2008 9:55 am
Location: India, Kerala

Re: How to make a correct limbo-hinge? ( door-wall example )

Post by bindumol »

Hi,
How i can make the door to open in a given angle....means i get it from the user as in degrees i give the limit as 0-90 degree.firstly i try to open it for 1 degree..next try it for 2 degree but it is not moving...why?
code

int iAngle = GetDlgItemInt(IDC_EDIT_Degree);
hingeC->setLimit(0.0f, iAngle*SIMD_RADS_PER_DEG);
btScalar fCurAngle = hingeC->getHingeAngle();
btScalar fTargetPercent = 0.008f;
btScalar fTargetAngle = 0.5 * (1 + sin(2 * M_PI * fTargetPercent));
btScalar fAngleError = fTargetAngle - fCurAngle;
btScalar fDesiredAngularVel = 1000000.f * fAngleError/ms;
hingeC->enableAngularMotor(true, fDesiredAngularVel, m_fMuscleStrength);
during the creation of the hinge i gave the limit as (0.0f, 90*SIMD_RADS_PER_DEG)
How i can do a controllable angular movement using hinge constraint?
Please help me....
User avatar
Dragonlord
Posts: 198
Joined: Mon Sep 04, 2006 5:31 pm
Location: Switzerland

Re: How to make a correct limbo-hinge? ( door-wall example )

Post by Dragonlord »

Use my path I posted in the release section which adds the needed constructors. Then build a btTransform for the door ( relative to the coordinate system of the door with the hinge point as center ). Then you need to create a second btTransform which is the first one transformed into world coordinates ( hence the same transform but this time in reference to the world/limbo ). Keep in mind that the rotation axis is the Z-Axis in Bullet so orient the transform accordingly.

Works only this way since the existing constructors can only handle one specific case which is that your rotation axis does point along the world Z-Axis but this is nearly never the case ( especially if in your game Y-Axis is up ).

EDIT: Maybe it's possible to use the constructor with one btTransform. It should do the same as mentioned above with the second transform derived from the first. But then your body has to be in the proper location already and it is tricky. Never worked for me.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: How to make a correct limbo-hinge? ( door-wall example )

Post by Erwin Coumans »

Thanks for the feedback, we will look into the issue, and see what can be done.

Have you tried the btSliderConstraint, does it have the same issue?
Thanks,
Erwin
bindumol
Posts: 15
Joined: Thu May 08, 2008 9:55 am
Location: India, Kerala

Re: How to make a correct limbo-hinge? ( door-wall example )

Post by bindumol »

hi,
I tried it by using btSliderConstraint, but there also the relative movement of bodies ie, one body rotated based on another one's axis , is not present.It is rotating as it's own center of mass position.But there the rotation happening is based on the body's center of mass position , not using the other body's axis.


1. Is it possible controllable rotation using slider motor?
2. Is there any sample applications present , that use both Irrlicht and bullet physics that use mesh file /.obj file loading?
Please help me..
Regards,
Bindumol
bindumol
Posts: 15
Joined: Thu May 08, 2008 9:55 am
Location: India, Kerala

Re: How to make a correct limbo-hinge? ( door-wall example )

Post by bindumol »

hi Dragonlord,
I am using Irrlicht and bullet physics for my gaming application , the two transform method i implemented in my application, but it makes a pblm as that transformed body is linked with another body by using a fixed constraint...but it is slowly moving...and the scene become view as two independent bodies movement, i know i can solve this by transforming the attached body ...but i want to know there is any otherway to do this with only one body movement...
My code
int iAngle = GetDlgItemInt(IDC_EDIT_Degree);
btTransform trans = body->getWorldTransform();
for(int i = 1; i <= iAngle; i+=3)
{
trans = body->getWorldTransform();
trans.setRotation(btQuaternion(btVector3(1,0,0), (btScalar)i));
body->setWorldTransform(trans);
}
Thanks&Regards,
Bindumol
User avatar
Dragonlord
Posts: 198
Joined: Mon Sep 04, 2006 5:31 pm
Location: Switzerland

Re: How to make a correct limbo-hinge? ( door-wall example )

Post by Dragonlord »

What are you trying to achieve? Altering the rotation of one body with the other following ( sort of gear shaft like )? If this is the case do not adjust the rotation manually but use a motor for this.
bindumol
Posts: 15
Joined: Thu May 08, 2008 9:55 am
Location: India, Kerala

Re: How to make a correct limbo-hinge? ( door-wall example )

Post by bindumol »

Hi,
The actual problem is , if i am using the motor , i want to stop the motor if it turns a fixed angle..the motor attached with a bodies one fixed and another is movable...that also linked to some other bodies which are joined with the movable using fixed constraint....can you help me to solve my problem.

Thanks & Regards,
Bindumol
User avatar
Dragonlord
Posts: 198
Joined: Mon Sep 04, 2006 5:31 pm
Location: Switzerland

Re: How to make a correct limbo-hinge? ( door-wall example )

Post by Dragonlord »

I've not worked so far with motors only applying velocity changes myself but a motor should work the same. Important is only to orientate the transforms correctly. Best results are obtained if the 0-degree point is exactly in the middle of the open and closed position. This gave me the least errors.