electrical_protocol
- Electrical-software communication standard¶
The electrical_protocol
module is meant to serve as a bridge between
a software library and a physical electrical device. The library is not dependent
on a particular communication standard (UART, CAN, etc.) being used. Rather, the
library just provides a packet structure that can be used by any project, and a
list of packets using this structure.
The library also provides a simple driver for UART/serial communication with a
physical electrical device – ROSSerialDevice
.
If a CAN standard is desired, the mil_usb_to_can.sub9.CANDeviceHandle
class can be used, which supports packets built through this library.
Packet Format¶
In order to reliably communicate with an electrical board, a consistent packet format must be defined.
Below is the electrical protocol packet format. This packet format wraps every message being sent over the serial connection to the USB to CAN board from ROS.
Name |
Length |
Description |
---|---|---|
Sync character 1 ( |
1 byte |
First sync character indicating the start of packets. |
Sync character 2 ( |
1 byte |
Second sync character indicating the start of packets. |
Class ID |
1 byte |
Message class. Determines the family of messages the packet belongs to. |
Subclass ID |
1 byte |
Message subclass. In combination with class, determines specific qualities of message. |
Payload Length |
2 bytes |
Length of payload. |
Payload |
0-65535 bytes |
Payload. Meaning of payload is determined by specific packet class/subclass. |
Checksum A |
1 byte |
First byte of Fletcher’s checksum. |
Checksum B |
1 byte |
Second byte of Fletcher’s checksum. |
Checksums¶
All messages contain a checksum to help verify data integrity. However, receiving packets also have a special byte containing a slightly modified checksum formula.
The checksum in all packets is found by adding up all bytes in the byte string, including the start/end flags, and then using modulo 16 on this result. The library checksum is implemented like so:
@classmethod
def _calculate_checksum(cls, data: bytes) -> tuple[int, int]:
"""
Used to calculate the Fletcher's checksum for a series of bytes. When
calculating the checksum for a new packet, the start bytes/sync characters
should not be included.
"""
sum1, sum2 = 0, 0
for byte in data:
sum1 = (sum1 + byte) % 255
sum2 = (sum2 + sum1) % 255
return sum1, sum2
Packet Listing¶
Below is a listing of all available packets. The payload format is the format
used by the struct
module. For more information, see the Python documentation
on the list of format characters, and their corresponding
byte length.
Message ID |
Subclass ID |
Payload Format |
Class |
---|---|---|---|
0x00 (Meta) |
0x00 |
Empty |
|
0x01 |
Empty |
||
0x01 (Sub8 Thrust/ Kill) |
0x00 |
Empty |
|
0x01 |
|
|
|
0x02 |
|
|
|
0x03 |
|
|
|
0x02 (Sub9 Thrust/ Kill) |
0x00 |
Empty |
|
0x01 |
Empty |
||
0x02 |
|
||
0x03 |
|
||
0x04 |
|
||
0x03 (Battery Monitor) |
0x00 |
Empty |
|
0x01 |
|
|
|
0x04 (Actuator Board) |
0x00 |
|
|
0x01 |
Empty |
||
0x02 |
|
||
0x05 (System Status) |
0x00 |
Empty |
|
0x10 (NaviGator Temporary Pico Kill Board) |
0x00 |
|
|
0x01 |
|
|
|
0x02 |
|
||
0x11 (NaviGator Ball Launcher Board) |
0x00 |
Empty |
|
0x01 |
|
||
0x20 (Drone) |
0x00 |
Empty |
|
0x01 |
Empty |
||
0x02 |
|
||
0x03 |
Empty |
||
0x04 |
|
||
0x05 |
Empty |
||
0x06 |
|
Exceptions¶
Exception Hierarchy¶
Exception List¶
ROSSerialDevice¶
- defadjust_read_rate
- defclose
- defconnect
- defon_packet_received
- defscale_read_rate
- defsend_packet
- defwrite
- class electrical_protocol.ROSSerialDevice(port: str | None, baudrate: int | None)[source]¶
Represents a generic serial device, which is expected to be the main component of an individual ROS node.
- device¶
The serial class used to communicate with the device.
- Type
Optional[serial.Serial]
- Parameters
- adjust_read_rate(rate: float) None [source]¶
Sets the reading rate to a specified amount.
- Parameters
rate (float) – The reading speed to use, in hz.
- connect(port: str, baudrate: int) None [source]¶
Connects to the port with the given baudrate. If the device is already connected, the input and output buffers will be flushed.
- abstract on_packet_received(packet: RecvPackets) None [source]¶
Abstract method to be implemented by subclasses for handling packets sent by the physical electrical board.
- Parameters
packet (
Packet
) – The packet that is received.
- scale_read_rate(scale: float) None [source]¶
Scales the reading rate of the device handle by some factor.
- Parameters
scale (float) – The amount to scale the reading rate by.
Packet¶
- class electrical_protocol.Packet[source]¶
Represents one packet that can be sent or received by a serial device. This class is able to handle packaging unique data values into a
bytes
object for sending over a data stream.This class should be overridden to implement unique packet payloads. Note that this class supports three subclass arguments to assign unique message IDs, subclass IDs, and payload formats. Note that all subclasses must be decorated with
dataclasses.dataclass()
.If any class members are annotated with a subclass of
enum.Enum
, the class will always make an attempt to convert the raw data value to an instance of the enum before constructing the rest of the values in the class.from dataclasses import dataclass @dataclass class ExamplePacket(Packet, class_id = 0x02, subclass_id = 0x01, payload_format = "BHHf"): example_char: int example_short: int example_short_two: int example_float: float
- bytes(x)
Returns a
bytes
object representing the data of the packet in the specified packet format.
- Parameters
class_id (int) – The message ID. Can be between 0 and 255.
subclass_id (int) – The message subclass ID. Can be between 0 and 255.
payload_format (str) – The format for the payload. This determines how the individual payload is assembled. Each character in the format string represents the position of one class variable. The class variables are assembled in the order they are defined in.
- classmethod from_bytes(packed: bytes, trim: bool = True) PacketSelf [source]¶
Constructs a packet from a packed packet in a
bytes
object. If a packet is found with the corresponding message and subclass ID, then an instance (or subclass) of that packet class will be returned.- Parameters
- Raises
ChecksumException – The checksum is invalid.
LookupError – No packet with the specified class and subclass IDs exist.
- Returns
An instance of the appropriate packet subclass.