Skip to content

Commit

Permalink
Make discrete version of impulse response vs pole location figure
Browse files Browse the repository at this point in the history
  • Loading branch information
calcmogul committed Oct 5, 2024
1 parent 4b40713 commit 21c2513
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ \subsection{Laplace transform}
\gls{system response} (the frequency domain) and also the x coordinate
representing the speed at which that oscillation decays and the \gls{system}
converges to zero (i.e., a decaying exponential). Figure
\ref{fig:impulse_response_poles} shows this for various points.
\ref{fig:cont_impulse_response_poles} shows this for various points.

If we move the component frequencies in the Fmajor4 chord example parallel to
the real axis to $\sigma = -25$, the resulting time domain response attenuates
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ \subsubsection{Poles and zeroes}
The locations of the closed-loop poles in the complex plane determine the
stability of the \gls{system}. Each pole represents a frequency mode of the
\gls{system}, and their location determines how much of each response is induced
for a given input frequency. Figure \ref{fig:impulse_response_poles} shows the
\glspl{impulse response} in the time domain for transfer functions with various
pole locations. They all have an initial condition of $1$.
for a given input frequency. Figure \ref{fig:cont_impulse_response_poles} shows
the \glspl{impulse response} in the time domain for transfer functions with
various pole locations. They all have an initial condition of $1$.
\begin{bookfigure}
\input{figs/impulse-response-vs-pole-location}
\caption{Impulse response vs pole location}
\label{fig:impulse_response_poles}
\input{figs/continuous-impulse-response-vs-pole-location}
\caption{Continuous impulse response vs pole location}
\label{fig:cont_impulse_response_poles}
\end{bookfigure}

Poles in the left half-plane (LHP) are stable; the \gls{system}'s output may
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,41 @@
\draw[->] (-4,0) -- (4,0) node[below] {\small Re};
\draw[->] (0,-2) -- (0,4) node[right] {\small Im};

