Apollo 10.0
自动驾驶开放平台
can_sender.h
浏览该文件的文档.
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
22#pragma once
23
24#include <algorithm>
25#include <array>
26#include <memory>
27#include <mutex>
28#include <thread>
29#include <unordered_map>
30#include <vector>
31
32#include "gtest/gtest_prod.h"
33
34#include "modules/common_msgs/basic_msgs/error_code.pb.h"
35
36#include "cyber/common/log.h"
37#include "cyber/common/macros.h"
38#include "cyber/time/time.h"
42
47namespace apollo {
48namespace drivers {
49namespace canbus {
50
55template <typename SensorType>
57 public:
64 SenderMessage(const uint32_t message_id,
65 ProtocolData<SensorType> *protocol_data);
66
76 SenderMessage(const uint32_t message_id,
77 ProtocolData<SensorType> *protocol_data, bool init_with_one);
78
82 virtual ~SenderMessage() = default;
83
88 void UpdateCurrPeriod(const int32_t delta_period);
89
94 void Update();
95
100 void Update_Heartbeat();
101
106 struct CanFrame CanFrame();
107
112 uint32_t message_id() const;
113
119 int32_t curr_period() const;
120
121 private:
122 uint32_t message_id_ = 0;
123 ProtocolData<SensorType> *protocol_data_ = nullptr;
124
125 int32_t period_ = 0;
126 int32_t curr_period_ = 0;
127
128 private:
129 static std::mutex mutex_;
130 struct CanFrame can_frame_to_send_;
131 struct CanFrame can_frame_to_update_;
132};
133
138template <typename SensorType>
140 public:
144 CanSender() = default;
145
149 virtual ~CanSender() = default;
150
157 common::ErrorCode Init(CanClient *can_client,
158 MessageManager<SensorType> *pt_manager,
159 bool enable_log);
160
169 void AddMessage(uint32_t message_id, ProtocolData<SensorType> *protocol_data,
170 bool init_with_one = false);
171
172 void ClearMessage();
173
174 bool IsMessageClear();
175
181
182 /*
183 * @brief Update the protocol data based the types.
184 */
185 void Update();
186
187 /*
188 * @brief Update the heartbeat protocol data based the types.
189 */
190 void Update_Heartbeat();
191
195 void Stop();
196
202 bool IsRunning() const;
203 bool enable_log() const;
204
205 FRIEND_TEST(CanSenderTest, OneRunCase);
206
207 private:
208 void PowerSendThreadFunc();
209
210 bool NeedSend(const SenderMessage<SensorType> &msg,
211 const int32_t delta_period);
212 bool is_init_ = false;
213 bool is_running_ = false;
214
215 CanClient *can_client_ = nullptr; // Owned by global canbus.cc
216 MessageManager<SensorType> *pt_manager_ = nullptr;
217 std::vector<SenderMessage<SensorType>> send_messages_;
218 std::unique_ptr<std::thread> thread_;
219 bool enable_log_ = false;
220
222};
223
224const uint32_t kSenderInterval = 6000;
225
226template <typename SensorType>
228
229template <typename SensorType>
231 const uint32_t message_id, ProtocolData<SensorType> *protocol_data)
232 : SenderMessage(message_id, protocol_data, false) {}
233
234template <typename SensorType>
236 const uint32_t message_id, ProtocolData<SensorType> *protocol_data,
237 bool init_with_one)
238 : message_id_(message_id), protocol_data_(protocol_data) {
239 if (init_with_one) {
240 for (int32_t i = 0; i < protocol_data->GetLength(); ++i) {
241 can_frame_to_update_.data[i] = 0xFF;
242 }
243 }
244 int32_t len = protocol_data_->GetLength();
245
246 can_frame_to_update_.id = message_id_;
247 can_frame_to_update_.len = static_cast<uint8_t>(len);
248
249 period_ = protocol_data_->GetPeriod();
250 curr_period_ = period_;
251
252 Update();
253}
254
255template <typename SensorType>
256void SenderMessage<SensorType>::UpdateCurrPeriod(const int32_t period_delta) {
257 curr_period_ -= period_delta;
258 if (curr_period_ <= 0) {
259 curr_period_ = period_;
260 }
261}
262
263template <typename SensorType>
265 if (protocol_data_ == nullptr) {
266 AERROR << "Attention: ProtocolData is nullptr!";
267 return;
268 }
269 protocol_data_->UpdateData(can_frame_to_update_.data);
270
271 std::lock_guard<std::mutex> lock(mutex_);
272 can_frame_to_send_ = can_frame_to_update_;
273}
274
275template <typename SensorType>
277 if (protocol_data_ == nullptr) {
278 AERROR << "Attention: ProtocolData is nullptr!";
279 return;
280 }
281 protocol_data_->UpdateData_Heartbeat(can_frame_to_update_.data);
282
283 std::lock_guard<std::mutex> lock(mutex_);
284 can_frame_to_send_ = can_frame_to_update_;
285}
286
287template <typename SensorType>
289 return message_id_;
290}
291
292template <typename SensorType>
293struct CanFrame SenderMessage<SensorType>::CanFrame() {
294 std::lock_guard<std::mutex> lock(mutex_);
295 return can_frame_to_send_;
296}
297
298template <typename SensorType>
300 return curr_period_;
301}
302
303template <typename SensorType>
305 CHECK_NOTNULL(can_client_);
306 CHECK_NOTNULL(pt_manager_);
307 sched_param sch;
308 sch.sched_priority = 99;
309 pthread_setschedparam(pthread_self(), SCHED_FIFO, &sch);
310
311 const int32_t INIT_PERIOD = 5000; // 5ms
312 int32_t delta_period = INIT_PERIOD;
313 int32_t new_delta_period = INIT_PERIOD;
314
315 int64_t tm_start = 0;
316 int64_t tm_end = 0;
317 int64_t sleep_interval = 0;
318
319 AINFO << "Can client sender thread starts.";
320
321 while (is_running_) {
322 tm_start = cyber::Time::Now().ToNanosecond() / 1e3;
323 new_delta_period = INIT_PERIOD;
324
325 for (auto &message : send_messages_) {
326 bool need_send = NeedSend(message, delta_period);
327 message.UpdateCurrPeriod(delta_period);
328 new_delta_period = std::min(new_delta_period, message.curr_period());
329
330 if (!need_send) {
331 continue;
332 }
333 std::vector<CanFrame> can_frames;
334 CanFrame can_frame = message.CanFrame();
335 can_frames.push_back(can_frame);
336 if (can_client_->SendSingleFrame(can_frames) != common::ErrorCode::OK) {
337 AERROR << "Send msg failed:" << can_frame.CanFrameString();
338 }
339 if (enable_log()) {
340 AINFO << "send_can_frame#" << can_frame.CanFrameString();
341 }
342 {
343 uint32_t uid = can_frame.id;
344 const uint8_t *data = can_frame.data;
345 uint8_t len = can_frame.len;
346 pt_manager_->ParseSender(uid, data, len);
347 }
348 }
349 delta_period = new_delta_period;
350 tm_end = cyber::Time::Now().ToNanosecond() / 1e3;
351 sleep_interval = delta_period - (tm_end - tm_start);
352
353 if (sleep_interval > 0) {
354 std::this_thread::sleep_for(std::chrono::microseconds(sleep_interval));
355 } else {
356 // do not sleep
357 AWARN << "Too much time for calculation: " << tm_end - tm_start
358 << "us is more than minimum period: " << delta_period << "us";
359 }
360 }
361 AINFO << "Can client sender thread stopped!";
362}
363
364template <typename SensorType>
366 CanClient *can_client, MessageManager<SensorType> *pt_manager,
367 bool enable_log) {
368 if (is_init_) {
369 AERROR << "Duplicated Init request.";
371 }
372 if (can_client == nullptr) {
373 AERROR << "Invalid can client.";
375 }
376 is_init_ = true;
377 can_client_ = can_client;
378 pt_manager_ = pt_manager;
379 enable_log_ = enable_log;
380 if (pt_manager_ == nullptr) {
381 AERROR << "Invalid protocol manager.";
382 return ::apollo::common::ErrorCode::CANBUS_ERROR;
383 }
385}
386
387template <typename SensorType>
388void CanSender<SensorType>::AddMessage(uint32_t message_id,
389 ProtocolData<SensorType> *protocol_data,
390 bool init_with_one) {
391 if (protocol_data == nullptr) {
392 AERROR << "invalid protocol data.";
393 return;
394 }
395 send_messages_.emplace_back(
396 SenderMessage<SensorType>(message_id, protocol_data, init_with_one));
397 AINFO << "Add send message:" << std::hex << message_id;
398}
399
400template <typename SensorType>
402 if (is_running_) {
403 AERROR << "Cansender has already started.";
405 }
406 is_running_ = true;
407 thread_.reset(new std::thread([this] { PowerSendThreadFunc(); }));
408
410}
411
412// cansender -> Update_Heartbeat()
413template <typename SensorType>
415 for (auto &message : send_messages_) {
416 message.Update_Heartbeat();
417 }
418}
419
420template <typename SensorType>
422 for (auto &message : send_messages_) {
423 message.Update();
424 }
425}
426
427template <typename SensorType>
429 send_messages_.clear();
430}
431
432template <typename SensorType>
434 if (send_messages_.empty()) {
435 return true;
436 }
437 return false;
438}
439
440template <typename SensorType>
442 if (is_running_) {
443 AINFO << "Stopping can sender ...";
444 is_running_ = false;
445 if (thread_ != nullptr && thread_->joinable()) {
446 thread_->join();
447 }
448 thread_.reset();
449 } else {
450 AERROR << "CanSender is not running.";
451 }
452
453 AINFO << "Can client sender stopped [ok].";
454}
455
456template <typename SensorType>
458 return is_running_;
459}
460
461template <typename SensorType>
463 return enable_log_;
464}
465
466template <typename SensorType>
468 const int32_t delta_period) {
469 return msg.curr_period() <= delta_period;
470}
471
472} // namespace canbus
473} // namespace drivers
474} // namespace apollo
Defines the CanFrame struct and CanClient interface.
uint64_t ToNanosecond() const
convert time to nanosecond.
Definition time.cc:83
static Time Now()
get the current time.
Definition time.cc:57
The class which defines the CAN client to send and receive message.
Definition can_client.h:92
common::ErrorCode Init(CanClient *can_client, MessageManager< SensorType > *pt_manager, bool enable_log)
Initialize by a CAN client based on its brand.
Definition can_sender.h:365
void Stop()
Stop the CAN sender.
Definition can_sender.h:441
void AddMessage(uint32_t message_id, ProtocolData< SensorType > *protocol_data, bool init_with_one=false)
Add a message with its ID, protocol data.
Definition can_sender.h:388
apollo::common::ErrorCode Start()
Start the CAN sender.
Definition can_sender.h:401
bool IsRunning() const
Get the working status of this CAN sender.
Definition can_sender.h:457
FRIEND_TEST(CanSenderTest, OneRunCase)
CanSender()=default
Constructor.
virtual ~CanSender()=default
Destructor.
message manager manages protocols.
This is the base class of protocol data.
This class defines the message to send.
Definition can_sender.h:56
SenderMessage(const uint32_t message_id, ProtocolData< SensorType > *protocol_data)
Constructor which takes message ID and protocol data.
Definition can_sender.h:230
void Update()
Update the protocol data.
Definition can_sender.h:264
void Update_Heartbeat()
Always update the protocol data.
Definition can_sender.h:276
virtual ~SenderMessage()=default
Destructor.
void UpdateCurrPeriod(const int32_t delta_period)
Update the current period for sending messages by a difference.
Definition can_sender.h:256
uint32_t message_id() const
Get the message ID.
Definition can_sender.h:288
int32_t curr_period() const
Get the current period to send messages.
Definition can_sender.h:299
#define DISALLOW_COPY_AND_ASSIGN(classname)
Definition macros.h:48
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
The class of MessageManager
const uint32_t kSenderInterval
Definition can_sender.h:224
class register implement
Definition arena_queue.h:37
The class of ProtocolData
The class which defines the information to send and receive.
Definition can_client.h:48
uint8_t len
Message length
Definition can_client.h:52
uint8_t data[8]
Message content
Definition can_client.h:54