So ... this is hard!

A project log for 3D Printed Robot Joint with Active Compliance

A general purpose robot joint using a cycloidal gearbox and an ODrive modified to support active compliance

Tim WilkinsonTim Wilkinson 06/07/2019 at 18:075 Comments

Perhaps unsurprisingly, this turns out to be hard when you don't start knowing a whole heck of a lot about this stuff. And my internet search haven't turned up much that is helpful (I continue to search).

After much tinkering, this is where I am:

// Detect if the axis motion deviates from what we expect and adjust the motion.
// We track the position error against the maximum displacement, and if it deviates too much we conclude
// an external force is acting on the axis.
pos_error_ = fabsf(encoder_pos_estimate - controller_pos_setpoint) / (1 + fabsf(max_pos_));
if (pos_error_ > config_.error_band) {
    // Recalculate the trajectory based on the new position.
    // Currently this assume the velocity is reduced to ~0 when at the central point of its oscillation.
    period_ = sqrtf(1 / config_.elasticity);
    max_pos_ = encoder_pos_estimate - pos_setpoint_;
    max_vel_ = -max_pos_ / period_;
    tick_ = 0;
// Damping due to kinetic friction.
float kfriction = max_vel_ * config_.kinetic_friction * current_meas_period;
if (fabsf(kfriction) < fabsf(max_vel_)) {
    max_vel_ -= kfriction;
    max_pos_ = -max_vel_ * period_;
// Bring axis to a halt once velocity falls below static friction.
float interval = 2 * PI * tick_ / period_;
if (fabsf(max_vel_) < config_.static_friction && interval <= PI && (interval + 2 * PI / period_) > PI) {
    max_vel_ = 0;
    max_pos_ = 0;
// Calculate the new position and velocity
axis_->controller_.pos_setpoint_ = cosf(interval) * max_pos_ + pos_setpoint_;
axis_->controller_.vel_setpoint_ = sinf(interval) * max_vel_;
// Tick, wrapping as necesssary
if (tick_ >= period_) {
    tick_ -= period_;
tick_+= current_meas_period;

This code can be divided into three parts:

  1. Detect an external force acting on the actuator and adjust its compliance.
  2. Apply friction forces to the actuator.
  3. Move the actuator to the new position

Of these parts, the first is the one still giving me the most problems. Accurately detecting an external force to a nominally oscillating actuator without extra sensors has proven difficult. The current solution tracks the position error in relation to the current maximum actuator displacement, and if a threshold is exceeded, recalculates the compliance. Unforuntately, this value needs to be tuned depending on other parameters and I'm unhappy with that.

Also, while this works relatively well for a "bare" motor, once the cycloidal gearing is added, the compliance adjustment works very poorly. This seems to be related to the default way ODrive manages the motor current (just fine normally of course) with position and velocity errors, and I will need to do more work here. Right now it can only handle small external deflection and that's not great.

Anyway, if anyone has thoughts and comments I'd love to hear them.


Tim Wilkinson wrote 06/08/2019 at 00:05 point

I'd be happy to add extra sensors if that'd get me there ... and then I'd probably work backwards from something that works to see if I can eliminate things again and keep it working.

  Are you sure? yes | no

Simon Merrett wrote 06/08/2019 at 11:57 point

So could you constrain your test setup to only apply impulses or forces on one point, in one axis (normal to the joint axis of rotation)? Then you can use a strain gauge, FSR or velostat to read analogue force input. Even a cheap capacitive touch sensor may work, if you can allow a tiny bit of passive compliance like a thin layer of foam, such as in #SoleSense? There are microcontroller capacitive/touch sense techniques that don't need a bespoke cap sense ic like the mpr121 I used (because I wanted several zones and reasonable resolution). 

  Are you sure? yes | no

Tim Wilkinson wrote 06/07/2019 at 20:59 point

Yes, I'm an avid fan of James's work. However, he's doing passive compliance (using analog elements like bungees and springs) while I'm trying to do active (like the work on NABi from UCLA).

  Are you sure? yes | no

Simon Merrett wrote 06/07/2019 at 22:26 point

For everyone else who also had to go away and look for an explanation of the difference! 

So would you be open to extra sensors and what would you be prepared to put up with (cost, technical integration burden, resilience etc)? 

  Are you sure? yes | no

Simon Merrett wrote 06/07/2019 at 18:33 point

Hi Tim, I'm afraid I don't have much insight myself but have you looked into @James Bruton 's recent videos on force-based controls? 

Here's the playlist for arm:

And the video on the gripper:

  Are you sure? yes | no