Apollo 11.0
自动驾驶开放平台
can_client_tool.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
17#include <cstdint>
18#include <iostream>
19#include <memory>
20#include <thread>
21
22#include "cyber/common/file.h"
23#include "cyber/common/log.h"
24#include "cyber/time/time.h"
25#include "gflags/gflags.h"
26#include "modules/common_msgs/basic_msgs/error_code.pb.h"
31#include "modules/common_msgs/drivers_msgs/can_card_parameter.pb.h"
32
33DEFINE_bool(only_one_send, false, "only send test.");
34DEFINE_string(can_client_conf_file_a,
35 "modules/canbus/conf/can_client_conf_a.pb.txt",
36 "can client conf for client a");
37DEFINE_string(can_client_conf_file_b,
38 "modules/canbus/conf/can_client_conf_b.pb.txt",
39 "can client conf for client b");
40DEFINE_int64(agent_mutual_send_frames, 1000, "Every agent send frame num");
41
42const int32_t MAX_CAN_SEND_FRAME_LEN = 1;
43const int32_t MAX_CAN_RECV_FRAME_LEN = 10;
44
46
47namespace apollo {
48namespace drivers {
49namespace canbus {
50
53 bool is_first_agent = false;
54 int32_t recv_cnt = 0;
55 int32_t recv_err_cnt = 0;
56 int32_t send_cnt = 0;
57 int32_t send_err_cnt = 0;
58 int32_t send_lost_cnt = 0;
59 int32_t send_time = 0;
60 int32_t recv_time = 0;
62
63 TestCanParam() = default;
64
65 void print() {
66 AINFO << "conf: " << conf.ShortDebugString()
67 << ", total send: " << send_cnt + send_err_cnt << "/"
68 << FLAGS_agent_mutual_send_frames << ", send_ok: " << send_cnt
69 << " , send_err_cnt: " << send_err_cnt
70 << ", send_lost_cnt: " << send_lost_cnt << ", recv_cnt: " << recv_cnt
71 << ", send_time: " << send_time << ", recv_time: " << recv_time;
72 }
73};
74
75class CanAgent {
76 public:
77 explicit CanAgent(TestCanParam *param_ptr) : param_ptr_(param_ptr) {}
78
79 TestCanParam *param_ptr() { return param_ptr_; }
80
81 CanAgent *other_agent() { return other_agent_; }
82
83 bool Start() {
84 thread_recv_.reset(new std::thread([this] { RecvThreadFunc(); }));
85 if (thread_recv_ == nullptr) {
86 AERROR << "Unable to create recv thread.";
87 return false;
88 }
89 thread_send_.reset(new std::thread([this] { SendThreadFunc(); }));
90 if (thread_send_ == nullptr) {
91 AERROR << "Unable to create send thread.";
92 return false;
93 }
94 return true;
95 }
96
99 AINFO << "Send thread starting...";
100 TestCanParam *param = param_ptr();
101 CanClient *client = param->can_client;
102 std::vector<CanFrame> frames;
103 frames.resize(MAX_CAN_SEND_FRAME_LEN);
104
105 int32_t count = 0;
106 int32_t start_id = 0;
107 int32_t end_id = 0;
108 int32_t id = 0;
109 if (param->is_first_agent) {
110 start_id = 1;
111 end_id = 128;
112 } else {
113 start_id = 129;
114 end_id = start_id + 127;
115 }
116 id = start_id;
117 int32_t send_id = id;
118 AINFO << "port:" << param->conf.ShortDebugString()
119 << ", start_id:" << start_id << ", end_id:" << end_id;
120
121 // wait for other agent receiving is ok.
122 while (!other_agent()->is_receiving()) {
123 std::this_thread::yield();
124 }
125 int64_t start = Time::Now().ToMicrosecond();
126 while (true) {
127 // param->print();
128 if (count >= FLAGS_agent_mutual_send_frames) {
129 break;
130 }
131 for (int32_t i = 0; i < MAX_CAN_SEND_FRAME_LEN; ++i) {
132 // frames[i].id = id_count & 0x3FF;
133 send_id = id;
134 frames[i].id = id;
135 frames[i].len = 8;
136 frames[i].data[7] = static_cast<uint8_t>(count % 256);
137 for (uint8_t j = 0; j < 7; ++j) {
138 frames[i].data[j] = j;
139 }
140 ++count;
141 ++id;
142 if (id > end_id) {
143 id = start_id;
144 }
145 }
146 int32_t frame_num = MAX_CAN_SEND_FRAME_LEN;
147 if (client->Send(frames, &frame_num) != ErrorCode::OK) {
149 AERROR << "send_thread send msg failed!, id:" << send_id
150 << ", conf:" << param->conf.ShortDebugString();
151 } else {
152 param->send_cnt += frame_num;
153 param->send_lost_cnt += MAX_CAN_SEND_FRAME_LEN - frame_num;
154 AINFO << "send_frames: " << frame_num << "send_frame#"
155 << frames[0].CanFrameString()
156 << " send lost:" << MAX_CAN_SEND_FRAME_LEN - frame_num
157 << ", conf:" << param->conf.ShortDebugString();
158 }
159 }
160 int64_t end = Time::Now().ToMicrosecond();
161 param->send_time = static_cast<int32_t>(end - start);
162 // In case for finish too quick to receiver miss some msg
163 sleep(2);
164 AINFO << "Send thread stopping..." << param->conf.ShortDebugString();
165 is_sending_finish(true);
166 return;
167 }
168
169 void AddOtherAgent(CanAgent *agent) { other_agent_ = agent; }
170
171 bool is_receiving() const { return is_receiving_; }
172
173 void is_receiving(bool val) { is_receiving_ = val; }
174
175 bool is_sending_finish() const { return is_sending_finish_; }
176
177 void is_sending_finish(bool val) { is_sending_finish_ = val; }
178
180 using common::ErrorCode;
181 AINFO << "Receive thread starting...";
182 TestCanParam *param = param_ptr();
183 CanClient *client = param->can_client;
184 int64_t start = 0;
185 std::vector<CanFrame> buf;
186
187 bool first = true;
188 while (!other_agent()->is_sending_finish()) {
189 is_receiving(true);
190 int32_t len = MAX_CAN_RECV_FRAME_LEN;
191 ErrorCode ret = client->Receive(&buf, &len);
192 if (len == 0) {
193 AINFO << "recv frame:0";
194 continue;
195 }
196 if (first) {
197 start = Time::Now().ToMicrosecond();
198 first = false;
199 }
200 if (ret != ErrorCode::OK || len == 0) {
201 // AINFO << "channel:" << param->conf.channel_id()
202 // << ", recv frame:failed, code:" << ret;
203 AINFO << "recv error:" << ret;
204 continue;
205 }
206 for (int32_t i = 0; i < len; ++i) {
207 param->recv_cnt = param->recv_cnt + 1;
208 AINFO << "recv_frame#" << buf[i].CanFrameString()
209 << " conf:" << param->conf.ShortDebugString()
210 << ",recv_cnt: " << param->recv_cnt;
211 }
212 }
213 int64_t end = Time::Now().ToMicrosecond();
214 param->recv_time = static_cast<int32_t>(end - start);
215 AINFO << "Recv thread stopping..., conf:" << param->conf.ShortDebugString();
216 return;
217 }
218
220 if (thread_send_ != nullptr && thread_send_->joinable()) {
221 thread_send_->join();
222 thread_send_.reset();
223 AINFO << "Send thread stopped. conf:"
224 << param_ptr_->conf.ShortDebugString();
225 }
226 if (thread_recv_ != nullptr && thread_recv_->joinable()) {
227 thread_recv_->join();
228 thread_recv_.reset();
229 AINFO << "Recv thread stopped. conf:"
230 << param_ptr_->conf.ShortDebugString();
231 }
232 }
233
234 private:
235 bool is_receiving_ = false;
236 bool is_sending_finish_ = false;
237 CanAgent *other_agent_ = nullptr;
238 TestCanParam *param_ptr_ = nullptr;
239 std::unique_ptr<std::thread> thread_recv_;
240 std::unique_ptr<std::thread> thread_send_;
241};
242
243} // namespace canbus
244} // namespace drivers
245} // namespace apollo
246
247int main(int32_t argc, char **argv) {
248 google::InitGoogleLogging(argv[0]);
249 google::ParseCommandLineFlags(&argc, &argv, true);
250
257 CANCardParameter can_client_conf_a;
258 std::shared_ptr<TestCanParam> param_ptr_a(new TestCanParam());
259 std::shared_ptr<TestCanParam> param_ptr_b(new TestCanParam());
260
261 auto can_client_factory = CanClientFactory::Instance();
262 can_client_factory->RegisterCanClients();
263
264 if (!apollo::cyber::common::GetProtoFromFile(FLAGS_can_client_conf_file_a,
265 &can_client_conf_a)) {
266 AERROR << "Unable to load canbus conf file: "
267 << FLAGS_can_client_conf_file_a;
268 return -1;
269 }
270 AINFO << "Conf file is loaded: " << FLAGS_can_client_conf_file_a;
271 AINFO << can_client_conf_a.ShortDebugString();
272 auto client_a = can_client_factory->CreateObject(can_client_conf_a.brand());
273 if (!client_a || !client_a->Init(can_client_conf_a) ||
274 client_a->Start() != ErrorCode::OK) {
275 AERROR << "Create can client a failed.";
276 return -1;
277 }
278 param_ptr_a->can_client = client_a.get();
279 param_ptr_a->is_first_agent = true;
280 param_ptr_a->conf = can_client_conf_a;
281
282 CANCardParameter can_client_conf_b;
283 std::unique_ptr<CanClient> client_b;
284 if (!FLAGS_only_one_send) {
285 if (!apollo::cyber::common::GetProtoFromFile(FLAGS_can_client_conf_file_b,
286 &can_client_conf_b)) {
287 AERROR << "Unable to load canbus conf file: "
288 << FLAGS_can_client_conf_file_b;
289 return -1;
290 }
291 AINFO << "Conf file is loaded: " << FLAGS_can_client_conf_file_b;
292 AINFO << can_client_conf_b.ShortDebugString();
293 client_b = can_client_factory->CreateObject(can_client_conf_b.brand());
294 if (!client_b || !client_b->Init(can_client_conf_b) ||
295 client_b->Start() != ErrorCode::OK) {
296 AERROR << "Create can client b failed.";
297 return -1;
298 }
299 param_ptr_b->can_client = client_b.get();
300 param_ptr_b->conf = can_client_conf_b;
301 }
302
303 CanAgent agent_a(param_ptr_a.get());
304 CanAgent agent_b(param_ptr_b.get());
305 agent_a.AddOtherAgent(&agent_b);
306 agent_b.AddOtherAgent(&agent_a);
307 if (!agent_a.Start()) {
308 AERROR << "Agent a start failed.";
309 return -1;
310 }
311 if (FLAGS_only_one_send) {
312 agent_b.is_receiving(true);
313 agent_b.is_sending_finish(true);
314 } else {
315 if (!agent_b.Start()) {
316 AERROR << "Agent b start failed.";
317 return -1;
318 }
319 }
320
321 agent_a.WaitForFinish();
322 if (!FLAGS_only_one_send) {
323 agent_b.WaitForFinish();
324 }
325 param_ptr_a->print();
326 if (!FLAGS_only_one_send) {
327 param_ptr_b->print();
328 }
329
330 return 0;
331}
Defines the Byte class.
Defines the CanFrame struct and CanClient interface.
Defines the CanClientFactory class.
DEFINE_int64(agent_mutual_send_frames, 1000, "Every agent send frame num")
const int32_t MAX_CAN_SEND_FRAME_LEN
int main(int32_t argc, char **argv)
const int32_t MAX_CAN_RECV_FRAME_LEN
DEFINE_string(can_client_conf_file_a, "modules/canbus/conf/can_client_conf_a.pb.txt", "can client conf for client a")
DEFINE_bool(only_one_send, false, "only send test.")
Cyber has builtin time type Time.
Definition time.h:31
uint64_t ToMicrosecond() const
convert time to microsecond (us).
Definition time.cc:85
static Time Now()
get the current time.
Definition time.cc:57
CanAgent(TestCanParam *param_ptr)
CanClientFactory inherites apollo::common::util::Factory.
The class which defines the CAN client to send and receive message.
Definition can_client.h:92
virtual apollo::common::ErrorCode Send(const std::vector< CanFrame > &frames, int32_t *const frame_num)=0
Send messages
virtual apollo::common::ErrorCode Receive(std::vector< CanFrame > *const frames, int32_t *const frame_num)=0
Receive messages
Defines the Factory class.
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
bool GetProtoFromFile(const std::string &file_name, google::protobuf::Message *message)
Parses the content of the file specified by the file_name as a representation of protobufs,...
Definition file.cc:132
const int32_t MAX_CAN_RECV_FRAME_LEN
const int32_t MAX_CAN_SEND_FRAME_LEN
class register implement
Definition arena_queue.h:37