Primary Pipeline Calibration example

This example is very similar to the Primary Pipeline example. However, it uses a specialized consumer that will analyze the calibration data sent from the robot instead of the ShellConsumer.

Consumer setup

This example uses a specialized type of consumer that stores data about the received robot calibration.

Listing 27 examples/primary_pipeline_calibration.cpp
26class CalibrationConsumer : public urcl::comm::IConsumer<urcl::primary_interface::PrimaryPackage>
27{
28public:
29  CalibrationConsumer() : calibrated_(0), have_received_data_(false)
30  {
31  }
32  virtual ~CalibrationConsumer() = default;
33
34  // This will consume any primary package
35  virtual bool consume(std::shared_ptr<urcl::primary_interface::PrimaryPackage> product)
36  {
37    // Try to cast the product to a KinematicsInfo package. If that succeeds, we handle the
38    // calibration information.
39    auto kin_info = std::dynamic_pointer_cast<urcl::primary_interface::KinematicsInfo>(product);
40    if (kin_info != nullptr)
41    {
42      URCL_LOG_INFO("%s", product->toString().c_str());
43      calibrated_ = kin_info->calibration_status_;
44      have_received_data_ = true;
45    }
46    return true;
47  }
48
49  bool isCalibrated() const
50  {
51    const uint32_t linearized = 2;
52    return calibrated_ == linearized;
53  }
54
55  bool calibrationStatusReceived()
56  {
57    return have_received_data_;
58  }
59
60private:
61  uint32_t calibrated_;
62  bool have_received_data_;
63};

Since the producer is reading every package from the primary interface, the consumer has to be able to consume any primary package.

Assemble the pipeline

The rest of the pipeline setup is the same as in the other pipeline example, just that we create a CalibrationConsumer instead of a ShellConsumer:

Listing 28 examples/primary_pipeline_calibration.cpp
 91  // The calibration consumer will print the package contents to the shell
 92  CalibrationConsumer calib_consumer;
 93
 94  // The notifer will be called at some points during connection setup / loss. This isn't fully
 95  // implemented atm.
 96  comm::INotifier notifier;
 97
 98  // Now that we have all components, we can create and start the pipeline to run it all.
 99  comm::Pipeline<primary_interface::PrimaryPackage> calib_pipeline(prod, &calib_consumer, "Pipeline", notifier);
100  calib_pipeline.run();

Again, product handling will be happening in the background, so in the rest of the program we wait until the calibration consumer received and processed data and then print information about that:

Listing 29 examples/primary_pipeline_calibration.cpp
104  while (!calib_consumer.calibrationStatusReceived())
105  {
106    std::this_thread::sleep_for(std::chrono::seconds(1));
107  }
108
109  if (calib_consumer.isCalibrated())
110  {
111    printf("The robot on IP: %s is calibrated.\n", robot_ip.c_str());
112  }
113  else
114  {
115    printf("The robot controller on IP: %s does not have a valid calibration.\n", robot_ip.c_str());
116    printf("Remeber to turn on the robot to get calibration stored on the robot!\n");
117  }
118
119  return 0;