Apollo  6.0
Open source self driving car software
can_sender.h
Go to the documentation of this file.
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 "cyber/common/macros.h"
35 
36 #include "cyber/common/log.h"
37 #include "cyber/time/time.h"
38 #include "modules/common/proto/error_code.pb.h"
41 
46 namespace apollo {
47 namespace drivers {
48 namespace canbus {
49 
54 template <typename SensorType>
56  public:
63  SenderMessage(const uint32_t message_id,
64  ProtocolData<SensorType> *protocol_data);
65 
75  SenderMessage(const uint32_t message_id,
76  ProtocolData<SensorType> *protocol_data, bool init_with_one);
77 
81  virtual ~SenderMessage() = default;
82 
87  void UpdateCurrPeriod(const int32_t delta_period);
88 
93  void Update();
94 
99  struct CanFrame CanFrame();
100 
105  uint32_t message_id() const;
106 
112  int32_t curr_period() const;
113 
114  private:
115  uint32_t message_id_ = 0;
116  ProtocolData<SensorType> *protocol_data_ = nullptr;
117 
118  int32_t period_ = 0;
119  int32_t curr_period_ = 0;
120 
121  private:
122  static std::mutex mutex_;
123  struct CanFrame can_frame_to_send_;
124  struct CanFrame can_frame_to_update_;
125 };
126 
131 template <typename SensorType>
132 class CanSender {
133  public:
137  CanSender() = default;
138 
142  virtual ~CanSender() = default;
143 
150  common::ErrorCode Init(CanClient *can_client, bool enable_log);
151 
160  void AddMessage(uint32_t message_id, ProtocolData<SensorType> *protocol_data,
161  bool init_with_one = false);
162 
167  apollo::common::ErrorCode Start();
168 
169  /*
170  * @brief Update the protocol data based the types.
171  */
172  void Update();
173 
177  void Stop();
178 
184  bool IsRunning() const;
185  bool enable_log() const;
186 
187  FRIEND_TEST(CanSenderTest, OneRunCase);
188 
189  private:
190  void PowerSendThreadFunc();
191 
192  bool NeedSend(const SenderMessage<SensorType> &msg,
193  const int32_t delta_period);
194  bool is_init_ = false;
195  bool is_running_ = false;
196 
197  CanClient *can_client_ = nullptr; // Owned by global canbus.cc
198  std::vector<SenderMessage<SensorType>> send_messages_;
199  std::unique_ptr<std::thread> thread_;
200  bool enable_log_ = false;
201 
203 };
204 
205 const uint32_t kSenderInterval = 6000;
206 
207 template <typename SensorType>
209 
210 template <typename SensorType>
212  const uint32_t message_id, ProtocolData<SensorType> *protocol_data)
213  : SenderMessage(message_id, protocol_data, false) {}
214 
215 template <typename SensorType>
217  const uint32_t message_id, ProtocolData<SensorType> *protocol_data,
218  bool init_with_one)
219  : message_id_(message_id), protocol_data_(protocol_data) {
220  if (init_with_one) {
221  for (int32_t i = 0; i < protocol_data->GetLength(); ++i) {
222  can_frame_to_update_.data[i] = 0xFF;
223  }
224  }
225  int32_t len = protocol_data_->GetLength();
226 
227  can_frame_to_update_.id = message_id_;
228  can_frame_to_update_.len = static_cast<uint8_t>(len);
229 
230  period_ = protocol_data_->GetPeriod();
231  curr_period_ = period_;
232 
233  Update();
234 }
235 
236 template <typename SensorType>
237 void SenderMessage<SensorType>::UpdateCurrPeriod(const int32_t period_delta) {
238  curr_period_ -= period_delta;
239  if (curr_period_ <= 0) {
240  curr_period_ = period_;
241  }
242 }
243 
244 template <typename SensorType>
246  if (protocol_data_ == nullptr) {
247  AERROR << "Attention: ProtocolData is nullptr!";
248  return;
249  }
250  protocol_data_->UpdateData(can_frame_to_update_.data);
251 
252  std::lock_guard<std::mutex> lock(mutex_);
253  can_frame_to_send_ = can_frame_to_update_;
254 }
255 
256 template <typename SensorType>
258  return message_id_;
259 }
260 
261 template <typename SensorType>
263  std::lock_guard<std::mutex> lock(mutex_);
264  return can_frame_to_send_;
265 }
266 
267 template <typename SensorType>
269  return curr_period_;
270 }
271 
272 template <typename SensorType>
274  CHECK_NOTNULL(can_client_);
275  sched_param sch;
276  sch.sched_priority = 99;
277  pthread_setschedparam(pthread_self(), SCHED_FIFO, &sch);
278 
279  const int32_t INIT_PERIOD = 5000; // 5ms
280  int32_t delta_period = INIT_PERIOD;
281  int32_t new_delta_period = INIT_PERIOD;
282 
283  int64_t tm_start = 0;
284  int64_t tm_end = 0;
285  int64_t sleep_interval = 0;
286 
287  AINFO << "Can client sender thread starts.";
288 
289  while (is_running_) {
290  tm_start = cyber::Time::Now().ToNanosecond() / 1e3;
291  new_delta_period = INIT_PERIOD;
292 
293  for (auto &message : send_messages_) {
294  bool need_send = NeedSend(message, delta_period);
295  message.UpdateCurrPeriod(delta_period);
296  new_delta_period = std::min(new_delta_period, message.curr_period());
297 
298  if (!need_send) {
299  continue;
300  }
301  std::vector<CanFrame> can_frames;
302  CanFrame can_frame = message.CanFrame();
303  can_frames.push_back(can_frame);
304  if (can_client_->SendSingleFrame(can_frames) != common::ErrorCode::OK) {
305  AERROR << "Send msg failed:" << can_frame.CanFrameString();
306  }
307  if (enable_log()) {
308  ADEBUG << "send_can_frame#" << can_frame.CanFrameString();
309  }
310  }
311  delta_period = new_delta_period;
312  tm_end = cyber::Time::Now().ToNanosecond() / 1e3;
313  sleep_interval = delta_period - (tm_end - tm_start);
314 
315  if (sleep_interval > 0) {
316  std::this_thread::sleep_for(std::chrono::microseconds(sleep_interval));
317  } else {
318  // do not sleep
319  AWARN << "Too much time for calculation: " << tm_end - tm_start
320  << "us is more than minimum period: " << delta_period << "us";
321  }
322  }
323  AINFO << "Can client sender thread stopped!";
324 }
325 
326 template <typename SensorType>
327 common::ErrorCode CanSender<SensorType>::Init(CanClient *can_client,
328  bool enable_log) {
329  if (is_init_) {
330  AERROR << "Duplicated Init request.";
331  return common::ErrorCode::CANBUS_ERROR;
332  }
333  if (can_client == nullptr) {
334  AERROR << "Invalid can client.";
335  return common::ErrorCode::CANBUS_ERROR;
336  }
337  is_init_ = true;
338  can_client_ = can_client;
339  enable_log_ = enable_log;
340  return common::ErrorCode::OK;
341 }
342 
343 template <typename SensorType>
345  ProtocolData<SensorType> *protocol_data,
346  bool init_with_one) {
347  if (protocol_data == nullptr) {
348  AERROR << "invalid protocol data.";
349  return;
350  }
351  send_messages_.emplace_back(
352  SenderMessage<SensorType>(message_id, protocol_data, init_with_one));
353  AINFO << "Add send message:" << std::hex << message_id;
354 }
355 
356 template <typename SensorType>
357 common::ErrorCode CanSender<SensorType>::Start() {
358  if (is_running_) {
359  AERROR << "Cansender has already started.";
360  return common::ErrorCode::CANBUS_ERROR;
361  }
362  is_running_ = true;
363  thread_.reset(new std::thread([this] { PowerSendThreadFunc(); }));
364 
365  return common::ErrorCode::OK;
366 }
367 
368 template <typename SensorType>
370  for (auto &message : send_messages_) {
371  message.Update();
372  }
373 }
374 
375 template <typename SensorType>
377  if (is_running_) {
378  AINFO << "Stopping can sender ...";
379  is_running_ = false;
380  if (thread_ != nullptr && thread_->joinable()) {
381  thread_->join();
382  }
383  thread_.reset();
384  } else {
385  AERROR << "CanSender is not running.";
386  }
387 
388  AINFO << "Can client sender stopped [ok].";
389 }
390 
391 template <typename SensorType>
393  return is_running_;
394 }
395 
396 template <typename SensorType>
398  return enable_log_;
399 }
400 
401 template <typename SensorType>
403  const int32_t delta_period) {
404  return msg.curr_period() <= delta_period;
405 }
406 
407 } // namespace canbus
408 } // namespace drivers
409 } // namespace apollo
const uint32_t kSenderInterval
Definition: can_sender.h:205
virtual ~SenderMessage()=default
Destructor.
std::string CanFrameString() const
CanFrame string including essential information about the message.
Definition: can_client.h:69
uint8_t data[8]
Message content.
Definition: can_client.h:54
PlanningContext is the runtime context in planning. It is persistent across multiple frames...
Definition: atomic_hash_map.h:25
uint32_t id
Message id.
Definition: can_client.h:50
This is the base class of protocol data.
Definition: protocol_data.h:44
SenderMessage(const uint32_t message_id, ProtocolData< SensorType > *protocol_data)
Constructor which takes message ID and protocol data.
Definition: can_sender.h:211
Defines the CanFrame struct and CanClient interface.
The class which defines the CAN client to send and receive message.
Definition: can_client.h:92
#define DISALLOW_COPY_AND_ASSIGN(classname)
Definition: macros.h:48
virtual int32_t GetLength() const
Definition: protocol_data.h:134
common::ErrorCode Init(CanClient *can_client, bool enable_log)
Initialize by a CAN client based on its brand.
Definition: can_sender.h:327
bool enable_log() const
Definition: can_sender.h:397
The class which defines the information to send and receive.
Definition: can_client.h:48
apollo::common::ErrorCode Start()
Start the CAN sender.
Definition: can_sender.h:357
uint8_t len
Message length.
Definition: can_client.h:52
void UpdateCurrPeriod(const int32_t delta_period)
Update the current period for sending messages by a difference.
Definition: can_sender.h:237
CAN sender.
Definition: can_sender.h:132
CanFrame()
Constructor.
Definition: can_client.h:61
#define ADEBUG
Definition: log.h:41
void Update()
Update the protocol data. But the updating process depends on the real type of protocol data which in...
Definition: can_sender.h:245
bool IsRunning() const
Get the working status of this CAN sender. To check if it is running.
Definition: can_sender.h:392
bool Init(const char *binary_name)
uint32_t message_id() const
Get the message ID.
Definition: can_sender.h:257
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:344
The class of ProtocolData.
This class defines the message to send.
Definition: can_sender.h:55
#define AERROR
Definition: log.h:44
void Update()
Definition: can_sender.h:369
#define AWARN
Definition: log.h:43
SensorType
Sensor types are set in the order of lidar, radar, camera, ultrasonic Please make sure SensorType has...
Definition: sensor_meta.h:29
uint64_t ToNanosecond() const
convert time to nanosecond.
bool OK()
Definition: state.h:44
static Time Now()
get the current time.
void Stop()
Stop the CAN sender.
Definition: can_sender.h:376
#define AINFO
Definition: log.h:42
int32_t curr_period() const
Get the current period to send messages. It may be different from the period from protocol data by up...
Definition: can_sender.h:268