Hello Pipeline!#

The examples presented on this page try to be as simple as possible. The resulting applications will not be particularly useful, but introduce a few basic concepts of the Pipeline in a practical manner. These examples will not involve any predictor or controller.

The examples presented on this page are snippets from the file applications/demo_hello_pipeline/main.cpp.

Example 1 - InOutputs only#

In example 1, we create a Pipeline object, add a few InOutput instance and perform three periodic updates (ticks).

 1void Example1(mpmca::utilities::Logger& logger)
 2{
 3    using namespace mpmca::pipeline;
 4
 5    // First, we create a Pipeline Options object, but do not modify it.
 6    Pipeline::Options pipeline_options;
 7
 8    // Then, construct the pipeline.
 9    Pipeline pipeline{pipeline_options};
10
11    // After construction, we can add InOutputs, Tasks and Steps. Here, we add
12    // three InOutputs, of which two are of type HelloWorld, and one is of type
13    // EmptyInOutput. The boolean option controls whether messages are printed.
14    pipeline.AddInOutput<in_output::HelloWorld>("HelloWorld InOutput One", true);
15    pipeline.AddInOutput<in_output::HelloWorld>("HelloWorld InOutput Two", true);
16    pipeline.AddInOutput<in_output::EmptyInOutput>("EmptyInOuput");
17
18    // After constructing all InOutputs, Tasks and Steps, and before running,
19    // the pipeline needs to be "prepared". In the preparing stage, the
20    // InOutputs and Steps may perform expensive (blocking) operations that
21    // could not be done during construction, and take too long to be done while
22    // the pipeline is being "ticked" periodically. The InOuputs and Steps
23    // should also declare themselves 'safe' to be ticked periodically.
24    pipeline.Prepare();
25
26    // This loop performs the periodic ticking of the pipeline.
27    for (size_t t = 0; t < 3; ++t) {
28        // This marks the start of one sample.
29        logger.Info("==== Start sample " + std::to_string(t) + " ====");
30
31        // Each sample, the pipeline needs to be "ticked". During a Tick() call,
32        // all InOutputs are "ticked".
33        pipeline.Tick();
34
35        // The Task runs at an integer multiple rate of the InOutputs. To check
36        // whether the current *Tick* is a *MainTick*, the
37        // GetCurrentTickIsMainTick() method can be called.
38        if (pipeline.GetCurrentTickIsMainTick()) {
39            // If this Tick is a MainTick, we need to call MainTick().
40            // The MainTick() call can be performed from a different thread than
41            // the thread from where Tick() is called.
42            pipeline.MainTick();
43        }
44
45        // This marks the end of the sample.
46        logger.Info("==== End sample " + std::to_string(t) + " ====");
47    }
48}
49
50// Run this example, by running ./demo_hello_pipeline --run_example1

The expected output is:

 1[Main <main>] : <<<<< Example 1 >>>>>
 2[HelloWorld InOutput One <HelloWorld>] : Constructor
 3[HelloWorld InOutput Two <HelloWorld>] : Constructor
 4[HelloWorld InOutput One <HelloWorld>] : PrepareInOutputMessageBus(MessageBus&)
 5[HelloWorld InOutput Two <HelloWorld>] : PrepareInOutputMessageBus(MessageBus&)
 6[HelloWorld InOutput One <HelloWorld>] : CheckInOutputMessageBusPrepared(const MessageBus&)
 7[HelloWorld InOutput Two <HelloWorld>] : CheckInOutputMessageBusPrepared(const MessageBus&)
 8[HelloWorld InOutput One <HelloWorld>] : Prepare()
 9[HelloWorld InOutput Two <HelloWorld>] : Prepare()
10[Pipeline <Pipeline>] : Prepared pipeline. Safety status is SAFE.
11[Main <main>] : ==== Start sample 0 ====
12[Pipeline <Pipeline>] : 
13State machine state: BOOTING
14                HelloWorld InOutput One     BOOTING            NONE
15                HelloWorld InOutput Two     BOOTING            NONE
16                          EmptyInOuput     BOOTING            NONE
17
18[HelloWorld InOutput One <HelloWorld>] : Tick()
19[HelloWorld InOutput Two <HelloWorld>] : Tick()
20[Main <main>] : ==== End sample 0 ====
21[Main <main>] : ==== Start sample 1 ====
22[Pipeline <Pipeline>] : 
23State machine state: BOOTING
24                HelloWorld InOutput One     BOOTING          BOOTED
25                HelloWorld InOutput Two     BOOTING          BOOTED
26                          EmptyInOuput     BOOTING          BOOTED
27
28[Pipeline <Pipeline>] : 
29State machine state: IDLE
30                HelloWorld InOutput One        IDLE            NONE
31                HelloWorld InOutput Two        IDLE            NONE
32                          EmptyInOuput        IDLE            NONE
33
34[HelloWorld InOutput One <HelloWorld>] : Tick()
35[HelloWorld InOutput Two <HelloWorld>] : Tick()
36[Main <main>] : ==== End sample 1 ====
37[Main <main>] : ==== Start sample 2 ====
38[HelloWorld InOutput One <HelloWorld>] : Tick()
39[HelloWorld InOutput Two <HelloWorld>] : Tick()
40[Main <main>] : ==== End sample 2 ====
41[Pipeline <Pipeline>] : Time measurement results for InOutput tick calls:
42        tick:HelloWorld InOutput One [us]  min: 7 max: 23 avg: 14.311000
43        tick:HelloWorld InOutput Two [us]  min: 5 max: 21 avg: 12.617000
44        tick:EmptyInOuput [us]  min: 0 max: 0 avg: 0.546000
45[HelloWorld InOutput One <HelloWorld>] : ~HelloWorld()
46[HelloWorld InOutput Two <HelloWorld>] : ~HelloWorld()
47[Pipeline <Watchdog>] : Watchdog did not detect failures.

