Python Autogeneration

Current System

Currently, we have autogeneration setup to take in a yaml_rx_all.c file. This structure allows us to define what a CAN message looks like, and have receiving code generated for us.

For example, in centre_console.yaml:

cc_info: id: 5 critical: true target: motor_controller: watchdog: 3 power_distribution: watchdog: 3 signals: target_velocity: length: 32 drive_state: length: 8 cruise_control: length: 8 regen_braking: length: 8 hazard_enabled: length: 8

Here, we can see that we have a few signals which target centre console. Through autogeneration, these are interpreted into .c files. One of these files is motor_controller_rx_all.c.

void can_rx_all() { CanMessage msg = { 0 }; while (can_receive(&msg) == STATUS_CODE_OK) { // TODO: Not sure if for loop is best way // Might be O(n) // If store all functions in callback array may be better? // Or do some sort or binary search for O(lgn) switch (msg.id.raw) { case SYSTEM_CAN_MESSAGE_CENTRE_CONSOLE_DRIVE_OUTPUT: g_rx_struct.drive_output_target_velocity = (msg.data >> 0); g_rx_struct.drive_output_drive_state = (msg.data >> 32); g_rx_struct.drive_output_cruise_control = (msg.data >> 40); g_rx_struct.drive_output_regen_braking = (msg.data >> 48); g_rx_struct.drive_output_precharge = (msg.data >> 56); g_rx_struct.received_drive_output = true; break; ... ... ... } } }

Python Generation for Telemetry

For telemetry, our system works with the following flow of data

Packet received by controller board → sent using XBee → Received on client-side Xbee → Packet decoded

The client side is entirely done in Python, and needs a way to interpret the packets in order to decode them. The received packet structure will look something like this:

received_packet/ ├─ packet_header ├─ CAN_data/ │ ├─ arbitration_id │ ├─ data │ ├─ crc

The purpose of adding new autogeneration to our Python client-side decoding is to parse out the CAN data into signals, similar to how it was done in C.

  • Validate the CRC (optional, do this once everything else is done)

  • Check the arbitration ID and determine the sending board

  • Using the arbitration ID, parse the data into the corresponding signals

    • Note how this step was executed on the C side. In the existing method, we check whether we are the target board and only parse those signals. On the client side for telemetry, we are always the receiving board, and now care about who sent the signals, and must parse out all of them.

This task is not to design telemetry, but to generate a supporting file which is dynamically updated as we update our CAN message structures. To complete this, additional functionality must be added to generator.py. The following items must be checked off:

All board yamls are read into some data structure
Using this data structure, create a function that takes in an input frame and parses it into the respective signals. Again, use something like a dictionary to return these items
Create a dummy packet to test the autogeneration, and put this into a unit test to go along with the PR.