Posted on May 30, 2014
This week I started work on implementing a general linearization method in
Sympy
. The current plan is to implement this in three parts:
Linearizer
classThis will hold the general form described by Luke and Gilbert's paper. The form is:
\begin{aligned} f_{c}(q, t) &= 0_{l \times 1} \\ f_{v}(q, u, t) &= 0_{m \times 1} \\ f_{a}(q, \dot{q}, u, \dot{u}, t) &= 0_{m \times 1} \\ f_{0}(q, \dot{q}, t) + f_{1}(q, u, t) &= 0_{n \times 1} \\ f_{2}(q, \dot{u}, t) + f_{3}(q, \dot{q}, u, r, t) &= 0_{(o-m) \times 1} \end{aligned}
with
\begin{aligned} q, \dot{q} & \in \mathbb{R}^n \\ u, \dot{u} & \in \mathbb{R}^o \\ r & \in \mathbb{R}^s \end{aligned}
Once in this general form, the algorithm devised by Luke and Gilbert is able to linearize the system properly (not messing up due to constraints, as shown last week). The resulting linearized form is:
$$ M \begin{bmatrix} \delta \dot{q} \\ \delta\dot{u} \end{bmatrix} = A \begin{bmatrix} \delta q_{i} \\ \delta u_{i} \end{bmatrix} + B \begin{bmatrix}\delta r \end{bmatrix}$$
where $M$, $A$, and $B$ are matrices. A class method linearize
is used to
perform this step.
linearize
functionThis will take input systems of various forms (formed by KanesMethod
,
LagrangesMethod
, or ideally a general matrix of equations). The function
will then turn the system into the general form described above, create
an instance of Linearizer
, call the linearize
method, and return the
result.
To make this conversion easy and general, any class that implements a
to_linearizer
method can be linearized. One has been written for
KanesMethod
already. Originally I thought I could get equations formed
with Lagranges Method into this general form as well, but now I'm not sure.
The multipliers could be treated as dependent speeds (eliminating them from
the state vector), but for the linearization to be valid a trim point for
each multiplier will still need to be chosen. I'm going to think about this for
a while, and finish the remaining functionality for the KanesMethod
class
first. If it turns out this can't be generalized for Lagrange's method, then a
seperate control flow path will need to be added.
linearize
class methods for KanesMethod
and LagrangesMethod
These will be nice wrappers for the linearize function, making the linearization
process as easy as creating the Method object, and then calling
Method.linearize()
.
This week I implemented the beginnings of the Linearizer
class. So far it can
only handle systems with both motion and configuration constraints. I plan on
finishing up the remaining control paths for just motion, just
configuration, and no constraint systems next week. For testing this
functionality, I used the rolling disk example used in Luke and Gilbert's paper.
With the current functionality, linearization works as:
# Equations for the disk are derived above, KM is a KanesMethod object
>>> linearizer = KM.to_linearizer()
>>> A, B = linearizer.linearize(eq_q, eq_u, eq_qd, eq_ud, A_and_B=True)
# Evaluating in an upright configuration at critical speed:
>>> upright_critical_speed = {q1d: 0, q2: 0, q3d: 1/sqrt(3), m: 1, r: 1, g: 1}
#Calculating the critical speed eigenvalues, they should all be zero
>>> A.subs(upright_critical_speed).eigenvals()
{0: 8}
I also added a to_linearizer
method to the KanesMethod
class. This finds all
the needed information in the KanesMethod
object, and returns a Linearizer
object. I'd say this is done as well, and is also tested in the
test_linearize_rolling_disc
test.
Two other tests were also written, but not finished. They build off the example
I wrote up last week with a minimal
and nonminimal pendulum system. I also have this same system worked out in
minimal and nonminimal coordinates using LagrangesMethod
. Because it is so
quick to compute, and intuitive to know if it's correct or not I think this
will be an excellent way to test the functionality of the linearization
routines.
All of this work can be seen (and hopefully commented on, I need code review!) in this pull request. As it's still very much a work in progress, I made a pull request on my own master branch, so that others can review it before I submit it to Sympy proper.