diff --git a/docs/commands.md b/docs/commands.md index 618ddaba..c647adfe 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -64,7 +64,7 @@ If you want a different mode, you can change `.controller.config.control_m Possible values are: * `CONTROL_MODE_POSITION_CONTROL` * `CONTROL_MODE_VELOCITY_CONTROL` -* `CONTROL_MODE_CURRENT_CONTROL` +* `CONTROL_MODE_TORQUE_CONTROL` * `CONTROL_MODE_VOLTAGE_CONTROL` - this one is not normally used. ### Input Mode diff --git a/docs/getting-started.md b/docs/getting-started.md index 9426f395..46b5af18 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -347,7 +347,7 @@ Activate the ramped velocity mode: `axis.controller.config.input_mode = INPUT_MO You can now control the velocity with `axis.controller.input_vel = 5000` [count/s]. ### Torque control -Set `axis.controller.config.control_mode = CONTROL_MODE_CURRENT_CONTROL`.
+Set `axis.controller.config.control_mode = CONTROL_MODE_TORQUE_CONTROL`.
You can now control the torque with `axis.controller.input_torque = 0.1` [Nm]. Note: If you exceed `vel_limit` in current control mode, the current is reduced. To disable this, set `axis.controller.enable_current_mode_vel_limit = False`. diff --git a/docs/input_modes.md b/docs/input_modes.md index 53463ad0..9a87bcee 100644 --- a/docs/input_modes.md +++ b/docs/input_modes.md @@ -31,7 +31,7 @@ Pass `input_xxx` through to `xxx_setpoint` directly. ### Valid Control modes: * `CONTROL_MODE_VOLTAGE_CONTROL` -* `CONTROL_MODE_CURRENT_CONTROL` +* `CONTROL_MODE_TORQUE_CONTROL` * `CONTROL_MODE_VELOCITY_CONTROL` * `CONTROL_MODE_POSITION_CONTROL` @@ -95,7 +95,7 @@ Ramp a torque command from the current value to the target value. * `input_torque` ### Valid Control Modes: -* `CONTROL_MODE_CURRENT_CONTROL` +* `CONTROL_MODE_TORQUE_CONTROL` ## INPUT_MODE_MIRROR Implements "electronic mirroring". This is like electronic camming, but you can only mirror exactly the movements of the other motor, according to a fixed ratio diff --git a/tools/odrive/enums.py b/tools/odrive/enums.py index 2fe32b24..8fccc74d 100644 --- a/tools/odrive/enums.py +++ b/tools/odrive/enums.py @@ -30,7 +30,7 @@ ENCODER_MODE_SPI_ABS_AEAT = 258 # ODrive.Controller.ControlMode CONTROL_MODE_VOLTAGE_CONTROL = 0 -CONTROL_MODE_CURRENT_CONTROL = 1 +CONTROL_MODE_TORQUE_CONTROL = 1 CONTROL_MODE_VELOCITY_CONTROL = 2 CONTROL_MODE_POSITION_CONTROL = 3 @@ -41,7 +41,7 @@ INPUT_MODE_VEL_RAMP = 2 INPUT_MODE_POS_FILTER = 3 INPUT_MODE_MIX_CHANNELS = 4 INPUT_MODE_TRAP_TRAJ = 5 -INPUT_MODE_CURRENT_RAMP = 6 +INPUT_MODE_TORQUE_RAMP = 6 INPUT_MODE_MIRROR = 7 # ODrive.Motor.MotorType diff --git a/tools/odrive/tests/can_test.py b/tools/odrive/tests/can_test.py index 8e8e9c4b..93e72210 100644 --- a/tools/odrive/tests/can_test.py +++ b/tools/odrive/tests/can_test.py @@ -187,10 +187,10 @@ class TestSimpleCAN(): test_assert_eq(axis.controller.input_vel, -10.0, range=0.01) test_assert_eq(axis.controller.input_torque, 30.1234, range=0.01) - axis.controller.config.control_mode = CONTROL_MODE_CURRENT_CONTROL - my_cmd('set_input_torque', input_torque=3.1415) + axis.controller.config.control_mode = CONTROL_MODE_TORQUE_CONTROL + my_cmd('set_input_torque', input_torque=0.1) fence() - test_assert_eq(axis.controller.input_torque, 3.1415, range=0.01) + test_assert_eq(axis.controller.input_torque, 0.1, range=0.01) my_cmd('set_velocity_limit', velocity_limit=23456.78) fence() diff --git a/tools/odrive/tests/closed_loop_test.py b/tools/odrive/tests/closed_loop_test.py index dcc9b962..d900e6a4 100644 --- a/tools/odrive/tests/closed_loop_test.py +++ b/tools/odrive/tests/closed_loop_test.py @@ -211,9 +211,9 @@ class TestRegenProtection(TestClosedLoopControlBase): test_assert_eq(axis_ctx.handle.motor.error, MOTOR_ERROR_DC_BUS_OVER_REGEN_CURRENT) -class TestVelLimitInCurrentControl(TestClosedLoopControlBase): +class TestVelLimitInTorqueControl(TestClosedLoopControlBase): """ - Ensures that the current setpoint in current control is always within the + Ensures that the current setpoint in torque control is always within the parallelogram that arises from -Ilim, +Ilim, vel_limit and vel_gain. """ @@ -222,7 +222,8 @@ class TestVelLimitInCurrentControl(TestClosedLoopControlBase): max_rps = 20.0 max_vel = float(enc_ctx.yaml['cpr']) * max_rps absolute_max_vel = max_vel * 1.2 - max_current = 10.0 + max_current = 15.0 + torque_constant = 0.0305 #correct for 5065 motor axis_ctx.handle.controller.config.vel_gain /= 10 # reduce the slope to make it easier to see what's going on vel_gain = axis_ctx.handle.controller.config.vel_gain @@ -231,11 +232,12 @@ class TestVelLimitInCurrentControl(TestClosedLoopControlBase): axis_ctx.handle.controller.config.vel_limit = max_vel axis_ctx.handle.controller.config.vel_limit_tolerance = inf # disable hard limit on velocity axis_ctx.handle.motor.config.current_lim = max_current - axis_ctx.handle.controller.config.control_mode = CONTROL_MODE_CURRENT_CONTROL + axis_ctx.handle.motor.config.torque_constant = torque_constant + axis_ctx.handle.controller.config.control_mode = CONTROL_MODE_TORQUE_CONTROL # Returns the expected limited setpoint for a given velocity and current def get_expected_setpoint(input_setpoint, velocity): - return clamp(clamp(input_setpoint, (velocity + max_vel) * -vel_gain, (velocity - max_vel) * -vel_gain), -max_current, max_current) + return clamp(clamp(input_setpoint / torque_constant, (velocity + max_vel) * -vel_gain / torque_constant, (velocity - max_vel) * -vel_gain / torque_constant), -max_current, max_current) def data_getter(): # sample velocity twice to avoid systematic bias @@ -252,13 +254,13 @@ class TestVelLimitInCurrentControl(TestClosedLoopControlBase): request_state(axis_ctx, AXIS_STATE_CLOSED_LOOP_CONTROL) # Move the system around its operating envelope - axis_ctx.handle.controller.input_torque = input_torque = 2.0 + axis_ctx.handle.controller.input_torque = input_torque = 2.0 * torque_constant dataA = record_log(data_getter, duration=1.0) - axis_ctx.handle.controller.input_torque = input_torque = -2.0 + axis_ctx.handle.controller.input_torque = input_torque = -2.0 * torque_constant dataA = np.concatenate([dataA, record_log(data_getter, duration=1.0)]) - axis_ctx.handle.controller.input_torque = input_torque = 4.0 + axis_ctx.handle.controller.input_torque = input_torque = 4.0 * torque_constant dataA = np.concatenate([dataA, record_log(data_getter, duration=1.0)]) - axis_ctx.handle.controller.input_torque = input_torque = -4.0 + axis_ctx.handle.controller.input_torque = input_torque = -4.0 * torque_constant dataA = np.concatenate([dataA, record_log(data_getter, duration=1.0)]) # Shrink the operating envelope while motor is moving faster than the envelope allows @@ -267,22 +269,22 @@ class TestVelLimitInCurrentControl(TestClosedLoopControlBase): axis_ctx.handle.controller.config.vel_limit = max_vel # Move the system around its operating envelope - axis_ctx.handle.controller.input_torque = input_torque = 2.0 + axis_ctx.handle.controller.input_torque = input_torque = 2.0 * torque_constant dataB = record_log(data_getter, duration=1.0) - axis_ctx.handle.controller.input_torque = input_torque = -2.0 + axis_ctx.handle.controller.input_torque = input_torque = -2.0 * torque_constant dataB = np.concatenate([dataB, record_log(data_getter, duration=1.0)]) - axis_ctx.handle.controller.input_torque = input_torque = 4.0 + axis_ctx.handle.controller.input_torque = input_torque = 4.0 * torque_constant dataB = np.concatenate([dataB, record_log(data_getter, duration=1.0)]) - axis_ctx.handle.controller.input_torque = input_torque = -4.0 + axis_ctx.handle.controller.input_torque = input_torque = -4.0 * torque_constant dataB = np.concatenate([dataB, record_log(data_getter, duration=1.0)]) # Try the shrink maneuver again at positive velocity axis_ctx.handle.controller.config.vel_limit = 20.0 * float(enc_ctx.yaml['cpr']) - axis_ctx.handle.controller.input_torque = 4.0 + axis_ctx.handle.controller.input_torque = 4.0 * torque_constant time.sleep(0.5) axis_ctx.handle.controller.config.vel_limit = max_vel - axis_ctx.handle.controller.input_torque = input_torque = 2.0 + axis_ctx.handle.controller.input_torque = input_torque = 2.0 * torque_constant dataB = np.concatenate([dataB, record_log(data_getter, duration=1.0)]) test_assert_no_error(axis_ctx) @@ -298,5 +300,5 @@ if __name__ == '__main__': test_runner.run([ TestClosedLoopControl(), TestRegenProtection(), - TestVelLimitInCurrentControl() + TestVelLimitInTorqueControl() ])