Skip to content

Commit ed60244

Browse files
authored
Add in timestamping for usability (#4)
* Add in timestamping for usability * Switch to promise future instead of sleeps
1 parent f6fb1bb commit ed60244

File tree

5 files changed

+290
-13
lines changed

5 files changed

+290
-13
lines changed

socketcan_adapter/include/socketcan_adapter/can_frame.hpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/can.h>
1919

2020
#include <array>
21+
#include <chrono>
2122
#include <cstdint>
2223
#include <memory>
2324
#include <string>
@@ -62,7 +63,7 @@ class CanFrame
6263
CanFrame(
6364
const canid_t raw_id,
6465
const std::array<unsigned char, CAN_MAX_DLC> & data,
65-
const uint64_t & timestamp,
66+
const uint64_t & bus_timestamp,
6667
uint8_t len = CAN_MAX_DLC);
6768

6869
/// @brief Initialize CanFrame with a partial ID and data defined in std::array
@@ -74,7 +75,7 @@ class CanFrame
7475
CanFrame(
7576
const canid_t id,
7677
const std::array<unsigned char, CAN_MAX_DLC> & data,
77-
const uint64_t & timestamp,
78+
const uint64_t & bus_timestamp,
7879
FrameType & frame_type,
7980
IdType & frame_id_type,
8081
uint8_t len = CAN_MAX_DLC);
@@ -113,9 +114,29 @@ class CanFrame
113114
/// @param data INPUT raw data to pass through the socket
114115
void set_data(const std::array<unsigned char, CAN_MAX_DLC> & data);
115116

116-
/// @brief Set timestamp
117+
/// @brief Set bus timestamp
118+
/// @param timestamp INPUT time as uint64_t from the bus
119+
void set_bus_timestamp(const uint64_t & timestamp);
120+
121+
/// @brief Set receive timestamp
117122
/// @param timestamp INPUT time as uint64_t from the bus
118-
void set_timestamp(const uint64_t & timestamp);
123+
void set_receive_timestamp(const uint64_t & timestamp);
124+
125+
/// @brief Set timestamp
126+
/// @param timestamp INPUT time as std::chrono::system_clock::time_point from the bus
127+
void set_bus_timestamp(const std::chrono::system_clock::time_point & timestamp);
128+
129+
/// @brief Set timestamp
130+
/// @param timestamp INPUT time as std::chrono::steady_clock::time_point from the adapter
131+
void set_receive_timestamp(const std::chrono::steady_clock::time_point & timestamp);
132+
133+
/// @brief Get bus time
134+
/// @return returns std::chrono::system_clock::time_point for when the frame was received on the bus
135+
std::chrono::system_clock::time_point get_bus_time() const;
136+
137+
/// @brief Get receive time
138+
/// @return returns std::chrono::steady_clock::time_point for when the frame was received by the adapter
139+
std::chrono::steady_clock::time_point get_receive_time() const;
119140

120141
/// @brief Get frame type
121142
/// @return returns polymath::socketcan::FrameType
@@ -156,7 +177,8 @@ class CanFrame
156177

157178
private:
158179
struct can_frame frame_{};
159-
uint64_t timestamp_{};
180+
std::chrono::steady_clock::time_point receive_time_{};
181+
std::chrono::system_clock::time_point bus_time_{};
160182
};
161183

162184
} // namespace polymath::socketcan

socketcan_adapter/src/can_frame.cpp

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,12 @@ CanFrame::CanFrame(const struct can_frame & frame)
3232
{}
3333

