# The minimum jerk hypothesis

> Marcos Duarte  
> Laboratory of Biomechanics and Motor Control ([http://demotu.org/](http://demotu.org/))  
> Federal University of ABC, Brazil

Hogan and Flash (1984, 1985), based on observations of voluntary movements in primates, suggested that movements are performed (organized) with the smoothest trajectory possible. In this organizing principle, the endpoint trajectory is such that the mean squared-jerk across time of this movement is minimum.   

Jerk is the derivative of acceleration and the observation of the minimum-jerk trajectory is for the endpoint in the extracorporal coordinates (not for joint angles) and according to Flash and Hogan (1985), the minimum-jerk trajectory of a planar movement is such that minimizes the following objective function:

$$ C=\frac{1}{2} \int\limits_{t_{i}}^{t_{f}}\;\left[\left(\frac{d^{3}x}{dt^{3}}\right)^2+\left(\frac{d^{3}y}{dt^{3}}\right)^2\right]\:\mathrm{d}t $$

Hogan (1984) found that the solution for this objective function is a fifth-order polynomial trajectory (see Shadmehr and Wise (2004) for a simpler proof): 

$$ \begin{array}{l l}
x(t) = a_0+a_1t+a_2t^2+a_3t^3+a_4t^4+a_5t^5 \\
y(t) = b_0+b_1t+b_2t^2+b_3t^3+b_4t^4+b_5t^5
\end{array} $$

With the following boundary conditions for $ x(t) $ and $ y(t) $: initial and final positions are $ (x_i,y_i) $ and $ (x_f,y_f) $ and initial and final velocities and accelerations are zero.

Let's employ [Sympy](http://sympy.org/en/index.html) to find the solution for the minimum jerk trajectory using symbolic algebra.


```python
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
from IPython.display import display, Math, Latex
from sympy import symbols, Matrix, latex, Eq, collect, solve, diff, simplify
from sympy.utilities.lambdify import lambdify
```

Using Sympy, the equation for minimum jerk trajectory for x is:


```python
# declare the symbolic variables
x, xi, xf, y, yi, yf, d, t = symbols('x, x_i, x_f, y, y_i, y_f, d, t')
a0, a1, a2, a3, a4, a5 = symbols('a_0:6')
x = a0 + a1*t + a2*t**2 + a3*t**3 + a4*t**4 + a5*t**5
display(Math(latex('x(t)=') + latex(x)))
```


$$x(t)=a_{0} + a_{1} t + a_{2} t^{2} + a_{3} t^{3} + a_{4} t^{4} + a_{5} t^{5}$$


Without loss of generality, consider $ t_i=0 $ and let's use $ d $ for movement duration ($ d=t_f $). The system of equations with the boundary conditions for $ x $ is:


```python
# define the system of equations
s = Matrix([Eq(x.subs(t,0)          , xi),
            Eq(diff(x,t,1).subs(t,0),  0),
            Eq(diff(x,t,2).subs(t,0),  0),
            Eq(x.subs(t,d)          , xf),
            Eq(diff(x,t,1).subs(t,d),  0),
            Eq(diff(x,t,2).subs(t,d),  0)])
display(Math(latex(s, mat_str='matrix', mat_delim='[')))
```


$$\left[\begin{matrix}a_{0} = x_{i}\\a_{1} = 0\\2 a_{2} = 0\\a_{0} + a_{1} d + a_{2} d^{2} + a_{3} d^{3} + a_{4} d^{4} + a_{5} d^{5} = x_{f}\\a_{1} + 2 a_{2} d + 3 a_{3} d^{2} + 4 a_{4} d^{3} + 5 a_{5} d^{4} = 0\\2 a_{2} + 6 a_{3} d + 12 a_{4} d^{2} + 20 a_{5} d^{3} = 0\end{matrix}\right]$$


Which gives the following solution:


```python
# algebraically solve the system of equations
sol = solve(s, [a0, a1, a2, a3, a4, a5])
display(Math(latex(sol)))
```


$$\left \{ a_{0} : x_{i}, \quad a_{1} : 0, \quad a_{2} : 0, \quad a_{3} : \frac{10}{d^{3}} \left(x_{f} - x_{i}\right), \quad a_{4} : \frac{15}{d^{4}} \left(- x_{f} + x_{i}\right), \quad a_{5} : \frac{6}{d^{5}} \left(x_{f} - x_{i}\right)\right \}$$


Substituting this solution in the fifth order polynomial trajectory equation, we have the actual displacement trajectories:


```python
# substitute the equation parameters by the solution
x2 = x.subs(sol)
x2 = collect(simplify(x2, ratio=1), xf-xi)
display(Math(latex('x(t)=') + latex(x2)))
y2 = x2.subs([(xi, yi), (xf, yf)])
display(Math(latex('y(t)=') + latex(y2)))
```


$$x(t)=x_{i} + \left(x_{f} - x_{i}\right) \left(\frac{10 t^{3}}{d^{3}} - \frac{15 t^{4}}{d^{4}} + \frac{6 t^{5}}{d^{5}}\right)$$



$$y(t)=y_{i} + \left(y_{f} - y_{i}\right) \left(\frac{10 t^{3}}{d^{3}} - \frac{15 t^{4}}{d^{4}} + \frac{6 t^{5}}{d^{5}}\right)$$


And for the velocity, acceleration, and jerk trajectories in x:


```python
# symbolic differentiation
vx = x2.diff(t, 1)
display(Math(latex('v_x(t)=') + latex(vx)))
ax = x2.diff(t, 2)
display(Math(latex('a_x(t)=') + latex(ax)))
jx = x2.diff(t, 3)
display(Math(latex('j_x(t)=') + latex(jx)))
```


$$v_x(t)=\left(x_{f} - x_{i}\right) \left(\frac{30 t^{2}}{d^{3}} - \frac{60 t^{3}}{d^{4}} + \frac{30 t^{4}}{d^{5}}\right)$$



$$a_x(t)=\frac{60 t}{d^{3}} \left(x_{f} - x_{i}\right) \left(1 - \frac{3 t}{d} + \frac{2 t^{2}}{d^{2}}\right)$$



$$j_x(t)=\frac{60}{d^{3}} \left(x_{f} - x_{i}\right) \left(1 - \frac{6 t}{d} + \frac{6 t^{2}}{d^{2}}\right)$$


Let's plot the minimum jerk trajectory for x and its velocity, acceleration, and jerk considering $x_i=0,x_f=1,d=1$:


```python
# substitute by the numerical values
x3  = x2.subs([(xi, 0), (xf, 1), (d, 1)])
#create functions for calculation of numerical values
xfu = lambdify(t, diff(x3, t, 0), 'numpy')
vfu = lambdify(t, diff(x3, t, 1), 'numpy')
afu = lambdify(t, diff(x3, t, 2), 'numpy')
jfu = lambdify(t, diff(x3, t, 3), 'numpy')
#plots using matplotlib
ts = np.arange(0, 1.01, .01)
fig, axs = plt.subplots(1, 4, figsize=(12, 5), sharex=True, squeeze=True)
axs[0].plot(ts, xfu(ts), linewidth=3)
axs[0].set_title('Displacement [$\mathrm{m}$]')
axs[1].plot(ts, vfu(ts), linewidth=3)
axs[1].set_title('Velocity [$\mathrm{m/s}$]')
axs[2].plot(ts, afu(ts), linewidth=3)
axs[2].set_title('Acceleration [$\mathrm{m/s^2}$]')
axs[3].plot(ts, jfu(ts), linewidth=3)
axs[3].set_title('Jerk [$\mathrm{m/s^3}$]')

for axi in axs:
    axi.set_xlabel('Time [s]', fontsize=14)
    axi.grid(True)

fig.suptitle('Minimum jerk trajectory kinematics', fontsize=20, y=1.03)
fig.tight_layout()
plt.show()
```

Note that for the minimum jerk trajectory, initial and final values of both velocity and acceleration are zero, but not for the jerk.  

Read more about the minimum jerk trajectory hypothesis in the [Shadmehr and Wise's book companion site](http://www.shadmehrlab.org/book/minimum_jerk/minimumjerk.htm) and in [Paul Gribble's website](http://www.gribblelab.org/compneuro/4_Computational_Motor_Control_Kinematics.html#sec-5-1).

### The angular trajectory of a minimum jerk trajectory 

Let's calculate the resulting angular trajectory given a minimum jerk linear trajectory, supposing it is from a circular motion of an elbow flexion. The length of the forearm is 0.5 m, the movement duration is 1 s, the elbow starts flexed at 90$^o$ and the flexes to 180$^o$.

First, the linear trajectories for this circular motion:


```python
# substitute by the numerical values
x3 = x2.subs([(xi, 0.5), (xf, 0), (d, 1)])
y3 = x2.subs([(xi, 0), (xf, 0.5), (d, 1)])
display(Math(latex('y(t)=') + latex(x3)))
display(Math(latex('x(t)=') + latex(y3)))
#create functions for calculation of numerical values
xfux = lambdify(t, diff(x3, t, 0), 'numpy')
vfux = lambdify(t, diff(x3, t, 1), 'numpy')
afux = lambdify(t, diff(x3, t, 2), 'numpy')
jfux = lambdify(t, diff(x3, t, 3), 'numpy')
xfuy = lambdify(t, diff(y3, t, 0), 'numpy')
vfuy = lambdify(t, diff(y3, t, 1), 'numpy')
afuy = lambdify(t, diff(y3, t, 2), 'numpy')
jfuy = lambdify(t, diff(y3, t, 3), 'numpy')
```


$$y(t)=- 3.0 t^{5} + 7.5 t^{4} - 5.0 t^{3} + 0.5$$



$$x(t)=3.0 t^{5} - 7.5 t^{4} + 5.0 t^{3}$$



```python
#plots using matplotlib
ts = np.arange(0, 1.01, .01)
fig, axs = plt.subplots(1, 4, figsize=(12, 5), sharex=True, squeeze=True)
axs[0].plot(ts, xfux(ts), 'b', linewidth=3)
axs[0].plot(ts, xfuy(ts), 'r', linewidth=3)
axs[0].set_title('Displacement [$\mathrm{m}$]')
axs[1].plot(ts, vfux(ts), 'b', linewidth=3)
axs[1].plot(ts, vfuy(ts), 'r', linewidth=3)
axs[1].set_title('Velocity [$\mathrm{m/s}$]')
axs[2].plot(ts, afux(ts), 'b', linewidth=3)
axs[2].plot(ts, afuy(ts), 'r', linewidth=3)
axs[2].set_title('Acceleration [$\mathrm{m/s^2}$]')
axs[3].plot(ts, jfux(ts), 'b', linewidth=3)
axs[3].plot(ts, jfuy(ts), 'r', linewidth=3)
axs[3].set_title('Jerk [$\mathrm{m/s^3}$]')

for axi in axs:
    axi.set_xlabel('Time [s]', fontsize=14)
    axi.grid(True)

fig.suptitle('Minimum jerk trajectory kinematics', fontsize=20, y=1.03)
fig.tight_layout()
plt.show()
```

Now, the angular trajectories for this circular motion:


```python
from sympy import atan2
ang = atan2(y3, x3)*180/np.pi
display(Math(latex('angle(t)=') + latex(ang)))
xang = lambdify(t, diff(ang, t, 0), 'numpy')
vang = lambdify(t, diff(ang, t, 1), 'numpy')
aang = lambdify(t, diff(ang, t, 2), 'numpy')
jang = lambdify(t, diff(ang, t, 3), 'numpy')
```


$$angle(t)=57.2957795130823 \operatorname{atan_{2}}{\left (3.0 t^{5} - 7.5 t^{4} + 5.0 t^{3},- 3.0 t^{5} + 7.5 t^{4} - 5.0 t^{3} + 0.5 \right )}$$



```python
ts = np.arange(0, 1.01, .01)
fig, axs = plt.subplots(1, 4, figsize=(12, 5), sharex=True, squeeze=True)
axs[0].plot(ts, xang(ts), linewidth=3)
axs[0].set_title('Displacement [$\mathrm{m}$]')
axs[1].plot(ts, vang(ts), linewidth=3)
axs[1].set_title('Velocity [$\mathrm{m/s}$]')
axs[2].plot(ts, aang(ts), linewidth=3)
axs[2].set_title('Acceleration [$\mathrm{m/s^2}$]')
axs[3].plot(ts, jang(ts), linewidth=3)
axs[3].set_title('Jerk [$\mathrm{m/s^3}$]')

for axi in axs:
    axi.set_xlabel('Time [s]', fontsize=14)
    axi.grid(True)

fig.suptitle('Minimum jerk trajectory angular kinematics', fontsize=20, y=1.03)
fig.tight_layout()
plt.show()
```

## Problems

1. What is your opinion on the the minimum jerk hypothesis? Do you think humans control movement based on this principle? (Think about what biomechanical and neurophysiological properties are not considered on this hypothesis.)
2. Calculate and plot the position, velocity, acceleration, and jerk trajectories for different movement speeds (for example, consider always a displacement of 1 m and movement durations of 0.5, 1, and 2 s).  
3. For the data in the previous item, calculate the ratio peak speed to average speed. Shadmehr and  Wise (2004) argue that psychophysical experiments show that reaching movements with the hand have this ratio equals to 1.75. Compare with the calculated values.  
4. Can you propose alternative hypotheses for the control of movement?  

## References

- Flash T, Hogan N (1985) [The coordination of arm movements: an experimentally confirmed mathematical model](http://www.jneurosci.org/cgi/reprint/5/7/1688.pdf). Journal of Neuroscience, 5, 1688-1703.   
- Hogan N (1984) [An organizing principle for a class of voluntary movements](http://www.jneurosci.org/content/4/11/2745.full.pdf). Journal of Neuroscience, 4, 2745-2754.
- Shadmehr R, Wise S (2004) [The Computational Neurobiology of Reaching and Pointing: A Foundation for Motor Learning](http://www.shadmehrlab.org/book/). A Bradford Book. [Companion site](http://www.shadmehrlab.org/book/).
- Zatsiorsky VM (1998) [Kinematics of Human Motion](http://books.google.com.br/books/about/Kinematics_of_Human_Motion.html?id=Pql_xXdbrMcC&redir_esc=y). Champaign, Human Kinetics.

ecd986b49e426cc473f9b14d9949d0ad02cb579b
ipynb
Jupyter Notebook
notebooks/MinimumJerkHypothesis.ipynb
0todd0000/BMC
bfad103e0fc02afc662ce417bf062b4758a39897
CC-BY-4.0
2015-01-17T12:36:30.000Z
2022-02-13T13:13:12.000Z
notebooks/MinimumJerkHypothesis.ipynb
0todd0000/BMC
bfad103e0fc02afc662ce417bf062b4758a39897
CC-BY-4.0
2018-06-21T21:40:40.000Z
2018-08-09T19:55:26.000Z
notebooks/MinimumJerkHypothesis.ipynb
0todd0000/BMC
bfad103e0fc02afc662ce417bf062b4758a39897
CC-BY-4.0
2015-01-16T22:54:31.000Z
2022-02-14T21:14:43.000Z
Qwen/Qwen-72B
1. YES
2. YES