Posted on June 06, 2014
This week I refactored the Linearizer
class to fit a general system of
equations. This means that any of the following can be absent, and the
linearization still is valid:
with
$$ \begin{array}[rl] \\q, \dot{q} & \in \mathbb{R}^n \\ u, \dot{u} & \in \mathbb{R}^o \\ r & \in \mathbb{R}^s \end{array} $$Note that vectors can be absent too. This means the system can be entirely $q$ or $u$ components. More on this later.
Much of the rest of the week was spent finishing up all methods related to the
KanesMethod
class. This was mostly cleaning up the code base, and fixing
all the tests in place for the previous linearize
method. As of this point,
the linearization routines accomplish everything that was in place before, but
in a more general and extensible way. This is all included in the
LinearizerClass
branch on my GitHub repo. There is a pull request on my own
master branch open right now for code review
here. I'll leave this up for another
day or two before closing it and making all pull request to Sympy/master
.
I also started work on linearizing a system of equations presented in matrix form. This still needs lots of code improvements (it's inefficient), but it currently works. Below is a demo.
The system is the same system I use for my research - a dual solenoid actuator.
There are two dependent variables: lam1
and lam2
. The dynamics are thus
expressed by 3 dynamic differential equations, and two constraint equations.
from sympy import symbols, Matrix
from sympy.physics.mechanics import dynamicsymbols, mprint
from sympy.physics.mechanics.linearize import Linearizer, matrix_to_linearizer
# Create constant symbols
B1, B2 = symbols('B1, B2')
d1, d2, D = symbols('d1, d2, D')
R1, R2 = symbols('R1, R2')
m = symbols('m')
t = symbols('t')
# Create dynamicsymbols
i1, i2 = dynamicsymbols('i1, i2')
V1, V2 = dynamicsymbols('V1, V2')
x = dynamicsymbols('x')
xdot = x.diff()
lam1, lam2 = dynamicsymbols('lam1, lam2')
lam1dot, lam2dot = dynamicsymbols('lam1, lam2', 1)
# Define vectors. Because all speeds are derivatives of the coordinates,
# the system is best represented as just a vector of u. The dependent
# states are lam1 and lam2
u = Matrix([i1, i2, xdot, x, lam1, lam2])
udep = u[4:]
# Define system of equations
eom = Matrix([B1/(d1 + x)*i1 - lam1,
B2/(D + d2 - x)*i2 - lam2,
-lam1dot - R1*i1 + V1,
-lam2dot - R2*i2 + V2,
-xdot.diff() + (B2/(d2 + D - x)**2 * i2**2 - B1/(d1 + x)**2 * i1**2)/m])
# Perform the linearization
linearizer = matrix_to_linearizer(eom, u=u, udep=udep)
A, B = linearizer.linearize(A_and_B=True)
mprint(A)
mprint(B)
You'll have to trust me that the above representations are the same ones that I derived for my research project. This is really exciting progress! If everything works out (and it looks like it will), it will be possible to derive a system of dynamic equations anywhere in sympy, and then linearize it using the functionality I implement in the linearize
function.
Currently the system of equations is must formed as a matrix, and then passed
to matrix_to_linearizer
to return a Linearizer
object. Once this code is
cleaned up, it will be used internally by the general linearize
function to
convert the system to a Linearizer
, perform the linearization, and return
the results. I plan on implementing this functionality next week.
The code used above is found in my matrix2linearizer
branch on GitHub here. As before, I made a pull request on my own rep, so people may review the code before i submit it to Sympy proper. The PR is here.