Reputation: 119
I have a Jupyter-Lab notebook that I've been trying to use to develop the Jacobian of a robotic arm symbolically with Sympy. I have expressions that are then used in subsequent expressions, and so forth. I receive the message 'Mul' object has no attribute 'cos' when attempting to run the lambdified final expression
Following the other questions such as
Sympy to numpy causes the AttributeError: 'Symbol' object has no attribute 'cos'
What causes this error (AttributeError: 'Mul' object has no attribute 'cos') in Python?
I've made sure to call sympy using:
import sympy as sp
And then calling everything with the sp
prefix:
sp.cos()
sp.pi
This is my code (I apologize for the long bits)
# symbolic analysis
import sympy as sp
# Variables
theta1, theta2, theta3, theta4, theta5, theta6 = sp.symbols('theta1 theta2 theta3 theta4 theta5 theta6')
# Constants (undecided)
a1, a2, a3 = sp.symbols('a1 a2 a3')
d1, d4, d6 = sp.symbols('d1 d4 d6')
# Constants (predetermined)
d2, d3, d5, a4, a5, a6, alpha2, alpha6 = 0, 0, 0, 0, 0, 0, 0, 0
alpha1, alpha3, alpha5 = (sp.pi/2,)*3
alpha4 = -sp.pi/2
# rotation around x
def rotx(angle):
return sp.Matrix([[1, 0, 0, 0], [0, sp.cos(angle), -sp.sin(angle), 0], [0, sp.sin(angle), sp.cos(angle), 0], [0, 0, 0, 1]])
# rotation around y
def roty(angle):
return sp.Matrix([[sp.cos(angle), 0, sp.sin(angle), 0], [0, 1, 0, 0], [-sp.sin(angle), 0, sp.cos(angle), 0], [0, 0, 0, 1]])
# rotation around z
def rotz(angle):
return sp.Matrix([[sp.cos(angle), -sp.sin(angle), 0, 0], [sp.sin(angle), sp.cos(angle), 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
# Translation in either x, y or z
def trans(x,y,z):
return sp.Matrix([[1, 0, 0, x], [0, 1, 0, y], [0, 0, 0, z], [0, 0, 0, 1]])
def dh_matrix(d, theta, a, alpha):
return trans(0,0,d)*rotz(theta)*trans(a,0,0)*rotx(alpha)
t_0_1 = dh_matrix(d1, theta1, a1, alpha1)
t_1_2 = dh_matrix(d2, theta2, a2, alpha2)
t_2_3 = dh_matrix(d3, theta3, a3, alpha3)
t_3_4 = dh_matrix(d4, theta4, a4, alpha4)
t_4_5 = dh_matrix(d5, theta5, a5, alpha5)
t_5_6 = dh_matrix(d6, theta6, a6, alpha6)
t_0_6 = t_0_1 * t_1_2 * t_2_3 * t_3_4 * t_4_5 * t_5_6
last_column = t_0_6.col(-1)
x = last_column.row(0)
y = last_column.row(1)
z = last_column.row(2)
# Partial derivatives of x
dxd1 = sp.diff(x,theta1)
dxd2 = sp.diff(x,theta2)
dxd3 = sp.diff(x,theta3)
dxd4 = sp.diff(x,theta4)
dxd5 = sp.diff(x,theta5)
dxd6 = sp.diff(x,theta6)
# Partial derivates of y
dyd1 = sp.diff(y,theta1)
dyd2 = sp.diff(y,theta2)
dyd3 = sp.diff(y,theta3)
dyd4 = sp.diff(y,theta4)
dyd5 = sp.diff(y,theta5)
dyd6 = sp.diff(y,theta6)
# Partial derivates of z
dzd1 = sp.diff(z,theta1)
dzd2 = sp.diff(z,theta2)
dzd3 = sp.diff(z,theta3)
dzd4 = sp.diff(z,theta4)
dzd5 = sp.diff(z,theta5)
dzd6 = sp.diff(z,theta6)
jacobian = sp.Matrix([[dxd1,dxd2,dxd3,dxd4,dxd5,dxd6], [dyd1,dyd2,dyd3,dyd4,dyd5,dyd6], [dzd1,dzd2,dzd3,dzd4,dzd5,dzd6]])
jacobian_numeric = sp.lambdify([theta1,theta2,theta3,theta4,theta5,theta6,a1,a2,a3,d1,d4,d6],jacobian)
jacobian_numeric(0,sp.pi/2,0,0,0,0,0,0,0,1,0.3,0.1)
A 3x6 matrix containing numeric values
The following error attributed to the final line:
AttributeError: 'Mul' object has no attribute 'cos'
I figure it has to do with how I have functions and multiple expressions all twisted together, but I'm not quite sure how to go about founding where exactly it's failing.
It's kind of gigantic; I cut out the rest of the expression with ...
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-21-d0f45c1787c2> in <module>
----> 1 current_jacobian = jacobian_numeric(0,sp.pi/2,0,0,0,0,0,0,0,1,0.3,0.1) # add pi/2 to theta2 because of the initial offset between x_2 and x_3
2 current_jacobian
<lambdifygenerated-1> in _lambdifygenerated(theta1, theta2, theta3, theta4, theta5, theta6, a1, a2, a3, d1, d4, d6)
1 def _lambdifygenerated(theta1, theta2, theta3, theta4, theta5, theta6, a1, a2, a3, d1, d4, d6):
----> 2 return (array([[array([[-a1*sin(theta1) - a2*sin(theta1)*cos(theta2) + a3*sin(theta1)*sin(theta2)*sin(theta3) - a3*sin(theta1)*cos(theta2)*cos(theta3) +...
AttributeError: 'Mul' object has no attribute 'cos'
Upvotes: 3
Views: 1250
Reputation: 6154
After you use lambdify
to create an executable function, you are no longer in the 'symbolic math' world of sympy
, and have to pass in numeric values, not symbolic ones.
You can either pass in the 𝜋 from numpy
as np.pi
(as you noted in BenT's answer), or you can numerically evaluate the 𝜋 from sympy
as sp.N(sp.pi)
. The N
function converts a symbolic value into a numeric one, including values like 𝜋.
Upvotes: 1
Reputation: 3200
I am not entirely sure why, but when I replace sp.pi
with np.pi
in the last line of the code jacobian_numeric(0,np.pi/2,0,0,0,0,0,0,0,1,0.3,0.1)
the error goes away. I have seen a couple other questions with similar problems but no good answer at this point. This could be a bug in simpy
or hopefully someone else has a better explanation.
Upvotes: 2