Apollo 11.0
自动驾驶开放平台
canbus_component.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
18
20#include "cyber/common/file.h"
21#include "cyber/time/time.h"
26
34
35namespace apollo {
36namespace canbus {
37
38std::string CanbusComponent::Name() const { return FLAGS_canbus_module_name; }
39
41 : monitor_logger_buffer_(
42 apollo::common::monitor::MonitorMessageItem::CANBUS) {}
43
44bool CanbusComponent::Init() {
45 if (!GetProtoConfig(&canbus_conf_)) {
46 AERROR << "Unable to load canbus conf file: " << ConfigFilePath();
47 return false;
48 }
49 AINFO << "The canbus conf file is loaded: " << FLAGS_canbus_conf_file;
50 ADEBUG << "Canbus_conf:" << canbus_conf_.ShortDebugString();
51
52 if (!apollo::cyber::common::PathExists(FLAGS_load_vehicle_library)) {
53 AERROR << FLAGS_load_vehicle_library << " No such vehicle library";
54 return false;
55 }
56 AINFO << "Load the vehicle factory library: " << FLAGS_load_vehicle_library;
57
58 ClassLoader loader(FLAGS_load_vehicle_library);
59 auto vehicle_object = loader.CreateClassObj<AbstractVehicleFactory>(
60 FLAGS_load_vehicle_class_name);
61 if (!vehicle_object) {
62 AERROR << "Failed to create the vehicle factory: "
63 << FLAGS_load_vehicle_class_name;
64 return false;
65 }
66 AINFO << "Successfully create vehicle factory: "
67 << FLAGS_load_vehicle_class_name;
68
69 vehicle_object_ = vehicle_object;
70 if (!vehicle_object_->Init(&canbus_conf_)) {
71 AERROR << "Fail to init vehicle factory.";
72 return false;
73 }
74 AINFO << "Vehicle factory is successfully initialized.";
75
76 cyber::ReaderConfig guardian_cmd_reader_config;
77 guardian_cmd_reader_config.channel_name = FLAGS_guardian_topic;
78 guardian_cmd_reader_config.pending_queue_size =
79 FLAGS_guardian_cmd_pending_queue_size;
80
81 cyber::ReaderConfig control_cmd_reader_config;
82 control_cmd_reader_config.channel_name = FLAGS_control_command_topic;
83 control_cmd_reader_config.pending_queue_size =
84 FLAGS_control_cmd_pending_queue_size;
85
86 cyber::ReaderConfig chassis_cmd_reader_config;
87 chassis_cmd_reader_config.channel_name = FLAGS_chassis_command_topic;
88 chassis_cmd_reader_config.pending_queue_size =
89 FLAGS_control_cmd_pending_queue_size;
90
91 // init cmd reader
92 if (FLAGS_receive_guardian) {
93 guardian_cmd_reader_ = node_->CreateReader<GuardianCommand>(
94 guardian_cmd_reader_config,
95 [this](const std::shared_ptr<GuardianCommand> &cmd) {
96 ADEBUG << "Received guardian data: run canbus callback.";
97 const auto start_time = Time::Now().ToMicrosecond();
98 OnGuardianCommand(*cmd);
99 const auto end_time = Time::Now().ToMicrosecond();
100 if ((end_time - start_time) * 1e-6 > FLAGS_guardian_period) {
101 AWARN << "Guardian callback time: "
102 << (end_time - start_time) * 1e-3 << " ms.";
103 }
104 });
105 } else {
106 control_command_reader_ = node_->CreateReader<ControlCommand>(
107 control_cmd_reader_config,
108 [this](const std::shared_ptr<ControlCommand> &cmd) {
109 ADEBUG << "Received control data: run canbus callback.";
110 const auto start_time = Time::Now().ToMicrosecond();
111 OnControlCommand(*cmd);
112 const auto end_time = Time::Now().ToMicrosecond();
113 if ((end_time - start_time) * 1e-6 > FLAGS_control_period) {
114 AWARN << "Control callback time: " << (end_time - start_time) * 1e-3
115 << " ms.";
116 }
117 });
118 }
119
120 // init chassis cmd reader
121 chassis_command_reader_ = node_->CreateReader<ChassisCommand>(
122 chassis_cmd_reader_config,
123 [this](const std::shared_ptr<ChassisCommand> &cmd) {
124 ADEBUG << "Received control data: run canbus callback.";
125 OnChassisCommand(*cmd);
126 });
127
128 // init chassis writer
129 chassis_writer_ = node_->CreateWriter<Chassis>(FLAGS_chassis_topic);
130
131 // start canbus vehicle
132 if (!vehicle_object_->Start()) {
133 AERROR << "Fail to start canclient, cansender, canreceiver, canclient, "
134 "vehicle controller.";
135 Clear();
136 return false;
137 }
138 AINFO << "Start canclient cansender, canreceiver, canclient, vehicle "
139 "controller successfully.";
140
141 monitor_logger_buffer_.INFO("Canbus is started.");
142
143 return true;
144}
145
146void CanbusComponent::Clear() {
147 vehicle_object_->Stop();
148 AINFO << "Cleanup Canbus component";
149}
150
151void CanbusComponent::PublishChassis() {
152 Chassis chassis = vehicle_object_->publish_chassis();
153 if (is_control_cmd_time_delay_) {
154 AERROR << "cmd time delay";
155 chassis.set_error_code(Chassis::CMD_NOT_IN_PERIOD);
156 }
157 common::util::FillHeader(node_->Name(), &chassis);
158 chassis_writer_->Write(chassis);
159 ADEBUG << chassis.ShortDebugString();
160}
161
162bool CanbusComponent::Proc() {
163 const auto start_time = Time::Now().ToMicrosecond();
164
165 if (FLAGS_receive_guardian) {
166 guardian_cmd_reader_->Observe();
167 const auto &guardian_cmd_msg = guardian_cmd_reader_->GetLatestObserved();
168 if (guardian_cmd_msg == nullptr) {
169 AERROR << "guardian cmd msg is not ready!";
170 } else {
171 OnGuardianCommandCheck(*guardian_cmd_msg);
172 }
173 } else {
174 control_command_reader_->Observe();
175 const auto &control_cmd_msg = control_command_reader_->GetLatestObserved();
176 if (control_cmd_msg == nullptr) {
177 AERROR << "control cmd msg is not ready!";
178 } else {
179 OnControlCommandCheck(*control_cmd_msg);
180 }
181 }
182
183 // check can receiver msg lost
184 if (vehicle_object_->CheckChassisCommunicationFault()) {
185 AERROR << "Can not get the chassis info, please check the chassis "
186 "communication!";
187 is_chassis_communication_fault_ = true;
188 } else {
189 is_chassis_communication_fault_ = false;
190 }
191
192 // publish "/apollo/canbus/chassis"
193 PublishChassis();
194
195 // publish "/apollo/canbus/chassis_detail"
196 if (FLAGS_enable_chassis_detail_pub) {
197 vehicle_object_->PublishChassisDetail();
198 }
199
200 // publish "/apollo/canbus/chassis_detail_sender"
201 if (FLAGS_enable_chassis_detail_sender_pub) {
202 vehicle_object_->PublishChassisDetailSender();
203 }
204
205 // update heartbeat in can sender
206 vehicle_object_->UpdateHeartbeat();
207
208 const auto end_time = Time::Now().ToMicrosecond();
209 const double time_diff_ms = (end_time - start_time) * 1e-3;
210 if (time_diff_ms > (1 / FLAGS_chassis_freq * 1e3)) {
211 AWARN << "CanbusComponent::Proc() takes too much time: " << time_diff_ms
212 << " ms";
213 }
214
215 return true;
216}
217
218void CanbusComponent::OnControlCommand(const ControlCommand &control_command) {
219 // us : microsecord = 1e-3 millisecond = 1e-6 second
220 double current_timestamp = Time::Now().ToMicrosecond();
221 // if command coming too soon, just ignore it.
222 // us < 5 ms(millisecond) *1000 (=5000us microsecord)
223 if (current_timestamp - last_timestamp_controlcmd_ <
224 FLAGS_min_cmd_interval * 1000) {
225 ADEBUG << "Control command comes too soon. Ignore. Required "
226 "FLAGS_min_cmd_interval["
227 << FLAGS_min_cmd_interval << "] ms, actual time interval["
228 << (current_timestamp - last_timestamp_controlcmd_) * 1e-3
229 << "] ms.";
230 return;
231 }
232 last_timestamp_controlcmd_ = current_timestamp;
233
234 if (!is_control_cmd_time_delay_) {
235 vehicle_object_->UpdateCommand(&control_command);
236 }
237}
238
239void CanbusComponent::OnControlCommandCheck(
240 const ControlCommand &control_command) {
241 // us : microsecord = 1e-3 millisecond = 1e-6 second
242 double current_timestamp = Time::Now().ToMicrosecond();
243 // cmd_time_diff: s
244 double cmd_time_diff =
245 current_timestamp * 1e-6 - control_command.header().timestamp_sec();
246 if ((FLAGS_use_control_cmd_check &&
247 (cmd_time_diff > (FLAGS_max_control_miss_num * FLAGS_control_period))) ||
248 is_chassis_communication_fault_) {
249 AERROR_IF(cmd_time_diff >
250 (FLAGS_max_control_miss_num * FLAGS_control_period))
251 << "Control cmd timeout, sequence_number:"
252 << control_command.header().sequence_num()
253 << ", Time_of_delay:" << cmd_time_diff << " s"
254 << ", time delay threshold: "
255 << (FLAGS_max_control_miss_num * FLAGS_control_period) << " s"
256 << ", need to process cmd timeout.";
257 AERROR_IF(is_chassis_communication_fault_)
258 << "Chassis communication fault, need to process cmd timeout.";
259
260 if (vehicle_object_->Driving_Mode() == Chassis::COMPLETE_AUTO_DRIVE ||
261 vehicle_object_->Driving_Mode() == Chassis::AUTO_STEER_ONLY ||
262 vehicle_object_->Driving_Mode() == Chassis::AUTO_SPEED_ONLY ||
263 FLAGS_chassis_debug_mode || is_chassis_communication_fault_) {
264 is_control_cmd_time_delay_ = true;
265 GuardianCommand new_guardian_command;
266 new_guardian_command.mutable_control_command()->CopyFrom(control_command);
267 ProcessGuardianCmdTimeout(&new_guardian_command);
268 ADEBUG << "new_guardian_command is "
269 << new_guardian_command.ShortDebugString();
270 vehicle_object_->UpdateCommand(&new_guardian_command.control_command());
271 }
272 } else {
273 is_control_cmd_time_delay_ = false;
274 }
275}
276
277void CanbusComponent::OnGuardianCommand(
278 const GuardianCommand &guardian_command) {
279 if (!is_control_cmd_time_delay_) {
280 OnControlCommand(guardian_command.control_command());
281 }
282}
283
284void CanbusComponent::OnGuardianCommandCheck(
285 const GuardianCommand &guardian_command) {
286 // us : microsecord = 1e-3 millisecond = 1e-6 second
287 double current_timestamp = Time::Now().ToMicrosecond();
288 // cmd_time_diff: s
289 double guardian_cmd_time_diff =
290 current_timestamp * 1e-6 - guardian_command.header().timestamp_sec();
291 if ((FLAGS_use_guardian_cmd_check &&
292 (guardian_cmd_time_diff >
293 (FLAGS_max_guardian_miss_num * FLAGS_guardian_period))) ||
294 is_chassis_communication_fault_) {
295 AERROR << "Guardain cmd timeout, sequence_number:"
296 << guardian_command.header().sequence_num()
297 << ", Time_of_delay:" << guardian_cmd_time_diff << " s"
298 << ", time delay threshold: "
299 << (FLAGS_max_guardian_miss_num * FLAGS_guardian_period) << " s"
300 << ", need to process cmd timeout.";
301
302 if (vehicle_object_->Driving_Mode() == Chassis::COMPLETE_AUTO_DRIVE ||
303 vehicle_object_->Driving_Mode() == Chassis::AUTO_STEER_ONLY ||
304 vehicle_object_->Driving_Mode() == Chassis::AUTO_SPEED_ONLY ||
305 is_chassis_communication_fault_) {
306 is_control_cmd_time_delay_ = true;
307 GuardianCommand new_guardian_command;
308 new_guardian_command.CopyFrom(guardian_command);
309 ProcessGuardianCmdTimeout(&new_guardian_command);
310 ADEBUG << "new_guardian_command is "
311 << new_guardian_command.ShortDebugString();
312 vehicle_object_->UpdateCommand(&new_guardian_command.control_command());
313 }
314 } else {
315 is_control_cmd_time_delay_ = false;
316 }
317}
318
319void CanbusComponent::OnChassisCommand(const ChassisCommand &chassis_command) {
320 // us : microsecord = 1e-3 millisecond = 1e-6 second
321 int64_t current_timestamp = Time::Now().ToMicrosecond();
322 // if command coming too soon, just ignore it.
323 // us < 5 ms(millisecond) *1000 (=5000us microsecord)
324 if (current_timestamp - last_timestamp_chassiscmd_ <
325 FLAGS_min_cmd_interval * 1000) {
326 ADEBUG << "Control command comes too soon. Ignore.\n Required "
327 "FLAGS_min_cmd_interval["
328 << FLAGS_min_cmd_interval << "], actual time interval["
329 << current_timestamp - last_timestamp_chassiscmd_ << "].";
330 return;
331 }
332 last_timestamp_chassiscmd_ = current_timestamp;
333
334 ADEBUG << "Control_sequence_number:"
335 << chassis_command.header().sequence_num() << ", Time_of_delay:"
336 << current_timestamp -
337 static_cast<int64_t>(chassis_command.header().timestamp_sec() *
338 1e6)
339 << " micro seconds";
340
341 vehicle_object_->UpdateCommand(&chassis_command);
342}
343
344common::Status CanbusComponent::OnError(const std::string &error_msg) {
345 monitor_logger_buffer_.ERROR(error_msg);
346 return ::apollo::common::Status(ErrorCode::CANBUS_ERROR, error_msg);
347}
348
349void CanbusComponent::ProcessTimeoutByClearCanSender() {
350 if (vehicle_object_->Driving_Mode() != Chassis::COMPLETE_AUTO_DRIVE &&
351 vehicle_object_->Driving_Mode() != Chassis::AUTO_STEER_ONLY &&
352 vehicle_object_->Driving_Mode() != Chassis::AUTO_SPEED_ONLY &&
353 !FLAGS_chassis_debug_mode) {
354 ADEBUG << "The current driving mode does not need to check cmd timeout.";
355 if (vehicle_object_->IsSendProtocolClear()) {
356 AINFO << "send protocol is clear, ignore driving mode, need to recover "
357 "send protol.";
358 vehicle_object_->AddSendProtocol();
359 }
360 return;
361 }
362
363 if (!is_control_cmd_time_delay_previous_ && is_control_cmd_time_delay_) {
364 AINFO << "control cmd time latency delay, clear send protocol.";
365 vehicle_object_->ClearSendProtocol();
366 } else if (is_control_cmd_time_delay_previous_ &&
367 !is_control_cmd_time_delay_) {
368 AINFO << "control cmd time latency reover, add send protocol.";
369 if (vehicle_object_->IsSendProtocolClear()) {
370 vehicle_object_->AddSendProtocol();
371 }
372 }
373 is_control_cmd_time_delay_previous_ = is_control_cmd_time_delay_;
374}
375
376void CanbusComponent::ProcessGuardianCmdTimeout(
377 GuardianCommand *guardian_command) {
378 AINFO << "Into cmd timeout process, set estop.";
379 guardian_command->mutable_control_command()->set_throttle(0.0);
380 guardian_command->mutable_control_command()->set_steering_target(0.0);
381 guardian_command->mutable_control_command()->set_steering_rate(25.0);
382 guardian_command->mutable_control_command()->set_brake(FLAGS_estop_brake);
383}
384
385} // namespace canbus
386} // namespace apollo
Defines the CanClientFactory class.
std::string Name() const
obtain module name
bool GetProtoConfig(T *config) const
const std::string & ConfigFilePath() const
std::shared_ptr< Node > node_
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
for library load,createclass object
CanClientFactory inherites apollo::common::util::Factory.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AERROR_IF(cond)
Definition log.h:74
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
Some util functions.
bool PathExists(const std::string &path)
Check if the path exists.
Definition file.cc:195
class register implement
Definition arena_queue.h:37
optional uint32 sequence_num
Definition header.proto:16
optional double timestamp_sec
Definition header.proto:9
optional apollo::common::Header header
optional apollo::common::Header header
optional apollo::common::Header header
Definition guardian.proto:8
optional apollo::control::ControlCommand control_command
Definition guardian.proto:9