Observe the following:

  1. The two HelloWorld instances print debug output in their constructors, Prepare(), Tick() and MainTick() functions. The EmptyInOutput does not.
  2. The Pipeline does not contain a Task with Step instances, and therefor, only the Tick() functions are called. The MainTick() functions are not called.
  3. At the start of the first sample, all InOutput instances are in the BOOTING state. During this sample, they all report that they have completed booting (i.e., they are booted) and can advance to the IDLE state. They declare themselves BOOTED.
  4. At the start of the second sample, the StateMachine is still in BOOTING, but detects that all InOutput instances have reported themselves BOOTED, and therefore moves the overall state to IDLE. The InOutput instances will be in IDLE when their Tick() function is called.
  5. At the third sample, nothing happens to the StateMachine and therefor it produces no output.
  6. When Pipeline object is destructed, it prints some time measurement related statistics.

Example 2 - InOutputs and Steps#

In example 2, we extend Example 1 by also adding a Task that will contain two Step instances. The update loop now performs 7 ticks.

 1void Example2(mpmca::utilities::Logger& logger)
 2{
 3    using namespace mpmca;
 4
 5    // First, we create a Pipeline object and add two InOutputs, similar to
 6    // Example1.
 7    pipeline::Pipeline::Options pipeline_options;
 8    // We explicitly set the base_step_ms option to 1, which means that the
 9    // InOutput update rate is once every millisecond.
10    pipeline_options.base_step_ms = 1;
11    // We also explicitly set the command_buffer_length option to 3, which means
12    // that the MainTick() of the Task may take 3 samples longer than intended.
13    // Search the documentation for "Command Buffer" for more
14    // information.
15    pipeline_options.command_buffer_length = 3;
16
17    pipeline::Pipeline pipeline{pipeline_options};
18
19    pipeline.AddInOutput<pipeline::in_output::HelloWorld>(
20        "Hello World InOutput One", true);
21    pipeline.AddInOutput<pipeline::in_output::HelloWorld>(
22        "Hello World InOutput Two", true);
23
24    // In this example, we also add a Task, containing two Steps.
25    // The `Horizon` argument refers to the MPC horizon properties. This
26    // constructor will create a Horizon with 50 steps, where each steps has a
27    // length of 3 milliseconds.
28    auto task = pipeline.MakeTask("Task", utilities::Horizon(3, 50));
29    // The behavior of the HelloWorld step is similar to the HelloWorld
30    // InOutput.
31    task->AddStep<pipeline::step::HelloWorld>("Hello World Step One", true);
32    task->AddStep<pipeline::step::HelloWorld>("Hello World Step Two", true);
33
34    // Again, we prepare all InOutputs and Steps.
35    pipeline.Prepare();
36
37    // And run the main loop.
38    for (size_t t = 0; t < 7; ++t) {
39        if (pipeline.GetNextTickIsMainTick()) {
40            logger.Info(
41                "The next sample is a MainTick! Both Tick and MainTick should "
42                "be called.");
43        }
44        else {
45            logger.Info(
46                "The next sample is a Tick! Only Tick should be called.");
47        }
48
49        logger.Info("==== Start sample " + std::to_string(t) + " ====");
50        pipeline.Tick();
51
52        if (pipeline.GetCurrentTickIsMainTick())
53            pipeline.MainTick();
54
55        logger.Info("==== End sample " + std::to_string(t) + " ====");
56    }
57}

