Main Content

rigidBodyJoint

Create a joint

Description

The rigidBodyJoint objects defines how a rigid body moves relative to an attachment point. In a tree-structured robot, a joint always belongs to a specific rigid body, and each rigid body has one joint.

The rigidBodyJoint object can describe joints of various types. When building a rigid body tree structure with rigidBodyTree, you must assign the Joint object to a rigid body using the rigidBody class.

The different joint types supported are:

  • fixed — Fixed joint that prevents relative motion between two bodies.

  • revolute — Single degree of freedom (DOF) joint that rotates around a given axis. Also called a pin or hinge joint.

  • prismatic — Single DOF joint that slides along a given axis. Also called a sliding joint.

  • floating — Six DOF joint that enables any translation and rotation.

Each joint type has different properties with different dimensions, depending on its defined geometry.

Creation

Description

jointObj = rigidBodyJoint(jname) creates a fixed joint with the specified name.

jointObj = rigidBodyJoint(jname,jtype) creates a joint of the specified type with the specified name.

example

Input Arguments

expand all

Joint name, specified as a string scalar or character vector. The joint name must be unique to access it off the rigid body tree.

Example: "elbow_right"

Data Types: char | string

Joint type, specified as a string scalar or character vector. The joint type predefines certain properties when creating the joint.

The different joint types supported are:

  • "fixed" — Fixed joint that prevents relative motion between two bodies.

  • "revolute" — Single degree of freedom (DOF) joint that rotates around a given axis. Also called a pin or hinge joint.

  • "prismatic" — Single DOF joint that slides along a given axis. Also called a sliding joint.

  • "floating" — Six DOF joint that enables free translation and rotation.

Example: "prismatic"

Data Types: char | string

Properties

expand all

This property is read-only.

Joint type, returned as a string scalar or character vector. The joint type predefines certain properties when creating the joint.

The different joint types supported are:

  • "fixed" — Fixed joint that prevents relative motion between two bodies.

  • "revolute" — Single degree of freedom (DOF) joint that rotates around a given axis. Also called a pin or hinge joint.

  • "prismatic" — Single DOF joint that slides along a given axis. Also called a sliding joint.

  • "floating" — Six DOF joint that enables free translation and rotation.

If the rigid body that contains this joint is added to a robot model, the joint type must be changed by replacing the joint using replaceJoint.

Example: "prismatic"

Data Types: char | string

Joint name, returned as a string scalar or character vector. The joint name must be unique to access it off the rigid body tree. If the rigid body that contains this joint is added to a robot model, the joint name must be changed by replacing the joint using replaceJoint.

Example: "elbow_right"

Data Types: char | string

Position limits of the joint, specified as a two-element row vector of [min max] values or as a 7-by-2 matrix of [min max] values depending on the type of joint:

  • fixed[NaN NaN] (default). A fixed joint has no joint limits. Bodies remain fixed between each other.

  • revolute[-pi pi] (default). The limits define the angle of rotation around the axis in radians.

  • prismatic[-0.5 0.5] (default). The limits define the linear motion along the axis in meters.

  • floating[NaN(4,2); repmat([-5 5],3,1)] (default). The rotation, represented as a quaternion, has no joint limits. Each row of the position limits defines the linear motion along the x-,y-, and z-axes, respectively.

Example: [-pi/2 pi/2]

Home position of joint, specified as a scalar or seven-element row vector depending on your joint type. The home position must fall in the range set by PositionLimits. This property is used by homeConfiguration to generate the predefined home configuration for an entire rigid body tree.

Depending on the joint type, the home position has a different definition.

  • fixed0 (default). A fixed joint has no relevant home position.

  • revolute0 (default). A revolute joint has a home position defined by the angle of rotation around the joint axis in radians.

  • prismatic0 (default). A prismatic joint has a home position defined by the linear motion along the joint axis in meters.

  • floating[1 0 0 0 0 0 0] (default). A floating joint has a home position defined by an identity quaternion and xyz-position.

