More stable acceleration limiting

Back in 2022 moteus added support for acceleration limited trajectories. This was a highly requested feature and has been used for all sorts of applications since. However when working on the recent trajectory optimization effort it became obvious that there were still some lingering stability issues on two fronts. First, when decelerating, there would occasionally be single control cycles where an acceleration was instead commanded. Second, termination at the end of a move would often involve small amounts of overshoot or oscillation. You can see both in one of the plots from that post here:

Acceleration instability

Acceleration instability

I’ve known about this for several years now, and occasionally have spent a few minutes trying to think of alternate formulations that would be more stable. With my recent attempts to use Claude Code, I thought maybe it could help here too since at least this part of the firmware is entirely tested by host side unit tests? Well, the answer was I suppose it did help, but not exactly in the way I originally intended. Read on for more details, or upgrade to moteus firmware 2026-01-21 if you just want the fixes.

The winding path

As mentioned, I wanted to explore if using Claude code could help solve some problems like this. Here I already had a unit test which kept track of instability and just had a wide bound on it. So, I started out asking claude the equivalent of, “here is this test”, “here is this code”, explore ways to alter the formulation to get the test to pass. I was not quite that brief, providing some general properties of the trajectory code that should be maintained. It then proceeded to do a bunch of noodling which added more state than I wanted, made the tests pass, but I’m not sure was actually correct in any useful way.

After that, I asked it to shelve that strategy and try an alternate one that I had thought of while watching it flail. It proceeded to give that a go, but then when it didn’t work right out of the bat, added some additional phases and steps, which upon prompting it claimed were related and even provided a derivation of the relationship. After much probing and asking for more tests, they all passed and I thought, sure, maybe this will work.

I then went through the final result line by line and removed or altered the constants and constraints to see what tests would fail and what behavior would break. To my not very large surprise, many of them seemed to have no effect, or certainly not the effect that was described or intended. Eventually I made it all the way through removing everything that could be removed or that didn’t make sense and the unit tests and experimental tests all still passed.

The final fixes

Ultimately the resolution boiled down to three main changes:

  1. Exact integration: The integration of position over time previously always assumed constant velocity. The closed form solution for constant acceleration is not particularly hard, so I just did that.

  2. Exact switching to deceleration: When switching from acceleration to deceleration the previous code waited until the system was one step beyond what was required, then began decelerating. This resulted in it being impossible for the system to reach the stop point while being limited to merely the acceleration limit. Instead now, the switch to deceleration happens the cycle before, leaving room to actually reach the target without overshoot.

  3. Using the computed deceleration: The old algorithm always decelerated at exactly the acceleration limit. In some cases, decelerating at the exact limit would result in being ever so slightly below the deceleration curve. Thus the next cycle the controller would decide to accelerate again. Instead, at each time step the exact deceleration required to hit the target is calculated and used, limited by the acceleration limit.

The final result is a much cleaner acceleration waveform. Here is a sample plot from the BE8108 fixture used in the trajectory optimization work.

Stable deceleration profile

Stable deceleration profile

Conclusions on the “vibe”

I will admit to not being very fastidious in cleaning up the verbiage in the Claude Code generated unit tests here. They are checking what I want to check, although they are not written nearly as clearly or concisely as I would have done myself. The firmware itself is in better shape, with hopefully all the unecessary junk gone and the comments re-written to match the same style and clarity as the existing ones. Was doing it the “vibe” way worth it? Probably, if nothing else because it encouraged me to fix it in the first place!

Upgrading

As usual, all existing moteus controllers are eligible for this fix. Just upgrade to any firmware newer than 2026-01-21 using the instructions from the reference manual.