# 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. ```cpp #include #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 { public: bool Init() override; bool Proc(const std::shared_ptr& msg0, const std::shared_ptr& msg1) override; }; CYBER_REGISTER_COMPONENT(CommonComponentSample) ``` ### Source File Implement both the `Init` and `Proc` functions in `common_component_example.cc`: ```cpp #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& msg0, const std::shared_ptr& msg1) { AINFO << "Start common component Proc [" << msg0->msg_id() << "] [" << msg1->msg_id() << "]"; return true; } ``` ### BUILD file ```python 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 ```protobuf # 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 ```xml common /apollo/cyber/examples/common_component_example/common.dag common ``` ## Launch the component ### Build Build the sample component by running the command below: ```bash cd /apollo bash apollo.sh build ``` ### Environment setup Then configure the environment: ```bash 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) ```bash cyber_launch start cyber/examples/common_component_example/common.launch ``` - Launch with the DAG file ```bash mainboard -d cyber/examples/common_component_example/common.dag ``` ### _Feed_ channel data for the component to process Open another terminal: ```bash 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: ```bash 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] ```