The expected output is as follows:

  1[Main <main>] : <<<<< Example 2 >>>>>
  2[Hello World InOutput One <HelloWorld>] : Constructor
  3[Hello World InOutput Two <HelloWorld>] : Constructor
  4[Task <Task>] : This Task will tick once every 3 base ticks.
  5[Hello World Step One <HelloWorld>] : Constructor
  6[Hello World Step Two <HelloWorld>] : Constructor
  7[Hello World InOutput One <HelloWorld>] : PrepareInOutputMessageBus(MessageBus&)
  8[Hello World InOutput Two <HelloWorld>] : PrepareInOutputMessageBus(MessageBus&)
  9[Hello World InOutput One <HelloWorld>] : CheckInOutputMessageBusPrepared(const MessageBus&)
 10[Hello World InOutput Two <HelloWorld>] : CheckInOutputMessageBusPrepared(const MessageBus&)
 11[Hello World InOutput One <HelloWorld>] : PrepareTaskMessageBus(MessageBus&)
 12[Hello World InOutput Two <HelloWorld>] : PrepareTaskMessageBus(MessageBus&)
 13[Hello World Step One <HelloWorld>] : PrepareTaskMessageBus(MessageBus&)
 14[Hello World Step Two <HelloWorld>] : PrepareTaskMessageBus(MessageBus&)
 15[Hello World InOutput One <HelloWorld>] : PrepareTaskMessageBus(MessageBus&)
 16[Hello World InOutput Two <HelloWorld>] : PrepareTaskMessageBus(MessageBus&)
 17[Hello World Step One <HelloWorld>] : PrepareTaskMessageBus(MessageBus&)
 18[Hello World Step Two <HelloWorld>] : PrepareTaskMessageBus(MessageBus&)
 19[Hello World InOutput One <HelloWorld>] : PrepareTaskMessageBus(MessageBus&)
 20[Hello World InOutput Two <HelloWorld>] : PrepareTaskMessageBus(MessageBus&)
 21[Hello World Step One <HelloWorld>] : PrepareTaskMessageBus(MessageBus&)
 22[Hello World Step Two <HelloWorld>] : PrepareTaskMessageBus(MessageBus&)
 23[Hello World InOutput One <HelloWorld>] : CheckTaskMessageBusPrepared(const MessageBus&)
 24[Hello World InOutput Two <HelloWorld>] : CheckTaskMessageBusPrepared(const MessageBus&)
 25[Hello World Step One <HelloWorld>] : CheckTaskMessageBusPrepared(const MessageBus&)
 26[Hello World Step Two <HelloWorld>] : CheckTaskMessageBusPrepared(const MessageBus&)
 27[Hello World InOutput One <HelloWorld>] : CheckTaskMessageBusPrepared(const MessageBus&)
 28[Hello World InOutput Two <HelloWorld>] : CheckTaskMessageBusPrepared(const MessageBus&)
 29[Hello World Step One <HelloWorld>] : CheckTaskMessageBusPrepared(const MessageBus&)
 30[Hello World Step Two <HelloWorld>] : CheckTaskMessageBusPrepared(const MessageBus&)
 31[Hello World InOutput One <HelloWorld>] : CheckTaskMessageBusPrepared(const MessageBus&)
 32[Hello World InOutput Two <HelloWorld>] : CheckTaskMessageBusPrepared(const MessageBus&)
 33[Hello World Step One <HelloWorld>] : CheckTaskMessageBusPrepared(const MessageBus&)
 34[Hello World Step Two <HelloWorld>] : CheckTaskMessageBusPrepared(const MessageBus&)
 35[Hello World Step One <HelloWorld>] : Prepare(Task&)
 36[Hello World Step Two <HelloWorld>] : Prepare(Task&)
 37[Hello World InOutput One <HelloWorld>] : Prepare()
 38[Hello World InOutput Two <HelloWorld>] : Prepare()
 39[Pipeline <Pipeline>] : Prepared pipeline. Safety status is SAFE.
 40[Main <main>] : The next sample is a MainTick! Both Tick and MainTick should be called.
 41[Main <main>] : ==== Start sample 0 ====
 42[Pipeline <Pipeline>] : 
 43State machine state: BOOTING
 44               Hello World InOutput One     BOOTING            NONE
 45               Hello World InOutput Two     BOOTING            NONE
 46                  Hello World Step One     BOOTING            NONE
 47                  Hello World Step Two     BOOTING            NONE
 48
 49[Hello World InOutput One <HelloWorld>] : Tick()
 50[Hello World InOutput Two <HelloWorld>] : Tick()
 51[Hello World InOutput One <HelloWorld>] : MainTick()
 52[Hello World InOutput Two <HelloWorld>] : MainTick()
 53[Hello World Step One <HelloWorld>] : MainTick(TaskDataBucket&)
 54[Hello World Step Two <HelloWorld>] : MainTick(TaskDataBucket&)
 55[Hello World InOutput One <HelloWorld>] : TaskCompleted()
 56[Hello World InOutput Two <HelloWorld>] : TaskCompleted()
 57[Main <main>] : ==== End sample 0 ====
 58[Main <main>] : The next sample is a Tick! Only Tick should be called.
 59[Main <main>] : ==== Start sample 1 ====
 60[Pipeline <Pipeline>] : 
 61State machine state: BOOTING
 62               Hello World InOutput One     BOOTING          BOOTED
 63               Hello World InOutput Two     BOOTING          BOOTED
 64                  Hello World Step One     BOOTING          BOOTED
 65                  Hello World Step Two     BOOTING          BOOTED
 66
 67[Hello World InOutput One <HelloWorld>] : Tick()
 68[Hello World InOutput Two <HelloWorld>] : Tick()
 69[Main <main>] : ==== End sample 1 ====
 70[Main <main>] : The next sample is a Tick! Only Tick should be called.
 71[Main <main>] : ==== Start sample 2 ====
 72[Pipeline <Pipeline>] : 
 73State machine state: BOOTING
 74               Hello World InOutput One     BOOTING          BOOTED
 75               Hello World InOutput Two     BOOTING          BOOTED
 76                  Hello World Step One     BOOTING          BOOTED
 77                  Hello World Step Two     BOOTING          BOOTED
 78
 79[Hello World InOutput One <HelloWorld>] : Tick()
 80[Hello World InOutput Two <HelloWorld>] : Tick()
 81[Main <main>] : ==== End sample 2 ====
 82[Main <main>] : The next sample is a MainTick! Both Tick and MainTick should be called.
 83[Main <main>] : ==== Start sample 3 ====
 84[Pipeline <Pipeline>] : 
 85State machine state: BOOTING
 86               Hello World InOutput One     BOOTING          BOOTED
 87               Hello World InOutput Two     BOOTING          BOOTED
 88                  Hello World Step One     BOOTING          BOOTED
 89                  Hello World Step Two     BOOTING          BOOTED
 90
 91[Pipeline <Pipeline>] : 
 92State machine state: IDLE
 93               Hello World InOutput One        IDLE            NONE
 94               Hello World InOutput Two        IDLE            NONE
 95                  Hello World Step One        IDLE            NONE
 96                  Hello World Step Two        IDLE            NONE
 97
 98[Hello World InOutput One <HelloWorld>] : Tick()
 99[Hello World InOutput Two <HelloWorld>] : Tick()