Example: pi/2 radians for a revolute joint

Axis of motion for joint, specified as a three-element unit vector. The vector can be any direction in 3-D space in local coordinates.

Depending on the joint type, the joint axis has a different definition.

  • fixed — A fixed joint has no relevant axis of motion.

  • revolute — A revolute joint rotates the body in the plane perpendicular to the joint axis.

  • prismatic — A prismatic joint moves the body in a linear motion along the joint axis direction.

  • floating — A floating joint rotates the body freely in space. You cannot set the JointAxis property for the floating joint.

Example: [1 0 0] for motion around the x-axis for a revolute joint

This property is read-only.

Fixed transform from joint to parent frame, returned as a 4-by-4 homogeneous transform matrix. The transform converts the coordinates of points in the joint predecessor frame to the parent body frame.

Example: eye(4)

This property is read-only.

Fixed transform from child body to joint frame, returned as a 4-by-4 homogeneous transform matrix. The transform converts the coordinates of points in the child body frame to the joint successor frame.

Example: eye(4)

Object Functions

copyCreate copy of joint
setFixedTransformSet fixed transform properties of joint

Examples

collapse all

Add a rigid body and corresponding joint to a rigid body tree. Each rigidBody object contains a rigidBodyJoint object and must be added to the rigidBodyTree using addBody.

Create a rigid body tree.

rbtree = rigidBodyTree;

Create a rigid body with a unique name.

body1 = rigidBody('b1');

Create a revolute joint. By default, the rigidBody object comes with a fixed joint. Replace the joint by assigning a new rigidBodyJoint object to the body1.Joint property.

jnt1 = rigidBodyJoint('jnt1','revolute');
body1.Joint = jnt1;

Add the rigid body to the tree. Specify the body name that you are attaching the rigid body to. Because this is the first body, use the base name of the tree.

basename = rbtree.BaseName;
addBody(rbtree,body1,basename)

Use showdetails on the tree to confirm the rigid body and joint were added properly.

showdetails(rbtree)
--------------------
Robot: (1 bodies)

 Idx    Body Name   Joint Name   Joint Type    Parent Name(Idx)   Children Name(s)
 ---    ---------   ----------   ----------    ----------------   ----------------
   1           b1         jnt1     revolute             base(0)   
--------------------

Use the Denavit-Hartenberg (DH) parameters of the Puma560® robot to build a robot. Each rigid body is added one at a time, with the child-to-parent transform specified by the joint object.

The DH parameters define the geometry of the robot with relation to how each rigid body is attached to its parent. For convenience, setup the parameters for the Puma560 robot in a matrix [1]. The Puma robot is a serial chain manipulator. The DH parameters are relative to the previous row in the matrix, corresponding to the previous joint attachment.

dhparams = [0   	pi/2	0   	0;
            0.4318	0       0       0
            0.0203	-pi/2	0.15005	0;
            0   	pi/2	0.4318	0;
            0       -pi/2	0   	0;
            0       0       0       0];

Create a rigid body tree object to build the robot.

robot = rigidBodyTree;

Create the first rigid body and add it to the robot. To add a rigid body:

  1. Create a rigidBody object and give it a unique name.

  2. Create a rigidBodyJoint object and give it a unique name.

  3. Use setFixedTransform to specify the body-to-body transformation using DH parameters. The last element of the DH parameters, theta, is ignored because the angle is dependent on the joint position.

  4. Call addBody to attach the first body joint to the base frame of the robot.

body1 = rigidBody('body1');
jnt1 = rigidBodyJoint('jnt1','revolute');

setFixedTransform(jnt1,dhparams(1,:),'dh');
body1.Joint = jnt1;

addBody(robot,body1,'base')

Create and add other rigid bodies to the robot. Specify the previous body name when calling addBody to attach it. Each fixed transform is relative to the previous joint coordinate frame.

