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

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

Run this example, by running ./demo_hello_pipeline --run_example2. 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[Task <Task>] : The total horizon length of this Task is 150 ms and has 50 steps.
  6[Hello World Step One <HelloWorld>] : Constructor
  7[Hello World Step Two <HelloWorld>] : Constructor
  8[Hello World InOutput One <HelloWorld>] : PrepareInOutputMessageBus(MessageBus&)
  9[Hello World InOutput Two <HelloWorld>] : PrepareInOutputMessageBus(MessageBus&)
 10[Hello World InOutput One <HelloWorld>] : CheckInOutputMessageBusPrepared(const MessageBus&)
 11[Hello World InOutput Two <HelloWorld>] : CheckInOutputMessageBusPrepared(const MessageBus&)
 12[Hello World InOutput One <HelloWorld>] : PrepareTaskMessageBus(const Task& task, MessageBus&)
 13[Hello World InOutput Two <HelloWorld>] : PrepareTaskMessageBus(const Task& task, MessageBus&)
 14[Hello World Step One <HelloWorld>] : PrepareTaskMessageBus(const Task& task, MessageBus&)
 15[Hello World Step Two <HelloWorld>] : PrepareTaskMessageBus(const Task& task, MessageBus&)
 16[Hello World InOutput One <HelloWorld>] : PrepareTaskMessageBus(const Task& task, MessageBus&)
 17[Hello World InOutput Two <HelloWorld>] : PrepareTaskMessageBus(const Task& task, MessageBus&)
 18[Hello World Step One <HelloWorld>] : PrepareTaskMessageBus(const Task& task, MessageBus&)
 19[Hello World Step Two <HelloWorld>] : PrepareTaskMessageBus(const Task& task, MessageBus&)
 20[Hello World InOutput One <HelloWorld>] : PrepareTaskMessageBus(const Task& task, MessageBus&)
 21[Hello World InOutput Two <HelloWorld>] : PrepareTaskMessageBus(const Task& task, MessageBus&)
 22[Hello World Step One <HelloWorld>] : PrepareTaskMessageBus(const Task& task, MessageBus&)
 23[Hello World Step Two <HelloWorld>] : PrepareTaskMessageBus(const Task& task, MessageBus&)
 24[Hello World InOutput One <HelloWorld>] : CheckTaskMessageBusPrepared(const Task& task, const MessageBus&)
 25[Hello World InOutput Two <HelloWorld>] : CheckTaskMessageBusPrepared(const Task& task, const MessageBus&)
 26[Hello World Step One <HelloWorld>] : CheckTaskMessageBusPrepared(const Task& task, const MessageBus&)
 27[Hello World Step Two <HelloWorld>] : CheckTaskMessageBusPrepared(const Task& task, const MessageBus&)
 28[Hello World InOutput One <HelloWorld>] : CheckTaskMessageBusPrepared(const Task& task, const MessageBus&)
 29[Hello World InOutput Two <HelloWorld>] : CheckTaskMessageBusPrepared(const Task& task, const MessageBus&)
 30[Hello World Step One <HelloWorld>] : CheckTaskMessageBusPrepared(const Task& task, const MessageBus&)
 31[Hello World Step Two <HelloWorld>] : CheckTaskMessageBusPrepared(const Task& task, const MessageBus&)
 32[Hello World InOutput One <HelloWorld>] : CheckTaskMessageBusPrepared(const Task& task, const MessageBus&)
 33[Hello World InOutput Two <HelloWorld>] : CheckTaskMessageBusPrepared(const Task& task, const MessageBus&)
 34[Hello World Step One <HelloWorld>] : CheckTaskMessageBusPrepared(const Task& task, const MessageBus&)
 35[Hello World Step Two <HelloWorld>] : CheckTaskMessageBusPrepared(const Task& task, const MessageBus&)
 36[Hello World Step One <HelloWorld>] : Prepare(Task&)
 37[Hello World Step Two <HelloWorld>] : Prepare(Task&)
 38[Hello World InOutput One <HelloWorld>] : Prepare()
 39[Hello World InOutput Two <HelloWorld>] : Prepare()
 40[Pipeline <Pipeline>] : Prepared pipeline. Safety status is SAFE.
 41[Main <main>] : The next sample is a MainTick! Both Tick and MainTick should be called.
 42[Main <main>] : ==== Start sample 0 ====
 43[Pipeline <Pipeline>] : Main state changed.
 44State machine state: BOOTING
 45          Hello World InOutput One     BOOTING        NONE
 46          Hello World InOutput Two     BOOTING        NONE
 47              Hello World Step One     BOOTING        NONE
 48              Hello World Step Two     BOOTING        NONE
 49
 50[Hello World InOutput One <HelloWorld>] : Tick()
 51[Hello World InOutput Two <HelloWorld>] : Tick()
 52[Hello World InOutput One <HelloWorld>] : MainTick()
 53[Hello World InOutput Two <HelloWorld>] : MainTick()
 54[Hello World Step One <HelloWorld>] : MainTick(DataBucket&)
 55[Hello World Step Two <HelloWorld>] : MainTick(DataBucket&)
 56[Hello World InOutput One <HelloWorld>] : TaskCompleted()
 57[Hello World InOutput Two <HelloWorld>] : TaskCompleted()
 58[Main <main>] : ==== End sample 0 ====
 59[Main <main>] : The next sample is a Tick! Only Tick should be called.
 60[Main <main>] : ==== Start sample 1 ====
 61[Hello World InOutput One <HelloWorld>] : Tick()
 62[Hello World InOutput Two <HelloWorld>] : Tick()
 63[Main <main>] : ==== End sample 1 ====
 64[Main <main>] : The next sample is a Tick! Only Tick should be called.
 65[Main <main>] : ==== Start sample 2 ====
 66[Hello World InOutput One <HelloWorld>] : Tick()
 67[Hello World InOutput Two <HelloWorld>] : Tick()
 68[Main <main>] : ==== End sample 2 ====
 69[Main <main>] : The next sample is a MainTick! Both Tick and MainTick should be called.
 70[Main <main>] : ==== Start sample 3 ====
 71[Pipeline <Pipeline>] : Client state(s) changed.
 72State machine state: BOOTING
 73          Hello World InOutput One     BOOTING      BOOTED
 74          Hello World InOutput Two     BOOTING      BOOTED
 75              Hello World Step One     BOOTING      BOOTED
 76              Hello World Step Two     BOOTING      BOOTED
 77
 78[Pipeline <Pipeline>] : Main state changed.
 79State machine state: IDLE
 80          Hello World InOutput One        IDLE        NONE
 81          Hello World InOutput Two        IDLE        NONE
 82              Hello World Step One        IDLE        NONE
 83              Hello World Step Two        IDLE        NONE
 84
 85[Hello World InOutput One <HelloWorld>] : Tick()
 86[Hello World InOutput Two <HelloWorld>] : Tick()
 87[Hello World InOutput One <HelloWorld>] : MainTick()
 88[Hello World InOutput Two <HelloWorld>] : MainTick()
 89[Hello World Step One <HelloWorld>] : MainTick(DataBucket&)
 90[Hello World Step Two <HelloWorld>] : MainTick(DataBucket&)
 91[Hello World InOutput One <HelloWorld>] : TaskCompleted()
 92[Hello World InOutput Two <HelloWorld>] : TaskCompleted()
 93[Main <main>] : ==== End sample 3 ====
 94[Main <main>] : The next sample is a Tick! Only Tick should be called.
 95[Main <main>] : ==== Start sample 4 ====
 96[Hello World InOutput One <HelloWorld>] : Tick()
 97[Hello World InOutput Two <HelloWorld>] : Tick()
 98[Main <main>] : ==== End sample 4 ====
 99[Main <main>] : The next sample is a Tick! Only Tick should be called.
