Tendon API
The Tendon API is a set of Python APIs that allow for easy interaction with the motor control system from a host PC over serial USB connection. If you reviewed the documentation for the Tendon Embedded Software Guide, then you will probably observe that the amount of control features for the system comes at the price of complexity. Fortunately, we don’t have to expose this complexity to everybody, and we can abstract away the communication protocol, which is the purpose of these APIs. This page documents how to use the APIs in your own code. There are two classes in the API and they are documented here.
batbot_bringup.bb_tendons package
Submodules
batbot_bringup.bb_tendons.TendonController module
This module provides high level functions for interacting with the motor communication protocol.
After following the Software Setup, you should be able to import this module as follows:
import batbot_bringup.bb_tendons.TendonController
See the rest of this documentation for the available classes and functions in this module.
- class batbot_bringup.bb_tendons.TendonController.COM_TYPE(*values)
Bases:
Enum
A data type for enumerating the communication types available for the TendonController.
- FAKE_SPI = 1
- NONE = -1
- SPI = 0
- UART = 2
- class batbot_bringup.bb_tendons.TendonController.OPCODE(*values)
Bases:
Enum
A data type for enumerating the opcodes for the tendon communication protocol. Note that the enum values correspond to the actual opcode value in the protocol. (TODO: Probably delete this and use the one in TendonHardware.py)
- ECHO = 0
- READ_ANGLE = 2
- READ_STATUS = 1
- SET_MAX_ANGLE = 6
- SET_ZERO_ANGLE = 5
- WRITE_ANGLE = 3
- WRITE_PID = 4
- class batbot_bringup.bb_tendons.TendonController.TendonController(com=COM_TYPE.NONE, port_name='')
Bases:
object
This class is used to control and interface with NEEC motor controller via a serial connection.
Built off the
TendonHardwareInterface
class for packing and unpacking serial packet data.’- Parameters:
com (COM_TYPE) – An enum specifying the communication interface to use (UART, SPI, etc.) (NOT USED!)
port_name (str) – The serial port name used for communication with the motor controller
- Variables:
test_mode (bool) – A boolean specifying if the tendon controller is in test mode
test__angle (int) – An internal variable used to store the angle in test mode
test__max_angle (int) – A internal variable used to store the max angle in test mode
th (
TendonHardwareInterface
) – An instance of theTendonHardwareInterface
class to be used as a packet handler
HOW TO USE
1) First, create a TendonController object specifying the communication type and port number. Example:
tendonController = TendonController(port_name="/dev/ttyACM0")
If no port name is specified, then the TendonController is started in test mode. In test mode, any commands are simply written or read from internal variables.
2) You can then call any function to control a motor. For example, to write motor 0 to 120 degrees call:
tendonController.writeMotorAngle(0, 120)
If this file is run as a script, it will run an example program utilizing this class.
- close()
- moveMotorToMax(id)
NOT USED!
- moveMotorToMin(id)
NOT USED!
- readMotorAngle(id)
This function reads the motor specified by id. Raises an assertion error if the status returned by the response packet is not
COMM_SUCCESS
TODO: The function currently breaks if any communication errors occured during packet transmission
In test mode, the angle value simply reads the value of
test__angle
.- Parameters:
id (int) – The motor id whose angle is to be set
- Returns:
The angle of motor
id
- Return type:
signed int16
- setMotorMaxAngle(id, angle)
This function sets the max angle of the motor specified by id to the passed in angle. Raises an assertion error if the status returned by the response packet is not
COMM_SUCCESS
TODO: The function currently breaks if any communication errors occured during packet transmission
In test mode, the angle value simply gets written to
test__max_angle
.- Parameters:
id (int) – The motor id whose angle is to be set
angle – The maximum motor angle
- setMotorPID(id, Kp, Ki, Kd)
Sets the PID (Proportional-Integral-Derivative) parameters for a motor.
- setNewZero(id)
Resets the encoder count of the motor specified by id, effectively setting the current position to the 0 angle. Raises an assertion error if the status returned by the response packet is not
COMM_SUCCESS
TODO: The function currently breaks if any communication errors occured during packet transmission
In test mode, the
test__angle
variable is simply set to 0.- Parameters:
id (int) – The motor id whose angle is to be reset
- writeMotorAbsoluteAngle(id, angle: int16)
This function sets the motor specified by id to move to the passed in angle. Raises an assertion error if the status returned by the response packet is not
COMM_SUCCESS
TODO: The function currently breaks if any communication errors occured during packet transmission
In test mode, the angle value simply gets written to
test__angle
.- Parameters:
id (int) – The motor id whose angle is to be set
angle – The motor angle
batbot_bringup.bb_tendons.TendonHardware module
This module provides utility functions interfacing with the motor communication protocol.
- class batbot_bringup.bb_tendons.TendonHardware.OPCODE(*values)
Bases:
Enum
A data type for enumerating the opcodes for the tendon communication protocol. Note that the enum values correspond to the actual opcode value in the protocol.
- ECHO = 0
- READ_ANGLE = 2
- READ_STATUS = 1
- WRITE_ANGLE = 3
- WRITE_PID = 4
- class batbot_bringup.bb_tendons.TendonHardware.TendonHardwareInterface(port_name)
Bases:
object
This module is designed acts as an abstraction layer between a high level Tendoncontrol API and the motor communication protocol. This class should not be instantiated directly for any user code. This class contains functions responsible for assembling and unpacking packet data transmitted to and from the motor controller.
Upon initialization, a serial connection is opened with the device specified by
port_name
. Ifport_name
, isNONE
, then no serial connection is opened. The serial device is closed automatically upon destruction.- Parameters:
port_name (str) – The serial port name used for communication with the motor controller
- Variables:
ser (pyserial.Serial) – An instance of the serial communication device
packet (byte) – A byte array storing the packet to be transmitted or received
- BuildPacket(id, opcode, params)
This function constructs a packet according to the the motor communication protocol and automatically appends a CRC16 checksum to the end of the packet. The packet is stored in the
packet
instance variable and NOT returned to the user. This function should therefore be called before everytime a packet is sent. This function does NOT check:if the id is valid
if the opcode is valid
- Parameters:
id (int) – The id of the motor to be commanded
opcode (int) – The opcode corresponding to the operation to perform on motor
id
params (list[int]) – An array of packet parameters for the motor operation
- ReadRx()
This function reads a packet from the serial device. Because the motor communication protocol function is a request-response model, this function shouldn’t be directly called by user code. Instead, this function is a helper function for the
SendTxRX
function.This function will return a timeout error if no valid packets are ever read. The error will be given as the function returning -1 (TODO: its preferrable to raise an exception instead). However, the function will block if no serial data is ever received (TODO: need to fix that and set a timeout). This function also performs automatic CRC checking, but will still return the data if CRC validation fails (TODO: maybe raise an exception instead). Otherwise, if a packet is successfully read, the function returns a byte array containing everything after the packet header.
- Returns:
A byte array containing the received packet data (without the packet header) or -1 if any communication errors occured
- Return type:
bytes or int
- SendTx()
This function sends a packet from the serial device without reading the response packet. This function can be called directly in user code, but please make sure to clear the serial buffer to ensure future packets are read properly. Before calling this function be sure to call
BuildPacket()
to set the packet to be sent.
- SendTxRx()
This function sends and reads a packet from the serial device. This function should be called directly in user code. Before calling this function be sure to call
BuildPacket()
to set the packet to be sent. ReadReadRxx()
for information on possible errors when reading packets. If any errors occured, this function will return -1 (TODO: maybe raise an exception instead). If the serial transaction was successfull, then a dictionary will be returned with the following fields:id: the id of the motor being commanded
opcode: the opcode corresponding to the motor command sent
status: the status bit returned by the motor operation (refer to Tendon Embedded Software Guide for status codes)
params: the parameters returned by the response packet
- Returns:
A dict containing the response packet data as described above or -1 if any communication errors occured
- Return type:
dict or int
- batbot_bringup.bb_tendons.TendonHardware.crc16(data: bytes)
A utility function for computing CRC-16 (CCITT) implemented with a precomputed lookup table
- Parameters:
data (bytes) – an array of bytes to compute crc 16 on
- Returns:
an array of 2 bytes with the first element being the high bytes, and the second being the low bytes
- Return type:
bytes
Module contents
Extending the Tendon API
After creating a new command (as shown in Tendon Embedded Software Guide), you will likely want to create a new API function for your command.
This is as simple as adding a new function to the TendonHardwareInterface
class.
You should utilize the class’s th
instance variable for automatic parsing and packing of your command packet.
Possible Improvements
More graceful error handling on the Python API (use exceptions instead of returns)
Implement all the functions created in the embedded side
Alternate communication protocols (SPI)