From 053a761244d75bcae4ca99684098f3188586832e Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Thu, 10 Feb 2022 13:01:30 -0800 Subject: [PATCH] CANParser: add field for all values from a cycle (#558) * could work * should be light-speed * clean up * clean up * make sure updated is empty if nothing is updated updating without a msg is undefined behavior * should be fast enough * more test Co-authored-by: Adeeb Shihadeh --- can/common.h | 1 + can/common.pxd | 1 + can/common_dbc.h | 3 ++- can/parser.cc | 14 ++++++++---- can/parser_pyx.pyx | 39 +++++++++++++++++++-------------- can/tests/test_packer_parser.py | 31 ++++++++++++++++++++++++++ 6 files changed, 68 insertions(+), 21 deletions(-) diff --git a/can/common.h b/can/common.h index 301d2af..be9089e 100644 --- a/can/common.h +++ b/can/common.h @@ -32,6 +32,7 @@ public: std::vector parse_sigs; std::vector vals; + std::vector> all_vals; uint64_t seen; uint64_t check_threshold; diff --git a/can/common.pxd b/can/common.pxd index 5fb35e9..dd54a0e 100644 --- a/can/common.pxd +++ b/can/common.pxd @@ -62,6 +62,7 @@ cdef extern from "common_dbc.h": uint32_t address const char* name double value + vector[double] all_values cdef struct SignalPackValue: string name diff --git a/can/common_dbc.h b/can/common_dbc.h index db885cf..2464dde 100644 --- a/can/common_dbc.h +++ b/can/common_dbc.h @@ -25,7 +25,8 @@ struct MessageParseOptions { struct SignalValue { uint32_t address; const char* name; - double value; + double value; // latest value + std::vector all_values; // all values from this cycle }; enum SignalType { diff --git a/can/parser.cc b/can/parser.cc index 67d4363..dc1887c 100644 --- a/can/parser.cc +++ b/can/parser.cc @@ -83,6 +83,7 @@ bool MessageState::parse(uint64_t sec, uint8_t * dat) { } vals[i] = tmp * sig.factor + sig.offset; + all_vals[i].push_back(vals[i]); } seen = sec; @@ -147,6 +148,7 @@ CANParser::CANParser(int abus, const std::string& dbc_name, if (sig->type != SignalType::DEFAULT) { state.parse_sigs.push_back(*sig); state.vals.push_back(0); + state.all_vals.push_back({}); } } @@ -160,6 +162,7 @@ CANParser::CANParser(int abus, const std::string& dbc_name, && sig->type == SignalType::DEFAULT) { state.parse_sigs.push_back(*sig); state.vals.push_back(0); + state.all_vals.push_back({}); break; } } @@ -188,6 +191,7 @@ CANParser::CANParser(int abus, const std::string& dbc_name, bool ignore_checksum const Signal *sig = &msg->sigs[j]; state.parse_sigs.push_back(*sig); state.vals.push_back(0); + state.all_vals.push_back({}); } message_states[state.address] = state; @@ -209,7 +213,7 @@ void CANParser::update_string(const std::string &data, bool sendcan) { last_sec = event.getLogMonoTime(); - auto cans = sendcan? event.getSendcan() : event.getCan(); + auto cans = sendcan ? event.getSendcan() : event.getCan(); UpdateCans(last_sec, cans); UpdateValid(last_sec); @@ -282,17 +286,19 @@ void CANParser::UpdateValid(uint64_t sec) { std::vector CANParser::query_latest() { std::vector ret; - for (const auto& kv : message_states) { - const auto& state = kv.second; + for (auto& kv : message_states) { + auto& state = kv.second; if (last_sec != 0 && state.seen != last_sec) continue; - for (int i=0; icv.name self.vl[cv.address][cv_name] = cv.value - updated_val.insert(cv.address) + self.vl_all[cv.address][cv_name].extend(cv.all_values) + updated_addrs.insert(cv.address) - return updated_val + return updated_addrs def update_string(self, dat, sendcan=False): + for v in self.vl_all.values(): + v.clear() + self.can.update_string(dat, sendcan) return self.update_vl() def update_strings(self, strings, sendcan=False): - updated_vals = set() + for v in self.vl_all.values(): + v.clear() + updated_addrs = set() for s in strings: - updated_val = self.update_string(s, sendcan) - updated_vals.update(updated_val) + updated_addrs = self.update_string(s, sendcan) + updated_addrs.update(updated_addrs) + return updated_addrs - return updated_vals cdef class CANDefine(): cdef: @@ -172,7 +180,6 @@ cdef class CANDefine(): values = [int(v) for v in def_val[::2]] defs = def_val[1::2] - # two ways to lookup: address or msg name dv[address][sgname] = dict(zip(values, defs)) dv[msgname][sgname] = dv[address][sgname] diff --git a/can/tests/test_packer_parser.py b/can/tests/test_packer_parser.py index 4b68594..c48776a 100644 --- a/can/tests/test_packer_parser.py +++ b/can/tests/test_packer_parser.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 import unittest +import random import cereal.messaging as messaging from opendbc.can.parser import CANParser @@ -122,6 +123,36 @@ class TestCanParserPacker(unittest.TestCase): idx += 1 + def test_updated(self): + """Test updated value dict""" + dbc_file = "honda_civic_touring_2016_can_generated" + + signals = [("USER_BRAKE", "VSA_STATUS")] + checks = [("VSA_STATUS", 50)] + + parser = CANParser(dbc_file, signals, checks, 0) + packer = CANPacker(dbc_file) + + # Make sure nothing is updated + self.assertEqual(len(parser.vl_all["VSA_STATUS"]["USER_BRAKE"]), 0) + + idx = 0 + for _ in range(10): + # Ensure CANParser holds the values of any duplicate messages + user_brake_vals = [random.randrange(100) for _ in range(random.randrange(10))] + msgs = [] + for user_brake in user_brake_vals: + values = {"USER_BRAKE": user_brake} + msgs.append(packer.make_can_msg("VSA_STATUS", 0, values, idx)) + idx += 1 + + parser.update_strings((can_list_to_can_capnp(msgs), )) + vl_all = parser.vl_all["VSA_STATUS"]["USER_BRAKE"] + + self.assertEqual(vl_all, user_brake_vals) + if len(user_brake_vals): + self.assertEqual(vl_all[-1], parser.vl["VSA_STATUS"]["USER_BRAKE"]) + if __name__ == "__main__": unittest.main()