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

Week 2025 01 #198

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Clone the repository::
git clone https://github.com/moorepants/learn-multibody-dynamics.git
cd learn-multibody-dynamics

Install miniconda_ or a similar tool (e.g. Anaconda_) and create a conda
Install miniconda_ or a similar tool (e.g. Anaconda_) and create a conda
environment for the book::

conda env create -f multibody-book-env.yml
Expand Down
14 changes: 8 additions & 6 deletions index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ Learn Multibody Dynamics
| Version: |version|

This online book aims to teach multibody dynamics using interactive code woven
into the text. It follows the organization and methods presented in [Kane1985]_
and can be thought of a retelling of many topics in the book. Each page can be
downloaded as a Python_ script or Jupyter_ Notebook. The book is also
`available in PDF format <learnmultibodydynamics.pdf>`_. This book is used
primarily as a companion resource for TU Delft's `Multibody Dynamics`_ course
taught by `Jason K. Moore`_ but it is designed to standalone from the course.
into the text. It generally follows the organization and methods presented in
[Kane1985]_ and can be thought of a retelling of many topics in the book. Each
page can be downloaded as a Python_ script or Jupyter_ Notebook. The book is
also `available in PDF format <learnmultibodydynamics.pdf>`_. This book is used
as a companion resource for TU Delft's `Multibody Dynamics`_ course taught by
`Jason K. Moore`_ but it is designed to stand alone from the course.

.. _Python: https://python.org
.. _Jupyter: https://jupyter.org
Expand Down Expand Up @@ -57,9 +57,11 @@ taught by `Jason K. Moore`_ but it is designed to standalone from the course.
Prior Versions
==============

- `Version 0.3`_: Final version after the 2024 course.
- `Version 0.2`_: Final version after the 2023 course.
- `Version 0.1`_: Final version after the 2022 course.

.. _Version 0.3: https://github.com/moorepants/learn-multibody-dynamics/releases/tag/v0.3
.. _Version 0.2: https://github.com/moorepants/learn-multibody-dynamics/releases/tag/v0.2
.. _Version 0.1: https://github.com/moorepants/learn-multibody-dynamics/releases/tag/v0.1

Expand Down
4 changes: 3 additions & 1 deletion introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ without the need of `Lagrange multipliers`_.
Choice of programming language
==============================

With the goal of teaching through computation, it means I need to also choose a
With the goal of teaching through computation, it means I also need to choose a
programming language. There are many programming languages well suited to
multibody dynamics computation, but I select Python_ for several reasons: 1)
Python is open source and freely available for use, 2) Python is currently one,
Expand Down Expand Up @@ -163,6 +163,8 @@ the text, in approximate order of first contribution:
- Abhinav Kamath, 2020
- Timo Stienstra, 2022
- Dr. Sam Brockie, 2023
- Hwayeon Kang, 2024
- Riccardo Di Girolamo, 2024

SymPy Mechanics is built on top of SymPy, whose `1000+ contributors`_ have also
greatly helped SymPy Mechanics be what it is. Furthermore, the software sits on
Expand Down
62 changes: 28 additions & 34 deletions sympy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ a format that is similar to the math in a textbook. Executing
:external:py:func:`~sympy.interactive.printing.init_printing` at the beginning
of your Jupyter Notebook will ensure that SymPy objects render as typeset
mathematics. I use the ``use_latex='mathjax'`` argument here to disable math
png image generation, but that keyword argument is not necessary.
png image generation, but that keyword argument is not strictly necessary.

.. jupyter-execute::

Expand Down Expand Up @@ -229,13 +229,14 @@ This is a visual representation of the tree:
"Pow(Symbol('omega'), Integer(-2))_(1, 1)" -> "Integer(-2)_(1, 1, 1)";
}

This representation is SymPy's "true" representation of the symbolic
expression. SymPy can display this expression in many other representations,
for example the typeset mathematical expression you have already seen is one of
those representations. This is important to know, because sometimes the
expressions are displayed to you in a way that may be confusing and checking
the ``srepr()`` version can help clear up misunderstandings. See the
`manipulation section`_ of the SymPy tutorial for more information on this.
This representation is SymPy's internal fundamental representation of the
symbolic expression. SymPy can display this expression in many other
representations, for example the typeset mathematical expression you have
already seen is one of those representations. This is important to know,
because sometimes the expressions are displayed to you in a way that may be
confusing and checking the ``srepr()`` version can help clear up
misunderstandings. See the `manipulation section`_ of the SymPy tutorial for
more information on this.

.. _manipulation section: https://docs.sympy.org/latest/tutorial/manipulation.html

Expand Down Expand Up @@ -350,7 +351,7 @@ to provide a form that more closely resembles typeset math:
sm.pprint(expr3)

