29#include <unordered_map>
32#include "gtest/gtest_prod.h"
34#include "modules/common_msgs/basic_msgs/error_code.pb.h"
55template <
typename SensorType>
122 uint32_t message_id_ = 0;
126 int32_t curr_period_ = 0;
129 static std::mutex mutex_;
131 struct CanFrame can_frame_to_update_;
138template <
typename SensorType>
170 bool init_with_one =
false);
208 void PowerSendThreadFunc();
211 const int32_t delta_period);
212 bool is_init_ =
false;
213 bool is_running_ =
false;
217 std::vector<SenderMessage<SensorType>> send_messages_;
218 std::unique_ptr<std::thread> thread_;
219 bool enable_log_ =
false;
226template <
typename SensorType>
229template <
typename SensorType>
234template <
typename SensorType>
238 : message_id_(message_id), protocol_data_(protocol_data) {
240 for (int32_t i = 0; i < protocol_data->
GetLength(); ++i) {
241 can_frame_to_update_.
data[i] = 0xFF;
244 int32_t len = protocol_data_->GetLength();
246 can_frame_to_update_.
id = message_id_;
247 can_frame_to_update_.
len =
static_cast<uint8_t
>(len);
249 period_ = protocol_data_->GetPeriod();
250 curr_period_ = period_;
255template <
typename SensorType>
257 curr_period_ -= period_delta;
258 if (curr_period_ <= 0) {
259 curr_period_ = period_;
263template <
typename SensorType>
265 if (protocol_data_ ==
nullptr) {
266 AERROR <<
"Attention: ProtocolData is nullptr!";
269 protocol_data_->UpdateData(can_frame_to_update_.data);
271 std::lock_guard<std::mutex> lock(mutex_);
272 can_frame_to_send_ = can_frame_to_update_;
275template <
typename SensorType>
277 if (protocol_data_ ==
nullptr) {
278 AERROR <<
"Attention: ProtocolData is nullptr!";
281 protocol_data_->UpdateData_Heartbeat(can_frame_to_update_.data);
283 std::lock_guard<std::mutex> lock(mutex_);
284 can_frame_to_send_ = can_frame_to_update_;
287template <
typename SensorType>
292template <
typename SensorType>
294 std::lock_guard<std::mutex> lock(mutex_);
295 return can_frame_to_send_;
298template <
typename SensorType>
303template <
typename SensorType>
305 CHECK_NOTNULL(can_client_);
306 CHECK_NOTNULL(pt_manager_);
308 sch.sched_priority = 99;
309 pthread_setschedparam(pthread_self(), SCHED_FIFO, &sch);
311 const int32_t INIT_PERIOD = 5000;
312 int32_t delta_period = INIT_PERIOD;
313 int32_t new_delta_period = INIT_PERIOD;
315 int64_t tm_start = 0;
317 int64_t sleep_interval = 0;
319 AINFO <<
"Can client sender thread starts.";
321 while (is_running_) {
323 new_delta_period = INIT_PERIOD;
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());
333 std::vector<CanFrame> can_frames;
334 CanFrame can_frame = message.CanFrame();
335 can_frames.push_back(can_frame);
337 AERROR <<
"Send msg failed:" << can_frame.CanFrameString();
340 AINFO <<
"send_can_frame#" << can_frame.CanFrameString();
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);
349 delta_period = new_delta_period;
351 sleep_interval = delta_period - (tm_end - tm_start);
353 if (sleep_interval > 0) {
354 std::this_thread::sleep_for(std::chrono::microseconds(sleep_interval));
357 AWARN <<
"Too much time for calculation: " << tm_end - tm_start
358 <<
"us is more than minimum period: " << delta_period <<
"us";
361 AINFO <<
"Can client sender thread stopped!";
364template <
typename SensorType>
369 AERROR <<
"Duplicated Init request.";
372 if (can_client ==
nullptr) {
373 AERROR <<
"Invalid can client.";
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;
387template <
typename SensorType>
390 bool init_with_one) {
391 if (protocol_data ==
nullptr) {
392 AERROR <<
"invalid protocol data.";
395 send_messages_.emplace_back(
397 AINFO <<
"Add send message:" << std::hex << message_id;
400template <
typename SensorType>
403 AERROR <<
"Cansender has already started.";
407 thread_.reset(
new std::thread([
this] { PowerSendThreadFunc(); }));
413template <
typename SensorType>
415 for (
auto &message : send_messages_) {
416 message.Update_Heartbeat();
420template <
typename SensorType>
422 for (
auto &message : send_messages_) {
427template <
typename SensorType>
429 send_messages_.clear();
432template <
typename SensorType>
434 if (send_messages_.empty()) {
440template <
typename SensorType>
443 AINFO <<
"Stopping can sender ...";
445 if (thread_ !=
nullptr && thread_->joinable()) {
450 AERROR <<
"CanSender is not running.";
453 AINFO <<
"Can client sender stopped [ok].";
456template <
typename SensorType>
461template <
typename SensorType>
466template <
typename SensorType>
468 const int32_t delta_period) {
Defines the CanFrame struct and CanClient interface.
uint64_t ToNanosecond() const
convert time to nanosecond.
static Time Now()
get the current time.
The class which defines the CAN client to send and receive message.
common::ErrorCode Init(CanClient *can_client, MessageManager< SensorType > *pt_manager, bool enable_log)
Initialize by a CAN client based on its brand.
void Stop()
Stop the CAN sender.
void AddMessage(uint32_t message_id, ProtocolData< SensorType > *protocol_data, bool init_with_one=false)
Add a message with its ID, protocol data.
apollo::common::ErrorCode Start()
Start the CAN sender.
bool IsRunning() const
Get the working status of this CAN sender.
FRIEND_TEST(CanSenderTest, OneRunCase)
CanSender()=default
Constructor.
virtual ~CanSender()=default
Destructor.
message manager manages protocols.
This is the base class of protocol data.
virtual int32_t GetLength() const
This class defines the message to send.
SenderMessage(const uint32_t message_id, ProtocolData< SensorType > *protocol_data)
Constructor which takes message ID and protocol data.
void Update()
Update the protocol data.
void Update_Heartbeat()
Always update the protocol data.
virtual ~SenderMessage()=default
Destructor.
void UpdateCurrPeriod(const int32_t delta_period)
Update the current period for sending messages by a difference.
uint32_t message_id() const
Get the message ID.
int32_t curr_period() const
Get the current period to send messages.
#define DISALLOW_COPY_AND_ASSIGN(classname)
The class of MessageManager
const uint32_t kSenderInterval
The class of ProtocolData
The class which defines the information to send and receive.
uint8_t len
Message length
uint8_t data[8]
Message content