# DH Parameter for OpenManipulator X from Robotis

I try to solve forward kinematics problem for OpenManipulator X from Robotis by using standard DH convention. The figure and dimension of the robot like this pic

I try to find DH parameter and got result like this

To match frame assignment requirement, I move frame 2 to the left 0.024m. But when I verify the forward kinematics result, the position of end effector is wrong when I move joint 3. For example if I move joint 3 to 90 degree, the position of end effector should be X = 0.024m, Y = 0, and Z = 0.455M. But I got from the software X = 0, Y = 0, and Z = 0.455. It is because of I move the centre of frame 3 to the left. But if I dont move it, the DH frame assignment rule doesn't match.

How to figure out this problem?

Here is my code to find forward kinematics

def std_DH(theta, alpha, a, d):
DH = np.array([[np.cos(theta),  -np.sin(theta)*np.cos(alpha),   np.sin(theta)*np.sin(alpha),    a*np.cos(theta)],
[np.sin(theta),  np.cos(theta)*np.cos(alpha),    -np.cos(theta)*np.sin(alpha),   a*np.sin(theta)],
[0,              np.sin(alpha),                  np.cos(alpha),                  d],
[0,              0,                              0,                              1]])
return DH

def forward_kinematics(q1, q2, q3, q4):
_0T1 = std_DH(q1, np.pi/2, 0, 0.077)
_1T2 = std_DH(q2+np.pi/2, 0, 0.128, 0)
_2T3 = std_DH(q3-np.pi/2, 0, 0.124, 0)
_3T4 = std_DH(q4, 0, 0.126, 0)
_0T4 = _0T1.dot(_1T2).dot(_2T3).dot(_3T4)
return _0T4


Is there any method to find forward kinematics without using DH convention?

• First of all, you could check if your dh parameter right or not by simulating in Robotic Toolbox in matlab. If your dh paramter didnt look alike your actual robot, fix it by trial and error. And you will get your dh parameter correct. i once try to fit every single law in frame assignment and create dh parameter from it but still didnt correct. so i simulate it. Hope this help you Jul 27, 2019 at 14:41

DH parameterisation is always hard. Using Robotics Toolbox for MATLAB we can easily do the forward kinematics without DH parameters. First create a string of simple transforms which I took directly from your diagrams

>> s = 'Rz(q1)Tz(0.077)Ry(q2)Tz(0.128)Tx(0.024)Ry(q3)Tx(0.124)Ry(q4)Tx(0.126)';


which describes the kinematic chain with length constants and variable angles represented by qj. Now the FK is simply

>> trchain(s, [0 0 0 0])
ans =
1.0000         0         0    0.2740
0    1.0000         0         0
0         0    1.0000    0.2050
0         0         0    1.0000


where the values in the second argument are substituted for the joint angles, in this case all zero. The resulting SE(3) matrix shows a translation in the x- and z-directions which is correct.

You could use this to check your DH version.

My Toolbox also has an automated symbolic manipulation tool, not perfect, to convert a similar string format (all length parameters must be symbolic not numeric) to DH parameters

>> s = 'Rz(q1)Tz(L1)Ry(q2)Tz(L2)Tx(L3)Ry(q3)Tx(L4)Ry(q4)Tx(L5)'
>> DHFactor(s)
DHFactor: error: Incomplete factorization, no DH equivalent found

ans =

DH(q1, L1, 0, -90).DH(q2, 0, L3, 0).Ty(-L2).DH(q3, 0, L4, 0).DH(q4, 0, L5, 90)


but it fails for your example. The translation L2 hasn't been assigned to any DH term. This is more likely a problem with my code than your mechanism.

Not sure if it still helps, but for both traditional and modified D-H convention, you need your Z-axis to be at the direction of the joint axis. Your frame 2 did not comply to this requirement. This probably explains the missing link parameter 0.024m.

I struggled with the same thing. I solved it rotating the second frame to a fixed angle, and using the 0.130 m distance. I think this satisfies the DH convention.

Actually, your forward kinematic solution is correct. You made a silly mistake in the code. While definining _2T3 you used a as 0.124 instead of 0.148 (as you mentioned in the DH parameters).

Corrected Code would be

def forward_kinematics(q1, q2, q3, q4):
_0T1 = std_DH(q1, np.pi/2, 0, 0.077)
_1T2 = std_DH(q2+np.pi/2, 0, 0.128, 0)
_2T3 = std_DH(q3-np.pi/2, 0, 0.148, 0)
_3T4 = std_DH(q4, 0, 0.126, 0)
_0T4 = _0T1.dot(_1T2).dot(_2T3).dot(_3T4)
return _0T4


I checked this and everything is working fine.