body2 = rigidBody('body2');
jnt2 = rigidBodyJoint('jnt2','revolute');
body3 = rigidBody('body3');
jnt3 = rigidBodyJoint('jnt3','revolute');
body4 = rigidBody('body4');
jnt4 = rigidBodyJoint('jnt4','revolute');
body5 = rigidBody('body5');
jnt5 = rigidBodyJoint('jnt5','revolute');
body6 = rigidBody('body6');
jnt6 = rigidBodyJoint('jnt6','revolute');

setFixedTransform(jnt2,dhparams(2,:),'dh');
setFixedTransform(jnt3,dhparams(3,:),'dh');
setFixedTransform(jnt4,dhparams(4,:),'dh');
setFixedTransform(jnt5,dhparams(5,:),'dh');
setFixedTransform(jnt6,dhparams(6,:),'dh');

body2.Joint = jnt2;
body3.Joint = jnt3;
body4.Joint = jnt4;
body5.Joint = jnt5;
body6.Joint = jnt6;

addBody(robot,body2,'body1')
addBody(robot,body3,'body2')
addBody(robot,body4,'body3')
addBody(robot,body5,'body4')
addBody(robot,body6,'body5')

Verify that your robot was built properly by using the showdetails or show function. showdetails lists all the bodies in the MATLAB® command window. show displays the robot with a given configuration (home by default). Calls to axis modify the axis limits and hide the axis labels.

showdetails(robot)
--------------------
Robot: (6 bodies)

 Idx    Body Name   Joint Name   Joint Type    Parent Name(Idx)   Children Name(s)
 ---    ---------   ----------   ----------    ----------------   ----------------
   1        body1         jnt1     revolute             base(0)   body2(2)  
   2        body2         jnt2     revolute            body1(1)   body3(3)  
   3        body3         jnt3     revolute            body2(2)   body4(4)  
   4        body4         jnt4     revolute            body3(3)   body5(5)  
   5        body5         jnt5     revolute            body4(4)   body6(6)  
   6        body6         jnt6     revolute            body5(5)   
--------------------
show(robot);
axis([-0.5,0.5,-0.5,0.5,-0.5,0.5])
axis off

Figure contains an axes object. The hidden axes object with xlabel X, ylabel Y contains 13 objects of type patch, line. These objects represent base, body1, body2, body3, body4, body5, body6.

References

[1] Corke, P. I., and B. Armstrong-Helouvry. “A Search for Consensus among Model Parameters Reported for the PUMA 560 Robot.” Proceedings of the 1994 IEEE International Conference on Robotics and Automation, IEEE Computer. Soc. Press, 1994, pp. 1608–13. DOI.org (Crossref), doi:10.1109/ROBOT.1994.351360.

Make changes to an existing rigidBodyTree object. You can get replace joints, bodies and subtrees in the rigid body tree.

Load an ABB IRB-120T manipulator from the Robotics System Toolbox™ loadrobot. It is specified as a rigidBodyTree object.

manipulator = loadrobot("abbIrb120T");

View the robot with show and read the details of the robot using showdetails.

show(manipulator);

Figure contains an axes object. The axes object with xlabel X, ylabel Y contains 24 objects of type patch, line. These objects represent base_link, base, link_1, link_2, link_3, link_4, link_5, link_6, tool0, link_1_mesh, link_2_mesh, link_3_mesh, link_4_mesh, link_5_mesh, link_6_mesh, base_link_mesh.

showdetails(manipulator)
--------------------
Robot: (8 bodies)

 Idx     Body Name            Joint Name            Joint Type     Parent Name(Idx)   Children Name(s)
 ---     ---------            ----------            ----------     ----------------   ----------------
   1          base        base_link-base                 fixed         base_link(0)   
   2        link_1               joint_1              revolute         base_link(0)   link_2(3)  
   3        link_2               joint_2              revolute            link_1(2)   link_3(4)  
   4        link_3               joint_3              revolute            link_2(3)   link_4(5)  
   5        link_4               joint_4              revolute            link_3(4)   link_5(6)  
   6        link_5               joint_5              revolute            link_4(5)   link_6(7)  
   7        link_6               joint_6              revolute            link_5(6)   tool0(8)  
   8         tool0          joint6-tool0                 fixed            link_6(7)   