3434
CanFrame::CanFrame(
35-
const canid_t raw_id, const std::array<unsigned char, CAN_MAX_DLC> & data, const uint64_t & timestamp, uint8_t len)
36-
: timestamp_(timestamp)
35+
const canid_t raw_id,
36+
const std::array<unsigned char, CAN_MAX_DLC> & data,
37+
const uint64_t & bus_timestamp,
38+
uint8_t len)
39+
: receive_time_(std::chrono::steady_clock::now())
40+
, bus_time_(std::chrono::system_clock::time_point(std::chrono::microseconds(bus_timestamp)))
3741
{
3842
set_can_id(raw_id);
3943
std::copy(data.begin(), data.end(), frame_.data);
@@ -43,11 +47,12 @@ CanFrame::CanFrame(
4347
CanFrame::CanFrame(
4448
const canid_t id,
4549
const std::array<unsigned char, CAN_MAX_DLC> & data,
46-
const uint64_t & timestamp,
50+
const uint64_t & bus_timestamp,
4751
FrameType & frame_type,
4852
IdType & frame_id_type,
4953
uint8_t len)
50-
: timestamp_(timestamp)
54+
: receive_time_(std::chrono::steady_clock::now())
55+
, bus_time_(std::chrono::system_clock::time_point(std::chrono::microseconds(bus_timestamp)))
5156
{
5257
set_can_id(id);
5358
set_data(data);
@@ -130,9 +135,34 @@ void CanFrame::set_data(const std::array<unsigned char, CAN_MAX_DLC> & data)
130135
std::copy(data.begin(), data.end(), frame_.data);
131136
}
132137

133-
void CanFrame::set_timestamp(const uint64_t & timestamp)
138+
void CanFrame::set_bus_timestamp(const uint64_t & timestamp)
139+
{
140+
bus_time_ = std::chrono::system_clock::time_point(std::chrono::microseconds(timestamp));
141+
}
142+
143+
void CanFrame::set_receive_timestamp(const uint64_t & timestamp)
144+
{
145+
receive_time_ = std::chrono::steady_clock::time_point(std::chrono::microseconds(timestamp));
146+
}
147+
148+
void CanFrame::set_bus_timestamp(const std::chrono::system_clock::time_point & timestamp)
149+
{
150+
bus_time_ = timestamp;
151+
}
152+
153+
void CanFrame::set_receive_timestamp(const std::chrono::steady_clock::time_point & timestamp)
154+
{
155+
receive_time_ = timestamp;
156+
}
157+
158+
std::chrono::system_clock::time_point CanFrame::get_bus_time() const
159+
{
160+
return bus_time_;
161+
}
162+
163+
std::chrono::steady_clock::time_point CanFrame::get_receive_time() const
134164
{
135-
timestamp_ = timestamp;
165+
return receive_time_;
136166
}
137167

138168
IdType CanFrame::get_id_type() const

socketcan_adapter/src/socketcan_adapter.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <unistd.h>
2525

2626
#include <cerrno>
27+
#include <chrono>
2728
#include <cstring>
2829
#include <future>
2930
#include <memory>
@@ -172,9 +173,12 @@ std::optional<SocketcanAdapter::socket_error_string_t> SocketcanAdapter::receive
172173
struct timeval tv;
173174
ioctl(socket_file_descriptor_, SIOCGSTAMP, &tv);
174175

175-
uint64_t timestamp_uint64 = static_cast<uint64_t>(tv.tv_sec) * 1e6 + tv.tv_usec;
176+
// uint64_t timestamp_uint64 = static_cast<uint64_t>(tv.tv_sec) * 1e6 + tv.tv_usec;
177+
std::chrono::system_clock::time_point timestamp{
178+
std::chrono::seconds{tv.tv_sec} + std::chrono::microseconds{tv.tv_usec}};
176179
polymath_can_frame.set_frame(frame);
177-
polymath_can_frame.set_timestamp(timestamp_uint64);
180+
polymath_can_frame.set_bus_timestamp(timestamp);
181+
polymath_can_frame.set_receive_timestamp(std::chrono::steady_clock::now());
178182
}
179183

180184
return error_string.empty() ? std::nullopt : std::optional<socket_error_string_t>(error_string);

socketcan_adapter/test/can_frame_test.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <algorithm>
1616
#include <array>
17+
#include <chrono>
1718
#include <cstdint>
1819
#include <string>
1920

@@ -168,3 +169,103 @@ TEST_CASE("Get error as string", "[CanFrame]")
168169
std::string error = frame.get_error();
169170
REQUIRE(!error.empty());
170171
}
172+
173+
TEST_CASE("Set and get bus timestamp with uint64_t", "[CanFrame]")
174+
{
175+
polymath::socketcan::CanFrame frame;
176+
std::uint64_t timestamp_us = 1000000; // 1 second in microseconds
177+
178+
frame.set_bus_timestamp(timestamp_us);
179+
auto bus_time = frame.get_bus_time();
180+
181+
auto expected = std::chrono::system_clock::time_point(std::chrono::microseconds(timestamp_us));
182+
REQUIRE(bus_time == expected);
183+
}
184+
185+
TEST_CASE("Set and get receive timestamp with uint64_t", "[CanFrame]")
186+
{
187+
polymath::socketcan::CanFrame frame;
188+
std::uint64_t timestamp_us = 2000000; // 2 seconds in microseconds
189+
190+
frame.set_receive_timestamp(timestamp_us);
191+
auto receive_time = frame.get_receive_time();
192+
193+
auto expected = std::chrono::steady_clock::time_point(std::chrono::microseconds(timestamp_us));
194+
REQUIRE(receive_time == expected);
195+
}
196+
197+
TEST_CASE("Set and get bus timestamp with time_point", "[CanFrame]")
198+
{
199+
polymath::socketcan::CanFrame frame;
200+
auto timestamp = std::chrono::system_clock::now();
201+
202+
frame.set_bus_timestamp(timestamp);
203+
auto bus_time = frame.get_bus_time();
204+
205+
REQUIRE(bus_time == timestamp);
206+
}
207+
208+
TEST_CASE("Set and get receive timestamp with time_point", "[CanFrame]")
209+
{
210+
polymath::socketcan::CanFrame frame;
211+
auto timestamp = std::chrono::steady_clock::now();
212+
213+
frame.set_receive_timestamp(timestamp);
214+
auto receive_time = frame.get_receive_time();
215+
216+
REQUIRE(receive_time == timestamp);
217+
}
218+
219+
TEST_CASE("Constructor initializes receive_time to now", "[CanFrame]")
220+
{
221+
auto before = std::chrono::steady_clock::now();
222+
223+
canid_t raw_id = 0x123;
224+
std::array<unsigned char, CAN_MAX_DLC> data = {1, 2, 3, 4, 5, 6, 7, 8};
225+
std::uint64_t bus_timestamp = 123456789;
226+
polymath::socketcan::CanFrame frame(raw_id, data, bus_timestamp);
227+
228+
auto after = std::chrono::steady_clock::now();
229+
auto receive_time = frame.get_receive_time();
230+
231+
REQUIRE(receive_time >= before);
232+
REQUIRE(receive_time <= after);
233+
}
234+
235+
TEST_CASE("Constructor sets bus_time from timestamp parameter", "[CanFrame]")
236+
{
237+
canid_t raw_id = 0x123;
238+
std::array<unsigned char, CAN_MAX_DLC> data = {1, 2, 3, 4, 5, 6, 7, 8};
239+
std::uint64_t bus_timestamp = 5000000; // 5 seconds in microseconds
240+
241+
polymath::socketcan::CanFrame frame(raw_id, data, bus_timestamp);
242+
auto bus_time = frame.get_bus_time();
243+
244+
auto expected = std::chrono::system_clock::time_point(std::chrono::microseconds(bus_timestamp));
245+
REQUIRE(bus_time == expected);
246+
}
247+
248+
TEST_CASE("Extended constructor initializes timestamps correctly", "[CanFrame]")
249+
{
250+
auto before = std::chrono::steady_clock::now();
251+
252+
canid_t raw_id = 0x789;
253+
std::array<unsigned char, CAN_MAX_DLC> data = {9, 8, 7, 6, 5, 4, 3, 2};
254+
std::uint64_t bus_timestamp = 10000000; // 10 seconds in microseconds
255+
auto frame_type = polymath::socketcan::FrameType::REMOTE;
256+
auto frame_id_type = polymath::socketcan::IdType::EXTENDED;
257+
258+
polymath::socketcan::CanFrame frame(raw_id, data, bus_timestamp, frame_type, frame_id_type);
259+
260+
auto after = std::chrono::steady_clock::now();
261+
262+
// Check receive_time was set to approximately now
263+
auto receive_time = frame.get_receive_time();
264+
REQUIRE(receive_time >= before);
265+
REQUIRE(receive_time <= after);
266+
267+
// Check bus_time was set from the parameter
268+
auto bus_time = frame.get_bus_time();
269+
auto expected_bus_time = std::chrono::system_clock::time_point(std::chrono::microseconds(bus_timestamp));
270+
REQUIRE(bus_time == expected_bus_time);
271+
}

0 commit comments

Comments
 (0)