Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prototype System class. #81

Merged
merged 18 commits into from
Aug 7, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 86 additions & 85 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ PyDy
PyDy_, short for Python Dynamics, is a tool kit written in and accessed through
the Python programming language that utilizes an array of scientific tools to
study multibody dynamics. The goal is to have a modular framework and
eventually a physics abstraction layer which utilizes a variety of backend that
can provide the user with their desired workflow, including:
eventually a physics abstraction layer which utilizes a variety of backends
that can provide the user with their desired workflow, including:

- Model specification
- Equation of motion generation
Expand All @@ -29,7 +29,7 @@ visualization.
Installation
============

The PyDy workflow has hard dependecies on these Python packages:
The PyDy workflow has hard dependencies on these Python packages:

- Python >= 2.7
- setuptools
Expand Down Expand Up @@ -85,11 +85,11 @@ Tests require nose:

- nose: 1.3.0

Isolated Virtual Environment Installation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Isolated Environments
~~~~~~~~~~~~~~~~~~~~~

The following installation assumes you have virtualenvwrapper_ and all the
dependencies needed to build the packages::
dependencies needed to build the various packages::

$ mkvirtualenv pydy-dev
(pydy-dev)$ pip install numpy scipy cython nose theano sympy
Expand All @@ -100,6 +100,16 @@ dependencies needed to build the packages::

.. _virtualenvwrapper: https://pypi.python.org/pypi/virtualenvwrappe://pypi.python.org/pypi/virtualenvwrapper

Or with conda_::

$ conda create -n pydy-dev numpy scipy cython nose theano sympy matplotlib
$ source activate pydy-dev
(pydy-dev)$ git clone git@github.com:pydy/pydy.git
(pydy-dev)$ cd pydy
(pydy-dev)$ python setup.py develop

.. _conda: https://github.com/conda/conda

Run the tests::

(pydy-dev)$ nosetests
Expand All @@ -124,61 +134,6 @@ Run the benchmark to test the n-link pendulum problem.::
Usage
=====

Simply import the modules and functions when in a Python interpreter::

>>> from sympy import symbols
>>> from sympy.physics import mechanics
>>> from pydy import codegen, viz

Documentation
=============

The documentation is hosted at http://pydy-viz.readthedocs.org but you can also
build them from source using the following instructions:

Requires:

- Sphinx
- numpydoc

::

pip install sphinx numpydoc

To build the HTML docs::

$ sphinx-build -b html docs/src docs/build

View::

$ firefox docs/build/index.html

Code Generation
===============

This package provides code generation facilities for PyDy_. For now, it
generates functions that can evaluate the right hand side of the ordinary
differential equations generated with sympy.physics.mechanics_ with three
different backends: SymPy's lambdify_, Theano_, and Cython_.

.. _PyDy: http://pydy.org
.. _sympy.physics.mechanics: http://docs.sympy.org/latest/modules/physics/mechanics
.. _lambdify: http://docs.sympy.org/latest/modules/utilities/lambdify.html#sympy.utilities.lambdify.lambdify
.. _Theano: http://deeplearning.net/software/theano/
.. _Cython: http://cython.org/

Optional Dependencies
---------------------

To enable different code generation backends, you can install the various
optional dependencies:

- Cython: >=0.15.1
- Theano: >=0.6.0

Usage
-----

This is an example of a simple 1 degree of freedom system: a mass, spring,
damper system under the influence of gravity and a force::

Expand Down Expand Up @@ -224,39 +179,31 @@ Derive the system::
particles = [block]

kane = me.KanesMethod(ceiling, q_ind=[position], u_ind=[speed],
kd_eqs=kinematic_equations)
kd_eqs=kinematic_equations)
kane.kanes_equations(forces, particles)

Store the expressions and symbols in sequences for the code generation::
Create a system to manage integration. Specify numerical values for the
constants and specified quantities. Here, we specify sinusoidal forcing::

mass_matrix = kane.mass_matrix_full
forcing_vector = kane.forcing_full
constants = (mass, stiffness, damping, gravity)
coordinates = (position,)
speeds = (speed,)
specified = (force,)
from numpy import array, linspace, sin
from pydy.system import System

Now generate the function needed for numerical evaluation of the ODEs. The
generator can use various back ends: ``lambdify``, ``theano``, or ``cython``::
sys = System(kane,
constants={mass: 1.0, stiffness: 1.0,
damping: 0.2, gravity: 9.8},
specified={'symbols': [force],
'values': lambda x, t: sin(t)},
initial_conditions=array([0.1, -1.0]))

from pydy.codegen.code import generate_ode_function
Now generate the function needed for numerical evaluation of the ODEs::

evaluate_ode = generate_ode_function(mass_matrix, forcing_vector, constants,
coordinates, speeds, specified,
generator='lambdify')
sys.generate_ode_function()

Integrate the equations of motion under the influence of a specified sinusoidal
force::

from numpy import array, linspace, sin
from scipy.integrate import odeint

x0 = array([0.1, -1.0])
args = {'constants': array([1.0, 1.0, 0.2, 9.8]),
'specified': lambda x, t: sin(t)}
t = linspace(0.0, 10.0, 1000)

y = odeint(evaluate_ode, x0, t, args=(args,))
y = sys.integrate(t)

Plot the results::

Expand All @@ -266,14 +213,62 @@ Plot the results::
plt.legend((str(position), str(speed)))
plt.show()

Documentation
=============

The documentation is hosted at http://pydy.readthedocs.org but you can also
build them from source using the following instructions:

Requires:

- Sphinx
- numpydoc

::

pip install sphinx numpydoc

