-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
GSoC 2016 Application James Brandon Milam: Base Class and Increased Efficiency for Equation of Motion Generators
Name: James Brandon Milam (Prefer Brandon) College: University of Florida, Gainesville, Masters in Mechanical Engineering Email: jmilam343@gmail.com Github: jbm950
I'm from Missouri and have obtained my bachelor's degree in mechanical engineering from the University of Missouri - Columbia. I began working with python during my undergraduate experience around four years ago and have loved programming ever since. I am currently pursuing my master's degree also in mechanical engineering at the University of Florida.
I currently do the majority of my programming on a MacBook pro, however, I have access to a Windows platform and virtual Linux machines for testing cross platform compatibility. My preferred editor of choice is vim. Not needing the mouse in the editor and the myriad of available short cut keys streamlines and greatly enhances productivity. In addition, by working in vim I have immediate access to the terminal which is of extreme use whenever I need to run code or use Git commands, etc.
I spend the majority of my programming time working with python, though in my undergraduate experience I was taught and used MATLAB. In addition, I have taught myself some C coding in order to work with an Arduino micro controller. Using the Arduino, I have created a temperature controller for my senior design class, I have implemented a four-wheel robot platform and have done some basic interactions with the Arduino and python over a serial connection.
My python background consists of being completely self taught, including reading all the way through "Learning Python" which is a hefty book that covers all of the basic language fundamentals from lists to metaclasses to decorators. I have used python to make some simple video games, a flashcard application utilizing tkinter, solve complicated engineering coursework, create a fuzzy speed controller for an aircraft and communicate through UDP to a flight simulator to run the fuzzy controller. While using python to make video games I made my own library to extend the functionality of the pygame library. My library, pygame_toolbox, is currently hosted on Github and is available through pypi (majority of the code lies in graphics/_init_.py). I feel this library best showcases my coding capabilities with object oriented design and cleanness/documentation of code. In addition to these projects I have also made contributions to python core.
The features that I love about python that I feel differentiate it from other programming languages are that it is open source, extremely versatile, it is dynamically typed and it was created with the specific intention of portraying clarity. The most advanced features/standard library functionalities I have used are communications through serial ports and UDP, creating and distributing my custom made library and designing class hierarchy trees to efficiently extend functionalities.
I have experience in using Git extensively for personal notes and projects as well as any other files that I do not want to lose. I have even created a PowerPoint presentation introducing the ideas of version control and Git that I have presented to friends and classmates. I use Git both with Github and with creating private repositories that I put on Dropbox. In addition to Git I have some experience working with Mercurial from contributing to python core, however, I am much more comfortable with Git.
Sympy drew me in with its ability to compute and create expressions
symbolically for engineering design purposes. To show this I will expand on the
simple mass, spring, damper example in LagrangesMethod
's docstring with a
simple input force, F which produces the following output.
>>> from sympy import *
>>> from sympy.physics.mechanics import LagrangesMethod, Lagrangian
>>> from sympy.physics.mechanics import ReferenceFrame, Particle, Point
>>> from sympy.physics.mechanics import dynamicsymbols, kinetic_energy
>>> q = dynamicsymbols('q')
>>> qd = dynamicsymbols('q', 1)
>>> m, k, c, F = symbols('m k c F')
>>> N = ReferenceFrame('N')
>>> P = Point('P')
>>> P.set_vel(N, qd * N.x)
>>> Pa = Particle('Pa', P, m)
>>> Pa.potential_energy = k * q**2 / 2.0
>>> L = Lagrangian(N, Pa)
>>> fl = [(P, -c * qd * N.x), (P, F * N.x)]
>>> l = LagrangesMethod(L, [q], forcelist=fl, frame=N)
>>> l.form_lagranges_equations()
>>> print(l.rhs())
Matrix([[Derivative(q(t), t)], [(F - c*Derivative(q(t), t) - 1.0*k*q(t))/m]])
This set of equations naturally lends to controls analysis because in order to
better design control laws the dynamics of the system need to be known. With
some simple, by hand re-arranging the output from LagrangesMethod
can be put
into state space form (xdot = Ax + Bu). Now with sympy the controllability of
the system and the natural system response can be determined.
>>> A = Matrix([[0, 1], [-k/m, -c/m]])
>>> B = Matrix([0, 1/m])
>>> M = Matrix([B.transpose(), (A*B).transpose()]).transpose()
>>> print(M.rank())
2
>>> eigA = A.eigenvals()
>>> print(eigA)
{-c/(2*m) + sqrt(c**2 - 4*k*m)/(2*m): 1, -c/(2*m) - sqrt(c**2 - 4*k*m)/(2*m): 1}
The system is full rank (rank = the number of states, x) and is therefore controllable by the input force. Also the eigenvalues are solved symbolically and this is where sympy shines over numeric tools such as scipy. As a controls engineer, the system response due to choice of damping and spring stiffness for a given mass are clearly visible in this symbolic representation, allowing for a more streamlined design stage. Obviously this is a simple example but it is these sort of uses that drew me to sympy and is the reason I wish to contribute to its development.
Pull Requests:
- Tutorial Documentation Fix [Merged]
- Docstring Typo Fix in init_printing() [Merged]
- Pass Arbitrary Inputs from init_printing to the printer [Merged]
For the project I propose working on creating a base class for the equations of motion generators in the physics module and add a Newton-Euler equation of motion generator. The benefits of creating a base class for equations of motion generators would include ease of adding additional equations of motion generators and making the code more compact and so speed enhancements and bug fixes will affect all generators simultaneously rather than having to be implemented on a per generator basis. In addition to this work I would also be working on increasing the speed/efficiency of the existing python code for the equations of motion generators since I will already be digging into their base functionality.
Just last semester I took a graduate level course on analytical dynamics during which we learned how to perform the Newton-Euler and Lagrange methods of equation of motion generation by hand. This will allow me to develop the Newton-Euler equation of motion generator in addition to having the base knowledge to be able to work with the Lagrange method and learn additional methods.
Another qualification I possess is experience in refactoring code and making base classes to organize shared functionality from my work with python core and from the library I built to work with pygame. When working with python core I altered the base class for the Windows web browser and subclassed it to allow specific browsers (ie. Google Chrome, Firefox) to pass their own flags. With my work on my personal library I created a base class for screens and subclassed it to make menus, or a screen that read like a book. This prior work with subclassing will aid greatly as I abstract the equations of motion generators in order to form a generic base class.
Lastly I have implemented python's multiprocessing capabilities while coding numerical integration methods. This is experience I can draw upon as I work to increase the speed of the python code any where that seems inherently parallelizable.
My background and qualifications directly point towards this specific project and is why I am excited to attempt to implement it. I will be able to translate in-class theoretical learning to applications and work towards creating a structure that promotes code growth. In addition, my mechanical engineering background includes an emphasis in control systems and so my interest in the equations of motion generators is that it would be useful for modeling the dynamics of the system and streamline the design process for control engineers.
No previous work has been done in creating a shared base class for the equations of motion generators, implementing a Newton-Euler equation of motion generator or specifically enhancing the run time of the python code of the existing equations of motion generators. There are existing equations of motion generators, however, that utilize Kane's and Lagrange's methods for equation of motion generation and this will be the starting point for the project.
The basic idea that I have for the base class is to round up methods
that are the same in both KanesMethod
and LagrangesMethod
classes. There
are currently ten methods in these classes with shared names. Of these methods
there are some that appear to run very differently or make use of different
attributes (to_linearlizer
, mass_matrix
, mass_matrix_full
, forcing
,
forcing_full
) but there are others that have very similar code with only
slight variations (linearize
, rhs
). For the methods that are more different,
research will need to be done into whether or not these differences stem from
the use of different naming conventions and processes or if the methods are
truly different. An attempt will then be made to rewrite these methods such
that they perform similarly for both classes and could therefore be transferred
to the base class. For the methods that are very close, the identical code can
be put in the base class and let the specific equation of motion generators
modify it as needed such as shown below.
class LagrangesMethod(BaseClass):
def rhs():
run Lagrange specific code/warnings
BaseClass.rhs()
In addition to the above mentioned methods, there are some methods that are
identical (q
, u
, forcelist
) and these would directly lend themselves to
being placed in the base class. Aside from the methods, any similar attributes
found between the two classes will also be transferred to the base class. This
will be done in the appropriate method that requires the attributes or in the
base class's init method which would result in the same call form as was
shown above (note the base class will be called something along the lines of
EOMBase
)
class KanesMethod(BaseClass):
def __init__(inputs):
Kanes Method specific attributes
BaseClass.__init__(base_class_inputs)
In general the API for KanesMethod
and LagrangesMethod
will be entirely
preserved as best as possible to allow backwards compatibility. The only
changes that would be made would be for consistency between the two methods.
For instance in KanesMethod
the equations of motion are generated by
KM.kanes_equations()
whereas LagrangesMethod
produces the equations of
motion by LM.form_lagranges_equation()
. For situations such as these an
agreed upon consistency would be implemented and the replaced method will issue
a deprecation warning then call the new method. The other possible API
changes/additions would be in response to looking through
pydy.system.System
's code. In this code there are some methods implemented to
access attributes of KanesMethod
that are not currently accessible directly
from KanesMethod
's API. These methods are _kane_inlist_syms
,
_kane_undefined_dynamic_symbols
and _kane_constant_symbols
and would be
better off implemented in sympy's code. In addition these are methods that can
be non-generator specific and could possibly be implemented in the base class
rather than specifically KanesMethod
or LagrangesMethod
.
For the NewtonEulerMethod
class I will attempt to build the same general API
as KanesMethod
and LagrangesMethod
where creating an instance of the class
initializes key information needed to compute the equations of motion and a
call to the class method named after the generation method will actually
generate the equations of motion.
>>> NEM = NewtonEulerMethod(inputs)
>>> NEM.newton_euler_equations()
In addition, NewtonEulerMethod
should in the very least provide the same
methods as are shared between KanesMethod
and LagrangesMethod
as described
in detail above. I plan on including the example code for a mass, spring,
damper system in the docstring of the NewtonEulerMethod
for consistency
between the three equations of motion generators.
I have already run a profiler on the n_link_pendulum_on_cart()
function found
in the pydy source as it makes use of sympy's KanesMethod
class. With this
profile I can prove that the work on speeding the code up for the equations of
motion generators will have an impact across all of sympy rather than just the
physics module. For instance, while running kanes_equations
the code spent
about 45% of its time in the sympy/matrices module. Therefore in order to speed
up the equations of motion generator the other parts of sympy will need to be
made to run more efficiently as well.
Currently my ideas for speeding up the code are rather sparse. My plan is to go
through function calls from the profiler and see if any functions are trying to
perform too many different tasks which are not necessarily related. Such
functions would be better off split so that unnecessary bits of code are not
run. In addition, looking through the profile generated of the
n_link_pendulum_on_cart()
function, there are some calls that appear to occur
often and do not take much time per call. I would look into seeing if such
calls could be parallelized. This could also apply to code within some of the
larger function calls. Lastly I will be making sure the code blocks are written
efficiently (use elif statements instead of separate if statements or rearrange
for loops so that unnecessary code is pulled out where applicable). These are
the sorts of things I will be looking for and will take greater advantage of
near the end of the project after having been fully immersed in the code for
most of the summer.
Before the project officially begins I will be spending time working on the project as I can while school is still in session. The school semester is completely over before May begins, however, and so I would be able to essentially start my project early by about two to three weeks. During this time, I would be familiarizing myself with Kane's method of equation of motion generation and beginning work in creating a benchmarking tool for use during the project.
During the project I have no other obligations and will be able to put in 40+ hours each week. I am thinking about taking a trip back home around the 4th of July, however, I will still be able to get work done and so this would not create a huge disturbance in the amount of weekly hours I put in.
After the summer ends I will be beginning my final semester of graduate school and so the amount of time I could continue to devote to sympy would be limited. This limitation would only last until December, though, and I would be able to more regularly return at the beginning of the new year.
Week 1 [May 23rd - May 30th]
-
Create benchmarking tool to track project progress
- The tool will run test code and simulations using both
KanesMethod
andLagrangesMethod
and save the results in an SQLite database where each table represents a different test - In addition to the speed results, each row in the table will include information on who ran the tests (probably see if I can access Github username for this),what version of python was used, what operating system was used and the hardware details of the computer used (CPU speed and RAM)
- A profile of portions of the tested code will be saved in a subfolder
- A viewer of the results would be made using the matplotlib library
- Sub options for viewing results will be added as time allows
- Tool will be made such that it is easily extendable
- Can be used by other members of the community for their projects
- Can be used with the
NewtonEuler
class that will be created later in the project
- PR: Resulting tool could be introduced as a pull request depending on whether or not this is desired in the main code base
- The tool will run test code and simulations using both
-
Learn and practice Kane's method of generating equations of motion so that I will have a better understanding of how the code works
-
Note: The items listed for week 1 would begin at the beginning of May much before the project officially begins
Week 2, 3 [May 30th - June 13th]
-
Begin going through internals of the
KanesMethod
andLagrangesMethod
to determine what the commonalities are that could be drawn from a base class -
Create a basic implementation of the base class from which
KanesMethod
andLagrangesMethod
would be subclasses
Week 4, 5 [June 13th - June 27th]
-
Continue working out and condensing code to complete the base class for the equations of motion generators
- Keeping attention to enhancing speed and performance of code during consolidation
-
Develop the supporting documentation for the base equations of motion generation class
-
Complete the midterm evaluation with the functioning base class, test code for the base class and the supporting documentation as the deliverable
- PR: Base class code, test code for the base class and documentation for the base class
Week 6, 7 [June 27th - July 11th]
- Look into best practices for coding a
NewtonEulerMethod
class and begin creation of that class. This will be a general design period and as the desired API is developed. Test code will be written to verify the agreed upon API.
Week 8, 9 [July 11th - July 25th]
-
Complete
NewtonEulerMethod
class -
Update the documentation explaining the new method
-
PR:
NewtonEulerMethod
class code, test code and documentation
Week 10 - 13 [July 25th - August 23rd]
-
Finish any documentation or code that is still needing to be completed
-
Continue to refactor and improve the quality of the code written for the project
-
By this point a complete understanding of the code underlying the methods should be obtained and thus effort towards performance enhancement and speed would return the greatest results
-
Make final preparations for the final evaluation
- Final deliverables would include
- Equations of motion generator base class
- Newton-Euler equations of motion generator class
- Benchmarking results
- PR: Any remaining items, code, documentation fixes etc.
- Final deliverables would include
Note: Any spare time during the weeks will be used towards speeding up the python code.
In the case that time runs short this section details the priority that the
different aspect of the project will receive. Top priority will be given to the
test code for the base class and the completeness and stability of the base
class code for the equations of motion generation. Next priority will be the
complete documentation of the base class. This is followed by completeness of
the test code and actual code for the NewtonEulerMethod
then by the
documentation for NewtonEulerMethod
. The last priority will be given to
speeding up the equations of motion generation code. Note that the tests, code
and documentation will be developed simultaneously and this is just a
declaration of priorities should time start to run out near the end of the
project.