100[Hello World InOutput One <HelloWorld>] : MainTick()
101[Hello World InOutput Two <HelloWorld>] : MainTick()
102[Hello World Step One <HelloWorld>] : MainTick(TaskDataBucket&)
103[Hello World Step Two <HelloWorld>] : MainTick(TaskDataBucket&)
104[Hello World InOutput One <HelloWorld>] : TaskCompleted()
105[Hello World InOutput Two <HelloWorld>] : TaskCompleted()
106[Main <main>] : ==== End sample 3 ====
107[Main <main>] : The next sample is a Tick! Only Tick should be called.
108[Main <main>] : ==== Start sample 4 ====
109[Hello World InOutput One <HelloWorld>] : Tick()
110[Hello World InOutput Two <HelloWorld>] : Tick()
111[Main <main>] : ==== End sample 4 ====
112[Main <main>] : The next sample is a Tick! Only Tick should be called.
113[Main <main>] : ==== Start sample 5 ====
114[Hello World InOutput One <HelloWorld>] : Tick()
115[Hello World InOutput Two <HelloWorld>] : Tick()
116[Main <main>] : ==== End sample 5 ====
117[Main <main>] : The next sample is a MainTick! Both Tick and MainTick should be called.
118[Main <main>] : ==== Start sample 6 ====
119[Hello World InOutput One <HelloWorld>] : Tick()
120[Hello World InOutput Two <HelloWorld>] : Tick()
121[Hello World InOutput One <HelloWorld>] : MainTick()
122[Hello World InOutput Two <HelloWorld>] : MainTick()
123[Hello World Step One <HelloWorld>] : MainTick(TaskDataBucket&)
124[Hello World Step Two <HelloWorld>] : MainTick(TaskDataBucket&)
125[Hello World InOutput One <HelloWorld>] : TaskCompleted()
126[Hello World InOutput Two <HelloWorld>] : TaskCompleted()
127[Main <main>] : ==== End sample 6 ====
128[Pipeline <Pipeline>] : Time measurement results for InOutput tick calls:
129        tick:Hello World InOutput One [us]  min: 5 max: 10 avg: 7.446571
130        tick:Hello World InOutput Two [us]  min: 5 max: 9 avg: 6.874857
131[Pipeline <Pipeline>] : Time measurement results for InOutput MainTick calls:
132        MainTick:Hello World InOutput One [us]  min: 8 max: 9 avg: 8.681333
133        MainTick:Hello World InOutput Two [us]  min: 11 max: 14 avg: 10.382000
134[Pipeline <Pipeline>] : Time measurement results for InOutput taskCompleted calls:
135        taskCompleted:Hello World InOutput One [us]  min: 9 max: 10 avg: 8.544000
136        taskCompleted:Hello World InOutput Two [us]  min: 13 max: 13 avg: 10.919000
137[Task <Task>] : Time measurement information for task Task:
138Task:MainTick:Hello World Step One [ms]  min: 0 max: 0 avg: 0.009061
139Task:MainTick:Hello World Step Two [ms]  min: 0 max: 0 avg: 0.010245
140[Hello World Step One <HelloWorld>] : Destructor
141[Hello World Step Two <HelloWorld>] : Destructor
142[Hello World InOutput One <HelloWorld>] : ~HelloWorld()
143[Hello World InOutput Two <HelloWorld>] : ~HelloWorld()
144[Pipeline <Watchdog>] : Watchdog did not detect failures.

