mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-09-21 23:44:48 +08:00
Changed docs to reflect removal of current control mode and addition of torque control mode
Regenerated enums changed can_test.py to reflect control mode change modified closed_loop_test.py to pass with A->Nm change.
This commit is contained in:
+1
-1
@@ -64,7 +64,7 @@ If you want a different mode, you can change `<axis>.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
|
||||
|
||||
@@ -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`.<br>
|
||||
Set `axis.controller.config.control_mode = CONTROL_MODE_TORQUE_CONTROL`.<br>
|
||||
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`.
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
])
|
||||
|
||||
Reference in New Issue
Block a user