100[Main <main>] : ==== Start sample 5 ====
101[Hello World InOutput One <HelloWorld>] : Tick()
102[Hello World InOutput Two <HelloWorld>] : Tick()
103[Main <main>] : ==== End sample 5 ====
104[Main <main>] : The next sample is a MainTick! Both Tick and MainTick should be called.
105[Main <main>] : ==== Start sample 6 ====
106[Hello World InOutput One <HelloWorld>] : Tick()
107[Hello World InOutput Two <HelloWorld>] : Tick()
108[Hello World InOutput One <HelloWorld>] : MainTick()
109[Hello World InOutput Two <HelloWorld>] : MainTick()
110[Hello World Step One <HelloWorld>] : MainTick(DataBucket&)
111[Hello World Step Two <HelloWorld>] : MainTick(DataBucket&)
112[Hello World InOutput One <HelloWorld>] : TaskCompleted()
113[Hello World InOutput Two <HelloWorld>] : TaskCompleted()
114[Main <main>] : ==== End sample 6 ====
115[Pipeline <Pipeline>] : Time measurement results for InOutput tick calls:
116    tick:Hello World InOutput One [us]  min: 
117    tick:Hello World InOutput Two [us]  min: 
118[Pipeline <Pipeline>] : Time measurement results for InOutput MainTick calls:
119    MainTick:Hello World InOutput One [us]  min: 
120    MainTick:Hello World InOutput Two [us]  min: 
121[Pipeline <Pipeline>] : Time measurement results for InOutput taskCompleted calls:
122    taskCompleted:Hello World InOutput One [us]  min: 
123    taskCompleted:Hello World InOutput Two [us]  min: 
124[Task <Task>] : Time measurement information for task Task:
125    Task:MainTick:Hello World Step One [ms]  min: 
126    Task:MainTick:Hello World Step Two [ms]  min: 
127[Hello World Step One <HelloWorld>] : Destructor
128[Hello World Step Two <HelloWorld>] : Destructor
129[Hello World InOutput One <HelloWorld>] : ~HelloWorld()
130[Hello World InOutput Two <HelloWorld>] : ~HelloWorld()

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

