Vector Differentiation

Note

You can download this example as a Python script: differentiation.py or Jupyter Notebook: differentiation.ipynb.

import sympy as sm
import sympy.physics.mechanics as me
sm.init_printing(use_latex='mathjax')

Learning Objectives

After completing this chapter readers will be able to:

  • Calculate the partial derivative of a vector with respect to any variable when viewed from any reference frame.

  • Use the product rule to find the relationship of changing measure numbers and changing unit vectors.

  • Explain the difference in expressing a vector in a reference frame and taking the derivative of the vector when observed from the reference frame.

  • Calculate second partial derivatives.

  • Calculate time derivatives of vector functions.

Partial Derivatives

If a vector \(\bar{v}\) is a function of \(n\) scalar variables \(q_1,q_2,\ldots,q_n\) in reference frame \(A\) then the first partial derivatives of \(\bar{v}\) in \(A\) with respect to \(q_r\) where \(r=1\ldots n\) can be formed by applying the product rule of differentation and taking into account that the mutually perpendicular unit vectors fixed in \(A\) do not change when observed from \(A\). The partial derivatives are then:

(43)\[\frac{{}^A\partial \bar{v}}{\partial q_r} = \sum_{i=1}^3 \frac{\partial v_i}{\partial q_r} \hat{a}_i \textrm{ for } r=1\ldots n\]

where \(v_i\) are the measure numbers of \(\bar{v}\) expressed in \(A\) associated with the mutually perpendicular unit vectors \(\hat{a}_1,\hat{a}_2,\hat{a}_3\).

If \(\bar{v}=v_x\hat{a}_x+v_y\hat{a}_y+v_z\hat{a}_z\) the above definition expands to:

(44)\[\frac{{}^A\partial \bar{v}}{\partial q_r} = \frac{\partial v_x}{\partial q_r} \hat{a}_x + \frac{\partial v_y}{\partial q_r} \hat{a}_y + \frac{\partial v_z}{\partial q_r} \hat{a}_z \textrm{ for } r=1\ldots n\]

Many of the vectors we will work with in multibody dynamics will be a function of a single variable, most often time \(t\). If that is the case, the partial derivative reduces to a single variate derivative:

(45)\[\frac{{}^A d \bar{v}}{dt} := \sum_{i=1}^3 \frac{d v_i}{dt} \hat{a}_i\]

Warning

A derivative written as \(\frac{\partial \bar{v}}{\partial q_r}\) is meaningless because no reference frame is indicated. The derivative is dependent on which reference frame the change is observed from, so without a reference frame, the derivative cannot be calculated. This is not the case for partial derivatives of scalar expressions, as no reference frame is involved.

The above definition implies that a vector must be expressed in the reference frame one is observing the change from before calculating the partial derivatives of the scalar measure numbers. For example, here is a vector that is expressed with unit vectors from three different reference frames:

alpha, beta = sm.symbols('alpha, beta')
a, b, c, d, e, f = sm.symbols('a, b, c, d, e, f')

A = me.ReferenceFrame('A')
B = me.ReferenceFrame('B')
C = me.ReferenceFrame('C')

B.orient_axis(A, alpha, A.x)
C.orient_axis(B, beta, B.y)

v = a*A.x + b*A.y + c*B.x + d*B.y + e*C.x + f*C.y
v
\[\displaystyle a\hat{a}_x + b\hat{a}_y + c\hat{b}_x + d\hat{b}_y + e\hat{c}_x + f\hat{c}_y\]

To calculate \(\frac{{}^A\partial\bar{v}}{\partial \alpha}\) we first need to project the vector \(\bar{v}\) onto the unit vectors of \(A\) and take the partial derivative of those measure numbers with respect to \(\alpha\). The dot product provides the projection and the resulting scalar is differentiated:

dvdalphaAx = v.dot(A.x).diff(alpha)
dvdalphaAx
\[\displaystyle 0\]
dvdalphaAy = v.dot(A.y).diff(alpha)
dvdalphaAy
\[\displaystyle - d \sin{\left(\alpha \right)} + e \sin{\left(\beta \right)} \cos{\left(\alpha \right)} - f \sin{\left(\alpha \right)}\]
dvdalphaAz = v.dot(A.z).diff(alpha)
dvdalphaAz
\[\displaystyle d \cos{\left(\alpha \right)} + e \sin{\left(\alpha \right)} \sin{\left(\beta \right)} + f \cos{\left(\alpha \right)}\]

We can then construct the vector \(\frac{{}^A\partial \bar{v}}{\partial \alpha}\) from the new measure numbers know that the \(A\) unit vectors are fixed:

