DriveWorks SDK Reference
3.0.4260 Release
For Test and Development only

CAN Interpreter
Note
SW Release Applicability: This tutorial is applicable to modules in both NVIDIA DriveWorks and NVIDIA DRIVE Software releases.

CAN Interpreter Module workflow

Initialization

The interpreter module for DBC format is initialized as follows:

dwCANInterpreter_buildFromDBC(&interpreter, "path/to/definition.dbc", ...);

The DBC message and signals definition file will be parsed to initialize the interpreter. Please refer to a DBC file format documentation for additional details on the expected syntax.

An interpreter for user-defined format is initialized as follows:

// following callbacks to be implemented by user
interpreter.addMessage = cb_addMessage;
interpreter.getDataf32 = cb_getDataf32;
interpreter.getDataf64 = cb_getDataf64;
interpreter.getDatai32 = cb_getDatai32;
interpreter.getNumAvailableSignals = cb_getNumAvailableSignals;
interpreter.getSignalInfo = cb_getSignalInfo;
dwCANInterpreter_buildFromCallbacks(&canParser, interpreter, NULL, ...);

The dwCANInterpreterInterface structure is populated with pointers to the callbacks implemented by the user. The expected callback signatures are detailed in Interpreter.h. The callbacks are used as follows:

The following callbacks are required to be implemented:

  • addMessage
  • getNumAvailableSignals
  • getSignalInfo

The following callbacks are optional and have to be implemented only if a signal data type requires them:

  • getDataf32
  • getDataf64
  • getDatai32

An example implementation of those callbacks is provided in CAN Message Interpreter Sample

Consuming messages

CAN messages can be provided to the interpreter for parsing as follows:

dwCANInterpreter_consume(&msg, interpreter);

Then used as follows:

uint32_t num;
dwStatus status = dwCANInterpreter_getNumberSignals(&num, interpreter);
if (status == DW_SUCCESS && num > 0)
{
int32_t int_value = 0;
float32_t float_value = 0;
dwTime_t timestamp = 0;
const char* name;
// for each signal
for (uint32_t i = 0; i < num; ++i)
{
// get name of signal
if (dwCANInterpreter_getSignalName(&name, i, interpreter) == DW_SUCCESS)
{
// do something based on signal name
if (strcmp(name, "some_signal_int") == 0)
{
if (dwCANInterpreter_geti32(&int_value, &timestamp, i, interpreter) == DW_SUCCESS)
std::cout << "some_signal_int value: " << int_value << std::endl;
else
std::cerr << "error getting value for some_signal_int" << std::endl;
}
elseif (strcmp(name, "some_signal_float") == 0)
{
if (dwCANInterpreter_getf32(&float_value, &timestamp, i, interpreter) == DW_SUCCESS)
std::cout << "some_signal_float value: " << float_value << std::endl;
else
std::cerr << "error getting value for some_signal_float" << std::endl;
}
else std::cerr << "unhandled signal name" << std::endl;
}
}
}

The above snippet iterates over all signals handled by the intepreter, and attempts to read a value for each signal, in the latest consumed dwCANMessage.

Note that in general the number of signals as returned by dwCANInterpreter_getNumberSignals() is the number of valid signals found in last consumed CAN message. However this does not have to be true in user-provided callback based interpreters, as it is implementation dependent.

Releasing the interpreter

The interpreter can be released as follows:

For more details see CAN Message Interpreter Sample