The typical uses of revolute joint are:
- wheels or rollers
- chains
- rotating doors,
- catapults,
- levers
How to create a revolute joint
Revolute joint (same as all the other joints in Moscrif) is represented by its own class RevoluteJoint. This class has no constructor, meaning that it has to be created by createRevoluteJoint function. This function creates revolute joint between two bodies that are set in first two parameters. The anchor point is set by following two parameters (firstly x then y coordinate). The coordinates of anchor point are ordinary screen coordinates (in pixels). In the fifth parameter, we could set additional joint options (motor or limits). The last parameter specifies if box2d detects collisions between the bodies connected in the joint or not.
Example: creating revolute joint
var joint = PhysicsScene.createRevoluteJoint(bodyA, bodyB,anchorX, anchorY, jointSet, true);
Anchor point
Anchor point defines the point around which bodies in joint rotate. Body rotation is influenced by its mass and gravity as well.
Image: anchor point

Motor
By default, revolute joint rotates without any resistance to interactions with other physical objects. It means, that bodies rotate if any force or mouse joint is applied onto them, or when the bodies collide with other objects. However, sometimes it is required to rotate the body by itself, without any interactions with other objects e.g.: when we want to create wheel on a vehicle. In such case, motor is used to rotate the joint. When the motor is specified, it tries to rotate by required speed. I wrote "tries to rotate", because it behaves like a real motor, so it can use only limited maximum torque specified in joint’s additional parameter motorTorque in (N•m). This means, that if something prevents the body rotating its speed is not guaranteed. The motor speed is set in angular velocity in radians per seconds.
Example: creating motor
// joint's options
var jointSet = {
enableMotor : true, // enable motor
motorSpeed : (- 1 * Math.PI / 2) * (800.0 / System.width), // final speed is linearly depends on radius (screen resolution)
maxMotorTorque : 2100000000, // maximum torque }
In our sample we use a motor which creates three rotors in the middle of the screen. Every rotor consists of two bodies. One of the bodies should stay without movement or rotation. We set its type to static, meaning that it does not move under the gravity or joint. We create the revolute joints and rotating body in _createRotor function.
Example: creating joint
function _createRotor(x, y)
{
var obj = {};
// get dimensions of the body
var (width, height) = (this._pictureRectangle.width, this._pictureRectangle.height); // static body, which do not moves
obj.bodyA = this.addPolygonBody(this._pictureRectangle, #static, 0.0, 1.0, 1.0, width, height);
// place the body
obj.bodyA.setPosition(x, y); // create second rotating body
obj.bodyB = this.addCircleBody(this._pictureCircle, #dynamic, 100.0, 0.0, 0.0, this._pictureCircle.width / 2);
// place the body
obj.bodyB.setPosition(x, y - System.width / 7 + this._pictureCircle.width / 4);
// joint's options
var jointSet = {
enableMotor : true, // enable motor
motorSpeed : (- 1 * Math.PI / 2) * (800.0 / System.width), // final speed is linearly depends on radius (screen resolution)
maxMotorTorque : 2100000000, // maximum torque }
// create joint
var joint = this.createRevoluteJoint(obj.bodyA, obj.bodyB, x, y, jointSet, true); // return object contains information about the joint
return obj;
}
Limits
Sometimes the joint is allowed to rotate only in certain specific range of angle. To limit the joint rotation, we can set lower and upper limits. The limits are ideal to use for simulating limbs. However, we do not use limits in this sample.
Additional sample feature
To make sample more interesting, there are also some additional features which are not directly related to revolute joint.
Body creating
When the user taps on the screen, new body is added. It is added randomly in rectangle or circular shape. It has less mass than the body used in revolute joint. When the body in revolute joint collides with other body of the same mass, its reaction to collision is significant jump away from collision place.
Example: creating a body in pointerPressed function
function pointerPressed(x, y)
{
// renerate random shape (1 is rectangle body, else is circular body)
var shape = rand(2); if (shape == 1) {
// get dimensions of the body
var (width, height) = (this._pictureRectangle.width, this._pictureRectangle.height);
// create the body
var body = this.addPolygonBody(this._pictureRectangle, #dynamic, 1.0 /*density*/, 1.0/*friction*/, 0.5/*bounce*/, width, height);
// place the body
body.setPosition(x, y);
} else {
// get dimensions of the body
var radius = this._pictureCircle.width;
// create the body
var body = this.addPolygonBody(this._pictureCircle, #dynamic, 1.0 /*density*/, 1.0/*friction*/, 0.5/*bounce*/, radius, radius);
// place the body
body.setPosition(x, y);
}
}
Drawing joints
In enterprise applications, joints are not visible. They are invisible components and the user does not know that something like joint even exists. For the purpose of sample applications, the lines are drawn up to joints. All bodies connected in joint are remembered in _rotors array. Then, in draw function, we can get coordinates of the bodies and draw lines between them.
Example: draw function, that draws lines instead of joints
function draw(canvas) {
var x1, y1, x2, y2;
// fill background with black color
canvas.clear(0xff000000); // draw joints
for (var i = 0; i < 3; i++) {
// get position of both bodies
(x1, y1) = this._rotors[i].bodyA.getPosition();
(x2, y2) = this._rotors[i].bodyB.getPosition();
// draw line
canvas.drawLine(x1.toInteger(), y1.toInteger(), x2.toInteger(), y2.toInteger(), this._jointPaint);
}
// draw informative text
canvas.drawText("Tap to add new objects.", (System.width - this._textWidth) / 2, 8*System.height / 10, this._textPaint);
// draw other elements
super.draw(canvas);
}
Change gravity
Gravity is changed according to the device position. If the user tilst the device, the gravity changes and all bodies fall down to the other side. However, the gravity is changing only on X axis to value -1.8 or 1.8N. If we kept changing the value of gravity on all axes; it would infuence the revolute joint significantly (it would not rotate smoothly).
Example: change gravity acording to device position
function _startSensor()
{
// check if accelometer sensor is available
if (!Sensor.isAvailable(#acceleration)) {
System.messageBox("No accelometer detected!");
} else {
// create sensor
var sensor = new Sensor(#acceleration, 40);
// setup handler for receiving data
sensor.onDataReceived = function(sender, timestamp, params) {
var (x, y, z) = (params[0], params[1], params[2]);
if (x > 0)
this super.setGravity(0, -1.8);
else if (x < 0)
this super.setGravity(0, 1.8);
};
// start receiving data
sensor.start();
}
}
Summary
Revolute joint connects two bodies which can rotate around the anchor point. It is suitable for connections like wheels, rollers, chains, rotating doors etc. In Moscrif we create revolute joint by using function createRevoluteJoint. Revolute joint can also use motor to rotate with body in certain required speed, or limits to limit body rotation to given range of angles between upper and lower angle. Only dynamic body types can rotate in revolute joint.
|