简体   繁体   中英

How to simplify sympy vectors?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM