Primary Pipeline example

This example shows how to use the Pipeline class for the robot’s primary interface. It reads all packages coming in from the robot’t primary interface and prints their contents.

At the current time parsing primary interface data is very limited, so this example will print the raw binary data for most package types. The example serves to demonstrate the basic control flow used for reading data from the robot.

In this library, a “pipeline” uses a producer / consumer architecture. A producer is reading data from a stream, parses that data and puts it into a queue. A consumer reads data from the queue and can do whatever its purpose is.

Producer setup

To setup the producer, we need to create a stream, a parser and create a producer with those:

Listing 20 examples/primary_pipeline.cpp
58  // First of all, we need a stream that connects to the robot's primary interface
59  comm::URStream<primary_interface::PrimaryPackage> primary_stream(robot_ip, urcl::primary_interface::UR_PRIMARY_PORT);
60
61  // This will parse the primary packages
62  primary_interface::PrimaryParser parser;
63
64  // The producer needs both, the stream and the parser to fully work
65  comm::URProducer<primary_interface::PrimaryPackage> prod(primary_stream, parser);
66
67  // Connect to the stream
68  prod.setupProducer();

Consumer setup

The consumer can be any consumer that is able to consume data produced by the producer, in this case urcl::primary_interface::PrimaryPackage. Here, we use a ShellExecutor that will try to print each package’s content to the shell output:

Listing 21 examples/primary_pipeline.cpp
70  // The shell consumer will print the package contents to the shell
71  auto consumer = std::make_unique<comm::ShellConsumer<primary_interface::PrimaryPackage>>();

Assemble the pipeline

Finally, we need to assemble the pipeline by connecting the producer to the consumer:

Listing 22 examples/primary_pipeline.cpp
72  // The notifer will be called at some points during connection setup / loss. This isn't fully
73  // implemented atm.
74  comm::INotifier notifier;
75
76  // Now that we have all components, we can create and start the pipeline to run it all.
77  comm::Pipeline<primary_interface::PrimaryPackage> pipeline(prod, consumer.get(), "Pipeline", notifier);
78  pipeline.run();

You can setup a custom notifier that can handle start and stop events of the pipeline. In this example we use the basic INotifier which doesn’t do anything.

With all that, we can create the pipeline by passing the producer, consumer, a name and the notifier to it’s constructor.

From this point on, the producer will read the data coming on from the stream and that data will be processed by the consumer. We keep the example program alive for a while to see some data:

Listing 23 examples/primary_pipeline.cpp
83  do
84  {
85    std::this_thread::sleep_for(std::chrono::seconds(second_to_run));
86  } while (second_to_run < 0);
87  return 0;