Lastly, the following lines show how SymPy expressions can be represented as
LaTeX code using :external:py:func:`sympy.printing.latex.latex`. The double
LaTeX code using :external:py:func:`~sympy.printing.latex.latex`. The double
backslashes are present because double backslashes represent the escape
character in Python strings.

Expand Down Expand Up @@ -543,11 +544,11 @@ To convert this to Python floating point number, use ``float()``:

.. jupyter-execute::

float(expr3.evalf(n=300, subs=repl))
float(expr3.evalf(n=80, subs=repl))

.. jupyter-execute::

type(float(expr3.evalf(n=300, subs=repl)))
type(float(expr3.evalf(n=80, subs=repl)))

This value is a `machine precision`_ floating point value and can be used with
standard Python functions that operate on floating point numbers.
Expand Down Expand Up @@ -705,8 +706,11 @@ Element-by-element multiplication requires the

sm.hadamard_product(mat1, mat2)

Note that NumPy uses ``*`` for element-by-element multiplication and ``@`` for matrix multiplication,
so to avoid possible confusion, use ``@`` for SymPy matrix multiplication.
.. warning::

Note that NumPy uses ``*`` for element-by-element multiplication and ``@``
for matrix multiplication, so to avoid possible confusion, use ``@`` for
SymPy matrix multiplication.

Differentiation operates on each element of the matrix:

Expand Down Expand Up @@ -850,21 +854,17 @@ To solve with SymPy, start with a column matrix of linear expressions:
exprs

Since we know these two expressions are linear in the :math:`a_1` and
:math:`a_2` variables, the partial derivatives with respect to those two
variables will return the linear coefficients. The :math:`\mathbf{A}` matrix
can be formed in one step with the ``.jacobian()`` method:
:math:`a_2` variables, the :math:`\mathbf{A}` and :math:`\bar{b}` matrices can
be formed in one step with the
:py:func:`~sympy.solvers.solveset.linear_eq_to_matrix` function:

.. jupyter-execute::

A = exprs.jacobian([a1, a2])
A, b = sm.linear_eq_to_matrix(exprs, [a1, a2])
A

The :math:`\bar{b}` vector can be formed by setting :math:`a_1=a_2=0`, leaving the
terms that are not linear in :math:`a_1` and :math:`a_2`.

.. jupyter-execute::

b = -exprs.xreplace({a1: 0, a2: 0})
b

The :external:py:meth:`~sympy.matrices.matrixbase.MatrixBase.inv` method can
Expand All @@ -888,21 +888,17 @@ especially as the dimension of :math:`\mathbf{A}` grows:
.. warning::

This method of solving symbolic linear systems is fast, but it can give
incorrect answers for:

1. expressions that are not acutally linear in the variables the Jacobian is
taken with respect to
2. :math:`\mathbf{A}` matrix entries that would evaluate to zero if
simplified or specific numerical values are provided
incorrect answers for :math:`\mathbf{A}` matrix entries that would evaluate
to zero if simplified or specific numerical values are provided.

So only use this method if you are sure your equations are linear and if
your :math:`\mathbf{A}` matrix is made up of complex expressions, watch out
for ``nan`` results after lambdifying.
:external:py:func:`~sympy.solvers.solvers.solve` and
:external:py:func:`~sympy.solvers.solveset.linsolve` can also solve linear
systems and they check for linearity and properties of the A matrix. The
cost is that they can be extremely slow for large expressions (which we will
have in this book).
systems and they check for linearity and various properties of the A matrix.
The cost is that they can be extremely slow for large expressions (which we
can have in this book).

.. admonition:: Exercise

Expand Down Expand Up @@ -940,8 +936,7 @@ especially as the dimension of :math:`\mathbf{A}` grows:

unknowns = sm.Matrix([L1, L2, L3, L4, L5, L6])

coef_mat = exprs.jacobian(unknowns)
rhs = -exprs.xreplace(dict(zip(unknowns, [0]*6)))
coef_mat, rhs = sm.linear_eq_to_matrix(exprs, unknowns)

sol = coef_mat.LUsolve(rhs)

Expand All @@ -966,8 +961,7 @@ complicated. Reproduced here:
[a1*sm.sin(f(t))*sm.cos(2*f(t)) + a2 + omega/sm.log(f(t), t) + 100],
[a1*omega**2 + f(t)*a2 + omega + f(t)**3],
])
A = exprs.jacobian([a1, a2])
b = -exprs.xreplace({a1: 0, a2: 0})
A, b = sm.linear_eq_to_matrix(exprs, [a1, a2])
sol = A.LUsolve(b)

SymPy has some functionality for automatically simplifying symbolic
Expand Down
Loading