I want to depict a Hierarchical Statemachine (HSM) in a latex document. I've implemented the state machine I want to depict in Qt's Statemachine Framework. Just so that you know what I'm talking about.

I do not need to depict all of the features of the statemachine framework (e.g. I did not use history states). If I could for instance reproduce this (http://doc.qt.io/qt-5/images/statemachine-button-nested.png) image from the Qt doc, this would be enough for my needs.

I don't not really care if the image is part of the tex-file itself (i.e. Tikz) or generated by an external program. It should, however, be a vector graphic.

I've looked into TikZ and it could probably be done with it, but it feels like a hustle right now:

\usetikzlibrary{arrows, shapes, 3d, calc, fit, positioning}
\begin{tikzpicture}[round/.style={rounded corners=1.5mm,minimum width=1cm,inner sep=2mm,above right,draw,align=left,text width=15mm}]
\node[round] (rotLeft) at (-3,-1) {rotation left};
\node[round] (rotRight) at (-3,1) {rotation right};
\node[round,fit=(rotLeft)(rotRight)] (ident) {identify};
\node[round] (pause) at (0,1) {pause};
\node[round] (observe) at (0,0) {observe};
\node[round] (origin) at (0,-1) {to origin};
\node[round] (left) at (3,-1) {left};
\node[round] (right) at (3,1) {right};
\node[round] (neutral) at (7,0) {neutral};
\node[round,fit=(left)(right)(neutral)] (running) {running};

\draw[-latex, bend left] ($(pause.north east) + (-0.5,0.3)$) coordinate (temp) to (pause);
\fill (temp) circle (0.1);
\draw[-latex, bend left] ($(rotLeft.north east) + (0,0.3)$) coordinate (temp2) to (rotLeft);
\fill (temp2) circle (0.1);
\draw[-latex, bend left] ($(neutral.north east) + (-0.5,0.3)$) coordinate (temp3) to (neutral);
\fill (temp3) circle (0.1);
\draw[-latex, bend left] (left) to (right);
\draw[-latex, bend left] (right) to (left); 
\draw[-latex, bend left] (left) to (neutral);
\draw[-latex, bend left] (neutral) to (right);
\draw[-latex, bend left] (neutral) to (left);
\draw[-latex, bend left] (right) to (neutral);

\draw[-latex, bend left] (pause) to (running);
\draw[-latex, bend left] (pause) to[in=-135,out=-90] (ident);
\draw[-latex, bend left] (pause) to (observe);
\draw[-latex, bend left] (observe) to (origin);
\draw[-latex, bend left] (origin) to (origin);
\draw[-latex, bend left] (origin) to (pause);
\draw[-latex, bend left] (running) to (origin);
\draw[-latex, bend left] (ident) to[out=-60,in=-90] (origin);
\draw[-latex, bend left] (rotLeft) to (rotRight);
\draw[-latex, bend left] (rotRight) to (rotLeft);

And the result is not really pretty neither.

enter image description here

Maybe I'm missing out on something. I'm pretty new to Tikz.

I considered graphviz (dot) which is much more to my liking, because it espacially takes care of all the layout stuff (where to place which node and the path of edges). But is doesn't have support nested node.

Any other suggestions would be most welcome.



P.S.: Ok, what do I mean by "pretty"? What looks ugly to me in this graph is:

  • Edges crossing nodes (from "to origin" ot "pause").
  • Edges crossing one another without need (e.g. between node "left" and "neutral").

These things could be resolved, I guess, when diving deeper into Tikz. But one of the things I really value graphviz for is that I don't need to concern myself with all this layout stuff. I just describe what nodes exist and who they are interconnected and gaphviz does all the rest. If only it could handle nested nodes...

  • Additionally the name of the nodes "identify" and "running" overlapping with the edges is not too pretty, neither. Maybe they could just be written at teh top of each of the two nodes?!?

Maybe I'm asking too much, but considering, that HSMs are quite frequently used, I would have though there should be an more easy to use solution for depicting them somewhere in the wide field of open source.

  • Welcome! Rather than posting a mere fragment, please complete your code to provide a minimal example we can copy-paste-compile. It should start \documentclass and end \end{document}. Especially crucial when your code relies on non-standard LaTeX macros. I don't really think the linked PNG is especially pretty, either. What exactly is non-pretty about the TikZ result? Prettiness is so much in the eye of the beholder, it is unclear what you want without your being more specific. – cfr Jan 20 '16 at 22:51

Looks this (at least slightly) better?

enter image description here

The code for above picture is derived from your MWE. In this I change mechanism for nodes positioning from your absolute to used relative providing by TikZ library positioning. In the node style I omitted the minimum width, define minimum height and increase inner xsep distance.

For arrows between nodes are used edges. This significantly shorter the code. Their style is defined in one place, so it can be easily changed. Hopefully, in all this changes I didn't overlooked something.

\usetikzlibrary{arrows.meta, bending, calc, fit, positioning, shapes}

node distance = 22mm and 17mm,
every node/.style = {draw, rounded corners=1.5mm,
                     inner ysep=2mm, inner xsep=4mm,
                     minimum height=6ex,
%                     font=\bfseries,
                     text width=13mm, align=center},
\node (rotLeft)                             {rotation left};
\node (rotRight)    [above=of rotLeft]      {rotation right};
\node (ident)   [fit=(rotLeft)(rotRight)]   {identify};
\node (pause)   [right=of rotRight]          {pause};
\node (observe) [right= of $(rotLeft.east)!0.5!(rotRight.east)$]
\node (origin)  [right=of rotLeft]          {to origin};
\node (left)    [right=of pause]            {left};
\node (right)   [right=of origin]           {right};
\node (neutral) [right=of $(left)!0.5!(right)$] {neutral};
\node (running) [fit=(left)(right)(neutral)]    {};
    \node[draw=none,above=7mm of neutral]   {running};
\coordinate[above left=5mm and 2mm of rotLeft.north east]   (temp1);
\coordinate[above left=5mm and 2mm of pause.north east]     (temp2);
\coordinate[above left=5mm and 2mm of neutral.north east]   (temp3);
\path[{Circle[length=2mm,flex]}-{Latex[flex]}, bend left]
        (temp1) edge (rotLeft.north east)
        (temp2) edge (pause.north east)
        (temp3) edge (neutral.north east);
\draw[-{Latex[length=3mm]}]   ([yshift=-1mm] origin.east) -- + (0,3mm);
% edges
\path[draw, -{Latex[]}, bend left, looseness=1.3]
        (rotLeft)   edge (rotRight)
        (rotRight)  edge (rotLeft)
        (pause.north)   edge[bend right] (ident.north) 
        (ident.south)   edge[bend right] (origin.south)
        (origin.north west)     edge (pause.south west)
        (pause.south east)      edge (observe.north east)
        (observe.south east)    edge (origin.north east)
        (left)      edge (right)
        (right)     edge (left)
        (left)      edge (neutral)
([yshift=1mm] neutral.west) edge ([xshift= 7mm] left.south)
([xshift=7mm] right.north)   to  ([yshift=-1mm] neutral.west)% exception!?
        (neutral)   edge (right)
        (pause)     edge (running)
        (running)   edge (origin);
  • Hi,first of all sorry for answering so late. On posting this, I was asked to provide a email address. This lead me to the (apparently false) assumption I would be notified by mail when there is a reply to this. Anyhow, not only does the image look much better, but so does the code. With this, depicting HSMs can be done fairly easily. This solves it for me, however if someone wants to add other suggestions for tools or program for depicting HSMs I and possibly others would still be interested to know about them. I will check occasionally. Thanks a lot! – Soraltan Jan 27 '16 at 10:07
  • @Soraltan. it seems, that I need to ping you with comment :-). If you need to add more nodes (presenting your "tools"), than add them on the same way as the present nodes are. If you will have problems with this, just ask new question (on SE). – Zarko Jan 27 '16 at 11:11
  • 1
    A followup problem occurred. I could not compile your document, much less include your solution into my existing document. I solved that, but decided I might point other to this: You need PGF version 3. This can be achieved using texlive. However on some ubutnu version the version of texlive in the reps is quite old and does not provide pgf3. What I needed to do in the end was 1. Remove texlive using apt 2. install texlive fom the web. 3. install pgf using that texlive version. See: tex.stackexchange.com/questions/208495/… – Soraltan Jan 27 '16 at 12:28
  • @Soraltan, good comment ... between from TikZ 2.1 to recent 3.0.1a is huge step in it progress, so I anticipate, that all who use pgf/TikZ, use the recent its version :-) – Zarko Jan 27 '16 at 12:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.