Apollo 10.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 std::string vehicle_library_path;
53 if (!apollo::cyber::common::GetFilePathWithEnv(FLAGS_load_vehicle_library,
54 "APOLLO_LIB_PATH",
55 &vehicle_library_path)) {
56 AERROR << FLAGS_load_vehicle_library << " No such vehicle library";
57 return false;
58 }
59 AINFO << "Load the vehicle factory library: " << FLAGS_load_vehicle_library
60 << "(" << vehicle_library_path << ")";
61
62 ClassLoader loader(vehicle_library_path);
63 auto vehicle_object = loader.CreateClassObj<AbstractVehicleFactory>(
64 FLAGS_load_vehicle_class_name);
65 if (!vehicle_object) {
66 AERROR << "Failed to create the vehicle factory: "
67 << FLAGS_load_vehicle_class_name;
68 return false;
69 }
70 AINFO << "Successfully create vehicle factory: "
71 << FLAGS_load_vehicle_class_name;
72
73 vehicle_object_ = vehicle_object;
74 if (!vehicle_object_->Init(&canbus_conf_)) {
75 AERROR << "Fail to init vehicle factory.";
76 return false;
77 }
78 AINFO << "Vehicle factory is successfully initialized.";
79
80 cyber::ReaderConfig guardian_cmd_reader_config;
81 guardian_cmd_reader_config.channel_name = FLAGS_guardian_topic;
82 guardian_cmd_reader_config.pending_queue_size =
83 FLAGS_guardian_cmd_pending_queue_size;
84
85 cyber::ReaderConfig control_cmd_reader_config;
86 control_cmd_reader_config.channel_name = FLAGS_control_command_topic;
87 control_cmd_reader_config.pending_queue_size =
88 FLAGS_control_cmd_pending_queue_size;
89
90 cyber::ReaderConfig chassis_cmd_reader_config;
91 chassis_cmd_reader_config.channel_name = FLAGS_chassis_command_topic;
92 chassis_cmd_reader_config.pending_queue_size =
93 FLAGS_control_cmd_pending_queue_size;
94
95 // init cmd reader
96 if (FLAGS_receive_guardian) {
97 guardian_cmd_reader_ = node_->CreateReader<GuardianCommand>(
98 guardian_cmd_reader_config,
99 [this](const std::shared_ptr<GuardianCommand> &cmd) {
100 ADEBUG << "Received guardian data: run canbus callback.";
101 const auto start_time = Time::Now().ToMicrosecond();
102 OnGuardianCommand(*cmd);
103 const auto end_time = Time::Now().ToMicrosecond();
104 if ((end_time - start_time) * 1e-6 > FLAGS_guardian_period) {
105 AWARN << "Guardian callback time: "
106 << (end_time - start_time) * 1e-3 << " ms.";
107 }
108 });
109 } else {
110 control_command_reader_ = node_->CreateReader<ControlCommand>(
111 control_cmd_reader_config,
112 [this](const std::shared_ptr<ControlCommand> &cmd) {
113 ADEBUG << "Received control data: run canbus callback.";
114 const auto start_time = Time::Now().ToMicrosecond();
115 OnControlCommand(*cmd);
116 const auto end_time = Time::Now().ToMicrosecond();
117 if ((end_time - start_time) * 1e-6 > FLAGS_control_period) {
118 AWARN << "Control callback time: " << (end_time - start_time) * 1e-3
119 << " ms.";
120 }
121 });
122 }
123
124 // init chassis cmd reader
125 chassis_command_reader_ = node_->CreateReader<ChassisCommand>(
126 chassis_cmd_reader_config,
127 [this](const std::shared_ptr<ChassisCommand> &cmd) {
128 ADEBUG << "Received control data: run canbus callback.";
129 OnChassisCommand(*cmd);
130 });
131
132 // init chassis writer
133 chassis_writer_ = node_->CreateWriter<Chassis>(FLAGS_chassis_topic);
134
135 // start canbus vehicle
136 if (!vehicle_object_->Start()) {
137 AERROR << "Fail to start canclient, cansender, canreceiver, canclient, "
138 "vehicle controller.";
139 Clear();
140 return false;
141 }
142 AINFO << "Start canclient cansender, canreceiver, canclient, vehicle "
143 "controller successfully.";
144
145 monitor_logger_buffer_.INFO("Canbus is started.");
146
147 return true;
148}
149
150void CanbusComponent::Clear() {
151 vehicle_object_->Stop();
152 AINFO << "Cleanup Canbus component";
153}
154
155void CanbusComponent::PublishChassis() {
156 Chassis chassis = vehicle_object_->publish_chassis();
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 }
188
189 // publish "/apollo/canbus/chassis"
190 PublishChassis();
191
192 // publish "/apollo/canbus/chassis_detail"
193 if (FLAGS_enable_chassis_detail_pub) {
194 vehicle_object_->PublishChassisDetail();
195 }
196
197 // publish "/apollo/canbus/chassis_detail_sender"
198 if (FLAGS_enable_chassis_detail_sender_pub) {
199 vehicle_object_->PublishChassisDetailSender();
200 }
201
202 // update heartbeat in can sender
203 vehicle_object_->UpdateHeartbeat();
204
205 const auto end_time = Time::Now().ToMicrosecond();
206 const double time_diff_ms = (end_time - start_time) * 1e-3;
207 if (time_diff_ms > (1 / FLAGS_chassis_freq * 1e3)) {
208 AWARN << "CanbusComponent::Proc() takes too much time: " << time_diff_ms
209 << " ms";
210 }
211
212 return true;
213}
214
215void CanbusComponent::OnControlCommand(const ControlCommand &control_command) {
216 // us : microsecord = 1e-3 millisecond = 1e-6 second
217 double current_timestamp = Time::Now().ToMicrosecond();
218 // if command coming too soon, just ignore it.
219 // us < 5 ms(millisecond) *1000 (=5000us microsecord)
220 if (current_timestamp - last_timestamp_controlcmd_ <
221 FLAGS_min_cmd_interval * 1000) {
222 ADEBUG << "Control command comes too soon. Ignore. Required "
223 "FLAGS_min_cmd_interval["
224 << FLAGS_min_cmd_interval << "] ms, actual time interval["
225 << (current_timestamp - last_timestamp_controlcmd_) * 1e-3
226 << "] ms.";
227 return;
228 }
229 last_timestamp_controlcmd_ = current_timestamp;
230
231 if (!is_control_cmd_time_delay_) {
232 vehicle_object_->UpdateCommand(&control_command);
233 }
234}
235
236void CanbusComponent::OnControlCommandCheck(
237 const ControlCommand &control_command) {
238 // us : microsecord = 1e-3 millisecond = 1e-6 second
239 double current_timestamp = Time::Now().ToMicrosecond();
240 // cmd_time_diff: s
241 double cmd_time_diff =
242 current_timestamp * 1e-6 - control_command.header().timestamp_sec();
243 if (FLAGS_use_control_cmd_check &&
244 (cmd_time_diff > (FLAGS_max_control_miss_num * FLAGS_control_period))) {
245 AERROR << "Control cmd timeout, sequence_number:"
246 << control_command.header().sequence_num()
247 << ", Time_of_delay:" << cmd_time_diff << " s"
248 << ", time delay threshold: "
249 << (FLAGS_max_control_miss_num * FLAGS_control_period) << " s";
250
251 if (vehicle_object_->Driving_Mode() == Chassis::COMPLETE_AUTO_DRIVE ||
252 vehicle_object_->Driving_Mode() == Chassis::AUTO_STEER_ONLY ||
253 vehicle_object_->Driving_Mode() == Chassis::AUTO_SPEED_ONLY) {
254 is_control_cmd_time_delay_ = true;
255 GuardianCommand new_guardian_command;
256 new_guardian_command.mutable_control_command()->CopyFrom(control_command);
257 ProcessGuardianCmdTimeout(&new_guardian_command);
258 ADEBUG << "new_guardian_command is "
259 << new_guardian_command.ShortDebugString();
260 vehicle_object_->UpdateCommand(&new_guardian_command.control_command());
261 }
262 } else {
263 is_control_cmd_time_delay_ = false;
264 }
265}
266
267void CanbusComponent::OnGuardianCommand(
268 const GuardianCommand &guardian_command) {
269 if (!is_control_cmd_time_delay_) {
270 OnControlCommand(guardian_command.control_command());
271 }
272}
273
274void CanbusComponent::OnGuardianCommandCheck(
275 const GuardianCommand &guardian_command) {
276 // us : microsecord = 1e-3 millisecond = 1e-6 second
277 double current_timestamp = Time::Now().ToMicrosecond();
278 // cmd_time_diff: s
279 double guardian_cmd_time_diff =
280 current_timestamp * 1e-6 - guardian_command.header().timestamp_sec();
281 if (FLAGS_use_guardian_cmd_check &&
282 (guardian_cmd_time_diff >
283 (FLAGS_max_guardian_miss_num * FLAGS_guardian_period))) {
284 AERROR << "Guardain cmd timeout, sequence_number:"
285 << guardian_command.header().sequence_num()
286 << ", Time_of_delay:" << guardian_cmd_time_diff << " s"
287 << ", time delay threshold: "
288 << (FLAGS_max_guardian_miss_num * FLAGS_guardian_period) << " s";
289
290 if (vehicle_object_->Driving_Mode() == Chassis::COMPLETE_AUTO_DRIVE ||
291 vehicle_object_->Driving_Mode() == Chassis::AUTO_STEER_ONLY ||
292 vehicle_object_->Driving_Mode() == Chassis::AUTO_SPEED_ONLY) {
293 is_control_cmd_time_delay_ = true;
294 GuardianCommand new_guardian_command;
295 new_guardian_command.CopyFrom(guardian_command);
296 ProcessGuardianCmdTimeout(&new_guardian_command);
297 ADEBUG << "new_guardian_command is "
298 << new_guardian_command.ShortDebugString();
299 vehicle_object_->UpdateCommand(&new_guardian_command.control_command());
300 }
301 } else {
302 is_control_cmd_time_delay_ = false;
303 }
304}
305
306void CanbusComponent::OnChassisCommand(const ChassisCommand &chassis_command) {
307 // us : microsecord = 1e-3 millisecond = 1e-6 second
308 int64_t current_timestamp = Time::Now().ToMicrosecond();
309 // if command coming too soon, just ignore it.
310 // us < 5 ms(millisecond) *1000 (=5000us microsecord)
311 if (current_timestamp - last_timestamp_chassiscmd_ <
312 FLAGS_min_cmd_interval * 1000) {
313 ADEBUG << "Control command comes too soon. Ignore.\n Required "
314 "FLAGS_min_cmd_interval["
315 << FLAGS_min_cmd_interval << "], actual time interval["
316 << current_timestamp - last_timestamp_chassiscmd_ << "].";
317 return;
318 }
319 last_timestamp_chassiscmd_ = current_timestamp;
320
321 ADEBUG << "Control_sequence_number:"
322 << chassis_command.header().sequence_num() << ", Time_of_delay:"
323 << current_timestamp -
324 static_cast<int64_t>(chassis_command.header().timestamp_sec() *
325 1e6)
326 << " micro seconds";
327
328 vehicle_object_->UpdateCommand(&chassis_command);
329}
330
331common::Status CanbusComponent::OnError(const std::string &error_msg) {
332 monitor_logger_buffer_.ERROR(error_msg);
333 return ::apollo::common::Status(ErrorCode::CANBUS_ERROR, error_msg);
334}
335
336void CanbusComponent::ProcessTimeoutByClearCanSender() {
337 if (vehicle_object_->Driving_Mode() != Chassis::COMPLETE_AUTO_DRIVE &&
338 vehicle_object_->Driving_Mode() != Chassis::AUTO_STEER_ONLY &&
339 vehicle_object_->Driving_Mode() != Chassis::AUTO_SPEED_ONLY &&
340 !FLAGS_chassis_debug_mode) {
341 ADEBUG << "The current driving mode does not need to check cmd timeout.";
342 if (vehicle_object_->IsSendProtocolClear()) {
343 AINFO << "send protocol is clear, ignore driving mode, need to recover "
344 "send protol.";
345 vehicle_object_->AddSendProtocol();
346 }
347 return;
348 }
349
350 if (!is_control_cmd_time_delay_previous_ && is_control_cmd_time_delay_) {
351 AINFO << "control cmd time latency delay, clear send protocol.";
352 vehicle_object_->ClearSendProtocol();
353 } else if (is_control_cmd_time_delay_previous_ &&
354 !is_control_cmd_time_delay_) {
355 AINFO << "control cmd time latency reover, add send protocol.";
356 if (vehicle_object_->IsSendProtocolClear()) {
357 vehicle_object_->AddSendProtocol();
358 }
359 }
360 is_control_cmd_time_delay_previous_ = is_control_cmd_time_delay_;
361}
362
363void CanbusComponent::ProcessGuardianCmdTimeout(
364 GuardianCommand *guardian_command) {
365 AINFO << "Into cmd timeout process, set estop.";
366 guardian_command->mutable_control_command()->set_throttle(0.0);
367 guardian_command->mutable_control_command()->set_steering_target(0.0);
368 guardian_command->mutable_control_command()->set_steering_rate(25.0);
369 guardian_command->mutable_control_command()->set_brake(FLAGS_estop_brake);
370}
371
372} // namespace canbus
373} // 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 GetFilePathWithEnv(const std::string &path, const std::string &env_var, std::string *file_path)
get file path, judgement priority:
Definition file.cc:436
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