% Stable: e^-1.75t * cos(1.75wt) (80/3*w for readability)
\drawtimeplot{-2.125cm}{2.5cm}{0.125cm}{0.44375cm}{
% Stable: exp(-1.75t) cos(1.75wt) (80/3*w for readability)
\drawcontinuoustimeplot{-2.125cm}{2.5cm}{0.125cm}{0.44375cm}{
exp(-1.75 * \x) * cos(80/3 * 1.75 * deg(\x))}
\drawpole{-1.75cm}{1.75cm}

% Stable: e^-2.5t
\drawtimeplot{-2.25cm}{0.75cm}{0.125cm}{0.125cm}{exp(-2 * \x)}
% Stable: exp(-2.5t)
\drawcontinuoustimeplot{-2.25cm}{0.75cm}{0.125cm}{0.125cm}{exp(-2 * \x)}
\drawpole{-2cm}{0cm}

% Stable: e^-t
\drawtimeplot{-1.125cm}{-0.75cm}{0.125cm}{0.125cm}{exp(-\x)}
% Stable: exp(-t)
\drawcontinuoustimeplot{-1.125cm}{-0.75cm}{0.125cm}{0.125cm}{exp(-\x)}
\drawpole{-1cm}{0cm}

% Marginally stable: cos(wt) (80/3*w for readability)
\drawtimeplot{-0.75cm}{1.125cm}{0.125cm}{0.44375cm}{cos(80/3 * deg(\x))}
\drawcontinuoustimeplot{-0.75cm}{1.125cm}{0.125cm}{0.44375cm}{cos(80/3 * deg(\x))}
\drawpole{0cm}{1cm}

% Marginally stable cos(2wt) (80/3*w for readability)
\drawtimeplot{0cm}{2.75cm}{0.125cm}{0.44375cm}{cos(80/3 * 2 * deg(\x))}
\drawcontinuoustimeplot{0cm}{2.75cm}{0.125cm}{0.44375cm}{cos(80/3 * 2 * deg(\x))}
\drawpole{0cm}{2cm}

% Integrator
\drawtimeplot{0.25cm}{-0.75cm}{0.125cm}{0.125cm}{1}
\drawcontinuoustimeplot{0.25cm}{-0.75cm}{0.125cm}{0.125cm}{1}
\drawpole{0cm}{0cm}

% Unstable: e^t
\drawtimeplot{1.125cm}{0.75cm}{0.125cm}{0.125cm}{exp(\x)}
% Unstable: exp(t)
\drawcontinuoustimeplot{1.125cm}{0.75cm}{0.125cm}{0.125cm}{exp(\x)}
\drawpole{1cm}{0cm}

% Unstable: e^2t
\drawtimeplot{2.25cm}{-0.75cm}{0.125cm}{0.125cm}{exp(2 * \x)}
% Unstable: exp(2t)
\drawcontinuoustimeplot{2.25cm}{-0.75cm}{0.125cm}{0.125cm}{exp(2 * \x)}
\drawpole{2cm}{0cm}

% Unstable: e^0.75t * cos(1.75wt) (80/3*w for readability)
\drawtimeplot{1.5cm}{2.25cm}{0.125cm}{0.44375cm}{
% Unstable: exp(0.75t) cos(1.75wt) (80/3*w for readability)
\drawcontinuoustimeplot{1.5cm}{2.25cm}{0.125cm}{0.44375cm}{
exp(0.75 * \x) * cos(80/3 * 1.75 * deg(\x))}
\drawpole{0.75cm}{1.75cm}

Expand Down
95 changes: 95 additions & 0 deletions figs/discrete-impulse-response-vs-pole-location.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
\begin{tikzpicture}[auto, >=latex']
% \draw [help lines] (-4,-4) grid (4,4);

% Draw main axes
\draw[->] (-4,0) -- (4,0) node[below] {\small Re};
\draw[->] (0,-4) -- (0,4) node[right] {\small Im};

% Unit circle
\draw[black] (0,0) circle (3cm);

% Exponent for the given x plot coordinate:
%
% exp(at) = x
% at = ln(x)
% a = ln(x)/t
%
% t = 50 ms

% LHP integrator
\drawdiscretecoordplot{-3cm - 0.166cm}{-0.75cm}{0.125cm}{0.44375cm}
{(0,1) (0.05,-1) (0.1,1) (0.15,-1) (0.2,1) (0.25,-1) (0.3,1) (0.35,-1)
(0.4,1) (0.45,-1) (0.5,1)}
\drawpole{-3cm}{0cm}

% LHP stable: xₖ₊₁ = −2/3xₖ
\drawdiscretecoordplot{-2cm}{0.75cm}{0.125cm}{0.44375cm}
{(0,1) (0.05,-0.667) (0.1,0.444) (0.15,-0.296) (0.2,0.198) (0.25,-0.132)
(0.3,0.088) (0.35,-0.059) (0.4,0.039) (0.45,-0.026) (0.5,0.017)}
\drawpole{-2cm}{0cm}

% LHP stable: xₖ₊₁ = −1/3xₖ
\drawdiscretecoordplot{-1cm + 0.166cm}{-0.75cm}{0.125cm}{0.44375cm}
{(0,1) (0.05,-0.333) (0.1,0.111) (0.15,-0.037) (0.2,0.012) (0.25,-0.004)
(0.3,0.001) (0.35,0) (0.4,0) (0.45,0) (0.5,0)}
\drawpole{-1cm}{0cm}

% LHP stable: xₖ₊₁ = (0.333 + 0.5i)xₖ
\drawdiscretecoordplot{-1cm}{2.25cm}{0.125cm}{0.44375cm}
{(0,1) (0.05,-0.333) (0.1,-0.139) (0.15,0.213) (0.2,-0.092) (0.25,-0.016)
(0.3,0.044) (0.35,-0.023) (0.4,0) (0.45,0.009) (0.5,-0.006)}
\drawpole{-1cm}{1.5cm}

% LHP unstable: xₖ₊₁ = (−1 − 0.75i)xₖ
\drawdiscretecoordplot{-2.25cm}{-2.25cm}{0.125cm}{0.44375cm}
{(0,1) (0.05,-1) (0.1,0.4375) (0.15,0.6875) (0.2,-2.059) (0.25,3.043)
(0.3,-2.869) (0.35,0.984) (0.4,2.515) (0.45,-6.568) (0.5,9.206)}
\drawpole{-3cm}{-2.25cm}

% RHP stable: exp(-10.192t) cos(19.665wt) (40/3*w for readability)
%
% a = ln(0.333 + 0.5i)/0.05 = -10.192 + 19.665i
\drawdiscretetimeplot{1cm}{2.25cm}{0.125cm}{0.44375cm}{
exp(-10.192 * \x) * cos(40/3 * 19.665 * deg(\x))}
\drawpole{1cm}{1.5cm}

% RHP stable: exp(-21.97t)
%
% a = ln(1/3)/0.05 = -21.97
\drawdiscretetimeplot{1cm - 0.166cm}{-0.75cm}{0.125cm}{0.125cm}{exp(-21.97 * \x)}
\drawpole{1cm}{0cm}

% RHP stable: exp(-8.109t)
%
% a = ln(2/3)/0.05 = -8.109
\drawdiscretetimeplot{2cm}{0.75cm}{0.125cm}{0.125cm}{exp(-8.109 * \x)}
\drawpole{2cm}{0cm}

% RHP marginally stable: cos(15.707wt)
%
% a = ln(√2 + √2i)/0.05 = 15.707i
\drawdiscretetimeplot{3 * (0.707cm + 0.25cm)}{3 * 0.707cm + 0.375cm}{0.125cm}{0.44375cm}{cos(15.707 * deg(\x))}
\drawpole{3 * 0.707cm}{3 * 0.707cm}

% RHP integrator
\drawdiscretetimeplot{3cm + 0.166cm}{-0.75cm}{0.125cm}{0.125cm}{exp(0 * \x)}
\drawpole{3cm}{0cm}

% RHP unstable: exp(4.463t) cos(-12.87wt)
%
% a = ln(1 - 0.75i)/0.05 = 4.463 - 12.87i
\drawdiscretetimeplot{2.25cm}{-2.25cm}{0.125cm}{0.44375cm}{exp(4.463 * \x) * cos(-12.87 * deg(\x))}
\drawpole{3cm}{-2.25cm}

% LHP and RHP labels
\draw (-3.5,1.5) node {LHP};
\draw (3.5,1.5) node {RHP};

% Stable and unstable labels
\fill[white] (-0.5,-2.25) rectangle (0.5,-1.75);
\draw (0,-2) node {\small Stable};
\draw (2.5,3.5) node {\small Unstable};
\draw (-2.5,3.5) node {\small Unstable};
\draw (-2.5,-3.5) node {\small Unstable};
\draw (2.5,-3.5) node {\small Unstable};
\end{tikzpicture}
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ \section{What is gain?}
% \draw [help lines] (-4,-2) grid (4,2);

% Input
\drawtimeplot{-2.5cm}{0cm}{0.125cm}{0.44375cm}{0.6 * cos(40 * deg(\x))}
\drawcontinuoustimeplot{-2.5cm}{0cm}{0.125cm}{0.44375cm}{0.6 * cos(40 * deg(\x))}
\draw (-2.5,1) node {\small input};

\node [block] (sys) {K};
\draw (0,1) node {\small system};

% Output
\drawtimeplot{2.5cm}{0cm}{0.125cm}{0.44375cm}{1.2 * cos(40* deg(\x))}
\drawcontinuoustimeplot{2.5cm}{0cm}{0.125cm}{0.44375cm}{1.2 * cos(40* deg(\x))}
\draw (2.5,1) node {\small output};

% Arrows between input/output and system
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ \section{Eigenvalues and stability}
\index{stability!poles}
The eigenvalues of $\mat{A}$ are called \textit{poles}.\footnote{This name comes
from classical control theory. See subsection \ref{subsec:poles_and_zeroes} for
more.} Figure \ref{fig:impulse_response_eig} shows the \glspl{impulse response}
in the time domain for \glspl{system} with various pole locations in the complex
plane (real numbers on the x-axis and imaginary numbers on the y-axis). Each
response has an initial condition of $1$.
more.} Figure \ref{fig:cont_impulse_response_eig} shows the \glspl{impulse
response} in the time domain for \glspl{system} with various pole locations in
the complex plane (real numbers on the x-axis and imaginary numbers on the
y-axis). Each response has an initial condition of $1$.
\begin{bookfigure}
\input{figs/impulse-response-vs-pole-location}
\caption{Impulse response vs pole location}
\label{fig:impulse_response_eig}
\input{figs/continuous-impulse-response-vs-pole-location}
\caption{Continuous impulse response vs pole location}
\label{fig:cont_impulse_response_eig}
\end{bookfigure}

Poles in the left half-plane (LHP) are stable; the \gls{system}'s output may
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,37 +29,40 @@ \section{Continuous to discrete pole mapping}

\subsection{Discrete system stability}

Eigenvalues of a \gls{system} that are within the unit circle are stable, but
why is that? Let's consider a scalar equation $x_{k + 1} = ax_k$. $a < 1$ makes
$x_{k + 1}$ converge to zero. The same applies to a complex number like
$z = x + yi$ for $x_{k + 1} = zx_k$. If the magnitude of the complex number $z$
is less than one, $x_{k+1}$ will converge to zero. Values with a magnitude of
$1$ oscillate forever because $x_{k+1}$ never decays.
Eigenvalues of a \gls{system} that are within the unit circle are stable. To
demonstrate this, consider the discrete system $x_{k + 1} = ax_k$ where $a$ is a
complex number. $|a| < 1$ will make $x_{k + 1}$ converge to zero.

\subsection{Discrete system behavior}

Figure \ref{fig:disc_impulse_response_eig} shows the \glspl{impulse response} in
the time domain for \glspl{system} with various pole locations in the complex
plane (real numbers on the x-axis and imaginary numbers on the y-axis). Each
response has an initial condition of $1$.
\begin{bookfigure}
\input{figs/discrete-impulse-response-vs-pole-location}
\caption{Discrete impulse response vs pole location}
\label{fig:disc_impulse_response_eig}
\end{bookfigure}

As $\omega$ increases in $s = j\omega$, a pole in the discrete plane moves
around the perimeter of the unit circle. Once it hits $\frac{\omega_s}{2}$ (half
the sampling frequency) at $(-1, 0)$, the pole wraps around. This is due to
poles faster than the sample frequency folding down to below the sample
frequency (that is, higher frequency signals \textit{alias} to lower frequency
ones).

You may notice that poles can be placed at $(0, 0)$ in the discrete plane. This
is known as a deadbeat controller. An $\rm N^{th}$-order deadbeat controller
decays to the \gls{reference} in N timesteps. While this sounds great, there are
other considerations like \gls{control effort}, \gls{robustness}, and
\gls{noise immunity}.
Placing the poles at $(0, 0)$ produces a \textit{deadbeat controller}. An
$\rm N^{th}$-order deadbeat controller decays to the \gls{reference} in N
timesteps. While this sounds great, there are other considerations like
\gls{control effort}, \gls{robustness}, and \gls{noise immunity}.

If poles from $(1, 0)$ to $(0, 0)$ on the x-axis approach infinity, then what do
poles from $(-1, 0)$ to $(0, 0)$ represent? Them being faster than infinity
doesn't make sense. Poles in this location exhibit oscillatory behavior similar
to complex conjugate pairs. See figures \ref{fig:continuous_oscillations_1p} and
\ref{fig:discrete_oscillations_2p}. The jaggedness of these signals is due to
the frequency of the \gls{system} dynamics being above the Nyquist frequency
(twice the sample frequency). The \glslink{discretization}{discretized} signal
doesn't have enough samples to reconstruct the continuous \gls{system}'s
dynamics.
Poles in the left half-plane cause jagged outputs because the frequency of the
\gls{system} dynamics is above the Nyquist frequency (twice the sample
frequency). The \glslink{discretization}{discretized} signal doesn't have enough
samples to reconstruct the continuous \gls{system}'s dynamics. See figures
\ref{fig:continuous_oscillations_1p} and \ref{fig:discrete_oscillations_2p} for
examples.
\begin{bookfigure}
\begin{minisvg}{2}{build/\chapterpath/z_oscillations_1p}
\caption{Single poles in various locations in discrete plane}
Expand Down
55 changes: 54 additions & 1 deletion preamble/macros.tex
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
% #3: xcoordshift
% #4: ycoordshift
% #5: func to plot
\newcommand{\drawtimeplot}[5] {
\newcommand{\drawcontinuoustimeplot}[5] {
\begin{scope}[xshift=#1-0.5cm,yshift=#2-0.5cm]
\def\xcoordshift{#3,0}
\def\ycoordshift{0,#4}
Expand All @@ -130,12 +130,65 @@
\draw[->,font=\tiny] (-0.075cm,0cm) -- (0.8125cm,0cm)
node[label={[below]90:$t$}] {};

\clip (0cm,-0.45cm) rectangle (1cm,0.55cm);
\draw[xscale=1.2,yscale=0.3,domain=0:0.5,smooth,variable=\x,line width=0.5]
plot ({\x},{#5});
\end{scope}
\end{scope}
\end{scope}}

% #1: xshift
% #2: yshift
% #3: xcoordshift
% #4: ycoordshift
% #5: func to plot
\newcommand{\drawdiscretetimeplot}[5] {
\begin{scope}[xshift=#1-0.5cm,yshift=#2-0.5cm]
\def\xcoordshift{#3,0}
\def\ycoordshift{0,#4}

\draw[fill=headingbg] (0,0) rectangle (1,1);
\begin{scope}[shift=(\xcoordshift)]
% Draw y-axis
\draw[->] (0cm,0.05cm) -- (0cm,0.9375cm) node {};
\begin{scope}[shift=(\ycoordshift)]
% Draw x-axis
\draw[->,font=\tiny] (-0.075cm,0cm) -- (0.8125cm,0cm)
node[label={[below]90:$t$}] {};

\clip (0cm,-0.45cm) rectangle (1cm,0.55cm);
\draw[xscale=1.2,yscale=0.3,domain=0:0.5,variable=\x,line width=0.5]
plot ({\x},{#5});
\end{scope}
\end{scope}
\end{scope}}

% #1: xshift
% #2: yshift
% #3: xcoordshift
% #4: ycoordshift
% #5: coordinates to plot
\newcommand{\drawdiscretecoordplot}[5] {
\begin{scope}[xshift=#1-0.5cm,yshift=#2-0.5cm]
\def\xcoordshift{#3,0}
\def\ycoordshift{0,#4}

\draw[fill=headingbg] (0,0) rectangle (1,1);
\begin{scope}[shift=(\xcoordshift)]
% Draw y-axis
\draw[->] (0cm,0.05cm) -- (0cm,0.9375cm) node {};
\begin{scope}[shift=(\ycoordshift)]
% Draw x-axis
\draw[->,font=\tiny] (-0.075cm,0cm) -- (0.8125cm,0cm)
node[label={[below]90:$t$}] {};

\clip (0cm,-0.45cm) rectangle (1cm,0.55cm);
\draw[xscale=1.2,yscale=0.3,domain=0:0.5,variable=\x,line width=0.5]
plot coordinates {#5};
\end{scope}
\end{scope}
\end{scope}}

% #1: xshift
% #2: yshift
\newcommand{\drawpole}[2] {
Expand Down

0 comments on commit 21c2513

Please sign in to comment.