--------------------

Get a specific body to inspect the properties. The only child of the link_3 body is the link_4 body. You can copy a specific body as well.

body3 = getBody(manipulator,"link_3");
childBody = body3.Children{1}
childBody = 
  rigidBody with properties:

            Name: 'link_4'
           Joint: [1x1 rigidBodyJoint]
            Mass: 1.3280
    CenterOfMass: [0.2247 1.5000e-04 4.1000e-04]
         Inertia: [0.0028 0.0711 0.0723 1.3052e-05 -1.3878e-04 -6.6037e-05]
          Parent: [1x1 rigidBody]
        Children: {[1x1 rigidBody]}
         Visuals: {'Mesh Filename link_4.stl'}
      Collisions: {'Mesh Filename link_4.stl'}

body3Copy = copy(body3);

Replace the joint on the link_3 body. You must create a new Joint object and use replaceJoint to ensure the downstream body geometry is unaffected. Call setFixedTransform if necessary to define a transform between the bodies instead of with the default identity matrices.

newJoint = rigidBodyJoint("prismatic");
replaceJoint(manipulator,"link_3",newJoint);

showdetails(manipulator)
--------------------
Robot: (8 bodies)

 Idx     Body Name            Joint Name            Joint Type     Parent Name(Idx)   Children Name(s)
 ---     ---------            ----------            ----------     ----------------   ----------------
   1          base        base_link-base                 fixed         base_link(0)   
   2        link_1               joint_1              revolute         base_link(0)   link_2(3)  
   3        link_2               joint_2              revolute            link_1(2)   link_3(4)  
   4        link_3             prismatic                 fixed            link_2(3)   link_4(5)  
   5        link_4               joint_4              revolute            link_3(4)   link_5(6)  
   6        link_5               joint_5              revolute            link_4(5)   link_6(7)  
   7        link_6               joint_6              revolute            link_5(6)   tool0(8)  
   8         tool0          joint6-tool0                 fixed            link_6(7)   
--------------------

Remove an entire body and get the resulting subtree using removeBody. The removed body is included in the subtree.

subtree = removeBody(manipulator,"link_4")
subtree = 
  rigidBodyTree with properties:

     NumBodies: 4
        Bodies: {[1x1 rigidBody]  [1x1 rigidBody]  [1x1 rigidBody]  [1x1 rigidBody]}
          Base: [1x1 rigidBody]
     BodyNames: {'link_4'  'link_5'  'link_6'  'tool0'}
      BaseName: 'link_3'
       Gravity: [0 0 0]
    DataFormat: 'struct'

show(subtree);

Figure contains an axes object. The axes object with xlabel X, ylabel Y contains 12 objects of type patch, line. These objects represent link_3, link_4, link_5, link_6, tool0, link_4_mesh, link_5_mesh, link_6_mesh.

Remove the modified link_3 body. Add the original copied link_3 body to the link_2 body, followed by the returned subtree. The robot model remains the same. See a detailed comparison through showdetails.

removeBody(manipulator,"link_3");
addBody(manipulator,body3Copy,"link_2")
addSubtree(manipulator,"link_3",subtree)

showdetails(manipulator)
--------------------
Robot: (8 bodies)

 Idx     Body Name            Joint Name            Joint Type     Parent Name(Idx)   Children Name(s)
 ---     ---------            ----------            ----------     ----------------   ----------------
   1          base        base_link-base                 fixed         base_link(0)   
   2        link_1               joint_1              revolute         base_link(0)   link_2(3)  
   3        link_2               joint_2              revolute            link_1(2)   link_3(4)  
   4        link_3               joint_3              revolute            link_2(3)   link_4(5)  
   5        link_4               joint_4              revolute            link_3(4)   link_5(6)  
   6        link_5               joint_5              revolute            link_4(5)   link_6(7)  
   7        link_6               joint_6              revolute            link_5(6)   tool0(8)  
   8         tool0          joint6-tool0                 fixed            link_6(7)   
