Apollo  6.0
Open source self driving car software
can_receiver.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 <atomic>
25 #include <cmath>
26 #include <future>
27 #include <iostream>
28 #include <memory>
29 #include <sstream>
30 #include <thread>
31 #include <vector>
32 
33 #include "cyber/common/macros.h"
34 #include "cyber/cyber.h"
35 
36 #include "modules/common/proto/error_code.pb.h"
37 
41 
46 namespace apollo {
47 namespace drivers {
48 namespace canbus {
49 
54 template <typename SensorType>
55 class CanReceiver {
56  public:
60  CanReceiver() = default;
61 
65  virtual ~CanReceiver() = default;
66 
75  common::ErrorCode Init(CanClient *can_client,
76  MessageManager<SensorType> *pt_manager,
77  bool enable_log);
78 
84  bool IsRunning() const;
85 
90  ::apollo::common::ErrorCode Start();
91 
95  void Stop();
96 
97  private:
98  void RecvThreadFunc();
99 
100  int32_t Start(bool is_blocked);
101 
102  private:
103  std::atomic<bool> is_running_ = {false};
104  // CanClient, MessageManager pointer life is managed by outer program
105  CanClient *can_client_ = nullptr;
106  MessageManager<SensorType> *pt_manager_ = nullptr;
107  bool enable_log_ = false;
108  bool is_init_ = false;
109  std::future<void> async_result_;
110 
111  DISALLOW_COPY_AND_ASSIGN(CanReceiver);
112 };
113 
114 template <typename SensorType>
115 ::apollo::common::ErrorCode CanReceiver<SensorType>::Init(
116  CanClient *can_client, MessageManager<SensorType> *pt_manager,
117  bool enable_log) {
118  can_client_ = can_client;
119  pt_manager_ = pt_manager;
120  enable_log_ = enable_log;
121  if (can_client_ == nullptr) {
122  AERROR << "Invalid can client.";
123  return ::apollo::common::ErrorCode::CANBUS_ERROR;
124  }
125  if (pt_manager_ == nullptr) {
126  AERROR << "Invalid protocol manager.";
127  return ::apollo::common::ErrorCode::CANBUS_ERROR;
128  }
129  is_init_ = true;
131 }
132 
133 template <typename SensorType>
135  AINFO << "Can client receiver thread starts.";
136  CHECK_NOTNULL(can_client_);
137  CHECK_NOTNULL(pt_manager_);
138 
139  int32_t receive_error_count = 0;
140  int32_t receive_none_count = 0;
141  const int32_t ERROR_COUNT_MAX = 10;
142  auto default_period = 10 * 1000;
143 
144  while (IsRunning()) {
145  std::vector<CanFrame> buf;
146  int32_t frame_num = MAX_CAN_RECV_FRAME_LEN;
147  if (can_client_->Receive(&buf, &frame_num) !=
149  LOG_IF_EVERY_N(ERROR, receive_error_count++ > ERROR_COUNT_MAX,
150  ERROR_COUNT_MAX)
151  << "Received " << receive_error_count << " error messages.";
152  cyber::USleep(default_period);
153  continue;
154  }
155  receive_error_count = 0;
156 
157  if (buf.size() != static_cast<size_t>(frame_num)) {
158  AERROR_EVERY(100) << "Receiver buf size [" << buf.size()
159  << "] does not match can_client returned length["
160  << frame_num << "].";
161  }
162 
163  if (frame_num == 0) {
164  LOG_IF_EVERY_N(ERROR, receive_none_count++ > ERROR_COUNT_MAX,
165  ERROR_COUNT_MAX)
166  << "Received " << receive_none_count << " empty messages.";
167  cyber::USleep(default_period);
168  continue;
169  }
170  receive_none_count = 0;
171 
172  for (const auto &frame : buf) {
173  uint8_t len = frame.len;
174  uint32_t uid = frame.id;
175  const uint8_t *data = frame.data;
176  pt_manager_->Parse(uid, data, len);
177  if (enable_log_) {
178  ADEBUG << "recv_can_frame#" << frame.CanFrameString();
179  }
180  }
181  cyber::Yield();
182  }
183  AINFO << "Can client receiver thread stopped.";
184 }
185 
186 template <typename SensorType>
188  return is_running_.load();
189 }
190 
191 template <typename SensorType>
192 ::apollo::common::ErrorCode CanReceiver<SensorType>::Start() {
193  if (is_init_ == false) {
194  return ::apollo::common::ErrorCode::CANBUS_ERROR;
195  }
196  is_running_.exchange(true);
197 
198  async_result_ = cyber::Async(&CanReceiver<SensorType>::RecvThreadFunc, this);
200 }
201 
202 template <typename SensorType>
204  if (IsRunning()) {
205  AINFO << "Stopping can client receiver ...";
206  is_running_.exchange(false);
207  async_result_.wait();
208  } else {
209  AINFO << "Can client receiver is not running.";
210  }
211  AINFO << "Can client receiver stopped [ok].";
212 }
213 
214 } // namespace canbus
215 } // namespace drivers
216 } // namespace apollo
const int32_t MAX_CAN_RECV_FRAME_LEN
Definition: canbus_consts.h:35
void Stop()
Stop the CAN receiver.
Definition: can_receiver.h:203
PlanningContext is the runtime context in planning. It is persistent across multiple frames...
Definition: atomic_hash_map.h:25
Defines the CanFrame struct and CanClient interface.
The class which defines the CAN client to send and receive message.
Definition: can_client.h:92
The class of MessageManager.
#define AERROR_EVERY(freq)
Definition: log.h:86
#define ADEBUG
Definition: log.h:41
virtual apollo::common::ErrorCode Receive(std::vector< CanFrame > *const frames, int32_t *const frame_num)=0
Receive messages.
virtual ~CanReceiver()=default
Destructor.
bool IsRunning() const
Get the working status of this CAN receiver. To check if it is running.
Definition: can_receiver.h:187
common::ErrorCode Init(CanClient *can_client, MessageManager< SensorType > *pt_manager, bool enable_log)
Initialize by a CAN client, message manager.
Definition: can_receiver.h:115
CanReceiver()=default
Constructor.
#define AERROR
Definition: log.h:44
message manager manages protocols. It supports parse and can get protocol data by message id...
Definition: message_manager.h:68
bool OK()
Definition: state.h:44
#define AINFO
Definition: log.h:42
CAN receiver.
Definition: can_receiver.h:55
::apollo::common::ErrorCode Start()
Start the CAN receiver.
Definition: can_receiver.h:192