目录:apollo/docs/cyber/CyberRT_API_for_Developers.md
This document provides an extensive technical deep dive into how to create, manipulate and use Cyber RT’s API.
The first part of demonstrating CyberRT API is to understand the Talker/Listener example. Following are three essential concepts: node (basic unit), reader(facility to read message) and writer(facility to write message) of the example.
总结起来一共需要三个主要步骤:
-创建一个node
-创建一个writer
-创建一个reader
In the Cyber RT framework, the node is the most fundamental unit, similar to the role of a handle
. When creating a specific functional object (writer, reader, etc.), you need to create it based on an existing node instance.
The node creation interface is as follows:
std::unique_ptr<Node> apollo::cyber::CreateNode(const std::string& node_name, const std::string& name_space = "");
Parameters:
name_space is empty by default. It is the name of the space concatenated with node_name. The format is(格式)
/namespace/node_name
Return value - An exclusive smart pointer to Node
Error Conditions - when cyber::Init()
has not called, the system is in an uninitialized state, unable to create a node, return nullptr
The writer is the basic facility used in Cyber RT to send messages. Every writer corresponds to a channel with a specific data type.
The writer is created by the CreateWriter
interface in the node class. The interfaces are listed as below:
template <typename MessageT>
auto CreateWriter(const std::string& channel_name)
-> std::shared_ptr<Writer<MessageT>>;//指函数返回值
template <typename MessageT>
auto CreateWriter(const proto::RoleAttributes& role_attr)
-> std::shared_ptr<Writer<MessageT>>;
The reader is the basic facility used in cyber to receive messages. Reader has to be bound to a callback function when it is created. When a new message arrives in the channel, the callback will be called. (LIKE ROS.)
The reader is created by the CreateReader
interface of the node class. The interfaces are listed as below:
template <typename MessageT>
auto CreateReader(const std::string& channel_name, const std::function<void(const std::shared_ptr<MessageT>&)>& reader_func)
-> std::shared_ptr<Reader<MessageT>>;
template <typename MessageT>
auto CreateReader(const ReaderConfig& config,
const CallbackFunc<MessageT>& reader_func = nullptr)
-> std::shared_ptr<cyber::Reader<MessageT>>;
template <typename MessageT>
auto CreateReader(const proto::RoleAttributes& role_attr,
const CallbackFunc<MessageT>& reader_func = nullptr)
-> std::shared_ptr<cyber::Reader<MessageT>>;
#include "cyber/cyber.h"
#include "cyber/proto/chatter.pb.h"
#include "cyber/time/rate.h"
#include "cyber/time/time.h"
using apollo::cyber::Rate;
using apollo::cyber::Time;
using apollo::cyber::proto::Chatter;
int main(int argc, char *argv[]) {
// init cyber framework
apollo::cyber::Init(argv[0]);
// create talker node
std::shared_ptr<apollo::cyber::Node> talker_node(
apollo::cyber::CreateNode("talker"));
// create talker
auto talker = talker_node->CreateWriter<Chatter>("channel/chatter");
Rate rate(1.0);
while (apollo::cyber::OK()) {
static uint64_t seq = 0;
auto msg = std::make_shared<apollo::cyber::proto::Chatter>();
msg->set_timestamp(Time::Now().ToNanosecond());
msg->set_lidar_timestamp(Time::Now().ToNanosecond());
msg->set_seq(seq++);
msg->set_content("Hello, apollo!");
talker->Write(msg);
AINFO << "talker sent a message!";
rate.Sleep();
}
return 0;
}
#include "cyber/cyber.h"
#include "cyber/proto/chatter.pb.h"
void MessageCallback(
const std::shared_ptr<apollo::cyber::proto::Chatter>& msg) {
AINFO << "Received message seq-> " << msg->seq();
AINFO << "msgcontent->" << msg->content();
}
int main(int argc, char *argv[]) {
// init cyber framework
apollo::cyber::Init(argv[0]);
// create listener node
auto listener_node = apollo::cyber::CreateNode("listener");
// create listener
auto listener =
listener_node->CreateReader<apollo::cyber::proto::Chatter>(
"channel/chatter", MessageCallback);
apollo::cyber::WaitForShutdown();
return 0;
}
cc_binary(
name = "talker",
srcs = [ "talker.cc", ],
deps = [
"//cyber",
"//cyber/examples/proto:examples_cc_proto",
],
)
cc_binary(
name = "listener",
srcs = [ "listener.cc", ],
deps = [
"//cyber",
"//cyber/examples/proto:examples_cc_proto",
],
)
In an autonomous driving system, there are many scenarios that require more from module communication than just sending or receiving messages. Service is another way of communication between nodes. Unlike channel, service implements two-way
communication, e.g. a node obtains a response by sending a request. This section introduces the service
module in Cyber RT API with examples.
Problem: create a client-server model that pass Driver.proto back and forth.
When a request is sent in by the client, the server parses/processes the request and returns the response.
client发送请求,server接受请求并做出回应返回给client。
The implementation of the demo mainly includes the following steps.
All messages in cyber are in the protobuf
format. 所有的cyber中的数据均以protobuf的形式存在
Any protobuf message with serialize/deserialize interfaces can be used as the service request and response message. Driver
in examples.proto is used as service request and response in this example:
// filename: examples.proto
syntax = "proto2";
package apollo.cyber.examples.proto;
message Driver {
optional string content = 1;
optional uint64 msg_id = 2;
optional uint64 timestamp = 3;
};
// filename: cyber/examples/service.cc
#include "cyber/cyber.h"
#include "cyber/examples/proto/examples.pb.h"
using apollo::cyber::examples::proto::Driver;
int main(int argc, char* argv[]) {
apollo::cyber::Init(argv[0]);
std::shared_ptr<apollo::cyber::Node> node(
apollo::cyber::CreateNode("start_node"));
auto server = node->CreateService<Driver, Driver>(
"test_server", [](const std::shared_ptr<Driver>& request,
std::shared_ptr<Driver>& response) {
AINFO << "server: I am driver server";
static uint64_t id = 0;
++id;
response->set_msg_id(id);
response->set_timestamp(0);
});
auto client = node->CreateClient<Driver, Driver>("test_server");
auto driver_msg = std::make_shared<Driver>();
driver_msg->set_msg_id(0);
driver_msg->set_timestamp(0);
while (apollo::cyber::OK()) {
auto res = client->SendRequest(driver_msg);
if (res != nullptr) {
AINFO << "client: response: " << res->ShortDebugString();
} else {
AINFO << "client: service may not ready.";
}
sleep(1);
}
apollo::cyber::WaitForShutdown();
return 0;
}
cc_binary(
name = "service",
srcs = [ "service.cc", ],
deps = [
"//cyber",
"//cyber/examples/proto:examples_cc_proto",
],
)
I1124 16:36:44.568845 14965 service.cc:30] [service] server: i am driver server
I1124 16:36:44.569031 14949 service.cc:43] [service] client: response: msg_id: 1 timestamp: 0
I1124 16:36:45.569514 14966 service.cc:30] [service] server: i am driver server
I1124 16:36:45.569932 14949 service.cc:43] [service] client: response: msg_id: 2 timestamp: 0
I1124 16:36:46.570627 14967 service.cc:30] [service] server: i am driver server
I1124 16:36:46.571024 14949 service.cc:43] [service] client: response: msg_id: 3 timestamp: 0
I1124 16:36:47.571566 14968 service.cc:30] [service] server: i am driver server
I1124 16:36:47.571962 14949 service.cc:43] [service] client: response: msg_id: 4 timestamp: 0
I1124 16:36:48.572634 14969 service.cc:30] [service] server: i am driver server
I1124 16:36:48.573030 14949 service.cc:43] [service] client: response: msg_id: 5 timestamp: 0
The Parameter Service is used for shared data between nodes, and provides basic operations such as set
, get
, and list
. The Parameter Service is based on the Service
implementation and contains service and client.
The interface that the user uses to perform parameter related operations:
All parameters passed through cyber are apollo::cyber::Parameter
objects, the table below lists the 5 supported parameter types.
Parameter type | C++ data type | protobuf data type |
---|---|---|
apollo::cyber::proto::ParamType::INT | int64_t | int64 |
apollo::cyber::proto::ParamType::DOUBLE | double | double |
apollo::cyber::proto::ParamType::BOOL | bool | bool |
apollo::cyber::proto::ParamType::STRING | std::string | string |
apollo::cyber::proto::ParamType::PROTOBUF | std::string | string |
apollo::cyber::proto::ParamType::NOT_SET | - | - |
Besides the 5 types above, Parameter also supports interface with protobuf object as incoming parameter. Post performing serialization processes the object and converts it to the STRING type for transfer.执行后序列化处理对象并将其转换为要传输的字符串类型。
Supported constructors:
支持的构造函数
Parameter(); // Name is empty, type is NOT_SET
explicit Parameter(const Parameter& parameter);
explicit Parameter(const std::string& name); // type为NOT_SET
Parameter(const std::string& name, const bool bool_value);
Parameter(const std::string& name, const int int_value);
Parameter(const std::string& name, const int64_t int_value);
Parameter(const std::string& name, const float double_value);
Parameter(const std::string& name, const double double_value);
Parameter(const std::string& name, const std::string& string_value);
Parameter(const std::string& name, const char* string_value);
Parameter(const std::string& name, const std::string& msg_str,
const std::string& full_name, const std::string& proto_desc);
Parameter(const std::string& name, const google::protobuf::Message& msg);
Sample code of using Parameter object:
Parameter a("int", 10);
Parameter b("bool", true);
Parameter c("double", 0.1);
Parameter d("string", "cyber");
Parameter e("string", std::string("cyber"));
// proto message Chatter
Chatter chatter;
Parameter f("chatter", chatter);
std::string msg_str("");
chatter.SerializeToString(&msg_str);
std::string msg_desc("");
ProtobufFactory::GetDescriptorString(chatter, &msg_desc);
Parameter g("chatter", msg_str, Chatter::descriptor()->full_name(), msg_desc);
Interface list:
inline ParamType type() const;
inline std::string TypeName() const;
inline std::string Descriptor() const;
inline const std::string Name() const;
inline bool AsBool() const;
inline int64_t AsInt64() const;
inline double AsDouble() const;
inline const std::string AsString() const;
std::string DebugString() const;
template <typename Type>
typename std::enable_if<std::is_base_of<google::protobuf::Message, Type>::value, Type>::type
value() const;
template <typename Type>
typename std::enable_if<std::is_integral<Type>::value && !std::is_same<Type, bool>::value, Type>::type
value() const;
template <typename Type>
typename std::enable_if<std::is_floating_point<Type>::value, Type>::type
value() const;
template <typename Type>
typename std::enable_if<std::is_convertible<Type, std::string>::value, const std::string&>::type
value() const;
template <typename Type>
typename std::enable_if<std::is_same<Type, bool>::value, bool>::type
value() const;
An example of how to use those interfaces:
Parameter a("int", 10);
a.Name(); // return int
a.Type(); // return apollo::cyber::proto::ParamType::INT
a.TypeName(); // return string: INT
a.DebugString(); // return string: {name: "int", type: "INT", value: 10}
int x = a.AsInt64(); // x = 10
x = a.value<int64_t>(); // x = 10
x = a.AsString(); // Undefined behavior, error log prompt
f.TypeName(); // return string: chatter
auto chatter = f.value<Chatter>();
If a node wants to provide a Parameter Service to other nodes, then you need to create a ParameterService
.
/**
* @brief Construct a new ParameterService object
*
* @param node shared_ptr of the node handler
*/
explicit ParameterService(const std::shared_ptr<Node>& node);
Since all parameters are stored in the parameter service object, the parameters can be manipulated directly in the ParameterService without sending a service request.
Setting parameters:
/**
* @brief Set the Parameter object
*
* @param parameter parameter to be set
*/
void SetParameter(const Parameter& parameter);
Getting parameters:
/**
* @brief Get the Parameter object
*
* @param param_name
* @param parameter the pointer to store
* @return true
* @return false call service fail or timeout
*/
bool GetParameter(const std::string& param_name, Parameter* parameter);
Getting the list of parameters:
/**
* @brief Get all the Parameter objects
*
* @param parameters pointer of vector to store all the parameters
* @return true
* @return false call service fail or timeout
*/
bool ListParameters(std::vector<Parameter>* parameters);
If a node wants to use parameter services of other nodes, you need to create a ParameterClient
.
/**
* @brief Construct a new ParameterClient object
*
* @param node shared_ptr of the node handler
* @param service_node_name node name which provide a param services
*/
ParameterClient(const std::shared_ptr<Node>& node, const std::string& service_node_name);
You could also perform SetParameter
, GetParameter
and ListParameters
mentioned under Parameter Service.
#include "cyber/cyber.h"
#include "cyber/parameter/parameter_client.h"
#include "cyber/parameter/parameter_server.h"
using apollo::cyber::Parameter;
using apollo::cyber::ParameterServer;
using apollo::cyber::ParameterClient;
int main(int argc, char** argv) {
apollo::cyber::Init(*argv);
std::shared_ptr<apollo::cyber::Node> node =
apollo::cyber::CreateNode("parameter");
auto param_server = std::make_shared<ParameterServer>(node);
auto param_client = std::make_shared<ParameterClient>(node, "parameter");
param_server->SetParameter(Parameter("int", 1));
Parameter parameter;
param_server->GetParameter("int", ¶meter);
AINFO << "int: " << parameter.AsInt64();
param_client->SetParameter(Parameter("string", "test"));
param_client->GetParameter("string", ¶meter);
AINFO << "string: " << parameter.AsString();
param_client->GetParameter("int", ¶meter);
AINFO << "int: " << parameter.AsInt64();
return 0;
}
The component is the base class that Cyber RT provides to build application modules. Each specific application module can inherit the Component class and define its own Init
and Proc
functions so that it can be loaded into the Cyber framework.
There are two options to use Cyber RT framework for applications:
Reader
and Writer
.The essential Component interface
Init()
function is like the main function that does some initialization of the algorithm.Proc()
function works like Reader’s callback function that is called by the framework when a message arrives.Advantages of using Component
An example dag file:
# Define all coms in DAG streaming.
module_config {
module_library : "lib/libperception_component.so"
components {
class_name : "PerceptionComponent"
config {
name : "perception"
readers {
channel: "perception/channel_name"
}
}
}
timer_components {
class_name : "DriverComponent"
config {
name : "driver"
interval : 100
}
}
}
setup.bash
)Header definition(common_component_example.h)
#include
#include "cyber/class_loader/class_loader.h"
#include "cyber/component/component.h"
#include "cyber/examples/proto/examples.pb.h"
using apollo::cyber::examples::proto::Driver;
using apollo::cyber::Component;
using apollo::cyber::ComponentBase;
class Commontestcomponent : 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(Commontestcomponent)
Cpp file implementation(common_component_example.cc)
#include "cyber/examples/common_component_smaple/common_component_example.h"
#include "cyber/class_loader/class_loader.h"
#include "cyber/component/component.h"
bool Commontestcomponent::Init() {
AINFO << "Commontest component init";
return true;
}
bool Commontestcomponent::Proc(const std::shared_ptr<Driver>& msg0,
const std::shared_ptr<Driver>& msg1) {
AINFO << "Start commontest component Proc [" << msg0->msg_id() << "] ["
<< msg1->msg_id() << "]";
return true;
}
Header definition(timer_component_example.h)
#include
#include "cyber/class_loader/class_loader.h"
#include "cyber/component/component.h"
#include "cyber/component/timer_component.h"
#include "cyber/examples/proto/examples.pb.h"
using apollo::cyber::examples::proto::Driver;
using apollo::cyber::Component;
using apollo::cyber::ComponentBase;
using apollo::cyber::TimerComponent;
using apollo::cyber::Writer;
class TimertestComponent : public TimerComponent {
public:
bool Init() override;
bool Proc() override;
private:
std::shared_ptr<Writer<Driver>> driver_writer_ = nullptr;
};
CYBER_REGISTER_COMPONENT(TimertestComponent)
Cpp file implementation(timer_component_example.cc)
#include "cyber/examples/timer_component_example/timer_component_example.h"
#include "cyber/class_loader/class_loader.h"
#include "cyber/component/component.h"
#include "cyber/examples/proto/examples.pb.h"
bool TimertestComponent::Init() {
driver_writer_ = node_->CreateWriter<Driver>("/carstatus/channel");
return true;
}
bool TimertestComponent::Proc() {
static int i = 0;
auto out_msg = std::make_shared<Driver>();
out_msg->set_msg_id(i++);
driver_writer_->Write(out_msg);
AINFO << "timertestcomponent: Write drivermsg->"
<< out_msg->ShortDebugString();
return true;
}
Use timertestcomponent as example:
CYBER_REGISTER_COMPONENT(DriverComponent)
If you use a namespace when registering, you also need to add a namespace when you define it in the dag file.
cyber_launch is the launcher of the Cyber RT framework. It starts multiple mainboards according to the launch file, and loads different components into different mainboards according to the dag file.
cyber_launch supports two scenarios for dynamically loading components or starting Binary programs in a child process.
<cyber>
<module>
<name>drivername>
<dag_conf>driver.dagdag_conf>
<process_name>process_name>
<exception_handler>exitexception_handler>
module>
<module>
<name>perceptionname>
<dag_conf>perception.dagdag_conf>
<process_name>process_name>
<exception_handler>respawnexception_handler>
module>
<module>
<name>planningname>
<dag_conf>planning.dagdag_conf>
<process_name>process_name>
module>
cyber>
Module:
Each loaded component or binary is a module
Timer can be used to create a timed task to run on a periodic basis, or to run only once
/**
* @brief Construct a new Timer object
*
* @param period The period of the timer, unit is ms
* @param callback The tasks that the timer needs to perform
* @param oneshot True: perform the callback only after the first timing cycle
* False: perform the callback every timed period
*/
Timer(uint32_t period, std::function<void()> callback, bool oneshot);
Or you could encapsulate the parameters into a timer option as follows:
struct TimerOption {
uint32_t period; // The period of the timer, unit is ms
std::function<void()> callback; // The tasks that the timer needs to perform
bool oneshot; // True: perform the callback only after the first timing cycle
// False: perform the callback every timed period
};
/**
* @brief Construct a new Timer object
*
* @param opt Timer option
*/
explicit Timer(TimerOption opt);
After creating a Timer instance, you must call Timer::Start()
to start the timer.
When you need to manually stop a timer that has already started, you can call the Timer::Stop()
interface.
#include
#include "cyber/cyber.h"
int main(int argc, char** argv) {
cyber::Init(argv[0]);
// Print current time every 100ms
cyber::Timer timer(100, [](){
std::cout << cyber::Time::Now() << std::endl;
}, false);
timer.Start()
sleep(1);
timer.Stop();
}
Time is a class used to manage time; it can be used for current time acquisition, time-consuming calculation, time conversion, and so on.
The time interfaces are as follows:
// constructor, passing in a different value to construct Time
Time(uint64_t nanoseconds); //uint64_t, in nanoseconds
Time(int nanoseconds); // int type, unit: nanoseconds
Time(double seconds); // double, in seconds
Time(uint32_t seconds, uint32_t nanoseconds);
// seconds seconds + nanoseconds nanoseconds
Static Time Now(); // Get the current time
Double ToSecond() const; // convert to seconds
Uint64_t ToNanosecond() const; // Convert to nanoseconds
Std::string ToString() const; // Convert to a string in the format "2018-07-10 20:21:51.123456789"
Bool IsZero() const; // Determine if the time is 0
A code example can be seen below:
#include
#include "cyber/cyber.h"
#include "cyber/duration.h"
int main(int argc, char** argv) {
cyber::Init(argv[0]);
Time t1(1531225311123456789UL);
std::cout << t1.ToString() << std::endl; // 2018-07-10 20:21:51.123456789
// Duration time interval
Time t1(100);
Duration d(200);
Time t2(300);
assert(d == (t1-t2)); // true
}
RecordReader is the component used to read messages in the cyber framework. Each RecordReader can open an existing record file through the Open
method, and the thread will asynchronously read the information in the record file. The user only needs to execute ReadMessage to extract the latest message in RecordReader, and then get the message information through GetCurrentMessageChannelName, GetCurrentRawMessage, GetCurrentMessageTime.
RecordWriter is the component used to record messages in the cyber framework. Each RecordWriter can create a new record file through the Open method. The user only needs to execute WriteMessage and WriteChannel to write message and channel information, and the writing process is asynchronous.
Write 100 RawMessage toTEST_FILE
through test_write
method, then read them out through test_read
method.
#include
#include "cyber/cyber.h"
#include "cyber/message/raw_message.h"
#include "cyber/proto/record.pb.h"
#include "cyber/record/record_message.h"
#include "cyber/record/record_reader.h"
#include "cyber/record/record_writer.h"
using ::apollo::cyber::record::RecordReader;
using ::apollo::cyber::record::RecordWriter;
using ::apollo::cyber::record::RecordMessage;
using apollo::cyber::message::RawMessage;
const char CHANNEL_NAME_1[] = "/test/channel1";
const char CHANNEL_NAME_2[] = "/test/channel2";
const char MESSAGE_TYPE_1[] = "apollo.cyber.proto.Test";
const char MESSAGE_TYPE_2[] = "apollo.cyber.proto.Channel";
const char PROTO_DESC[] = "1234567890";
const char STR_10B[] = "1234567890";
const char TEST_FILE[] = "test.record";
void test_write(const std::string &writefile) {
RecordWriter writer;
writer.SetSizeOfFileSegmentation(0);
writer.SetIntervalOfFileSegmentation(0);
writer.Open(writefile);
writer.WriteChannel(CHANNEL_NAME_1, MESSAGE_TYPE_1, PROTO_DESC);
for (uint32_t i = 0; i < 100; ++i) {
auto msg = std::make_shared<RawMessage>("abc" + std::to_string(i));
writer.WriteMessage(CHANNEL_NAME_1, msg, 888 + i);
}
writer.Close();
}
void test_read(const std::string &readfile) {
RecordReader reader(readfile);
RecordMessage message;
uint64_t msg_count = reader.GetMessageNumber(CHANNEL_NAME_1);
AINFO << "MSGTYPE: " << reader.GetMessageType(CHANNEL_NAME_1);
AINFO << "MSGDESC: " << reader.GetProtoDesc(CHANNEL_NAME_1);
// read all message
uint64_t i = 0;
uint64_t valid = 0;
for (i = 0; i < msg_count; ++i) {
if (reader.ReadMessage(&message)) {
AINFO << "msg[" << i << "]-> "
<< "channel name: " << message.channel_name
<< "; content: " << message.content
<< "; msg time: " << message.time;
valid++;
} else {
AERROR << "read msg[" << i << "] failed";
}
}
AINFO << "static msg=================";
AINFO << "MSG validmsg:totalcount: " << valid << ":" << msg_count;
}
int main(int argc, char *argv[]) {
apollo::cyber::Init(argv[0]);
test_write(TEST_FILE);
sleep(1);
test_read(TEST_FILE);
return 0;
}
I1124 16:56:27.248200 15118 record.cc:64] [record] msg[0]-> channel name: /test/channel1; content: abc0; msg time: 888
I1124 16:56:27.248227 15118 record.cc:64] [record] msg[1]-> channel name: /test/channel1; content: abc1; msg time: 889
I1124 16:56:27.248239 15118 record.cc:64] [record] msg[2]-> channel name: /test/channel1; content: abc2; msg time: 890
I1124 16:56:27.248252 15118 record.cc:64] [record] msg[3]-> channel name: /test/channel1; content: abc3; msg time: 891
I1124 16:56:27.248297 15118 record.cc:64] [record] msg[4]-> channel name: /test/channel1; content: abc4; msg time: 892
I1124 16:56:27.248378 15118 record.cc:64] [record] msg[5]-> channel name: /test/channel1; content: abc5; msg time: 893
...
I1124 16:56:27.250422 15118 record.cc:73] [record] static msg=================
I1124 16:56:27.250434 15118 record.cc:74] [record] MSG validmsg:totalcount: 100:100
介绍3个Cyber RT的开发工具
Apollo Cyber RT framework comes with a collection of useful tools for daily development, including one visualization tool cyber_visualizer and two command line tools cyber_monitor and cyber_recorder.
Note: apollo docker environment is required to use the tools, please follow apollo wiki to enter docker
All the tools from Apollo Cyber RT rely on Apollo Cyber RT library, so you must source the setup.bash file for environment setup before using any Apollo Cyber RT tools, shown as below:
username@computername:~$: source /your-path-to-apollo-install-dir/cyber/setup.bash
对比ROS:
ROS | Cyber | 备注 |
---|---|---|
rosbag | cyber_recorder | 处理数据文件 |
rostopic | cyber_channel | 查看某个topic的信息 |
scripts/diagnostics.sh | cyber_monitor | 查看诊断消息 |
offline_lidar_visualizer_tool | cyber_visualizer | 激光点云及摄像头可视化工具,需要安装NVIDIA显卡驱动及CUDA |
ROS | Cyber | 备注 |
---|---|---|
rosbag play example.bag | cyber_recorder play -f example.record | 播放一个包 |
rosbag info example.bag cyber_recorder info example.record | 查看一个包的信息 | |
rosbag record /apollo/canbus/chassis \ /apollo/canbus/chassis_detail | cyber_recorder record -c /apollo/canbus/chassis \ /apollo/canbus/chassis_detail | 录制多个topic |
rosbag filter input.bag output.bag ‘topic != “/apollo/planning”’ | cyber_recorder split -f input_file.record -o ouput_file.record -k “/apollo/planning” | 滤除一个topic |
rosbag filter csc.bag csc_no_plannig_and_relativemap.bag ‘topic != “/apollo/planning” and “/apollo/relative_map”’ | cyber_recorder split -f input_file.record -o ouput_file.record -k “/apollo/planning” -k “/apollo/relative_map”’ | 滤除多个topic |
rostopic list | cyber_channel list | 列出所有活动的topic |
rostopic info /apollo/planning | cyber_channel info /apollo/planning | 查看 /apollo/planning topic的概要信息 |
rostopic echo /apollo/planning | cyber_channel echo /apollo/planning | 查看 /apollo/planning topic的内容 |
rostopic hz /apollo/planning | cyber_channel hz /apollo/planning | 查看 /apollo/planning topic的发送频率 |
rostopic bw /apollo/planning | cyber_channel bw /apollo/planning | 查看 /apollo/planning topic的带宽 |
rostopic type /apollo/planning | cyber_channel type /apollo/planning | 查看 /apollo/planning topic的数据类型 |
本文主要参考:
百度开源代码:link
Apollo开发者社区:link
博客:Link