How to Create and Run a new Component in Cyber RT

Apollo Cyber RT framework is built upon the concept of components. As the building block of Cyber RT, each component is a specific algorithm module which processes a set of inputs and generates its set of outputs.

To successfully create and launch a new component, there are basically 4 steps:

  • Set up directory layout

  • Implement the component class

  • Configuration setup

  • Launch the component

The example below demonstrates how to create, build and run a simple component named CommonComponentExample. To explore more about Cyber RT, you can find a couple of examples showing different functionalities of Cyber RT under the cyber/examples directory.

Note: The examples need to run after successfully built within Apollo Docker container.

Set up directry layout

Take the sample component under cyber/examples/common_component_example for example:

  • Header file: common_component_example.h

  • Source file: common_component_example.cc

  • BUILD file: BUILD

  • DAG file: common.dag

  • Launch file: common.launch

Implement the sample component class

Header file

In the header file (common_component_example.h) for the sample component:

  • Inherit the Component base class

  • Define your own Init and Proc functions. Please note that for proc, input data types need to be specified also.

  • Register the sample component class to be globally visible using the CYBER_REGISTER_COMPONENT macro.

#include <memory>

#include "cyber/component/component.h"
#include "cyber/examples/proto/examples.pb.h"

using apollo::cyber::Component;
using apollo::cyber::ComponentBase;
using apollo::cyber::examples::proto::Driver;

class CommonComponentSample : public Component<Driver, Driver> {
 public:
  bool Init() override;
  bool Proc(const std::shared_ptr<Driver>& msg0,
            const std::shared_ptr<Driver>& msg1) override;
};
CYBER_REGISTER_COMPONENT(CommonComponentSample)

Source File

Implement both the Init and Proc functions in common_component_example.cc:

#include "cyber/examples/common_component_example/common_component_example.h"

bool CommonComponentSample::Init() {
  AINFO << "Commontest component init";
  return true;
}

bool CommonComponentSample::Proc(const std::shared_ptr<Driver>& msg0,
                                 const std::shared_ptr<Driver>& msg1) {
  AINFO << "Start common component Proc [" << msg0->msg_id() << "] ["
        << msg1->msg_id() << "]";
  return true;
}

BUILD file

load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
load("//tools:cpplint.bzl", "cpplint")

package(default_visibility = ["//visibility:public"])

cc_binary(
    name = "libcommon_component_example.so",
    linkshared = True,
    linkstatic = False,
    deps = [":common_component_example_lib"],
)

cc_library(
    name = "common_component_example_lib",
    srcs = ["common_component_example.cc"],
    hdrs = ["common_component_example.h"],
    visibility = ["//visibility:private"],
    deps = [
        "//cyber",
        "//cyber/examples/proto:examples_cc_proto",
    ],
)

cpplint()

Configuration setup

DAG file

To configure the DAG file (common.dag here), specify the following items:

  • Channel names: for data input and output

  • Library path: library built from component class

  • Class name: the class name of the component

# Define all components in DAG streaming.
module_config {
module_library : "/apollo/bazel-bin/cyber/examples/common_component_example/libcommon_component_example.so"
components {
    class_name : "CommonComponentSample"
    config {
        name : "common"
        readers {
            channel: "/apollo/prediction"
        }
        readers {
            channel: "/apollo/test"
        }
    }
  }
}

Launch file

To configure the launch (common.launch) file, specify the following items:

  • The name of the component

  • The DAG file created in the previous step

  • The name of the process to run the component

<cyber>
    <component>
        <name>common</name>
        <dag_conf>/apollo/cyber/examples/common_component_example/common.dag</dag_conf>
        <process_name>common</process_name>
    </component>
</cyber>

Launch the component

Build

Build the sample component by running the command below:

cd /apollo
bash apollo.sh build

Environment setup

Then configure the environment:

source cyber/setup.bash

# To see output from terminal
export GLOG_alsologtostderr=1

Launch the component

You can choose either of the two ways to launch the newly built component:

  • Launch with the launch file (recommended)

cyber_launch start cyber/examples/common_component_example/common.launch
  • Launch with the DAG file

mainboard -d cyber/examples/common_component_example/common.dag

Feed channel data for the component to process

Open another terminal:

source cyber/setup.bash
export GLOG_alsologtostderr=1
/apollo/bazel-bin/cyber/examples/common_component_example/channel_test_writer

Open the 3rd terminal and run:

source cyber/setup.bash
export GLOG_alsologtostderr=1
/apollo/bazel-bin/cyber/examples/common_component_example/channel_prediction_writer

And you should see output from terminal #1 like the following:

I0331 16:49:34.736016 1774773 common_component_example.cc:25] [mainboard]Start common component Proc [1094] [766]
I0331 16:49:35.069005 1774775 common_component_example.cc:25] [mainboard]Start common component Proc [1095] [767]
I0331 16:49:35.402289 1774783 common_component_example.cc:25] [mainboard]Start common component Proc [1096] [768]