Observe the following:

  1. Directly following the constructor calls, note that a lot of calls to PrepareTaskMessageBus and CheckTaskMessageBusPrepared are performed. This is not by mistake! That is, for each 'buffer element', a separate TaskMessageBus needs to be initialized and prepared. The option command_buffer_length is set to 3, and so three TaskMessageBus instances need to be prepared, once by each InOutput and Step instance.
  2. The first sample is immediately both a Tick and a MainTick!
  3. At the start of the program, the InOutput and Step instances are all in BOOTING, and declare themselves BOOTED.
  4. In this example, a Task with Step instances is added to the Pipeline, therefore, the MainTick() function on the InOutput instances is called.
  5. The global StateMachine will only change states on a MainTick! This prevents (under normal circumstances), that the global state changes while some expensive computations are performed in the Task::MainTick().

Example 3 - StateMachine demo#

In the third example, we also add an InOutput of type GoToRun, which will move the StateMachine to the RUN state and back to IDLE, see this page.

 1void Example3(mpmca::utilities::Logger& logger)
 2{
 3    using namespace mpmca;
 4
 5    pipeline::Pipeline::Options pipeline_options;
 6    pipeline::Pipeline pipeline{pipeline_options};
 7
 8    pipeline.AddInOutput<pipeline::in_output::HelloWorld>(
 9        "Hello World InOutput One", false);
10    pipeline.AddInOutput<pipeline::in_output::HelloWorld>(
11        "Hello World InOutput Two", false);
12    auto go_to_run_inoutput =
13        pipeline.AddInOutput<pipeline::in_output::GoToRun>(
14            "Go To Run InOutput");
15    pipeline.AddInOutput<pipeline::in_output::DelayedStateFollower>(
16        "Delayed Follower", 2);
17
18    auto task = pipeline.MakeTask("Task", utilities::Horizon(3, 50));
19
20    task->AddStep<pipeline::step::HelloWorld>("Hello World Step One", false);
21    task->AddStep<pipeline::step::HelloWorld>("Hello World Step Two", false);
22
23    pipeline.Prepare();
24
25    for (size_t t = 0; t < 18; ++t) {
26        logger.Info("==== Start sample " + std::to_string(t) + " ====");
27
28        pipeline.Tick();
29
30        if (pipeline.GetCurrentTickIsMainTick())
31            pipeline.MainTick();
32
33        logger.Info("==== End sample " + std::to_string(t) + " ====");
34    }
35
36    // After reaching state kRun on the 17th sample, we tell the GoToRunInOutput
37    // to command the StateMachine back to IDLE.
38    go_to_run_inoutput->SetTargetState(
39        pipeline::in_output::GoToRun::TargetState::kIdle);
40
41    for (size_t t = 18; t < 25; ++t) {
42        logger.Info("==== Start sample " + std::to_string(t) + " ====");
43
44        pipeline.Tick();
45
46        if (pipeline.GetCurrentTickIsMainTick())
47            pipeline.MainTick();
48
49        logger.Info("==== End sample " + std::to_string(t) + " ====");
50    }
51}

