Ben's Website

Serious musings

Control Diagrams in LaTeX

Note: This post broke years ago, but I still like the idea of creating declarative graphics..

Over Christmas break I've become dangerous with $\LaTeX$ document typesetting (wikipedia).  There's something incredibly attractive about having the entire source of a document embedded in a single, text file.  Indeed the learning curve has been a bit steep (it may yet get stepper...), but I'm now able to reasonably produce dynamics and controls documents with integrated figures.  Here's the state block diagram for the quintessential spring-mass-damper problem, composted in $\LaTeX$:

\\begin{tikzpicture}\[node distance=5mm and 15mm, >=stealth, skip loopDL/.style={to path={-- ++(0,-.5) |- (\\tikztotarget)}},skip loopLU/.style={to path={ -| (\\tikztotarget)}}\] \[+preamble\] \\usepackage{tikz} \\usepackage{graphicx} \\usetikzlibrary{ arrows,  shapes.misc,  shapes.arrows,  chains,  matrix,  positioning,  scopes,  decorations.pathmorphing,  shadows, calc} \\tikzset{ nonterminal/.style={rectangle, minimum size=6mm, very thick, draw=red!50!black!20, top color=white, bottom color=red!50!black!50, font=\\itshape }, terminal/.style={rounded rectangle,  minimum size=6mm, very thick,draw=black!50, top color=white, bottom color=black!20, font=\\ttfamily}, junction/.style={circle, draw }} \\pgfsetlinewidth{.4mm} \[/preamble\]

\node (xddot) {}; \node (plus1) [junction,right=of xddot] {[N]}; \node(invM) [nonterminal,right=of plus1] {$\frac{1}{M_p}$}; \node(intT1) [nonterminal,right=of invM] {$\int$dt}; \node(intT2) [nonterminal,right=of intT1] {$\int$dt}; \node(x)    [right=of intT2] {}; \node(Cp) [nonterminal,below=of invM] {$C_p$}; \node(Kp) [nonterminal,below=of Cp] {$K_p$};

\path[->,every node] (xddot)                 edge node[pos=-.1]    {$\ddot{x}$}                 (plus1) (plus1)                edge node[above]        {\emph{ $M_p\frac{d\nu}{dt}$ }}     (invM) (invM)                    edge node[above]         {\emph{ $\frac{d\nu}{dt}$ }}         (intT1) (intT1)                edge node[above]        {\emph{ $\nu=\frac{d\nu}{dt}$ }}    (intT2) (intT2)                edge node[pos=1.1]    {\emph{x}}                    (x) ($ (intT1.east)+(2mm,0)$)    edge[skip loopDL]                                (Cp.east) (Cp.west)                 edge[skip loopLU]                                (plus1.south) ($ (intT2.east)+(2mm,0)$)     edge[skip loopDL]                                (Kp.east) (Kp.west)                 edge[skip loopLU]                                 (plus1.south west); %add minus signs to plus1 -- can't this be added to the skip loops above? \node at ($(plus1.west)+(-.2,.2)$) {+}; \node at ($(plus1.south west)+(-.2,-.2)$) {$-$}; \node at ($(plus1.south)+(.2,-.2)$) {$-$};

\end{tikzpicture}

Some parts are still a little rough, but the capability is there.  In case you're wondering, I'm using QuickLatex, which renders TikZ graphics.  I'm planning to write some more advanced posts in Dynamics and Controls using these tools, but for now here's the code for the above diagram:

!\\begin{tikzpicture}\[node distance=5mm and 15mm, >=stealth, skip loopDL/.style={to path={-- ++(0,-.5) |- (\\tikztotarget)}},skip loopLU/.style={to path={ -| (\\tikztotarget)}}\] \[+preamble\] \\usepackage{tikz} \\usepackage{graphicx} \\usetikzlibrary{ arrows,  shapes.misc,  shapes.arrows,  chains,  matrix,  positioning,  scopes,  decorations.pathmorphing,  shadows, calc} \\tikzset{ nonterminal/.style={rectangle, minimum size=6mm, very thick, draw=red!50!black!20, top color=white, bottom color=red!50!black!50, font=\\itshape }, terminal/.style={rounded rectangle,  minimum size=6mm, very thick,draw=black!50, top color=white, bottom color=black!20, font=\\ttfamily}, junction/.style={circle, draw }} \\pgfsetlinewidth{.4mm} \[/preamble\]

\node (xddot) {}; \node (plus1) [junction,right=of xddot] {[N]}; \node(invM) [nonterminal,right=of plus1] {$\frac{1}{M_p}$}; \node(intT1) [nonterminal,right=of invM] {$\int$dt}; \node(intT2) [nonterminal,right=of intT1] {$\int$dt}; \node(x)    [right=of intT2] {}; \node(Cp) [nonterminal,below=of invM] {$C_p$}; \node(Kp) [nonterminal,below=of Cp] {$K_p$};

\path[->,every node] (xddot) edge node[pos=-.1] {$\ddot{x}$} (plus1) (plus1) edge node[above]   {\emph{ $M_p\frac{d\nu}{dt}$ }}     (invM) (invM)  edge node[above]   {\emph{ $\frac{d\nu}{dt}$ }}        (intT1) (intT1) edge node[above]   {\emph{ $\nu=\frac{d\nu}{dt}$ }}    (intT2) (intT2) edge node[pos=1.1] {\emph{x}}                     (x) ($ (intT1.east)+(2mm,0)$) edge[skip loopDL]                    (Cp.east) (Cp.west) edge[skip loopLU]  (plus1.south) ($ (intT2.east)+(2mm,0)$) edge[skip loopDL]                    (Kp.east) (Kp.west) edge[skip loopLU]                                  (plus1.south west); %add minus signs to plus1 -- can't this be added to the skip loops above? \node at ($(plus1.south west)+(-.2,-.2)$) {$-$}; \node at ($(plus1.south)+(.2,-.2)$) {$-$};

\end{tikzpicture}