Skip to content

Commit 2427d64

Browse files
committed
Merge branch 'master' of github.com:moorepants/learn-multibody-dynamics
2 parents 7402a0d + 6d78942 commit 2427d64

2 files changed

Lines changed: 208 additions & 37 deletions

File tree

nonholonomic-eom.rst

Lines changed: 201 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -55,25 +55,29 @@ Introduction
5555
In chapters, :ref:`Holonomic Constraints` and :ref:`Nonholonomic Constraints`,
5656
I introduced two types of constraints: holonomic (configuration) constraints
5757
and nonholonomic (motion) constraints. Holonomic constraints are nonlinear
58-
constraints in the coordinates [#]_. Nonholonomic constraints are linear in the
59-
generalized speeds, by definition. We will address the nonholonomic equations
60-
of motion first, as they are slightly easier to deal with.
58+
constraints in the coordinates [#]_. Nonholonomic constraints are linear
59+
constraints in the generalized speeds, by definition. We will address the
60+
nonholonomic equations of motion first, as they are slightly easier to deal
61+
with due to their linearity.
6162

6263
.. [#] They can be linear in the coordinates, but then there is little reason
63-
not to solve for the depedendent coordinates and eliminate them.
64+
not to solve for the depedendent coordinates explicitly and eliminate them.
6465
6566
Nonholonomic constraint equations are linear in both the independent and
6667
dependent generalized speeds (see Sec. :ref:`Snakeboard`). We have shown that
6768
you can explicitly solve for the dependent generalized speeds :math:`\bar{u}_r`
68-
as a function of the independent generalized speeds :math:`\bar{u}_s`. This
69-
means that number of dynamical differential equations can be reduced to
70-
:math:`p` from :math:`n` with :math:`m` nonholonomic constraints. Recall that
71-
the nonholonomic constraints take this form:
69+
as a function of the independent generalized speeds :math:`\bar{u}_s` as long
70+
as :math:`\mathbf{A}_r` is invertible. This implies that number of dynamical
71+
differential equations can be reduced to :math:`p` from :math:`n` with
72+
:math:`m` nonholonomic constraints. Recall that the nonholonomic constraints
73+
take this form:
7274

7375
.. math::
7476
:label: eq-nonholonomic-constraints
7577
76-
\bar{f}_n(\bar{u}_s, \bar{u}_r, \bar{q}, t) = \mathbf{M}_n\bar{u}_r + \bar{g}_n = 0 \in \mathbb{R}^m
78+
\bar{f}_n(\bar{u}_s, \bar{u}_r, \bar{q}, t)
79+
= \mathbf{M}_n(\bar{q}, t)\bar{u}_r + \bar{g}_n(\bar{u}_s, \bar{q}, t)
80+
= 0 \in \mathbb{R}^m
7781
7882
and :math:`u_r` can be solved for as so:
7983

@@ -83,21 +87,60 @@ and :math:`u_r` can be solved for as so:
8387
\bar{u}_r = -\mathbf{M}_n(\bar{q}, t)^{-1}\bar{g}_n(\bar{u}_s, \bar{q}, t)
8488
8589
which is the same as Eq. :math:numref:`eq-constraint-linear-form-solve` we
86-
originally developed:
90+
originally developed in Sec. :ref:`Snakeboard`:
8791

8892
.. math::
8993
:label: eq-dep-speeds-repeat
9094
91-
\bar{u}_r = \mathbf{A}_n \bar{u}_s + \bar{b}_n\\
95+
\bar{u}_r = \mathbf{A}_n \bar{u}_s + \bar{b}_n \in \mathbb{R}^m
9296
93-
Using Eq. :math:numref:`eq-dep-speeds-solve` equation we can now write our
97+
If you partition the holonomic (unconstrained) dynamical differential equations
98+
into:
99+
100+
.. math::
101+
102+
\bar{F}_r + \bar{F}_r^* =
103+
\bar{f}_d(\dot{\bar{u}}, \bar{u}, \bar{q}, t)
104+
=
105+
\begin{bmatrix}
106+
\bar{f}_{ds}(\dot{\bar{u}}, \bar{u}, \bar{q}, t) \\
107+
\bar{f}_{dr}(\dot{\bar{u}}, \bar{u}, \bar{q}, t) \\
108+
\end{bmatrix}
109+
= 0 \in \mathbb{R}^n
110+
111+
where :math:`\bar{f}_{ds}` and :math:`\bar{f}_{dr}` are the equations
112+
associated with the :math:`p` independent and :math:`m` dependent generalized
113+
speeds, respectively. Then using :math:numref:`eq-non-hol-fr` and
114+
:math:numref:`eq-non-hol-frstar` the :math:`p` nonholonomic (constrained)
115+
dynamical differential equations are:
116+
117+
.. math::
118+
119+
\tilde{F}_r + \tilde{F}_r^* =
120+
\bar{f}_{ds}(\dot{\bar{u}}, \bar{u}, \bar{q}, t)
121+
+ \mathbf{A}_n^T \bar{f}_{dr}(\dot{\bar{u}}, \bar{u}, \bar{q}, t)
122+
= 0 \in \mathbb{R}^p
123+
124+
and combined with Eq. :math:numref:`eq-dep-speeds-repeat` give a set of
125+
:math:`n` differential algebraic equations of differentiation index 1.
126+
127+
You can time differentiate Eq. :math:numref:`eq-dep-speeds-repeat` to get:
128+
129+
.. math::
130+
131+
\dot{\bar{u}}_r = \dot{\mathbf{A}}_n \bar{u}_s + \mathbf{A}_n \dot{\bar{u}}_s + \dot{\bar{b}}_n \\
132+
133+
and the :math:`n` differential algebraic equations can be reduced fully to
134+
:math:`p` unique ordinary differential equations by substituting all
135+
:math:`\dot{\bar{u}}_r` and :math:`\bar{u}_r`. This lets you write the full
94136
equations of motion as :math:`n` kinematical differential equations and
95-
:math:`p` dynamical differential equations.
137+
:math:`p` dynamical differential equations, which are all ordinary differential
138+
equations.
96139

97140
.. math::
98141
:label: eq-nonholonomic-eom
99142
100-
\bar{f}_k(\bar{u}_s, \dot{\bar{q}}, \bar{q}, t) = \mathbf{M}_k\dot{\bar{q}} + \bar{g}_k = 0 \in \mathbb{R}^n \\
143+
\bar{f}_k(\dot{\bar{q}}, \bar{u}_s, \bar{q}, t) = \mathbf{M}_k\dot{\bar{q}} + \bar{g}_k = 0 \in \mathbb{R}^n \\
101144
\bar{f}_d(\dot{\bar{u}}_s, \bar{u}_s, \bar{q}, t) = \mathbf{M}_d\dot{\bar{u}}_s + \bar{g}_d = 0 \in \mathbb{R}^p
102145
103146
and these can be written in explicit form:
@@ -128,8 +171,8 @@ inertia of the three bodies are the same.
128171

129172
Configuration diagram of a planar Snakeboard model.
130173

131-
1. Declare all the variables
132-
----------------------------
174+
Declare all the variables
175+
-------------------------
133176

134177
First introduce the necessary variables; adding :math:`I` for the central
135178
moment of inertia of each body and :math:`m` as the mass of each body. Then
@@ -177,8 +220,8 @@ expressions we create.
177220

178221
urd_zero, usd_zero
179222

180-
2. Establish the kinematics
181-
---------------------------
223+
Establish the kinematics
224+
------------------------
182225

183226
The following code sets up the orientations, positions, and velocities exactly
184227
as done in the original example. All of the velocities are in terms of
@@ -212,8 +255,8 @@ as done in the original example. All of the velocities are in terms of
212255
Bo.v2pt_theory(Ao, N, A)
213256
Co.v2pt_theory(Ao, N, A);
214257

215-
3. Specify the kinematical differential equations
216-
-------------------------------------------------
258+
Specify the kinematical differential equations
259+
----------------------------------------------
217260

218261
Now create the :math:`n=5` kinematical differential equations
219262
:math:`\bar{f}_k`:
@@ -248,8 +291,8 @@ dictionary we can use for substitutions:
248291
qd_repl = dict(zip(qd, qd_sol))
249292
qd_repl
250293

251-
4. Establish the nonholonomic constraints
252-
-----------------------------------------
294+
Establish the nonholonomic constraints
295+
--------------------------------------
253296

254297
Create the :math:`m=2` nonholonomic constraints:
255298

@@ -270,14 +313,15 @@ and rewrite them in terms of the generalized speeds:
270313
me.find_dynamicsymbols(fn)
271314

272315
With the nonholonomic constraint equations we choose :math:`\bar{u}_r=[u_1 \
273-
u_2]^T` and symbolically for these dependent speeds.
316+
u_2]^T` and symbolically solve for these dependent speeds.
274317

275318
.. jupyter-execute::
276319

277320
Mn = fn.jacobian(ur)
278321
gn = fn.xreplace(ur_zero)
279322
ur_sol = Mn.LUsolve(-gn)
280323
ur_repl = dict(zip(ur, ur_sol))
324+
ur_repl
281325

282326
In our case, the dependent generalized speeds are only a function of one
283327
independent generalized speed, :math:`u_3`.
@@ -301,8 +345,11 @@ later use in our numerical functions.
301345

302346
me.find_dynamicsymbols(gk)
303347

304-
5. Rewrite velocities in terms of independent speeds
305-
----------------------------------------------------
348+
Approach 1: Substitute dependent generalized speeds first
349+
=========================================================
350+
351+
Rewrite velocities in terms of independent speeds
352+
-------------------------------------------------
306353

307354
The snakeboard model, as described, has no generalized active forces because
308355
there are no contributing external forces acting on the system, so we only need
@@ -325,8 +372,8 @@ speeds.
325372
for vel in vels:
326373
print(me.find_dynamicsymbols(vel, reference_frame=N))
327374

328-
6. Compute the partial velocities
329-
---------------------------------
375+
Compute the partial velocities
376+
------------------------------
330377

331378
With the velocities only in terms of the independent generalized speeds, we can
332379
calculate the :math:`p` nonholonomic partial velocities:
@@ -335,8 +382,8 @@ calculate the :math:`p` nonholonomic partial velocities:
335382

336383
w_A, w_B, w_C, v_Ao, v_Bo, v_Co = me.partial_velocity(vels, us, N)
337384

338-
7. Rewrite the accelerations in terms of the independent generalized speeds
339-
---------------------------------------------------------------------------
385+
Rewrite the accelerations in terms of the independent generalized speeds
386+
------------------------------------------------------------------------
340387

341388
We can also write the accelerations in terms of only the independent
342389
generalized speeds, their time derivatives, and the generalized coordinates. To
@@ -376,8 +423,8 @@ dependent generalized speeds in :math:`\bar{g}_{nd}` instead of
376423

377424
me.find_dynamicsymbols(urd_sol)
378425

379-
8. Create the generalized forces
380-
--------------------------------
426+
Create the generalized forces
427+
-----------------------------
381428

382429
Now we can form the inertia forces and inertia torques. First check what
383430
derivatives appear in the accelerations.
@@ -454,8 +501,8 @@ and eliminate the dependent generalized accelerations:
454501
me.find_dynamicsymbols(Ts_B, reference_frame=N) |
455502
me.find_dynamicsymbols(Ts_C, reference_frame=N))
456503

457-
9. Formulate the dynamical differential equations
458-
-------------------------------------------------
504+
Formulate the dynamical differential equations
505+
----------------------------------------------
459506

460507
All of the components are present to formulate the nonholonomic generalized
461508
inertia forces. After we form them, make sure they are only a function of the
@@ -502,7 +549,127 @@ coordinates.
502549
We now have :math:`\mathbf{M}_k, \bar{g}_k, \mathbf{M}_d` and :math:`\bar{g}_d`
503550
and can proceed to numerical evaluation.
504551

505-
.. todo:: Also show how Fr and Frs can be formed using An.
552+
Approach 2: Use :math:`\mathbf{A}_n` and substitute dependent generalized speeds last
553+
=====================================================================================
554+
555+
Write all important velocity vectors in terms of all of the generalized speeds
556+
(as opposed to only the independent generalized speeds shown in Approach 1).
557+
558+
.. jupyter-execute::
559+
560+
N_w_A = A.ang_vel_in(N).xreplace(qd_repl)
561+
N_w_B = B.ang_vel_in(N).xreplace(qd_repl)
562+
N_w_C = C.ang_vel_in(N).xreplace(qd_repl)
563+
N_v_Ao = Ao.vel(N).xreplace(qd_repl)
564+
N_v_Bo = Bo.vel(N).xreplace(qd_repl)
565+
N_v_Co = Co.vel(N).xreplace(qd_repl)
566+
567+
vels = (N_w_A, N_w_B, N_w_C, N_v_Ao, N_v_Bo, N_v_Co)
568+
569+
for vel in vels:
570+
print(me.find_dynamicsymbols(vel, reference_frame=N))
571+
572+
Treat the system as an unconstrained system (holonomic) and calculate all
573+
:math:`n` partial velocities for each important velocity:
574+
575+
.. jupyter-execute::
576+
577+
w_A, w_B, w_C, v_Ao, v_Bo, v_Co = me.partial_velocity(vels, u, N)
578+
579+
Formulate the holonomic dynamical differential equations
580+
--------------------------------------------------------
581+
582+
Write all accelerations in terms of all of the generalized speeds and their
583+
derivatives.
584+
585+
.. jupyter-execute::
586+
587+
qdd_repl = {k.diff(t): v.diff(t).xreplace(qd_repl) for k, v in qd_repl.items()}
588+
qdd_repl
589+
590+
.. jupyter-execute::
591+
592+
Rs_Ao = -m*Ao.acc(N).xreplace(qdd_repl)
593+
Rs_Bo = -m*Bo.acc(N).xreplace(qdd_repl)
594+
Rs_Co = -m*Co.acc(N).xreplace(qdd_repl)
595+
Ts_A = -A.ang_acc_in(N).dot(I_A_Ao).xreplace(qdd_repl)
596+
Ts_B = -B.ang_acc_in(N).dot(I_B_Bo).xreplace(qdd_repl)
597+
Ts_C = -C.ang_acc_in(N).dot(I_C_Co).xreplace(qdd_repl)
598+
599+
Write the holonomic :math:`\bar{F}_r^*` with :math:`n=5` elements that are a
600+
function of all generalized speeds and their time derivatives.
601+
602+
.. jupyter-execute::
603+
604+
Frs = []
605+
for i in range(len(u)):
606+
Frs.append(v_Ao[i].dot(Rs_Ao) + v_Bo[i].dot(Rs_Bo) + v_Co[i].dot(Rs_Co) +
607+
w_A[i].dot(Ts_A) + w_B[i].dot(Ts_B) + w_C[i].dot(Ts_C))
608+
Frs = sm.Matrix(Frs)
609+
610+
Frs.shape, me.find_dynamicsymbols(Frs)
611+
612+
Formulate the nonholonomic dynamical differential equations
613+
-----------------------------------------------------------
614+
615+
Calculate :math:`\mathbf{A}_n` from the nonholonomic constraints.
616+
617+
.. jupyter-execute::
618+
619+
An = sm.trigsimp(fn.jacobian(ur).LUsolve(-fn.jacobian(us)))
620+
An
621+
622+
Now partition :math:`\bar{F}_r^*` and form :math:`\tilde{F}_r^*` noting it has
623+
:math:`p=3` elements that are still functions of all generalized speeds and their
624+
time derivatives.
625+
626+
.. jupyter-execute::
627+
628+
fdr = Frs[:2, 0]
629+
fds = Frs[2:, 0]
630+
631+
Frs_tilde = fds + An.transpose()*fdr
632+
633+
Frs_tilde.shape, me.find_dynamicsymbols(Frs_tilde)
634+
635+
Combined with :math:`\bar{f}_n`, the dynamical differential algebraic
636+
equations of index 1, :math:`\bar{f}_d(\dot{\bar{u}}, \bar{u}, \bar{q}, t)`,
637+
are formed:
638+
639+
.. jupyter-execute::
640+
641+
fd = Frs_tilde.col_join(fn)
642+
sm.trigsimp(fd)
643+
644+
These are a function of all the generalized speeds.
645+
646+
.. jupyter-execute::
647+
648+
me.find_dynamicsymbols(fd)
649+
650+
To reduce to a set of :math:`p` ordinary differential equations, substitute to
651+
remove the dependent speeds and their derivatives.
652+
653+
.. jupyter-execute::
654+
655+
fd = Frs_tilde.xreplace(urd_repl).xreplace(ur_repl)
656+
me.find_dynamicsymbols(fd)
657+
658+
Now :math:`\mathbf{M}_d` and :math:`\mathbf{g}_d` are identical to the those
659+
found in Approach 1.
660+
661+
.. jupyter-execute::
662+
663+
Md = fd.jacobian(usd)
664+
gd = fd.xreplace(usd_zero)
665+
666+
.. jupyter-execute::
667+
668+
me.find_dynamicsymbols(Md)
669+
670+
.. jupyter-execute::
671+
672+
me.find_dynamicsymbols(gd)
506673

507674
Simulate the Snakeboard
508675
=======================

notation.rst

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,18 @@ Equations of Motion with Nonholonomic Constraints
231231
equations.
232232
:math:`\dot{\bar{f}}_n(\dot{\bar{u}}_s, \dot{\bar{u}}_r, \bar{u}_s, \bar{u}_r, \bar{q}, t) = 0`
233233
Time derivative of the nonholonomic constraint equations.
234-
:math:`\mathbf{M}_{nd}`
234+
:math:`\mathbf{M}_{nd}=\mathbf{M}_n`
235235
Linear coefficient matrix for :math:`\dot{\bar{u}}_r` in the time
236236
differentiated nonholonomic constraint equations.
237237
:math:`\bar{g}_{nd}`
238238
Terms not linear in :math:`\dot{\bar{u}}_r` in the time differentiated
239239
nonholonomic constraint equations.
240-
241-
.. todo:: Mnd = Mn = Ar, right?
240+
:math:`\bar{f}_{ds}`
241+
:math:`p` holonomic dynamical differential equations associated with the
242+
independent generalized speeds :math:`\bar{u}_s`.
243+
:math:`\bar{f}_{dr}`
244+
:math:`m` holonomic dynamical differential equations associated with the
245+
dependent generalized speeds :math:`\bar{u}_r`.
242246

243247
Equations of Motion with Holonomic Constraints
244248
==============================================

0 commit comments

Comments
 (0)