Page 1 of 1

Accessing joint information and direct control

Posted: Fri Apr 23, 2010 9:17 pm
by naokunew
Hi,

I'm using the ObjectiveC wrapper for Chipmunk for an iPhone project.
My intended use is to allow users to create an avatar which will move around.

To accomplish this, I wanted to have the avatar both control and interpret information about elements of it's body.
Specifically, what I am trying to achieve at the moment is to be able to interpret the angle between the two bodies joined by a joint. Ideally, I would also like to be able to set a goal angle between the two bodies, and lerp that over time.

I am currently using a PivotJoint to join the bodies, and this functions correctly, however I cannot get access to anything that appears to be the angle.
To adjust the relationship between the bodies across the constraint, I am applying an impulse to one of the bodies, but this is a step removed from what I actually wish to achieve. It also requires me to specify a vector (2 values) when I really wish to be able to control it with one.

In summary:
I would like to control the angle of a joint by specifying a value - how could I achieve this?
I would like to be able to read the angle of a joint - how could I achieve this?

Re: Accessing joint information and direct control

Posted: Sun Apr 25, 2010 1:09 pm
by slembcke
Joints only store information about the values that they constrain. A pivot joint doesn't know anything about angles. Bodies store their current absolute rotation so you can just do body2->a - body1->a. If you just want the absolute angle between the two vectors (like the body->rot vector), you can just do acos(cpvdot(body1->rot, body2->rot)). If you need the relative angle, you can do cpvtoangle(cpvrotate(body1->rot, body2->rot)). Getting the angle between the rotations like this will always give you a angle of less than half a revolution.

If you want to control the angle between two bodies use a gear joint with a gear ratio of 1.0 so that they always match rotations. To smoothly control the angle, set the maxBias (in radians per second) and maxForce of the joint as well. You can safely change the gear joint's phase property at any time to change the desired rotation between the bodies.

Re: Accessing joint information and direct control

Posted: Mon Apr 26, 2010 8:41 am
by naokunew
Thanks for the reply,

I've given this a go, but I can't get it to behave as I wish.

While I can use the gear to set the desired angle, if I have any gravity applied it doesnt seem to apply enough force to actually move anything. For example, if you imagine a ragdoll which has fallen onto it's legs on the ground, if I tell it to bend it's knee where you might expect it to straighten it's leg and raise it's body slightly, nothing happens.
I have set the biasCoeff, the maxBias and maxForce, but my understanding is that none of these affect the torque being applied, just limit the effect it would have.

How is the force being applied being calculated? Can I have control over that, or am I better off manually applying a torque and relying on the pivot joint to ensure the correct behavior?

Would it be possible to get a bit more documentation and maybe some worked examples of the constraints in the wiki docs? They are very light on, at this point it isn't really clear to me what joint I should use to get a particular outcome, nor what I can and can't control about them. I found the youtube clip very helpful for understanding the constraints in general, but in this specific case I am pretty much at a loss at how to achieve what I want.

Re: Accessing joint information and direct control

Posted: Mon Apr 26, 2010 9:23 am
by slembcke
http://code.google.com/p/chipmunk-physi ... y_Feedback
I have set the biasCoeff, the maxBias and maxForce, but my understanding is that none of these affect the torque being applied, just limit the effect it would have.
That's not exactly true. By default, each frame a joint will correct itself by 10% of the amount it is off by. This doesn't sound like a lot, but 30 frames later the error would be reduced to 4.2%. Assuming 60fps, a second later it would only be 0.18% off. The default joint values that control this are a biasCoef of 0.1 and a maxForce and maxBias of infinity. This means that the joint can correct itself as fast as it wants and with as much force as it wants to reach that 10% correction goal every frame. In the case of a radial joint like the gear joint, maxBias is in radians per second and maxForce is actually the maximum torque.

So my guess is that you are setting your maxForce too low to be able to lift the joint any more. Keeping in mind that this is a torque value, you might need to set a very large value depending on the scale you are using. I would probably leave biasCoef alone. It rarely needs to be changed, and 0.1 seems to give nice stable results.

Re: Accessing joint information and direct control

Posted: Tue Apr 27, 2010 5:15 pm
by naokunew
Thanks again for the reply,

you are correct, upping the maxforce had the desired affect. The value required was orders of magnitude beyond what I had expected, which is why I saw no result.
For anyone searching here later, I'm using trianglular bodies with a mass of 1, and a size off roughly 40 tall by 20 wide attached to a 40x40 square with a mass of 1 as well, but the required maxforce is on the order of 10000 to 100000. The values of infinity give odd behaviour in my case because of the multiple joints and the rate which i change the phase, but were a good indicator that the values required tweaking rather than not working at all.

So to summarise, to control the angle across a pivot joint I am also using a gear constraint. I can alter the phase to set the desired angle.

This tends to prevent the pivot joint from acting normally under gravity, so I also alter the maxforce as well as the phase. In my case, I wish to control only one thing at a time:

Code: Select all

        for(ChipmunkGearJoint* gear in gears){
		gear.maxForce = 1000.0;
	}
	ChipmunkGearJoint* gear = [gears objectAtIndex: selectedGear];
	gear.phase = desiredAngle;				
	gear.maxForce = 10000.0;
In the above I set the maxforce back down, which allows gravity to affect the pivotjoint as I want (in this case phase becomes irrelvant), and then on my selected gear, I up the
maxForce and set the phase.