Tutorial - Joints

From Newton Wiki
Jump to: navigation, search

Constraints or joints are objects that connect two rigid bodies by canceling one or more degree of freedom between them. In this tutorial we are going to demonstrate how to use the different types of constraint provided with the Newton API. Newton possesses a very rich set of joints. It will be too much work to cover each one of them in a simple tutorial. We will only show four of the most commonly used joints: ball and socket, hinge, corkscrew and slider. The application should be able to determine how to implement its own features using other joints by comparing them to any of these four.

Open the project tutorial5_UsingJoints. The project is almost exactly the same as tutorial4_IntroductionToMaterials but it will add some extra functionality. Open the file Tutorial.cpp a go to function InitScene().

After the ball character is created, it will add three different set of rigid bodies each one linked by one or more different joints.

// Add some joint configurations
AddRope (nWorld);
AddRollingBeats (nWorld);
AddDoubleSwingDoors (nWorld);

Open the file JointsTutorial.cpp

Find the function AddRope. This function will create a short rope made by connecting a few skinny rectangular rods with ball and socket joints.

For a rope to behave realistically the pieces should have an accurate moment of inertia.

// Calculate an accurate moment of inertia
mass = 2.0f;
Ixx = 0.7f * mass * (size.m_y * size.m_y + size.m_z * size.m_z) / 12.0f;
Iyy = 0.7f * mass * (size.m_x * size.m_x + size.m_z * size.m_z) / 12.0f;
Izz = 0.7f * mass * (size.m_x * size.m_x + size.m_y * size.m_y) / 12.0f;

Then we find the position for the first piece in global space

// Set position for this root in global space
dMatrix location (GetIdentityMatrix());
Location.m_posit.m_y = 11.5f; 
Location.m_posit.m_z = -5.0f; 

Next we create a common collision geometry to be shared by each rope segment

// Create a collision primitive to be shared by all links
collision = NewtonCreateBox (nWorld, size.m_x, size.m_y, size.m_z, NULL);

The following loop will create each rope piece and set it initial condition and parameter

for (i = 0; i < 6; i ++)
	// create the a graphic character (use a box as our body
	box = new BoxPrimitive (location, size);

	//create the rigid body
	link1 = NewtonCreateBody (nWorld, collision);

	// Set Material Id for this object
	NewtonBodySetMaterialGroupID (link1, woodID);

	// Save the pointer to the graphic object with the body.
	NewtonBodySetUserData (link1, box);

	// Set a destructor for this rigid body
	NewtonBodySetDestructorCallback (link1, PhysicsBodyDestructor);

	// Set the transform call back function
	NewtonBodySetTransformCallback (link1, PhysicsSetTransform);

	// Set the force and torque call back function
	NewtonBodySetForceAndTorqueCallback (link1, hysicsApplyForceAndTorque);

	// Set the mass matrix
	NewtonBodySetMassMatrix (link1, mass, Ixx, Iyy, Izz);
	// Set the matrix for both the rigid body and the graphic body
	NewtonBodySetMatrix (link1, &location [0][0]);
	PhysicsSetTransform (link1, &location [0][0]);

Then each two rope pieces are connected by a ball and socket joint. The first piece is an exception as it is connected to the world.

	dVector pivot (location.m_posit);
	pivot.m_y += size.m_y * 0.5f;

	// Connect these two bodies by a ball and sockect joint
	joint = NewtonConstraintCreateBall (nWorld, &pivot.m_x, link1, link0); 

Each segment of the rope is only allowed to spin 10 degrees around the segment axis. This will make the rope to looks mare realistic. The ball and socket joint can set also a cone limit. But it won’t be used with this particular configuration. A value of zero for cone limit disables the joint limit altogether

	// Set a twist angle to prevent the links to spin unrealistically
	dVector pin (location.m_up.Scale (-1.0f));
	NewtonBallSetConeLimits (joint, &pin.m_x, 0.0f, 10.0f * 3.1416f / 180.0f); 

The rest prepares the loop for creating the next rope segment

	link0 = link1;
	Location.m_posit.m_y -= size.m_y;

Finally after the entire rope is completed, we release the collision geometry. That completes the rope setup

// Release the collision geometry when not need it
NewtonReleaseCollision (nWorld, collision); 

Now find the function DoubleDoorUserCallback. This function creates a double wing door with two wood planks and two hinges. Setting up the bodies is almost the same as the previous function; so don’t have to explain it again.

The code fragment:

dVector pivot (location.m_posit);
dVector pin (location.m_up);
pivot.m_x += size.m_x * 0.5f;
// Connect these two bodies by a ball and sockect joint
joint = NewtonConstraintCreateHinge (nWorld, &pivot.m_x, &pin.m_x, link1, NULL);

// Set limit to the door
NewtonHingeSetUserCallback (joint, DoubleDoorUserCallback);

Create a hinge and set a function callback to update the hinge acceleration. The function DoubleDoorUserCallback is called for every update to the hinge axis acceleration. Here the application can perform several things like: making a motor, setting joint limits, or making a hinge with friction (rusty hinge)

The third function, AddRollingBeats, follows the same procedure as DoubleDoorUserCallback except that it plugs a sliding joint and a corkscrew joint. The only thing worth noticing here is that these joints, in addition to have their own update callback, they also keep their own private data and function destructor. Also notice that the corkscrew joint controls two degrees of freedom, one rotational (a motor) and one linear with limits.