Apollo 9.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 common::util::FillHeader(node_->Name(), &chassis);
154 chassis_writer_->Write(chassis);
155 ADEBUG << chassis.ShortDebugString();
156}
157
158bool CanbusComponent::Proc() {
159 const auto start_time = Time::Now().ToMicrosecond();
160
161 if (FLAGS_receive_guardian) {
162 guardian_cmd_reader_->Observe();
163 const auto &guardian_cmd_msg = guardian_cmd_reader_->GetLatestObserved();
164 if (guardian_cmd_msg == nullptr) {
165 AERROR << "guardian cmd msg is not ready!";
166 } else {
167 OnGuardianCommandCheck(*guardian_cmd_msg);
168 }
169 } else {
170 control_command_reader_->Observe();
171 const auto &control_cmd_msg = control_command_reader_->GetLatestObserved();
172 if (control_cmd_msg == nullptr) {
173 AERROR << "control cmd msg is not ready!";
174 } else {
175 OnControlCommandCheck(*control_cmd_msg);
176 }
177 }
178
179 // check can receiver msg lost
180 if (vehicle_object_->CheckChassisCommunicationFault()) {
181 AERROR << "Can not get the chassis info, please check the chassis "
182 "communication!";
183 }
184
185 // publish "/apollo/canbus/chassis"
186 PublishChassis();
187
188 // publish "/apollo/canbus/chassis_detail"
189 if (FLAGS_enable_chassis_detail_pub) {
190 vehicle_object_->PublishChassisDetail();
191 }
192
193 // publish "/apollo/canbus/chassis_detail_sender"
194 if (FLAGS_enable_chassis_detail_sender_pub) {
195 vehicle_object_->PublishChassisDetailSender();
196 }
197
198 // update heartbeat in can sender
199 vehicle_object_->UpdateHeartbeat();
200
201 const auto end_time = Time::Now().ToMicrosecond();
202 const double time_diff_ms = (end_time - start_time) * 1e-3;
203 if (time_diff_ms > (1 / FLAGS_chassis_freq * 1e3)) {
204 AWARN << "CanbusComponent::Proc() takes too much time: " << time_diff_ms
205 << " ms";
206 }
207
208 return true;
209}
210
211void CanbusComponent::OnControlCommand(const ControlCommand &control_command) {
212 // us : microsecord = 1e-3 millisecond = 1e-6 second
213 double current_timestamp = Time::Now().ToMicrosecond();
214 // if command coming too soon, just ignore it.
215 // us < 5 ms(millisecond) *1000 (=5000us microsecord)
216 if (current_timestamp - last_timestamp_controlcmd_ <
217 FLAGS_min_cmd_interval * 1000) {
218 ADEBUG << "Control command comes too soon. Ignore. Required "
219 "FLAGS_min_cmd_interval["
220 << FLAGS_min_cmd_interval << "] ms, actual time interval["
221 << (current_timestamp - last_timestamp_controlcmd_) * 1e-3
222 << "] ms.";
223 return;
224 }
225 last_timestamp_controlcmd_ = current_timestamp;
226
227 if (!is_control_cmd_time_delay_) {
228 vehicle_object_->UpdateCommand(&control_command);
229 }
230}
231
232void CanbusComponent::OnControlCommandCheck(
233 const ControlCommand &control_command) {
234 // us : microsecord = 1e-3 millisecond = 1e-6 second
235 double current_timestamp = Time::Now().ToMicrosecond();
236 // cmd_time_diff: s
237 double cmd_time_diff =
238 current_timestamp * 1e-6 - control_command.header().timestamp_sec();
239 if (FLAGS_use_control_cmd_check &&
240 (cmd_time_diff > (FLAGS_max_control_miss_num * FLAGS_control_period))) {
241 AERROR << "Control cmd timeout, sequence_number:"
242 << control_command.header().sequence_num()
243 << ", Time_of_delay:" << cmd_time_diff << " s"
244 << ", time delay threshold: "
245 << (FLAGS_max_control_miss_num * FLAGS_control_period) << " s";
246
247 if (vehicle_object_->Driving_Mode() == Chassis::COMPLETE_AUTO_DRIVE ||
248 vehicle_object_->Driving_Mode() == Chassis::AUTO_STEER_ONLY ||
249 vehicle_object_->Driving_Mode() == Chassis::AUTO_SPEED_ONLY) {
250 is_control_cmd_time_delay_ = true;
251 GuardianCommand new_guardian_command;
252 new_guardian_command.mutable_control_command()->CopyFrom(control_command);
253 ProcessGuardianCmdTimeout(&new_guardian_command);
254 ADEBUG << "new_guardian_command is "
255 << new_guardian_command.ShortDebugString();
256 vehicle_object_->UpdateCommand(&new_guardian_command.control_command());
257 }
258 } else {
259 is_control_cmd_time_delay_ = false;
260 }
261}
262
263void CanbusComponent::OnGuardianCommand(
264 const GuardianCommand &guardian_command) {
265 if (!is_control_cmd_time_delay_) {
266 OnControlCommand(guardian_command.control_command());
267 }
268}
269
270void CanbusComponent::OnGuardianCommandCheck(
271 const GuardianCommand &guardian_command) {
272 // us : microsecord = 1e-3 millisecond = 1e-6 second
273 double current_timestamp = Time::Now().ToMicrosecond();
274 // cmd_time_diff: s
275 double guardian_cmd_time_diff =
276 current_timestamp * 1e-6 - guardian_command.header().timestamp_sec();
277 if (FLAGS_use_guardian_cmd_check &&
278 (guardian_cmd_time_diff >
279 (FLAGS_max_guardian_miss_num * FLAGS_guardian_period))) {
280 AERROR << "Guardain cmd timeout, sequence_number:"
281 << guardian_command.header().sequence_num()
282 << ", Time_of_delay:" << guardian_cmd_time_diff << " s"
283 << ", time delay threshold: "
284 << (FLAGS_max_guardian_miss_num * FLAGS_guardian_period) << " s";
285
286 if (vehicle_object_->Driving_Mode() == Chassis::COMPLETE_AUTO_DRIVE ||
287 vehicle_object_->Driving_Mode() == Chassis::AUTO_STEER_ONLY ||
288 vehicle_object_->Driving_Mode() == Chassis::AUTO_SPEED_ONLY) {
289 is_control_cmd_time_delay_ = true;
290 GuardianCommand new_guardian_command;
291 new_guardian_command.CopyFrom(guardian_command);
292 ProcessGuardianCmdTimeout(&new_guardian_command);
293 ADEBUG << "new_guardian_command is "
294 << new_guardian_command.ShortDebugString();
295 vehicle_object_->UpdateCommand(&new_guardian_command.control_command());
296 }
297 } else {
298 is_control_cmd_time_delay_ = false;
299 }
300}
301
302void CanbusComponent::OnChassisCommand(const ChassisCommand &chassis_command) {
303 // us : microsecord = 1e-3 millisecond = 1e-6 second
304 int64_t current_timestamp = Time::Now().ToMicrosecond();
305 // if command coming too soon, just ignore it.
306 // us < 5 ms(millisecond) *1000 (=5000us microsecord)
307 if (current_timestamp - last_timestamp_chassiscmd_ <
308 FLAGS_min_cmd_interval * 1000) {
309 ADEBUG << "Control command comes too soon. Ignore.\n Required "
310 "FLAGS_min_cmd_interval["
311 << FLAGS_min_cmd_interval << "], actual time interval["
312 << current_timestamp - last_timestamp_chassiscmd_ << "].";
313 return;
314 }
315 last_timestamp_chassiscmd_ = current_timestamp;
316
317 ADEBUG << "Control_sequence_number:"
318 << chassis_command.header().sequence_num() << ", Time_of_delay:"
319 << current_timestamp -
320 static_cast<int64_t>(chassis_command.header().timestamp_sec() *
321 1e6)
322 << " micro seconds";
323
324 vehicle_object_->UpdateCommand(&chassis_command);
325}
326
327common::Status CanbusComponent::OnError(const std::string &error_msg) {
328 monitor_logger_buffer_.ERROR(error_msg);
329 return ::apollo::common::Status(ErrorCode::CANBUS_ERROR, error_msg);
330}
331
332void CanbusComponent::ProcessTimeoutByClearCanSender() {
333 if (vehicle_object_->Driving_Mode() != Chassis::COMPLETE_AUTO_DRIVE &&
334 vehicle_object_->Driving_Mode() != Chassis::AUTO_STEER_ONLY &&
335 vehicle_object_->Driving_Mode() != Chassis::AUTO_SPEED_ONLY &&
336 !FLAGS_chassis_debug_mode) {
337 ADEBUG << "The current driving mode does not need to check cmd timeout.";
338 if (vehicle_object_->IsSendProtocolClear()) {
339 AINFO << "send protocol is clear, ignore driving mode, need to recover "
340 "send protol.";
341 vehicle_object_->AddSendProtocol();
342 }
343 return;
344 }
345
346 if (!is_control_cmd_time_delay_previous_ && is_control_cmd_time_delay_) {
347 AINFO << "control cmd time latency delay, clear send protocol.";
348 vehicle_object_->ClearSendProtocol();
349 } else if (is_control_cmd_time_delay_previous_ &&
350 !is_control_cmd_time_delay_) {
351 AINFO << "control cmd time latency reover, add send protocol.";
352 if (vehicle_object_->IsSendProtocolClear()) {
353 vehicle_object_->AddSendProtocol();
354 }
355 }
356 is_control_cmd_time_delay_previous_ = is_control_cmd_time_delay_;
357}
358
359void CanbusComponent::ProcessGuardianCmdTimeout(
360 GuardianCommand *guardian_command) {
361 AINFO << "Into cmd timeout process, set estop.";
362 guardian_command->mutable_control_command()->set_throttle(0.0);
363 guardian_command->mutable_control_command()->set_steering_target(0.0);
364 guardian_command->mutable_control_command()->set_steering_rate(25.0);
365 guardian_command->mutable_control_command()->set_brake(FLAGS_estop_brake);
366}
367
368} // namespace canbus
369} // 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 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
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