In my last post I mentioned I did have “some successes” with my efforts earlier this year. In case there is interest, I can give a high-level description of the approach I was persuing.
The current code produces “queue_step” commands with interval/count/add parameters. For example, one can see this in the batch output - here’s an example of a simple X homing move on a cartesian printer.
queue_step oid=1 interval=4379818 count=1 add=0
queue_step oid=1 interval=31827 count=2 add=-9492
queue_step oid=1 interval=17575 count=3 add=-1793
queue_step oid=1 interval=12292 count=7 add=-599
queue_step oid=1 interval=8496 count=8 add=-216
queue_step oid=1 interval=7201 count=138 add=0
queue_step oid=1 interval=7200 count=111 add=0
queue_step oid=1 interval=7200 count=111 add=0
queue_step oid=1 interval=7200 count=111 add=0
...
The above results in acceleration followed by constant velocity moves (ultimately arriving at a constant interval of 7200 clock ticks between steps). Although the above can look cryptic, it kinda makes sense. As the stepper accelerates, the interval between steps decreases. This is seen both as an “interval” parameter that decreases as well as a negative “add” parameter.
Looking a little closer, one can see that the “interval” parameter is generally close to the interval of the previous sequence. This makes sense as we expect the motion to be smooth. This leads to an opportunity to reduce overall bandwidth as the code could transmit just the change in interval instead of having to send the (potentially lengthy) interval value explicitly. (I mentioned this in that blog post years ago - https://www.patreon.com/posts/17811875 ).
The work I did earlier this year used this insight in an effort to design a different host compression algorithm. That is, the current system of “interval”, “count”, and “add” parameters could instead be viewed as “first_add”, “count”, and “add”. Where “first_add” is the difference between the inteval of the first step in the new sequence relative to the interval of the last step of the previous sequence.
If we were to encode the example X acceleration steps above with this new way of looking at the data we’d get:
queue_step oid=1 (interval=4379818) first_add=? count=1 add=0
queue_step oid=1 (interval=31827) first_add=-4347991 count=2 add=-9492
queue_step oid=1 (interval=17575) first_add=-4760 count=3 add=-1793
queue_step oid=1 (interval=12292) first_add=-1697 count=7 add=-599
queue_step oid=1 (interval=8496) first_add=-202 count=8 add=-216
queue_step oid=1 (interval=7201) first_add=217 count=138 add=0
queue_step oid=1 (interval=7200) first_add=-1 count=111 add=0
queue_step oid=1 (interval=7200) first_add=0 count=111 add=0
queue_step oid=1 (interval=7200) first_add=0 count=111 add=0
...
I’ve included the original “interval” parameter for reference - it wouldn’t need to be transmitted explicitly as it could be calculated from the other parameters.
The above transformation shows two interesting features - first that a newer encoding generally uses smaller integers and thus could reduce the amount of data sent to the mcu, and second that there is indeed quirks in the velocity data. In particular, the “add” (or change between interval) isn’t steadily decreasing - at one point we actually increase it (first_add=217
). Strikingly, if the previous queue_step had just been count=7
then the resulting interval would have been exactly 7200 and there could also have been one less queue_step command.
This is an example of the “micro velocity jumps” due to “taking too many steps” that I mentioned in the previous post.
Taking the above encoding further, one could imagine adding a “count1” parameter alongside the “first_add” parameter - something like: queue_step add1=-1697 count1=1 add2=-599 count2=6
(or, equivalently, send two “queue_step” commands that just have “add” and “count” parameters).
This was the “gist” of my attempt earlier this year to rework step compression. (Or, at least, my most successful attempt.) More concretely, I attempted to find “add1”, “add2”, and “count1” parameters such that I could maximize “totalcount” (count1+count2). It then accepted the “add1/count1” sequence and attempted to find parameters for the longest possible “count2+count3” sequence. (Then accepted “add2/count2” and went on to find longest possible “count3+count4”, and so on.) Alas, trying to maximize “totalcount” with three free variables while still keeping the absolute range constraints proved challenging. I could approximate it, but the resulting data was still quirky and it wasn’t particularly fast. I ultimately paused the work.
Crucially, by not sending an explicit “interval” the algorithm should be more likely to produce smooth transitions between queue_step commands.
Anyway, this concludes my posts on past work. I thought I’d give a little context on my previous experiences. (With the obvious caveat that those attempts had limitations.) Hopefully I haven’t careened too far off topic.
Cheers,
-Kevin