Run this example, by running ./demo_hello_pipeline --run_example3. The expected output is as follows:

  1[Main <main>] : <<<<< Example 3 >>>>>
  2[Task <Task>] : This Task will tick once every 3 base ticks.
  3[Task <Task>] : The total horizon length of this Task is 150 ms and has 50 steps.
  4[Pipeline <Pipeline>] : Prepared pipeline. Safety status is SAFE.
  5[Main <main>] : ==== Start sample 0 ====
  6[Pipeline <Pipeline>] : Main state changed.
  7State machine state: BOOTING
  8          Hello World InOutput One     BOOTING        NONE
  9          Hello World InOutput Two     BOOTING        NONE
 10                Go To Run InOutput     BOOTING        NONE
 11                  Delayed Follower     BOOTING        NONE
 12              Hello World Step One     BOOTING        NONE
 13              Hello World Step Two     BOOTING        NONE
 14
 15[Main <main>] : ==== End sample 0 ====
 16[Main <main>] : ==== Start sample 1 ====
 17[Main <main>] : ==== End sample 1 ====
 18[Main <main>] : ==== Start sample 2 ====
 19[Main <main>] : ==== End sample 2 ====
 20[Main <main>] : ==== Start sample 3 ====
 21[Pipeline <Pipeline>] : Client state(s) changed.
 22State machine state: BOOTING
 23          Hello World InOutput One     BOOTING      BOOTED
 24          Hello World InOutput Two     BOOTING      BOOTED
 25                Go To Run InOutput     BOOTING      BOOTED
 26                  Delayed Follower     BOOTING      BOOTED
 27              Hello World Step One     BOOTING      BOOTED
 28              Hello World Step Two     BOOTING      BOOTED
 29
 30[Pipeline <Pipeline>] : Main state changed.
 31State machine state: IDLE
 32          Hello World InOutput One        IDLE        NONE
 33          Hello World InOutput Two        IDLE        NONE
 34                Go To Run InOutput        IDLE        NONE
 35                  Delayed Follower        IDLE        NONE
 36              Hello World Step One        IDLE        NONE
 37              Hello World Step Two        IDLE        NONE
 38
 39[Main <main>] : ==== End sample 3 ====
 40[Main <main>] : ==== Start sample 4 ====
 41[Main <main>] : ==== End sample 4 ====
 42[Main <main>] : ==== Start sample 5 ====
 43[Main <main>] : ==== End sample 5 ====
 44[Main <main>] : ==== Start sample 6 ====
 45[Pipeline <Pipeline>] : Client state(s) changed.
 46State machine state: IDLE
 47          Hello World InOutput One        IDLE        NONE
 48          Hello World InOutput Two        IDLE        NONE
 49                Go To Run InOutput        IDLE   PREPARING
 50                  Delayed Follower        IDLE        NONE
 51              Hello World Step One        IDLE        NONE
 52              Hello World Step Two        IDLE        NONE
 53
 54[Pipeline <Pipeline>] : Main state changed.
 55State machine state: PREPARING
 56          Hello World InOutput One   PREPARING        NONE
 57          Hello World InOutput Two   PREPARING        NONE
 58                Go To Run InOutput   PREPARING        NONE
 59                  Delayed Follower   PREPARING        NONE
 60              Hello World Step One   PREPARING        NONE
 61              Hello World Step Two   PREPARING        NONE
 62
 63[Main <main>] : ==== End sample 6 ====
 64[Main <main>] : ==== Start sample 7 ====
 65[Main <main>] : ==== End sample 7 ====
 66[Main <main>] : ==== Start sample 8 ====
 67[Main <main>] : ==== End sample 8 ====
 68[Main <main>] : ==== Start sample 9 ====
 69[Pipeline <Pipeline>] : Client state(s) changed.
 70State machine state: PREPARING
 71          Hello World InOutput One   PREPARING    PREPARED
 72          Hello World InOutput Two   PREPARING    PREPARED
 73                Go To Run InOutput   PREPARING    PREPARED
 74                  Delayed Follower   PREPARING    PREPARED
 75              Hello World Step One   PREPARING    PREPARED
 76              Hello World Step Two   PREPARING    PREPARED
 77
 78[Pipeline <Pipeline>] : Main state changed.
 79State machine state: READY
 80          Hello World InOutput One       READY        NONE
 81          Hello World InOutput Two       READY        NONE
 82                Go To Run InOutput       READY        NONE
 83                  Delayed Follower       READY        NONE
 84              Hello World Step One       READY        NONE
 85              Hello World Step Two       READY        NONE
 86
 87[Main <main>] : ==== End sample 9 ====
 88[Main <main>] : ==== Start sample 10 ====
 89[Main <main>] : ==== End sample 10 ====
 90[Main <main>] : ==== Start sample 11 ====
 91[Main <main>] : ==== End sample 11 ====
 92[Main <main>] : ==== Start sample 12 ====
 93[Pipeline <Pipeline>] : Client state(s) changed.
 94State machine state: READY
 95          Hello World InOutput One       READY        NONE
 96          Hello World InOutput Two       READY        NONE
 97                Go To Run InOutput       READY    STARTING
 98                  Delayed Follower       READY        NONE
 99              Hello World Step One       READY        NONE
