teach the packer how to count (#669)

* teach the packer how to count

* fix tests

* same as checksum

* little test
This commit is contained in:
Adeeb Shihadeh 2022-07-21 17:51:49 -07:00 committed by GitHub
parent 72d3f935e6
commit 387dcf9628
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 31 deletions

View File

@ -87,9 +87,10 @@ private:
const DBC *dbc = NULL;
std::map<std::pair<uint32_t, std::string>, Signal> signal_lookup;
std::map<uint32_t, Msg> message_lookup;
std::map<uint32_t, uint32_t> counters;
public:
CANPacker(const std::string& dbc_name);
std::vector<uint8_t> pack(uint32_t address, const std::vector<SignalPackValue> &values, int counter);
std::vector<uint8_t> pack(uint32_t address, const std::vector<SignalPackValue> &values);
Msg* lookup_message(uint32_t address);
};

View File

@ -82,4 +82,4 @@ cdef extern from "common.h":
cdef cppclass CANPacker:
CANPacker(string)
vector[uint8_t] pack(uint32_t, vector[SignalPackValue], int counter)
vector[uint8_t] pack(uint32_t, vector[SignalPackValue])

View File

@ -40,10 +40,12 @@ CANPacker::CANPacker(const std::string& dbc_name) {
init_crc_lookup_tables();
}
std::vector<uint8_t> CANPacker::pack(uint32_t address, const std::vector<SignalPackValue> &signals, int counter) {
std::vector<uint8_t> CANPacker::pack(uint32_t address, const std::vector<SignalPackValue> &signals) {
std::vector<uint8_t> ret(message_lookup[address].size, 0);
// set all values for all given signal/value pairs
bool counter_set = false;
bool checksum_set = false;
for (const auto& sigval : signals) {
auto sig_it = signal_lookup.find(std::make_pair(address, sigval.name));
if (sig_it == signal_lookup.end()) {
@ -57,24 +59,30 @@ std::vector<uint8_t> CANPacker::pack(uint32_t address, const std::vector<SignalP
if (ival < 0) {
ival = (1ULL << sig.size) + ival;
}
set_value(ret, sig, ival);
counter_set = counter_set || (sigval.name == "COUNTER");
checksum_set = checksum_set || (sigval.name == "CHECKSUM");
if (counter_set) {
counters[address] = sigval.value;
}
}
// set message counter
if (counter >= 0){
auto sig_it = signal_lookup.find(std::make_pair(address, "COUNTER"));
if (sig_it == signal_lookup.end()) {
WARN("COUNTER not defined\n");
return ret;
auto sig_it_counter = signal_lookup.find(std::make_pair(address, "COUNTER"));
if (!counter_set && sig_it_counter != signal_lookup.end()) {
const auto& sig = sig_it_counter->second;
if (counters.find(address) == counters.end()) {
counters[address] = 0;
}
const auto& sig = sig_it->second;
set_value(ret, sig, counter);
set_value(ret, sig, counters[address]);
counters[address] = (counters[address] + 1) % (1 << sig.size);
}
// set message checksum
auto sig_it_checksum = signal_lookup.find(std::make_pair(address, "CHECKSUM"));
if (sig_it_checksum != signal_lookup.end()) {
if (!checksum_set && sig_it_checksum != signal_lookup.end()) {
const auto &sig = sig_it_checksum->second;
if (sig.calc_checksum != nullptr) {
unsigned int checksum = sig.calc_checksum(address, sig, ret);

View File

@ -30,7 +30,7 @@ cdef class CANPacker:
self.name_to_address_and_size[string(msg.name)] = (msg.address, msg.size)
self.address_to_size[msg.address] = msg.size
cdef vector[uint8_t] pack(self, addr, values, counter):
cdef vector[uint8_t] pack(self, addr, values):
cdef vector[SignalPackValue] values_thing
values_thing.reserve(len(values))
cdef SignalPackValue spv
@ -40,9 +40,9 @@ cdef class CANPacker:
spv.value = value
values_thing.push_back(spv)
return self.packer.pack(addr, values_thing, counter)
return self.packer.pack(addr, values_thing)
cpdef make_can_msg(self, name_or_addr, bus, values, counter=-1):
cpdef make_can_msg(self, name_or_addr, bus, values):
cdef int addr, size
if type(name_or_addr) == int:
addr = name_or_addr
@ -50,5 +50,5 @@ cdef class CANPacker:
else:
addr, size = self.name_to_address_and_size[name_or_addr.encode('utf8')]
cdef vector[uint8_t] val = self.pack(addr, values, counter)
cdef vector[uint8_t] val = self.pack(addr, values)
return [addr, 0, (<char *>&val[0])[:size], bus]

View File

@ -32,10 +32,10 @@ class TestCanChecksums(unittest.TestCase):
checksum_std = [11, 10, 9, 8]
checksum_ext = [4, 3, 2, 1]
for idx, (std, ext) in enumerate(zip(checksum_std, checksum_ext)):
for std, ext in zip(checksum_std, checksum_ext):
msgs = [
packer.make_can_msg("LKAS_HUD", 0, values, idx),
packer.make_can_msg("LKAS_HUD_A", 0, values, idx),
packer.make_can_msg("LKAS_HUD", 0, values),
packer.make_can_msg("LKAS_HUD_A", 0, values),
]
can_strings = [can_list_to_can_capnp(msgs), ]
parser.update_strings(can_strings)

View File

@ -45,6 +45,39 @@ class TestCanParserPacker(unittest.TestCase):
self.assertEqual(bus, b)
self.assertEqual(dat[0], i)
def test_packer_counter(self):
signals = [
("COUNTER", "CAN_FD_MESSAGE"),
]
checks = [("CAN_FD_MESSAGE", 0), ]
packer = CANPacker(TEST_DBC)
parser = CANParser(TEST_DBC, signals, checks, 0)
# packer should increment the counter
for i in range(1000):
msg = packer.make_can_msg("CAN_FD_MESSAGE", 0, {})
dat = can_list_to_can_capnp([msg, ])
parser.update_string(dat)
self.assertEqual(parser.vl["CAN_FD_MESSAGE"]["COUNTER"], i % 256)
# setting COUNTER should override
for _ in range(100):
cnt = random.randint(0, 255)
msg = packer.make_can_msg("CAN_FD_MESSAGE", 0, {
"COUNTER": cnt,
})
dat = can_list_to_can_capnp([msg, ])
parser.update_string(dat)
self.assertEqual(parser.vl["CAN_FD_MESSAGE"]["COUNTER"], cnt)
# then, should resume counting from the override value
cnt = parser.vl["CAN_FD_MESSAGE"]["COUNTER"]
for i in range(100):
msg = packer.make_can_msg("CAN_FD_MESSAGE", 0, {})
dat = can_list_to_can_capnp([msg, ])
parser.update_string(dat)
self.assertEqual(parser.vl["CAN_FD_MESSAGE"]["COUNTER"], (cnt + i) % 256)
def test_parser_can_valid(self):
signals = [
("COUNTER", "CAN_FD_MESSAGE"),
@ -89,18 +122,15 @@ class TestCanParserPacker(unittest.TestCase):
packer = CANPacker(TEST_DBC)
parser = CANParser(TEST_DBC, signals, checks, 0)
idx = 0
for steer in range(-256, 255):
for active in (1, 0):
v1 = {
"STEER_TORQUE": steer,
"STEER_TORQUE_REQUEST": active,
}
m1 = packer.make_can_msg("STEERING_CONTROL", 0, v1, idx)
m1 = packer.make_can_msg("STEERING_CONTROL", 0, v1)
v2 = {
"COUNTER": idx % 256,
"SIGNED": steer,
"64_BIT_LE": random.randint(0, 100),
"64_BIT_BE": random.randint(0, 100),
@ -120,7 +150,6 @@ class TestCanParserPacker(unittest.TestCase):
for sig in ("STEER_TORQUE", "STEER_TORQUE_REQUEST", "COUNTER", "CHECKSUM"):
self.assertEqual(parser.vl["STEERING_CONTROL"][sig], parser.vl[228][sig])
idx += 1
def test_scale_offset(self):
"""Test that both scale and offset are correctly preserved"""
@ -134,16 +163,14 @@ class TestCanParserPacker(unittest.TestCase):
parser = CANParser(dbc_file, signals, checks, 0)
packer = CANPacker(dbc_file)
idx = 0
for brake in range(0, 100):
values = {"USER_BRAKE": brake}
msgs = packer.make_can_msg("VSA_STATUS", 0, values, idx)
msgs = packer.make_can_msg("VSA_STATUS", 0, values)
bts = can_list_to_can_capnp([msgs])
parser.update_string(bts)
self.assertAlmostEqual(parser.vl["VSA_STATUS"]["USER_BRAKE"], brake)
idx += 1
def test_subaru(self):
# Subuaru is little endian
@ -162,7 +189,6 @@ class TestCanParserPacker(unittest.TestCase):
packer = CANPacker(dbc_file)
idx = 0
for steer in range(-256, 255):
for active in [1, 0]:
values = {
@ -171,7 +197,7 @@ class TestCanParserPacker(unittest.TestCase):
"SET_1": 1
}
msgs = packer.make_can_msg("ES_LKAS", 0, values, idx)
msgs = packer.make_can_msg("ES_LKAS", 0, values)
bts = can_list_to_can_capnp([msgs])
parser.update_string(bts)
@ -179,7 +205,6 @@ class TestCanParserPacker(unittest.TestCase):
self.assertAlmostEqual(parser.vl["ES_LKAS"]["LKAS_Request"], active)
self.assertAlmostEqual(parser.vl["ES_LKAS"]["SET_1"], 1)
self.assertAlmostEqual(parser.vl["ES_LKAS"]["COUNTER"], idx % 16)
idx += 1
def test_bus_timeout(self):
@ -243,7 +268,7 @@ class TestCanParserPacker(unittest.TestCase):
for frame, brake_vals in enumerate((user_brake_vals[:half_idx], user_brake_vals[half_idx:])):
for user_brake in brake_vals:
values = {"USER_BRAKE": user_brake}
can_msgs[frame].append(packer.make_can_msg("VSA_STATUS", 0, values, idx))
can_msgs[frame].append(packer.make_can_msg("VSA_STATUS", 0, values))
idx += 1
can_strings = [can_list_to_can_capnp(msgs) for msgs in can_msgs]