Issues with Gimbal Motor Control


I have been utilizing the O-Drive 24V motor driver (on version with two TMotor G60 Kv 25 motors and I am running into issues with using the gimbal motor config type. I have both motors wired to the O-Drive, along with the included brake resistor and a 24V power supply. I have configured each axes to current control with the motor type of MOTOR_TYPE_GIMBAL, which, as far as I’m aware, changes all current control parameters into voltage control variables (such as current_lim turns into voltage_lim, etc.). I have also tried to utilize voltage control mode as well, but there were no changes to the motor behavior. I have an issue occurring that I would like to figure out the root cause.

No matter what torque constant I put into the motor configuration (I know this is improper), my input torque command is always “capping out” to ~0.22 N-m (reading the input_torque will read the value that I had sent through the Anaconda interface, but there is no change in the average Iq_measured or voltage going to each phase of the motor). I have double-checked the config_.torque_lim set for each axes are set to inf, as well as ensured that the current_lim parameter is set to 24 for the 24V bus voltage. This behavior can be better shown in the below chart, where past a certain current_lim, the average Iq_measured going to the motor is approaching a max of 2 A. This current is well below the manufacturer’s specifications. Do you know what could be causing this issue?

Here is the table of data that I collected for the chart above:

For full context, I have the following parameters for the motor and controller configs listed on the bottom of the post.

I have scoured through the STM32 firmware files on GitHub looking for some explanations for this behavior. One of the lines that caught my attention was the following command under ODrive/Firmware/MotorControl/motor.cpp.

Lines 368-372:

if (axis_->motor_.config_.motor_type == Motor::MOTOR_TYPE_GIMBAL) {
current_lim = std::min(current_lim, 0.98f*one_by_sqrt3*vbus_voltage); //gimbal motor is voltage control
} else {
current_lim = std::min(current_lim, axis_->motor_.max_allowed_current_);

Why is the voltage for the gimbal motor limited by .98*1/sqrt(3) of the bus voltage? I am wondering if this might be the issue that I am facing. This current_lim leads directly into the max_torque constant.

Another portion I would like to ask about is the Vdq setpoint, also located in motor.cpp.

Lines 587-592:

if (axis_->motor_.config_.motor_type == Motor::MOTOR_TYPE_GIMBAL) {
// reinterpret current as voltage
Vdq_setpoint_ = {vd + id, vq + iq};
} else {
Vdq_setpoint_ = {vd, vq};

I don’t understand why vq and iq are added here, as the Iq is set to be:

iq = torque / axis_->motor_.config_.torque_constant;

Which would seem to me to put it into units of amps. The other parameter I noticed in the calculations of vq and vd was phase_vel. I’m not sure what this parameter is. Could this also be what is contributing to the limiting behavior?

Any help would be greatly appreciated!

Motor Config:

In [5]: odrv0.axis1.motor.config
I_bus_hard_max: inf (float)
I_bus_hard_min: -inf (float)
I_leak_max: 0.10000000149011612 (float)
R_wL_FF_enable: False (bool)
acim_autoflux_attack_gain: 10.0 (float)
acim_autoflux_decay_gain: 1.0 (float)
acim_autoflux_enable: False (bool)
acim_autoflux_min_Id: 10.0 (float)
acim_gain_min_flux: 10.0 (float)
bEMF_FF_enable: False (bool)
calibration_current: 2.0 (float)
current_control_bandwidth: 1000.0 (float)
current_lim: 24.0 (float)
current_lim_margin: 8.0 (float)
dc_calib_tau: 0.20000000298023224 (float)
inverter_temp_limit_lower: 100.0 (float)
inverter_temp_limit_upper: 120.0 (float)
motor_type: 2 (uint8)
phase_inductance: 0.0027199999894946814 (float)
phase_resistance: 6.0 (float)
pole_pairs: 14 (int32)
pre_calibrated: False (bool)
requested_current_range: 60.0 (float)
resistance_calib_max_voltage: 9.199999809265137 (float)
torque_constant: 0.03999999910593033 (float)
torque_lim: inf (float)

Controller Config:

In [8]: odrv0.axis1.controller.config
anticogging_enabled: True (bool)
calib_anticogging: False (bool)
calib_pos_threshold: 1.0 (float)
calib_vel_threshold: 1.0 (float)
cogging_ratio: 1.0 (float)
index: 0 (uint32)
pre_calibrated: False (bool)
axis_to_mirror: 255 (uint8)
circular_setpoint_range: 1.0 (float)
circular_setpoints: False (bool)
control_mode: 1 (uint8)
electrical_power_bandwidth: 20.0 (float)
enable_gain_scheduling: False (bool)
enable_overspeed_error: True (bool)
enable_torque_mode_vel_limit: True (bool)
enable_vel_limit: True (bool)
gain_scheduling_width: 10.0 (float)
homing_speed: 0.25 (float)
inertia: 0.0 (float)
input_filter_bandwidth: 2.0 (float)
input_mode: 1 (uint8)
load_encoder_axis: 1 (uint8)
mechanical_power_bandwidth: 20.0 (float)
mirror_ratio: 1.0 (float)
pos_gain: 5.0 (float)
spinout_electrical_power_threshold: 10.0 (float)
spinout_mechanical_power_threshold: -10.0 (float)
steps_per_circular_range: 1024 (int32)
torque_mirror_ratio: 0.0 (float)
torque_ramp_rate: 100.0 (float)
vel_gain: 0.05000000074505806 (float)
vel_integrator_gain: 0.05000000074505806 (float)
vel_integrator_limit: inf (float)
vel_limit: 5.0 (float)
vel_limit_tolerance: 1.2000000476837158 (float)
vel_ramp_rate: 16.0 (float)

enable_torque_mode_vel_limit: True (bool)

You need to set this value to false, or change your vel_limit and vel_gain appropriately. In your case, with vel_gain = 0.05 and vel_limit = 5, your torque is limited to… 0.05 * 5 = 0.25

This is described here in the documentation: Control Modes — ODrive Documentation 0.0 documentation

I’ll add the following image and some extra information about how exactly it works, but please please read the documentation, we spend a lot of time on it :slight_smile:


Thank you very much for the information and the convenient graph! I was under the impression that the velocity gain and velocity limit had no connection to the torque when the motor type is set to MOTOR_TYPE_GIMBAL, and, since I was testing the motor under stall conditions, I had assumed that the velocity limit did not apply. I will try this tomorrow and edit this reply if this parameter was the reason behind this behavior.

EDIT: The torque velocity limit was the reason for this issue! Thank you very much for your help!