Gsoc 2020 Application - Control Theory - Implement A Control Systems Package
Gsoc 2020 Application - Control Theory - Implement A Control Systems Package
About Me
Basic Information
Personal Background
I spend my free time playing soccer with my friends, reading books (poetry
and biographies) or playing chess online. Few of the courses I had the
chance to take at school are Linear Algebra and calculus; complex
analysis; Differential equations; Signals and Systems (covering some part
of Control theory); principles of communication; Object-Oriented Design
and Analysis; & Data Structures.
Programming Background
I use Ubuntu 19.04 as my operating system, along with VS Code being my
primary source code editor. I try to complete some of the mundane tasks
using the terminal. I am familiar with the git and Github workflow.
I like python because of its English like syntax, and because of its
advantages over other languages. I’m amongst the top 3 committers to this
ProjectEuler focused repository as can be seen here because I really like
problem-solving in general and I frequently take part in coding competitions
including ACM ICPC, and on various other platforms.
⎛2 2⎞
√2⋅⎝x - 5⋅x⋅y + 10⋅y ⎠
───────────────────
4
Contributions
I started using SymPy in November 2019 and made my first contribution to
the main repository the next month. I have been continuously contributing
to the software since then. I’m a long-term-contributor and will continue to
improve this software even after this program is finished.
Merged PRs
Unmerged PRs
The Project
Implementation Plan
I have planned to divide my work into four phases so that the package can
be added swiftly and systematically.
Phase 1
where u(t) is any input signal, y(t) is the corresponding output and x(t) is
the state of the system.
Here, A, B, C, and D are sympy matrices.
An important property that the transfer function may have is that of being
proper. So in this phase, I also implement a function is_proper which
checks if the degree of the numerator is less than or equal to the degree of
the denominator.
As we know that the transfer function is a ratio of polynomials, we already
have a way to represent that using sympy’s core class Mul. We are now
able to use all the features from that class, for example --
as_numer_denom, expressing in evaluated and non evaluated form and
much more.
Both the classes have already been proposed in #17866, I will continue
working in #18436 (WIP) which I had raised before. We can use these
guidelines (suggested by @sylee957) to make this a candidate for a full
symbolic model. All that can be done while we subclass Basic.
Along with addressing all the comments, I’m gonna define total_degree
for TransferFunctionModel. This gives back the total degree of the
rational function. If the degree of the denominator is greater than that of the
numerator, we get a negative result.
otal_degree(en):
def t
num, denom = en.as_numer_denom()
return degree(num) - degree(denom)
To this:
----------------------------------------------------------------------------------------------------
We can use less matrices as well, and the rest will be filled with a minimum
of zeros.
>>> ssm_2 = StateSpaceModel(A, B)
>>> ssm_2
Matrix([
[1],
[2]]),
Matrix([
[2],
[3]]),
Matrix([[0]]),
Matrix([[0]]))
----------------------------------------------------------------------------------------------------
>>> s = Symbol('s')
>>> u = Matrix([1/s])
>>> # example for `evaluate` method.
>>> TransferFunctionModel(Matrix([s/(1 +
s**2),1/s])).evaluate(u, s)
Matrix([
[1/(s**2 + 1)],
[ s**(-2)]])
Required tests will be added in the last week of this phase to ensure that
everything is implemented correctly. If possible, I’ll start coding in the last
week of the community bonding period so that I get a good headstart and
work in the next phases will proceed swiftly.
Phase 2
Now I’ll further add more features to this control systems package by
opening up a PR. These are the following methods that I will implement.
● observability_matrix (in StateSpaceModel)
● observable_subspace (in StateSpaceModel)
● is_observable (in StateSpaceModel)
● __neg__ (in TransferFunctionModel)
● __neg__ (in StateSpaceModel)
● _eval_rewrite_as_TransferFunctionModel (in SSM)
● _eval_rewrite_as_StateSpaceModel (in TFM)
bservable_subspace(self):
def o
return self.observability_matrix().columnspace()
Proposed API:
>>> ssm.observability_matrix() # depends only on A and C.
>>> ssm.observable_subspace() # returns a list of vectors,
and depends only on A and C
>>> ssm.is_observable() # returns a Boolean
def __neg__(self):
return StateSpaceModel(self.args[0], self.args[1],
-self.args[2], -self.args[3])
-----------------------------------------------------------
>>> A, B, C, D = Matrix([1, 2]), Matrix([2, 3]),
Matrix([2]), Matrix([0]);
def _eval_rewrite_as_TransferFunctionModel(self):
return self.rewrite(TransferFunctionModel)
def _eval_rewrite_as_StateSpaceModel(self):
return self.rewrite(StateSpaceModel)
After defining both of them, model interconversion would be as simple as
.rewrite(StateSpaceModel) & .rewrite(TransferFunctionModel)
All the required tests will be added along in the same PR. So, with this our
basic control systems functionality is implemented!
Phase 3
Following is a rough idea of what the plot would look like for gains between
0 and 10. The purple (dark blue) plot is the locus, x is for poles and o is for
zeros for our transfer function.
transfer function
>>> #
>>> t f = (2*s**2 + 5*s + 1)/(s**2 + 2*s + 3)
>>> t f.bode_plot(range) # pass frequency range.
Examples will also be added in the same PR. Some of them can be taken
from this manuscript.
Phase 4
By the time I would reach this phase, I would have implemented a control
package for SymPy along with the tests and docs.
I can easily find a bunch of examples in this manuscript and in this book -
Linear Systems Theory by Joao P. Hespanha, 2009.
------------------------------------
In the following weeks (Week 11, 12), I’ll add an object, IVPSolution, that
represents the solution of an ODE initial value problem. Given an ODE of
type Eq(f(x).diff(x), x) with an initial condition Eq(f(x), 0), we’ll be
able to define an object IVPSolution(t, (Eq(f(x).diff(x), x),),
(Eq(f(x), 0)) which would mathematically represent f(t) (f is the
solution of the initial value problem).
We can now apply subs, e valf, or lambdify for further work as per our
requirement. The idea (suggested by @oscarbenjamin in #18023) would be
to get numerical solutions for ODE.
IVPSolution.evalf will use the odefun of mpmath to give us numeric
solutions to ODE initial value problems.
Like this for example:
Required tests and documentation will be added along in the same PR.
----------------------------------------------------------------------------------------------------
Timeline
I have prepared a tentative timeline for the above mentioned tasks. I assure
that I’ll give all my time to this project and try to finish what I have
proposed.
● I will make sure all the PRs are successfully merged into the
codebase.
● Submitting final evaluations.
Post GSoC
After working with SymPy for about nine months, I would still be eager to
contribute more to this software. If the circumstances are good enough, I
will become a mentor for next year’s GSoC.
Notes
I’ve got no other commitments apart from this project, and thus would be
able to devote 40 to 50 hours per week. My college will restart on the 2nd
of August, and in the first month we have light coursework, so I would be
able to give all my time and energy to finish the project.
References
[1] - Oscar Benjamin
https://github.com/oscarbenjamin
[6] - SY Lee
https://github.com/sylee957