The expected output is as follows:

  1[Main <main>] : <<<<< Example 3 >>>>>
  2[Task <Task>] : This Task will tick once every 3 base ticks.
  3[Pipeline <Pipeline>] : Prepared pipeline. Safety status is SAFE.
  4[Main <main>] : ==== Start sample 0 ====
  5[Pipeline <Pipeline>] : 
  6State machine state: BOOTING
  7               Hello World InOutput One     BOOTING            NONE
  8               Hello World InOutput Two     BOOTING            NONE
  9                    Go To Run InOutput     BOOTING            NONE
 10                      Delayed Follower     BOOTING            NONE
 11                  Hello World Step One     BOOTING            NONE
 12                  Hello World Step Two     BOOTING            NONE
 13
 14[Main <main>] : ==== End sample 0 ====
 15[Main <main>] : ==== Start sample 1 ====
 16[Pipeline <Pipeline>] : 
 17State machine state: BOOTING
 18               Hello World InOutput One     BOOTING          BOOTED
 19               Hello World InOutput Two     BOOTING          BOOTED
 20                    Go To Run InOutput     BOOTING          BOOTED
 21                      Delayed Follower     BOOTING            NONE
 22                  Hello World Step One     BOOTING          BOOTED
 23                  Hello World Step Two     BOOTING          BOOTED
 24
 25[Main <main>] : ==== End sample 1 ====
 26[Main <main>] : ==== Start sample 2 ====
 27[Pipeline <Pipeline>] : 
 28State machine state: BOOTING
 29               Hello World InOutput One     BOOTING          BOOTED
 30               Hello World InOutput Two     BOOTING          BOOTED
 31                    Go To Run InOutput     BOOTING          BOOTED
 32                      Delayed Follower     BOOTING          BOOTED
 33                  Hello World Step One     BOOTING          BOOTED
 34                  Hello World Step Two     BOOTING          BOOTED
 35
 36[Main <main>] : ==== End sample 2 ====
 37[Main <main>] : ==== Start sample 3 ====
 38[Pipeline <Pipeline>] : 
 39State machine state: BOOTING
 40               Hello World InOutput One     BOOTING          BOOTED
 41               Hello World InOutput Two     BOOTING          BOOTED
 42                    Go To Run InOutput     BOOTING          BOOTED
 43                      Delayed Follower     BOOTING          BOOTED
 44                  Hello World Step One     BOOTING          BOOTED
 45                  Hello World Step Two     BOOTING          BOOTED
 46
 47[Pipeline <Pipeline>] : 
 48State machine state: IDLE
 49               Hello World InOutput One        IDLE            NONE
 50               Hello World InOutput Two        IDLE            NONE
 51                    Go To Run InOutput        IDLE            NONE
 52                      Delayed Follower        IDLE            NONE
 53                  Hello World Step One        IDLE            NONE
 54                  Hello World Step Two        IDLE            NONE
 55
 56[Main <main>] : ==== End sample 3 ====
 57[Main <main>] : ==== Start sample 4 ====
 58[Pipeline <Pipeline>] : 
 59State machine state: IDLE
 60               Hello World InOutput One        IDLE            NONE
 61               Hello World InOutput Two        IDLE            NONE
 62                    Go To Run InOutput        IDLE       PREPARING
 63                      Delayed Follower        IDLE            NONE
 64                  Hello World Step One        IDLE            NONE
 65                  Hello World Step Two        IDLE            NONE
 66
 67[Main <main>] : ==== End sample 4 ====
 68[Main <main>] : ==== Start sample 5 ====
 69[Pipeline <Pipeline>] : 
 70State machine state: IDLE
 71               Hello World InOutput One        IDLE            NONE
 72               Hello World InOutput Two        IDLE            NONE
 73                    Go To Run InOutput        IDLE       PREPARING
 74                      Delayed Follower        IDLE            NONE
 75                  Hello World Step One        IDLE            NONE
 76                  Hello World Step Two        IDLE            NONE
 77
 78[Main <main>] : ==== End sample 5 ====
 79[Main <main>] : ==== Start sample 6 ====
 80[Pipeline <Pipeline>] : 
 81State machine state: IDLE
 82               Hello World InOutput One        IDLE            NONE
 83               Hello World InOutput Two        IDLE            NONE
 84                    Go To Run InOutput        IDLE       PREPARING
 85                      Delayed Follower        IDLE            NONE
 86                  Hello World Step One        IDLE            NONE
 87                  Hello World Step Two        IDLE            NONE
 88
 89[Pipeline <Pipeline>] : 
 90State machine state: PREPARING
 91               Hello World InOutput One   PREPARING            NONE
 92               Hello World InOutput Two   PREPARING            NONE
 93                    Go To Run InOutput   PREPARING            NONE
 94                      Delayed Follower   PREPARING            NONE
 95                  Hello World Step One   PREPARING            NONE
 96                  Hello World Step Two   PREPARING            NONE
 97
 98[Main <main>] : ==== End sample 6 ====
 99[Main <main>] : ==== Start sample 7 ====
