Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,21 @@ my_can_socket->send(frame);

```

### Time Stamps and `socketcan_adapter`

Each message carries `receive_time` (`std::chrono::steady_clock`) and `bus_time` (`std::chrono::system_clock`), both default to the epoch.

Constructing a message from a [`polymath::socketcan::CanFrame`](https://github.com/polymathrobotics/socketcan_adapter) decodes the frame and copies both time stamps.

```c++
polymath::socketcan::CanFrame frame = ...;
my_can_library_name::MessageName message{frame};
message.receive_time;
message.bus_time;
```

This makes `socketcan_adapter` a dependency of `dbc_gen_cpp`, installed by `rosdep install`.

### Signal Value Maps (Enums)

DBC value tables (`VAL_` lines, and the global `VAL_TABLE_`) map raw signal values
Expand Down
3 changes: 3 additions & 0 deletions dbc_gen_cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ endif()

find_package(ament_cmake REQUIRED)
find_package(ament_cmake_python REQUIRED)
find_package(socketcan_adapter REQUIRED)

ament_python_install_package(${PROJECT_NAME}
SCRIPTS_DESTINATION bin
Expand All @@ -23,6 +24,7 @@ target_include_directories(${PROJECT_NAME} INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include/${PROJECT_NAME}>
)
target_link_libraries(${PROJECT_NAME} INTERFACE socketcan_adapter::socketcan_adapter)

install(
TARGETS ${PROJECT_NAME}
Expand Down Expand Up @@ -50,6 +52,7 @@ if(BUILD_TESTING)
endif()

ament_export_targets(${PROJECT_NAME}Targets HAS_LIBRARY_TARGET)
ament_export_dependencies(socketcan_adapter)
ament_package(
CONFIG_EXTRAS "dbc_gen_cpp-extras.cmake"
)
14 changes: 14 additions & 0 deletions dbc_gen_cpp/dbc_gen_cpp/templates/can.hpp.j2
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@

#include <linux/can.h>

#include <chrono>
#include <cstdint>
#include <stdexcept>

#include "socketcan_adapter/can_frame.hpp"
#include "{{ library_name }}/{{ c_header }}"

namespace {{ library_name }}
Expand Down Expand Up @@ -54,6 +56,10 @@ struct {{ message.name }}
}
{% endif %}

// Time stamps
std::chrono::steady_clock::time_point receive_time{};
std::chrono::system_clock::time_point bus_time{};

// Signals
{% for signal in message.signals %}
double {{ signal.name }};
Expand Down Expand Up @@ -104,6 +110,14 @@ struct {{ message.name }}
{% endif %}
}

// Constructor from socketcan CanFrame, keeps its time stamps
explicit {{ message.name }}(const polymath::socketcan::CanFrame & frame)
: {{ message.name }}(frame.get_frame())
{
receive_time = frame.get_receive_time();
bus_time = frame.get_bus_time();
}

// Conversion operator to can_frame
operator can_frame() const
{
Expand Down
2 changes: 2 additions & 0 deletions dbc_gen_cpp/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
<buildtool_depend>ament_cmake</buildtool_depend>
<buildtool_depend>ament_cmake_python</buildtool_depend>

<depend>socketcan_adapter</depend>

<exec_depend>python3-cantools-pip</exec_depend>
<exec_depend>python3-jinja2</exec_depend>

Expand Down
32 changes: 32 additions & 0 deletions test_dbc_gen_cpp/test/test_dbc_cpp.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2026 Polymath Robotics, Inc.
// SPDX-License-Identifier: Apache-2.0

#include <chrono>
#include <cstring>
#include <type_traits>

Expand Down Expand Up @@ -368,6 +369,37 @@ TEST_CASE("Standard CAN ID mismatch throws")
REQUIRE_THROWS(fake_vehicle_can::SteeringFeedback{frame});
}

TEST_CASE("Construct from socketcan CanFrame keeps time stamps")
{
can_frame raw;
memset(&raw, 0, sizeof(raw));
raw.can_id = fake_vehicle_can::SteeringFeedback::Id;
raw.can_dlc = fake_vehicle_can::SteeringFeedback::DataLength;
raw.data[0] = 25;

polymath::socketcan::CanFrame frame{raw};
const auto receive_time = std::chrono::steady_clock::time_point{std::chrono::seconds{5}};
const auto bus_time = std::chrono::system_clock::time_point{std::chrono::seconds{7}};
frame.set_receive_timestamp(receive_time);
frame.set_bus_timestamp(bus_time);

const fake_vehicle_can::SteeringFeedback msg{frame};

REQUIRE(msg.receive_time == receive_time);
REQUIRE(msg.bus_time == bus_time);
REQUIRE(msg.angle == 25);
}

TEST_CASE("Construct from socketcan CanFrame with wrong ID throws")
{
can_frame raw;
memset(&raw, 0, sizeof(raw));
raw.can_id = 100;
raw.can_dlc = 1;

REQUIRE_THROWS(fake_vehicle_can::SteeringFeedback{polymath::socketcan::CanFrame{raw}});
}

// ============================================================================
// J1939 Protocol Parsing Tests
// ============================================================================
Expand Down
Loading