100              Hello World Step Two       READY        NONE
101
102[Pipeline <Pipeline>] : Main state changed.
103State machine state: STARTING
104          Hello World InOutput One    STARTING        NONE
105          Hello World InOutput Two    STARTING        NONE
106                Go To Run InOutput    STARTING        NONE
107                  Delayed Follower    STARTING        NONE
108              Hello World Step One    STARTING        NONE
109              Hello World Step Two    STARTING        NONE
110
111[Main <main>] : ==== End sample 12 ====
112[Main <main>] : ==== Start sample 13 ====
113[Main <main>] : ==== End sample 13 ====
114[Main <main>] : ==== Start sample 14 ====
115[Main <main>] : ==== End sample 14 ====
116[Main <main>] : ==== Start sample 15 ====
117[Pipeline <Pipeline>] : Client state(s) changed.
118State machine state: STARTING
119          Hello World InOutput One    STARTING     STARTED
120          Hello World InOutput Two    STARTING     STARTED
121                Go To Run InOutput    STARTING     STARTED
122                  Delayed Follower    STARTING     STARTED
123              Hello World Step One    STARTING     STARTED
124              Hello World Step Two    STARTING     STARTED
125
126[Pipeline <Pipeline>] : Main state changed.
127State machine state: RUN
128          Hello World InOutput One         RUN        NONE
129          Hello World InOutput Two         RUN        NONE
130                Go To Run InOutput         RUN        NONE
131                  Delayed Follower         RUN        NONE
132              Hello World Step One         RUN        NONE
133              Hello World Step Two         RUN        NONE
134
135[Main <main>] : ==== End sample 15 ====
136[Main <main>] : ==== Start sample 16 ====
137[Main <main>] : ==== End sample 16 ====
138[Main <main>] : ==== Start sample 17 ====
139[Main <main>] : ==== End sample 17 ====
140[Main <main>] : ==== Start sample 18 ====
141[Main <main>] : ==== End sample 18 ====
142[Main <main>] : ==== Start sample 19 ====
143[Main <main>] : ==== End sample 19 ====
144[Main <main>] : ==== Start sample 20 ====
145[Main <main>] : ==== End sample 20 ====
146[Main <main>] : ==== Start sample 21 ====
147[Pipeline <Pipeline>] : Client state(s) changed.
148State machine state: RUN
149          Hello World InOutput One         RUN        NONE
150          Hello World InOutput Two         RUN        NONE
151                Go To Run InOutput         RUN    STOPPING
152                  Delayed Follower         RUN        NONE
153              Hello World Step One         RUN        NONE
154              Hello World Step Two         RUN        NONE
155
156[Pipeline <Pipeline>] : Main state changed.
157State machine state: STOPPING
158          Hello World InOutput One    STOPPING        NONE
159          Hello World InOutput Two    STOPPING        NONE
160                Go To Run InOutput    STOPPING        NONE
161                  Delayed Follower    STOPPING        NONE
162              Hello World Step One    STOPPING        NONE
163              Hello World Step Two    STOPPING        NONE
164
165[Main <main>] : ==== End sample 21 ====
166[Main <main>] : ==== Start sample 22 ====
167[Main <main>] : ==== End sample 22 ====
168[Main <main>] : ==== Start sample 23 ====
169[Main <main>] : ==== End sample 23 ====
170[Main <main>] : ==== Start sample 24 ====
171[Pipeline <Pipeline>] : Client state(s) changed.
172State machine state: STOPPING
173          Hello World InOutput One    STOPPING     STOPPED
174          Hello World InOutput Two    STOPPING     STOPPED
175                Go To Run InOutput    STOPPING     STOPPED
176                  Delayed Follower    STOPPING     STOPPED
177              Hello World Step One    STOPPING     STOPPED
178              Hello World Step Two    STOPPING     STOPPED
179
180[Pipeline <Pipeline>] : Main state changed.
181State machine state: IDLE
182          Hello World InOutput One        IDLE        NONE
183          Hello World InOutput Two        IDLE        NONE
184                Go To Run InOutput        IDLE        NONE
185                  Delayed Follower        IDLE        NONE
186              Hello World Step One        IDLE        NONE
187              Hello World Step Two        IDLE        NONE
188
189[Main <main>] : ==== End sample 24 ====
190[Pipeline <Pipeline>] : Time measurement results for InOutput tick calls:
191    tick:Hello World InOutput One [us]  min: 
192    tick:Hello World InOutput Two [us]  min: 
193    tick:Go To Run InOutput [us]  min: 
194    tick:Delayed Follower [us]  min: 
195[Pipeline <Pipeline>] : Time measurement results for InOutput MainTick calls:
196    MainTick:Hello World InOutput One [us]  min: 
197    MainTick:Hello World InOutput Two [us]  min: 
198    MainTick:Go To Run InOutput [us]  min: 
199    MainTick:Delayed Follower [us]  min: 
200[Pipeline <Pipeline>] : Time measurement results for InOutput taskCompleted calls:
201    taskCompleted:Hello World InOutput One [us]  min: 
202    taskCompleted:Hello World InOutput Two [us]  min: 
203    taskCompleted:Go To Run InOutput [us]  min: 
204    taskCompleted:Delayed Follower [us]  min: 
205[Task <Task>] : Time measurement information for task Task:
206    Task:MainTick:Hello World Step One [ms]  min: 
207    Task:MainTick:Hello World Step Two [ms]  min: 

Observe that:

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