100[Pipeline <Pipeline>] : 
101State machine state: PREPARING
102               Hello World InOutput One   PREPARING        PREPARED
103               Hello World InOutput Two   PREPARING        PREPARED
104                    Go To Run InOutput   PREPARING        PREPARED
105                      Delayed Follower   PREPARING        PREPARED
106                  Hello World Step One   PREPARING        PREPARED
107                  Hello World Step Two   PREPARING        PREPARED
108
109[Main <main>] : ==== End sample 7 ====
110[Main <main>] : ==== Start sample 8 ====
111[Pipeline <Pipeline>] : 
112State machine state: PREPARING
113               Hello World InOutput One   PREPARING        PREPARED
114               Hello World InOutput Two   PREPARING        PREPARED
115                    Go To Run InOutput   PREPARING        PREPARED
116                      Delayed Follower   PREPARING        PREPARED
117                  Hello World Step One   PREPARING        PREPARED
118                  Hello World Step Two   PREPARING        PREPARED
119
120[Main <main>] : ==== End sample 8 ====
121[Main <main>] : ==== Start sample 9 ====
122[Pipeline <Pipeline>] : 
123State machine state: PREPARING
124               Hello World InOutput One   PREPARING        PREPARED
125               Hello World InOutput Two   PREPARING        PREPARED
126                    Go To Run InOutput   PREPARING        PREPARED
127                      Delayed Follower   PREPARING        PREPARED
128                  Hello World Step One   PREPARING        PREPARED
129                  Hello World Step Two   PREPARING        PREPARED
130
131[Pipeline <Pipeline>] : 
132State machine state: READY
133               Hello World InOutput One       READY            NONE
134               Hello World InOutput Two       READY            NONE
135                    Go To Run InOutput       READY            NONE
136                      Delayed Follower       READY            NONE
137                  Hello World Step One       READY            NONE
138                  Hello World Step Two       READY            NONE
139
140[Main <main>] : ==== End sample 9 ====
141[Main <main>] : ==== Start sample 10 ====
142[Pipeline <Pipeline>] : 
143State machine state: READY
144               Hello World InOutput One       READY            NONE
145               Hello World InOutput Two       READY            NONE
146                    Go To Run InOutput       READY        STARTING
147                      Delayed Follower       READY            NONE
148                  Hello World Step One       READY            NONE
149                  Hello World Step Two       READY            NONE
150
151[Main <main>] : ==== End sample 10 ====
152[Main <main>] : ==== Start sample 11 ====
153[Pipeline <Pipeline>] : 
154State machine state: READY
155               Hello World InOutput One       READY            NONE
156               Hello World InOutput Two       READY            NONE
157                    Go To Run InOutput       READY        STARTING
158                      Delayed Follower       READY            NONE
159                  Hello World Step One       READY            NONE
160                  Hello World Step Two       READY            NONE
161
162[Main <main>] : ==== End sample 11 ====
163[Main <main>] : ==== Start sample 12 ====
164[Pipeline <Pipeline>] : 
165State machine state: READY
166               Hello World InOutput One       READY            NONE
167               Hello World InOutput Two       READY            NONE
168                    Go To Run InOutput       READY        STARTING
169                      Delayed Follower       READY            NONE
170                  Hello World Step One       READY            NONE
171                  Hello World Step Two       READY            NONE
172
173[Pipeline <Pipeline>] : 
174State machine state: STARTING
175               Hello World InOutput One    STARTING            NONE
176               Hello World InOutput Two    STARTING            NONE
177                    Go To Run InOutput    STARTING            NONE
178                      Delayed Follower    STARTING            NONE
179                  Hello World Step One    STARTING            NONE
180                  Hello World Step Two    STARTING            NONE
181
182[Main <main>] : ==== End sample 12 ====
183[Main <main>] : ==== Start sample 13 ====
184[Pipeline <Pipeline>] : 
185State machine state: STARTING
186               Hello World InOutput One    STARTING         STARTED
187               Hello World InOutput Two    STARTING         STARTED
188                    Go To Run InOutput    STARTING         STARTED
189                      Delayed Follower    STARTING            NONE
190                  Hello World Step One    STARTING         STARTED
191                  Hello World Step Two    STARTING         STARTED
192
193[Main <main>] : ==== End sample 13 ====
194[Main <main>] : ==== Start sample 14 ====
195[Pipeline <Pipeline>] : 
196State machine state: STARTING
197               Hello World InOutput One    STARTING         STARTED
198               Hello World InOutput Two    STARTING         STARTED
199                    Go To Run InOutput    STARTING         STARTED
200                      Delayed Follower    STARTING         STARTED
201                  Hello World Step One    STARTING         STARTED
202                  Hello World Step Two    STARTING         STARTED
203
204[Main <main>] : ==== End sample 14 ====
205[Main <main>] : ==== Start sample 15 ====
206[Pipeline <Pipeline>] : 
207State machine state: STARTING
208               Hello World InOutput One    STARTING         STARTED
209               Hello World InOutput Two    STARTING         STARTED
210                    Go To Run InOutput    STARTING         STARTED
211                      Delayed Follower    STARTING         STARTED
212                  Hello World Step One    STARTING         STARTED
213                  Hello World Step Two    STARTING         STARTED
214
215[Pipeline <Pipeline>] : 
216State machine state: RUN
217               Hello World InOutput One         RUN            NONE
218               Hello World InOutput Two         RUN            NONE
219                    Go To Run InOutput         RUN            NONE
220                      Delayed Follower         RUN            NONE
221                  Hello World Step One         RUN            NONE
222                  Hello World Step Two         RUN            NONE
223
224[Main <main>] : ==== End sample 15 ====
225[Main <main>] : ==== Start sample 16 ====
226[Main <main>] : ==== End sample 16 ====
227[Main <main>] : ==== Start sample 17 ====
228[Main <main>] : ==== End sample 17 ====
229[Main <main>] : ==== Start sample 18 ====
230[Main <main>] : ==== End sample 18 ====
231[Main <main>] : ==== Start sample 19 ====
232[Pipeline <Pipeline>] : 
233State machine state: RUN
234               Hello World InOutput One         RUN            NONE
235               Hello World InOutput Two         RUN            NONE
236                    Go To Run InOutput         RUN        STOPPING
237                      Delayed Follower         RUN            NONE
238                  Hello World Step One         RUN            NONE
239                  Hello World Step Two         RUN            NONE
240
241[Main <main>] : ==== End sample 19 ====
242[Main <main>] : ==== Start sample 20 ====
243[Pipeline <Pipeline>] : 
244State machine state: RUN
245               Hello World InOutput One         RUN            NONE
246               Hello World InOutput Two         RUN            NONE
247                    Go To Run InOutput         RUN        STOPPING
248                      Delayed Follower         RUN            NONE
249                  Hello World Step One         RUN            NONE
250                  Hello World Step Two         RUN            NONE
251
252[Main <main>] : ==== End sample 20 ====
253[Main <main>] : ==== Start sample 21 ====
254[Pipeline <Pipeline>] : 
255State machine state: RUN
256               Hello World InOutput One         RUN            NONE
257               Hello World InOutput Two         RUN            NONE
258                    Go To Run InOutput         RUN        STOPPING
259                      Delayed Follower         RUN            NONE
260                  Hello World Step One         RUN            NONE
261                  Hello World Step Two         RUN            NONE
262
263[Pipeline <Pipeline>] : 
264State machine state: STOPPING
265               Hello World InOutput One    STOPPING            NONE
266               Hello World InOutput Two    STOPPING            NONE
267                    Go To Run InOutput    STOPPING            NONE
268                      Delayed Follower    STOPPING            NONE
269                  Hello World Step One    STOPPING            NONE
270                  Hello World Step Two    STOPPING            NONE
271
272[Main <main>] : ==== End sample 21 ====
273[Main <main>] : ==== Start sample 22 ====
274[Pipeline <Pipeline>] : 
275State machine state: STOPPING
276               Hello World InOutput One    STOPPING         STOPPED
277               Hello World InOutput Two    STOPPING         STOPPED
278                    Go To Run InOutput    STOPPING         STOPPED
279                      Delayed Follower    STOPPING         STOPPED
280                  Hello World Step One    STOPPING         STOPPED
281                  Hello World Step Two    STOPPING         STOPPED
282
283[Main <main>] : ==== End sample 22 ====
284[Main <main>] : ==== Start sample 23 ====
285[Pipeline <Pipeline>] : 
286State machine state: STOPPING
287               Hello World InOutput One    STOPPING         STOPPED
288               Hello World InOutput Two    STOPPING         STOPPED
289                    Go To Run InOutput    STOPPING         STOPPED
290                      Delayed Follower    STOPPING         STOPPED
291                  Hello World Step One    STOPPING         STOPPED
292                  Hello World Step Two    STOPPING         STOPPED
293
294[Main <main>] : ==== End sample 23 ====
295[Main <main>] : ==== Start sample 24 ====
296[Pipeline <Pipeline>] : 
297State machine state: STOPPING
298               Hello World InOutput One    STOPPING         STOPPED
299               Hello World InOutput Two    STOPPING         STOPPED
300                    Go To Run InOutput    STOPPING         STOPPED
301                      Delayed Follower    STOPPING         STOPPED
302                  Hello World Step One    STOPPING         STOPPED
303                  Hello World Step Two    STOPPING         STOPPED
304
305[Pipeline <Pipeline>] : 
306State machine state: IDLE
307               Hello World InOutput One        IDLE            NONE
308               Hello World InOutput Two        IDLE            NONE
309                    Go To Run InOutput        IDLE            NONE
310                      Delayed Follower        IDLE            NONE
311                  Hello World Step One        IDLE            NONE
312                  Hello World Step Two        IDLE            NONE
313
314[Main <main>] : ==== End sample 24 ====
315[Pipeline <Pipeline>] : Time measurement results for InOutput tick calls:
316        tick:Hello World InOutput One [us]  min: 0 max: 1 avg: 0.725960
317        tick:Hello World InOutput Two [us]  min: 0 max: 0 avg: 0.411080
318        tick:Go To Run InOutput [us]  min: 0 max: 0 avg: 0.427960
319        tick:Delayed Follower [us]  min: 0 max: 0 avg: 0.444000
320[Pipeline <Pipeline>] : Time measurement results for InOutput MainTick calls:
321        MainTick:Hello World InOutput One [us]  min: 0 max: 1 avg: 0.533889
322        MainTick:Hello World InOutput Two [us]  min: 0 max: 0 avg: 0.371111
323        MainTick:Go To Run InOutput [us]  min: 0 max: 0 avg: 0.509333
324        MainTick:Delayed Follower [us]  min: 0 max: 0 avg: 0.356000
325[Pipeline <Pipeline>] : Time measurement results for InOutput taskCompleted calls:
326        taskCompleted:Hello World InOutput One [us]  min: 0 max: 0 avg: 0.465556
327        taskCompleted:Hello World InOutput Two [us]  min: 0 max: 0 avg: 0.336889
328        taskCompleted:Go To Run InOutput [us]  min: 0 max: 0 avg: 0.365000
329        taskCompleted:Delayed Follower [us]  min: 0 max: 0 avg: 0.350667
330[Task <Task>] : Time measurement information for task Task:
331Task:MainTick:Hello World Step One [ms]  min: 0 max: 0 avg: 0.000607
332Task:MainTick:Hello World Step Two [ms]  min: 0 max: 0 avg: 0.000416
333[Pipeline <Watchdog>] : Watchdog did not detect failures.

Observe that:

  1. The states follow the state flow as depicted here.
  2. The global state only changes on MainTicks.