Velocity Feedforward Issue using Arduino library with CAN

I am working on putting together a testbed to exercise an actuator we are developing. My goal is to send open loop command profiles with position, velocity_FF, and torque_FF for performance tuning and validation. I’m using an ODrive Pro updated to 0.6.9-1 firmware.

I have a Teensy 4.1 running a timed loop and stepping through the profile at 100 Hz. I’m using the ODriveArduino Library (0.10.0). Using only the position command, I get the expected performance from a few test profiles I’ve run. I tried adding velocity feedforward, and I’m seeing some unexpected behavior.

Here’s a plot of the test profile I was running. You can see it starts out good but then the velocity feedforward drives it off the correct trajectory.

I puzzled over this for some time, then tried a test where I set the postion gain to 0 and commanded only the velocity feedforward in a simple ramped profile. This shows the problem…

I think this means the command coming from the Teensy is not being encoded correctly which seems would be related to the ODriveArduino library, or the ODrive is not interpreting it correctly.

I think I’ll set up to grab a raw CAN log to see what’s going across as the command to see if that looks as expected or not.

Wizards of ODrive, any ideas? Am I silly to be using the Arduino library for this?

1 Like

CAN log: Nothing obviously wrong. I didn’t decode these but from the plot it looks like there’s a wraparound happening.

The Arduino library function accepts a floating point value.

The CAN documentation specifies the velocity and torque FF’s as 16 bit integers…

And that should be the problem, 16 bit integers are -32,768 to 32,767. So that bounds the FF range to +/- 32.7 rev/s. My application requires 100’s of rev/s.

Is there a way to scale the range accepted for the feedforwards? Or perhaps is there a way to scale the position/velocity to be calibrated to a different unit like meters?

A scale is a good idea, we can look into that! Though my immediate recommendation would be to just set the pos as well as vel/torque feedforwards directly using arbitrary parameter access. It’ll take three separate messages, but if this is the only ODrive on the bus and you’re running at 1Mbps then that’s only ~14us between each message, much smaller than the ODrive’s ~8kHz control loop update period.

Agree, but you forgot to add the 125usec it takes to transmit the message :wink:

Maybe we should change the FFWD scale on vel to 0.01, that would allow 327.67 rev/sec, seems pretty reasonable.

Agreed that .01 rev/s resolution would be a better default. That would make this a non issue for most reasonably applications, and .001 rev/s is too fine to ever really help. This might still be limiting with motors at or under 8 poles if the drives will be capable of 2000 Hz electrical frequency. I may be an edge case but was hopeful to go faster. A better behavior for the Arduino/ROS CAN library would be to saturate the max command limit rather than wraparound of the limit of feed forward term is exceeded.

We updated this btw, it now has a configurable scaling factor.

Superb! Thank you very much both for implementing and letting me know.

@Wetmelon Hello again! I’m back working on the same project where I’d like to achieve highly dynamic motion with optimal command tracking. I updated to the latest firmware 0.6.10 a while back and was getting into tuning of the controller. The velocity feedforward is working as expected, but I’m not getting the expected effect out of the torque feedforward. I’ve been scratching my head trying a number of things. I initially tried increasing the gain on the torque calculation, multiplying by 1.5, 2, 5, and 10 had no effect. I even tried negative values, but the lag during high acceleration remained about the same.

I’ve confirmed that I’m sending the torque feedforward in the CAN message and the value is correct. I started with the input_torque_scale at 100 to match velocity, and saw 11 on the last two bytes corresponding to a feedforward of 0.11 N*m. I’ve increased to 1000 and now see 112 going out.

In an effort to isolate, I’ve now set the position and velocity gains to 0, and I’m sending out the test command profile including the torque feedforward. I’m expecting this to be equivalent to operating in torque control using the torque feedforward. I should be seeing 20A peak for .11 N*m, but I’m seeing no response from the motor.

I’m curious if you have any advice for something I may be missing in the configuration or that you’d suggest I try/test. I’m out of ideas. Next I’m going to use the original work around to send 3 commands to command position, then velocity FF, then torque FF individually, but I need to get that set up again for the new firmware mapping. Ideally that would help isolate the command path if there’s an issue getting the CAN message unpacked and into that register. Based on the previous testing, this was very effective at eliminating the position and velocity overshoot I see during high acceleration. Thank you in advance!

Pinging @solomondg as well for any thoughts or advice.

Here’s a sample run with everything otherwise working well. Pointing out the region where the tracking lags without torque FF.

And with 10x Torque FF

Here’s the test profile with position gains and velocity gains set to zero.

Hi! We resolved this in the Discord, for anyone with the same issue, a fix has been pushed to the devel branch (odrivetool dfu --channel devel), and will be released in the upcoming 0.6.11 firmware release.

1 Like

Also note that the new firmware does allow setting custom feed-forward torque:
It has been available for a while to set automatic feed-forward torque by setting the inertia parameter.