opensourceleg
opensourceleg copied to clipboard
feat: Add TMotor servo mode actuator with native CAN protocol support
Implements complete TMotor servo mode control for AK series actuators (AK80-9, AK10-9) using native CAN communication protocol.
Architecture
Core Classes:
-
TMotorServoActuator: Main actuator class extending ActuatorBase- Manages motor state, control modes, and command interface
- Implements thermal protection via ThermalModel
- Tracks communication timeouts and error states
-
CANManagerServo: Singleton CAN communication manager- Configures CAN0 interface: 1MHz bitrate, txqueuelen 1000
- Handles message sending/receiving via python-can library
- Power on/off commands: 0xFC (on), 0xFD (off)
-
MotorListener: CAN message listener (can.Listener)- Asynchronous message reception via can.Notifier
- Filters messages by motor ID (arbitration_id & 0x00000FF)
- Triggers async state updates in actuator
Data Structures:
-
ServoMotorState: Motor state container- position (degrees), velocity (ERPM), current (amps)
- temperature (celsius), error code, acceleration (rad/s)
-
ServoControlMode: Enum for control modes- POSITION (4), VELOCITY (3), CURRENT (1), IDLE (7)
CAN Protocol Implementation
Message IDs (Extended CAN):
- SET_DUTY: 0x00 (not used)
- SET_CURRENT: 0x01 (current control)
- SET_CURRENT_BRAKE: 0x02 (not used)
- SET_RPM: 0x03 (velocity control)
- SET_POS: 0x04 (position control)
- SET_ORIGIN_HERE: 0x05 (homing)
- SET_POS_SPD: 0x06 (not used)
- Control mode switch: 0x07
Message Format:
-
TX (4 bytes, big-endian): int32 command value
- Position: degrees * 10 (0.1 resolution, configurable to *1000000)
- Velocity: ERPM value directly
- Current: milliamps (current * 1000)
-
RX (8 bytes, big-endian parsing):
- Bytes[0-1]: Position (int16, *0.1 degrees)
- Bytes[2-3]: Velocity (int16, *10 ERPM)
- Bytes[4-5]: Current (int16, *0.01 amps)
- Byte[6]: Temperature (uint8, celsius)
- Byte[7]: Error code (uint8)
Control Features
Implemented Methods:
set_motor_torque(Nm): Converts via Kt to current commandset_output_torque(Nm): Applies gear ratio compensationset_motor_current(A): Direct current commandset_motor_position(rad): Converts to degrees, sends position commandset_motor_velocity(rad/s): Converts to ERPM via pole pairsset_output_velocity(rad/s): Applies gear ratiohome(): Sets origin via CAN_PACKET_SET_ORIGIN_HERE
State Properties:
- motor_position/output_position (radians)
- motor_velocity/output_velocity (rad/s)
- motor_current (amps)
- motor_torque/output_torque (Nm)
- case_temperature/winding_temperature (C)
- error_info: Optional[tuple[error_code, error_message]]
Safety Features
- Thermal protection: 80C case, 110C winding limits (configurable)
- Communication timeout: 100ms threshold warning
- Auto-stop on critical errors (overcurrent, overtemp)
- Acceleration calculation for sudden change detection
- Control mode verification via test command
- Detailed status reporting via
get_detailed_status()
Utility Functions
degrees_to_radians()/radians_to_degrees()erpm_to_rad_per_sec()/rad_per_sec_to_erpm()- Accounts for motor pole pairs in conversion
_pack_int32(): Big-endian int32 packing for CAN TX
Control Mode Management
Each mode has entry/exit callbacks:
- POSITION: Switch to mode 4, no exit action
- VELOCITY: Switch to mode 3, zero velocity on exit
- CURRENT: Switch to mode 1, zero current on exit
- IDLE: Switch to mode 7, no exit action
- All modes wait 100ms after switching for stabilization
Example Code (main)
Demonstrates current control mode with 15Nm torque command:
- Initialize motor (AK80-9, ID:1, offline mode for testing)
- Home motor and activate current control mode
- Command 15Nm output torque
- Run 10Hz monitoring loop for 5 seconds displaying:
- Commanded vs actual torque (motor and output)
- Motor and output angles (rad and degrees)
- Motor and output velocities (rad/s)
- Current, voltage, temperature
- Error status
- Safe shutdown with zero torque
- Display final state summary
Note: Position resolution currently set to 0.1 for simplicity. To enable high-precision mode (0.000001), modify line 323.
Hey @DasuanerA, can you please address the comments soon so that we can merge this PR and start planning our tests?
Welcome to Codecov :tada:
Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.
:information_source: You can also turn on project coverage checks and project coverage reporting on Pull Request comment
Thanks for integrating Codecov - We've got you covered :open_umbrella:
Hey @DasuanerA was any of this tested on hardware?
Hey @DasuanerA was any of this tested on hardware?
Yes. Here is the plot of my testing. I'm now testing the motor on the MBlue Knee.
Can you please resolve the remaining conflicts? And do you have some more information on what kinds of tests you ran?
Can you please resolve the remaining conflicts? And do you have some more information on what kinds of tests you ran?
The test I’m running is static test to check whether the commanded current under the current loop can accurately track the desired trajectory, and the sensors can correctly read all the data.