dvdalphaA = dvdalphaAx*A.x + dvdalphaAy*A.y + dvdalphaAz*A.z
dvdalphaA
\[\displaystyle (- d \sin{\left(\alpha \right)} + e \sin{\left(\beta \right)} \cos{\left(\alpha \right)} - f \sin{\left(\alpha \right)})\hat{a}_y + (d \cos{\left(\alpha \right)} + e \sin{\left(\alpha \right)} \sin{\left(\beta \right)} + f \cos{\left(\alpha \right)})\hat{a}_z\]

SymPy Mechanics vectors have a special diff() method that manages taking partial derivatives from different reference frames. For the vector .diff() method you provide first the variable \(\alpha\) followed by the reference frame you are observing from:

v.diff(alpha, A)
\[\displaystyle (- d \sin{\left(\alpha \right)} + e \sin{\left(\beta \right)} \cos{\left(\alpha \right)} - f \sin{\left(\alpha \right)})\hat{a}_y + (d \cos{\left(\alpha \right)} + e \sin{\left(\alpha \right)} \sin{\left(\beta \right)} + f \cos{\left(\alpha \right)})\hat{a}_z\]

This gives the identical result as our manually constructed partial derivative above.

Exercise

Calculate \(\frac{{}^B\partial \bar{v}}{\partial e}\) manually and with diff() and show the results are the same.

Warning

What’s the difference in .express() and .diff()?

Any vector can be “expressed” in any reference frame. To express a vector in a reference frame means to project it onto the three mutually perpendicular unit vectors fixed in the reference frame and then to rewrite the vector in terms of measure numbers associated with those three unit vectors using the relevant direction cosine matrix entries. This has nothing to do with differentiation.

We can also take the derivative of a vector when viewed from a specific reference frame. To do so, we observe how the vector changes when viewed from the reference frame and formulate that derivative. Once the derivative is taken, we can express the new vector in any reference frame we desire.

Expressing a vector in a reference frame and taking a derivative of a vector when observered from a reference frame are two different things! Try not to get tripped up by this important distinction.

Product Rule

Consider again vector \(\bar{v}=v_x\hat{a}_x+v_y\hat{a}_y+v_z\hat{a}_z\). Previously, only the measure numbers of this vector were scalar functions of \(q_r\). Now consider a reference frame \(N\) that is oriented relative to \(A\) such that the relative orientation also depends on \(q_r\). This means, that when observed from \(N\), the unit vectors \(\hat{a}_x,\hat{a}_y,\hat{a}_z\) may be a function of \(q_r\). With both the measure numbers and unit vectors dependent on \(q_r\) the derivative of \(\bar{v}\) in \(N\) requires the use of the product rule when taking the partial derivative. For example:

(46)\[\frac{{}^N\partial \bar{v}}{\partial q_r} = \frac{{}^N\partial v_x}{\partial q_r}\hat{a}_x + v_x \frac{{}^N\partial \hat{a}_x}{\partial q_r} + \frac{{}^N\partial v_y}{\partial q_r}\hat{a}_y + v_y \frac{{}^N\partial \hat{a}_y}{\partial q_r} + \frac{{}^N\partial v_z}{\partial q_r}\hat{a}_z + v_z \frac{{}^N\partial \hat{a}_z}{\partial q_r}\]

The three similar terms with scalar derivatives have the same interpretation of the ones in the prior section.

(47)\[\frac{{}^N\partial v_x}{\partial q_r}\hat{a}_x, \frac{{}^N\partial v_y}{\partial q_r}\hat{a}_y, \frac{{}^N\partial v_z}{\partial q_r}\hat{a}_z\]

But the part with unit vector derivatives is more interesting. The partial derivative of a unit vector depends on how it changes. But unit vectors do not change in length, only in orientation.

(48)\[v_x \frac{{}^N\partial \hat{a}_x}{\partial q_r}, v_y \frac{{}^N\partial \hat{a}_y}{\partial q_r}, v_z \frac{{}^N\partial \hat{a}_z}{\partial q_r}\]

You will learn in the next chapter how to interpret and use these terms to simplify the calculations of common derivatives. But for now, just be aware of the nature of this partial derivative in \(N\).

The product rule also applies to the dot and cross products:

(49)\[ \begin{align}\begin{aligned}\frac{\partial}{\partial q_r}(\bar{v} \cdot \bar{w}) = & \frac{\partial \bar{v}}{\partial q_r} \cdot \bar{w} + \bar{v} \cdot \frac{\partial \bar{w}}{\partial q_r}\\\frac{\partial}{\partial q_r}(\bar{v} \times \bar{w}) = & \frac{\partial \bar{v}}{\partial q_r} \times \bar{w} + \bar{v} \times \frac{\partial \bar{w}}{\partial q_r}\end{aligned}\end{align} \]

