I’m playing around and tuning the ODrive for our system and want to make sure I understand the various bandwidth parameters: axis0.config.motor.current_control_bandwidth, axis0.config.encoder_bandwidth and axis0.controller.config.input_filter_bandwidth.
From the documentation, my understanding of axis0.config.motor.current_control_bandwidth is that the current controller is critically damped with a transfer function of w^2 / (s^2 + 2 * s * w + w^2) where w is axis0.config.motor.current_control_bandwidth. Is this correct? Is there any additional transfer function to be aware of between the current and applied torque or do we just scale by the torque constant.
Is it a similar case for axis0.config.encoder_bandwidth? I.e. the transfer function between actual rotor position and the rotor position output of the state estimator is also w^2 / (s^2 + 2 * s * w + w^2) where w is now axis0.config.encoder_bandwidth?
For axis0.controller.config.input_filter_bandwidth - is this just a first order low pass filter applied to commanded position with a transfer function of w/(s+w)?
Can I confirm that the units of all these parameters are radians/second.
From the documentation, my understanding of axis0.config.motor.current_control_bandwidth is that the current controller is critically damped with a transfer function of w^2 / (s^2 + 2 * s * w + w^2) where w is axis0.config.motor.current_control_bandwidth. Is this correct? Is there any additional transfer function to be aware of between the current and applied torque or do we just scale by the torque constant.
From my rusty controls knowledge, this is correct And yes, current to torque just scales by the torque constant (assuming you’re not hitting current/torque limits, your motor isn’t saturating, you’re not using field weakening, etc).
Is it a similar case for axis0.config.encoder_bandwidth? I.e. the transfer function between actual rotor position and the rotor position output of the state estimator is also w^2 / (s^2 + 2 * s * w + w^2) where w is now axis0.config.encoder_bandwidth?
Not for this one – it’s a second order Luenberger observer, to allow for zero steady-state position lag. But yes, bandwidth given by encoder_bandwidth.
For axis0.controller.config.input_filter_bandwidth - is this just a first order low pass filter applied to commanded position with a transfer function of w/(s+w)?
This is also a second order filter, it simulates a critically damped system moving to your input_pos, and uses that to generate a trajectory. Note it also generates velocity feedforwards and (if inertia is set) torque feedforwards, so it can really help with consistent performance while following a position-only trajectory.
Can I confirm that the units of all these parameters are radians/second.
All our bandwidth units are in “1/s” aka 1/τ (time constant) – which is the same as rad/s. We’ve historically had some issues with confusion as “radians per second” make people think of motor rotations so instead we represent as 1/τ.