Galaxis Codebase  1.0.0
Team Galaxis software stack for the Carolo Cup 2023 - ROS2 based software
ECUHandler.cpp
Go to the documentation of this file.
1 #include "ECUHandler.hpp"
2 #include "rclcpp/rclcpp.hpp"
3 #include <cstring>
4 #include <sstream>
5 #include <string>
6 #include <iostream>
9 #include <galaxis/Errors.hpp>
10 
11 static const uint8_t gcu8_header[8] = { 0xDE, 0xAD, 0xF0, 0x0D, 0xDE, 0xAD, 0xBE, 0xEF };
12 
14  CRCType crc;
15  crc.reset();
16  /* compute crc without crc of packet */
17  crc.process_bytes(&packet, sizeof(ComputerPacket) - sizeof(packet.crc));
18 
19  return crc.checksum();
20 }
21 
23  CRCType crc;
24  crc.reset();
25  /* compute crc without crc of packet */
26  crc.process_bytes(&packet, sizeof(SettingsPacket) - sizeof(packet.crc));
27 
28  return crc.checksum();
29 }
30 
32  cb_ = cb;
34  xlog("ECUHandler", "Successfully Initialised...");
35 }
36 
38  memcpy(&(packet.preamble), gcu8_header, sizeof(packet.preamble));
39  packet.packet_id = PACKET_ID_COMPUTER;
40 
41  packet.crc = calculateChecksum(packet);
42 
43  m_lastEcuPacket = packet;
44 
45  size_t written = m_pCommunication->VSendData(&packet, sizeof(ComputerPacket));
46  if(written != sizeof(ComputerPacket)) {
47  xlog("ECUHandler", "Could not write the whole computer packet");
48  }
49 }
50 
52  memcpy(&(packet.preamble), gcu8_header, sizeof(packet.preamble));
53  packet.packet_id = PACKET_ID_SETTINGS;
54 
55  packet.crc = calculateChecksum(packet);
56 
57  size_t written = m_pCommunication->VSendData(&packet, sizeof(SettingsPacket));
58  if(written != sizeof(SettingsPacket)) {
59  xlog("ECUHandler", "Could not write the whole settings packet");
60  /* TODO: ... */
62  }
63 }
64 
65 void ECUHandler::onNewPacketReceived(const EcuPacket* const packet) {
66  if(this->cb_ == nullptr || packet == nullptr) {
67  xlog("ECUHandler Error", "callback is a nullptr");
68  /* TODO: go in failsafe mode */
70  }
71 
72  this->cb_(packet, packet_differences);
73 }
74 
76  receiverThreadRunning = false;
77  if(receiverThread != nullptr)
78  delete receiverThread;
79 }
80 
82  xlog("ECUHandler", "INIT UART");
83  m_pCommunication = std::shared_ptr<ICommunication>(new UART());
84 
85  if(m_pCommunication != nullptr) {
86  m_pCommunication->VConnect();
87  if(!m_pCommunication->IsConnected()) {
88  xlog("ECUHandler", "Failed to open serial port to breakout");
89  return;
90  }
91 
92  receiverThreadRunning = true;
93  receiverThread = new std::thread(&ECUHandler::ReceiveHandler, this);
94 
95  while(!firstPacketReceived) {
96  /* TODO: why do we sleep here for 1 ms? */
97  std::this_thread::sleep_for(std::chrono::milliseconds(1));
98  }
99  }
100 }
101 
103  CRCType crc;
104  uint8_t buf[4096];
105  uint8_t packet[sizeof(EcuPacket)];
106 
107  int packetIndex = 0;
108 
109  enum {
110  RECEIVING_PREAMBLE,
111  RECEIVING_DATA,
112  CRC_UPDATE,
113  } state = RECEIVING_PREAMBLE;
114 
115  while(receiverThreadRunning) {
116  uint8_t byte;
117  size_t bytesRead = m_pCommunication->VReceiveData(buf, sizeof(buf));
118 
119  for(size_t i = 0; i < bytesRead; i++) {
120 
121  byte = buf[i];
122 
123  switch(state) {
124  case RECEIVING_PREAMBLE:
125 
126  packet[packetIndex] = byte;
127  if(gcu8_header[packetIndex++] != byte) {
128  packetIndex = 0;
129  }
130  if(packetIndex == 8)
131  state = RECEIVING_DATA;
132 
133  break;
134 
135  case RECEIVING_DATA:
136 
137  packet[packetIndex++] = byte;
138 
139  if(packetIndex == sizeof(packet))
140  state = CRC_UPDATE;
141  break;
142 
143  default:
144  /* TODO: errorhandler */
145  return;
146  break;
147  }
148 
149  if(state == CRC_UPDATE) {
150  const size_t begin_of_crc_sum = sizeof(packet) - 4;
151  crc.reset();
152  crc.process_bytes(packet, begin_of_crc_sum);
153  const uint32_t computed_crc = crc.checksum();
154 
155  uint32_t packetCrc = packet[begin_of_crc_sum];
156  packetCrc |= packet[begin_of_crc_sum + 1] << 8;
157  packetCrc |= packet[begin_of_crc_sum + 2] << 16;
158  packetCrc |= packet[begin_of_crc_sum + 3] << 24;
159 
160  if(packetCrc == computed_crc) {
161  std::stringstream ss;
162  //xlog("ECUHandler","Received new Packet");
163 
164  current_timestamp = std::chrono::steady_clock::now();
165  if(firstPacketReceived) {
166  std::chrono::duration<double, std::milli> diff_ms =
168  if(diff_ms.count() < 9.5 || diff_ms.count() > 10.5 /*ms*/) {
169  //ss << "=====>Current difference is " << diff_ms.count() << "ms";
170 
171  //std::cout << ss.str() << std::endl;
172  }
173  packet_differences.at(difference_index) = diff_ms;
174  }
176 
178  if(difference_index == packet_differences.size()) {
179  difference_index = 0;
180  }
181 
182  firstPacketReceived = true;
183  memcpy(&currentPacket, packet, sizeof(currentPacket));
185  //std::thread(&ECUHandler::onNewPacketReceived, this, &currentPacket);
186  } else {
187  xlog("ECUHandler", "Wrong CRC checksum");
188  }
189 
190  packetIndex = 0;
191  state = RECEIVING_PREAMBLE;
192  }
193  }
194  }
195 }
ECUHandler::firstPacketReceived
bool firstPacketReceived
Definition: ECUHandler.hpp:111
ECUHandler::receiverThreadRunning
bool receiverThreadRunning
Definition: ECUHandler.hpp:101
motorSettings.hpp
UART
Definition: UART.hpp:6
ECUHandler::m_lastEcuPacket
ComputerPacket m_lastEcuPacket
Definition: ECUHandler.hpp:88
ECUHandler::current_timestamp
std::chrono::steady_clock::time_point current_timestamp
Definition: ECUHandler.hpp:71
ECUHandler::difference_index
size_t difference_index
Definition: ECUHandler.hpp:73
ECUHandler::InitializeCommunication
void InitializeCommunication()
Definition: ECUHandler.cpp:81
ECUHandler::ReceiveHandler
void ReceiveHandler()
Definition: ECUHandler.cpp:102
EcuPacket
EcuPacket
Definition: Packets.hpp:242
galaxis::Errors::POINTER_ERROR
Definition: Errors.hpp:18
ECUHandler::TransmitPacket
void TransmitPacket(SettingsPacket &packet)
This function transmits a packet to the ECU.
Definition: ECUHandler.cpp:51
ECUHandler::onNewPacketReceived
void onNewPacketReceived(const EcuPacket *const)
Definition: ECUHandler.cpp:65
galaxis::Errors::UNDEFINED_ERROR
Definition: Errors.hpp:12
ECUHandler::currentPacket
EcuPacket currentPacket
Definition: ECUHandler.hpp:109
ECUHandler::cb_
PublishMeasurementsCallback cb_
Definition: ECUHandler.hpp:94
PublishMeasurementsCallback
std::function< void(const EcuPacket *const, const std::array< std::chrono::duration< double, std::milli >, 10 > &)> PublishMeasurementsCallback
Callback function that processes an ECU packet.
Definition: ECUHandler.hpp:34
CRCType
boost::crc_32_type CRCType
Definition: ECUHandler.hpp:29
ECUHandler::m_pCommunication
std::shared_ptr< ICommunication > m_pCommunication
Definition: ECUHandler.hpp:117
ECUHandler.hpp
ECUHandler::init
void init(PublishMeasurementsCallback cb)
Provides the handler with a connection to the ECUNode to communicate via ROS.
Definition: ECUHandler.cpp:31
servoSettings.hpp
ECUHandler::receiverThread
std::thread * receiverThread
Definition: ECUHandler.hpp:100
ECUHandler::last_timestamp
std::chrono::steady_clock::time_point last_timestamp
Definition: ECUHandler.hpp:72
xlog
#define xlog(X, Y)
Definition: ECUHandler.hpp:3
ComputerPacket
ComputerPacket
Definition: Packets.hpp:103
ECUHandler::packet_differences
std::array< std::chrono::duration< double, std::milli >, 10 > packet_differences
Definition: ECUHandler.hpp:74
ECUHandler::calculateChecksum
uint32_t calculateChecksum(ComputerPacket const &packet)
Definition: ECUHandler.cpp:13
SettingsPacket
SettingsPacket
Definition: Packets.hpp:31
PACKET_ID_COMPUTER
#define PACKET_ID_COMPUTER
Definition: Packets.hpp:12
ECUHandler::Stop
void Stop()
Definition: ECUHandler.cpp:75
PACKET_ID_SETTINGS
#define PACKET_ID_SETTINGS
Definition: Packets.hpp:13
gcu8_header
static const uint8_t gcu8_header[8]
Definition: ECUHandler.cpp:11
Errors.hpp