and generalizes to any series of products. Let \(G=f_1 \cdots f_n\) be a series of products, then:

(50)\[\frac{\partial G}{\partial q_r} = \frac{\partial f_1}{\partial q_r}\cdot f_2 \cdots f_n + f_1 \cdot\frac{\partial f_2}{\partial q_r}\cdot f_3 \cdots f_n + \dots + f_1 \cdots f_{n-1} \cdot \frac{\partial f_n}{\partial q_r}\]

Second Derivatives

\(\frac{{}^A\partial \bar{v}}{\partial q_r}\) is also a vector and, just like \(\bar{v}\), may be a vector function. We can thus calculate the second partial derivative with respect to \(q_s\) where \(s=1\ldots n\). This second partial derivative need not be taken with respect to the same reference frame as the first partial derivative. If we first differentiate with when viewed from \(A\) and then when viewed from \(B\), the second partial derivative is:

(51)\[\frac{{}^B\partial}{\partial q_s} \left(\frac{{}^A\partial\bar{v}}{\partial q_r}\right)\]

Second partials in different reference frames do not necessarily commute:

(52)\[\frac{{}^B\partial}{\partial q_s} \left(\frac{{}^A\partial\bar{v}}{\partial q_r}\right) \neq \frac{{}^A\partial}{\partial q_r} \left(\frac{{}^B\partial\bar{v}}{\partial q_s}\right)\]

If the reference frames of each partial derivative are the same, then mixed partials do commute.

Vector Functions of Time

In multibody dynamics we are primarily concerned with how motion changes with respect to time \(t\) and our vectors and measure numbers will often be implicit functions of time, i.e. \(q_r(t)\). When that is the case the chain rule can be used to take total derivatives:

(53)\[\frac{{}^A d\bar{v}}{dt} = \sum_{i=1}^n \frac{{}^A\partial \bar{v}}{\partial q_r(t)} \frac{d q_r(t)}{dt} + \frac{{}^A \partial \bar{v}}{\partial t} \textrm{ where } r=1,\ldots,n\]

Note

We will typically use the “dot” notation for time derivatives, i.e. \(\frac{dq}{dt}\) as \(\dot{q}\) and \(\frac{d^2q}{dt^2}\) as \(\ddot{q}\) and so on.

In SymPy Mechanics, scalar functions of time can be created like so:

t = sm.symbols('t')
q_of = sm.Function('q')

q = q_of(t)
q
\[\displaystyle q{\left(t \right)}\]

And these scalar functions can be differentiated:

q.diff(t)
\[\displaystyle \frac{d}{d t} q{\left(t \right)}\]

SymPy Mechanics provides the convenience function dynamicsymbols() to create scalar functions of time just like symbols():

q1, q2, q3 = me.dynamicsymbols('q1, q2, q3')
q1, q2, q3
\[\displaystyle \left( q_{1}{\left(t \right)}, \ q_{2}{\left(t \right)}, \ q_{3}{\left(t \right)}\right)\]

The time variable used in q1,q2,q3 can be accessed like so:

t = me.dynamicsymbols._t

SymPy Mechanics also provide a special printing function init_vprinting() which enables the dot notation on functions of time:

me.init_vprinting(use_latex='mathjax')
q1.diff(t), q2.diff(t, 2), q3.diff(t, 3)
\[\displaystyle \left( \dot{q}_{1}, \ \ddot{q}_{2}, \ \dddot{q}_{3}\right)\]

Now these scalar functions of time can be used to formulate vectors:

A = me.ReferenceFrame('A')
B = me.ReferenceFrame('B')
B.orient_body_fixed(A, (q1, q2, q3), 'ZXZ')
v = q1*A.x + q2*A.y + t**2*A.z
v
\[\displaystyle q_{1}\hat{a}_x + q_{2}\hat{a}_y + t^{2}\hat{a}_z\]

And the time derivative can be found with:

v.diff(t, A)
\[\displaystyle \dot{q}_{1}\hat{a}_x + \dot{q}_{2}\hat{a}_y + 2 t\hat{a}_z\]

Lastly, vectors have a dt() method that calculates time derivatives when viewed from a reference frame, saving a few characters of typing:

v.dt(A)
\[\displaystyle \dot{q}_{1}\hat{a}_x + \dot{q}_{2}\hat{a}_y + 2 t\hat{a}_z\]

We will use time derivatives in the next chapters to formulate velocity and acceleration.