I am doing some symbolic vector calculations using sympy
, but I can't simplify the arguments of the vector class in a proper way. Consider this code:
from sympy.physics.mechanics import ReferenceFrame, dot, cross
from sympy import symbols, sin, cos, simplify
alpha, theta, l = symbols('alpha theta l')
def Rodrigues(v, k, angle):
return cos(angle) * v + cross(k, v) * sin(angle) + k * dot(k, v) * (1- cos(angle))
N = ReferenceFrame('N')
P0 = -l * N.y
P2 = Rodrigues(
Rodrigues(P0, -N.z, alpha),
Rodrigues(N.x, -N.z, alpha),
theta)
which returns:
trying the simplify(P2)
I get the error:
AttributeError: 'function' object has no attribute 'x'
which I think is because the simplify
requires a sympy
expression object. trying the dir(P2)
there is a simplify
method which returns:
<bound method Vector.simplify of - l*sin(alpha)*cos(theta)*N.x - l*cos(alpha)*cos(theta)*N.y + (-l*sin(alpha)**2 - l*cos(alpha)**2)*sin(theta)*N.z>
which I have no idea what it is! trying the P2.args
I get:
[(Matrix([
[ -l*sin(alpha)*cos(theta)],
[ -l*cos(alpha)*cos(theta)],
[(-l*sin(alpha)**2 - l*cos(alpha)**2)*sin(theta)]]), N)]
which is a 1D List of a 2D tuple with a nested 3x1 sympy
Matrix! I don't know whos choice was to make the vector class so obscure, but now I can simplify the last element with simplify(P2.args[0][0][2])
and change the function to:
def Rodrigues(v, k, angle):
tmpVec = cos(angle) * v + cross(k, v) * sin(angle) + k * dot(k, v) * (1- cos(angle))
tmpFrame = tmpVec.args[0][1]
return simplify(tmpVec.args[0][0][0]) * tmpFrame.x + simplify(tmpVec.args[0][0][1]) * tmpFrame.y + simplify(tmpVec.args[0][0][2]) * tmpFrame.z
which to me seems like a very bad solution.
I was wondering if you could help me know if there is a more Pythonic way to do this. For example, force sympy
to simplify all expressions by default. Or maybe I'm using the vector.simplify
method in a wrong way? Thanks for your support in advance.
PS Rodrigues rotation formula
Instead of print(P2.simplify)
you need to call this method like print(P2.simplify())
. After that you will get - l*sin(alpha)*cos(theta)*Nx - l*cos(alpha)*cos(theta)*Ny - l*sin(theta)*Nz
as output which is the same to last version of your def Rodrigues
.
An alternative solution is to force sympy to simplify all vectors by default:
from sympy.physics.vector import Vector
Vector.simp = True
more info here
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.