--------------------

This example shows how to model a floating robot as a rigid body tree using a floating joint, represented by a rigidBodyJoint of type "floating", at the fixed base. Use this approach for most applications such as forward kinematics and dynamics. However, if you need to use inverse kinematics solvers or motion models for a robot with a floating base, you cannot use the "floating" joint. To model a floating-base robot for inverse kinematics or motion models, see Inverse Kinematics for Robots with Floating Base.

First create a fixed base as an empty rigid body tree. Then, create a rigid body and add a rigid body joint of type "floating" to the rigid body.

rbt = rigidBodyTree(DataFormat="row");
floatingBaseBody = rigidBody("floatingBase");
floatingBaseBody.Joint = rigidBodyJoint("j1","floating");

Add the rigid body to the fixed-base rigid body tree. Now the rigid body and the fixed base are joined at the floating joint, enabling free translation and rotation in and along the xyz-axes.

addBody(rbt,floatingBaseBody,rbt.BaseName);

Load the rigid body tree model of the ABB IRB 120 robotic arm and add the loaded rigid body tree to the floating-base rigid body tree. Change the name of the BaseName property of the floating base rigid body tree to 'world' to avoid name conflicts. This name conflict is due to both rigid body trees using the default base name, 'base_link'.

abbirb = loadrobot("abbIrb120",DataFormat="row");
rbt.BaseName = 'world';
addSubtree(rbt,"floatingBase",abbirb,ReplaceBase=false);

To demonstrate that the rigid body tree can both freely translate and rotate in space, visualize the base of the robotic arm at the xyz-coordinate [-1.1, 0.2, 0.3] with an orientation of [0 pi/2 pi/3] in the fixed base frame.

baseOrientation = eul2quat([0 pi/3 pi/3]); % ZYX Euler rotation order
basePosition = [-1.1 0.2 0.3];
floatingRBTConfig = [baseOrientation,basePosition,homeConfiguration(abbirb)]
floatingRBTConfig = 1×13

    0.7500    0.4330    0.4330   -0.2500   -1.1000    0.2000    0.3000         0         0         0         0         0         0

show(rbt,floatingRBTConfig);
axis equal
title(["Robot Joint Configuration With Base", "at Desired Position and Orientation"])

Figure contains an axes object. The axes object with title Robot Joint Configuration With Base at Desired Position and Orientation, xlabel X, ylabel Y contains 28 objects of type patch, line. These objects represent world, floatingBase, base_link, base, link_1, link_2, link_3, link_4, link_5, link_6, tool0, base_link_mesh, link_1_mesh, link_2_mesh, link_3_mesh, link_4_mesh, link_5_mesh, link_6_mesh.

Now you can use this floating base robot for applications such as forward kinematics and dynamics. As previously mentioned, you cannot model a floating-base robot in this way if you plan to use inverseKinematics or do motion planning for it. Attempting to do so causes an error from the inverse kinematics function. To model a floating robot for inverse kinematics and motion planning, see Inverse Kinematics for Robots with Floating Base.

Limitations

For more information about these limitations and how to model a floating-base robot for use with these objects, functions, and blocks, see Inverse Kinematics for Robots with Floating Base.

References

[1] Craig, John J. Introduction to Robotics: Mechanics and Control. Reading, MA: Addison-Wesley, 1989.

[2] Siciliano, Bruno. Robotics: Modelling, Planning and Control. London: Springer, 2009.

Extended Capabilities

C/C++ Code Generation
Generate C and C++ code using MATLAB® Coder™.

Version History

Introduced in R2016b

expand all