To build the HTML docs::

$ sphinx-build -b html docs/src docs/build

View::

$ firefox docs/build/index.html

Packages
========

Code Generation
---------------

This package provides code generation facilities for PyDy_. For now, it
generates functions that can evaluate the right hand side of the ordinary
differential equations generated with sympy.physics.mechanics_ with three
different backends: SymPy's lambdify_, Theano_, and Cython_.

.. _PyDy: http://pydy.org
.. _sympy.physics.mechanics: http://docs.sympy.org/latest/modules/physics/mechanics
.. _lambdify: http://docs.sympy.org/latest/modules/utilities/lambdify.html#sympy.utilities.lambdify.lambdify
.. _Theano: http://deeplearning.net/software/theano/
.. _Cython: http://cython.org/

To enable different code generation backends, you can install the various
optional dependencies:

- Cython: >=0.15.1
- Theano: >=0.6.0

Visualization (viz)
===================
-------------------

Visualization of multibody systems generated with PyDy.

Related Packages
================

These are various related Python packages that have similar functionality.

- https://github.com/cdsousa/sympybotics
- https://pypi.python.org/pypi/Hamilton
- https://pypi.python.org/pypi/arboris
Expand All @@ -296,10 +291,16 @@ Related Packages
Release Notes
=============

0.3.0
-----

- Added a new System class and module to more seamlessly manage integrating the
equations of motion.

0.2.1
-----

- Unbundled unecessary files from tar ball.
- Unbundled unnecessary files from tar ball.

0.2.0
-----
Expand Down
2 changes: 1 addition & 1 deletion bin/benchmark_pydy_code_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def run_benchmark(max_num_links, num_time_steps=1000):
# odeint arguments
x0 = hstack((0, pi / 2 * ones(len(results[3]) - 1), 1e-3 *
ones(len(results[4]))))
args = {'constants': array(parameter_vals)}
args = {'constants': dict(zip(results[2], array(parameter_vals)))}
t = linspace(0, 10, num_time_steps)

for k, method in enumerate(methods):
Expand Down
8 changes: 8 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ codegen package

codegen/api.rst

System class
------------

.. toctree::
:maxdepth: 1

system.rst

viz package
-----------

Expand Down
7 changes: 7 additions & 0 deletions docs/system.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
System class
============

.. automodule:: pydy.system

.. autoclass:: pydy.system.System
:members:
16 changes: 8 additions & 8 deletions examples/double_pendulum/double_pendulum.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@
KM = KanesMethod(N, q_ind=[q1, q2], u_ind=[u1, u2], kd_eqs=kd)


(fr, frstar) = KM.kanes_equations(FL, BL)
kdd = KM.kindiffdict()
mass_matrix = KM.mass_matrix_full
forcing_vector = KM.forcing_full
qudots = mass_matrix.inv() * forcing_vector
qudots = qudots.subs(kdd)
qudots.simplify()

KM.kanes_equations(FL, BL)
#kdd = KM.kindiffdict()
#mass_matrix = KM.mass_matrix_full
#forcing_vector = KM.forcing_full
#qudots = mass_matrix.inv() * forcing_vector
#qudots = qudots.subs(kdd)
#qudots.simplify()
#
43 changes: 8 additions & 35 deletions examples/double_pendulum/simulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,22 @@
"""

from numpy import concatenate, array, linspace
from pydy.codegen.code import generate_ode_function
from pydy.system import System
from scipy.integrate import odeint

from double_pendulum import *

# List the symbolic arguments
# ===========================

# Constants
# ---------

constants = {l: 10.0, m: 10.0, g: 9.81}

# Time-varying
# ------------

coordinates = [q1, q2]

speeds = [u1, u2]


# Generate function that returns state derivatives
# ================================================

xdot_function = generate_ode_function(mass_matrix, forcing_vector,
constants.keys(), coordinates, speeds)
initial_conditions = {q1: 1.0, q2: 0.0, u1: 0.0, u2: 0.0}


# Specify numerical quantities
# ============================

initial_coordinates = [1.0, 0.0]
initial_speeds = [0.0, 0.0]
x0 = concatenate((initial_coordinates, initial_speeds), axis=1)

args = {'constants': constants.values()}


# Simulate
# ========
sys = System(KM, constants=constants,
initial_conditions=initial_conditions)

frames_per_sec = 60
final_time = 5.0

t = linspace(0.0, final_time, final_time * frames_per_sec)
x = odeint(xdot_function, x0, t, args=(args,))
times = linspace(0.0, final_time, final_time * frames_per_sec)

x = sys.integrate(times)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I had been implying for re-integrating Scene visualization stuff.
So that we supply times and sys to the Scene class, and is easier to handle than the existing structure.
I am ready to work on integrating this code with Scene class(after tomorrow).

But also there will be some backwards incompatible changes(in Scene class as well), when this is integrated into Scene.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is why we are creating this, so that you can have something easier to work with in your viz code. It won't be ready tomorrow, but please help contribute to this so we can get it done more quickly.


2 changes: 1 addition & 1 deletion examples/double_pendulum/visualize.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
# Create the visualization
# ========================

scene.generate_visualization_json(coordinates + speeds, constants.keys(), x,
scene.generate_visualization_json(sys.states, constants.keys(), x,
constants.values())

scene.display()
2 changes: 1 addition & 1 deletion examples/three_link_conical_pendulum/simulate.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,5 @@

print("Integrating equations of motion.")
state_trajectories = odeint(right_hand_side, x0, t,
args=({'constants': param_vals},))
args=({'constants': dict(zip(param_syms, param_vals))},))
print("Integration done.")
Loading