hckrnws
Show HN: A 5th order motion planner with PH spline blending, written in Ada
by LiamPowell
Some thoughts:
1. It looks like you're selling hardware to go along with the firmware, which seems like it has nice features but also seems like it will be expensive. Sometimes the presence of first-class hardware results in other hardware being treated as "second-class" and results in limited adoption, especially since it sounds like the first-class hardware will eventually be much more than $100. (another hobbyist community, the FPV drone community, has shown this with FETtec brand having their own KISS firmware which is basically only used by them, and almost everyone else uses another alternative). You should care about limited adoption because that means a smaller number of outside contributors to your project.
2. You list that Prunt has features not available on other systems, which is nice, but it is not obvious how this will affect print quality/speed/accuracy, which I think are the primary concerns of most users.
a. Adjustable acceleration is already an option on most systems, does editing jerk/snap/crackle actually improve my print quality or just give me more parameters to fiddle with? I say this because Klipper is fairly impressive, and it would be nice to see some examples of how much extra motion terms improves a print.
b. Editing pinouts is a one-time thing and not an issue on common boards, so this is a limited benefit when you already need to be technically savvy to be building or modifying a 3D printer.
c. Safter/faster homing seems like a niche issue- I have never had any homing issues, and how much time do I actually save if I crank the speed up? A few seconds per print?
I guess I should add- good luck! The 3D printing community will certainly benefit from more ideas and development effort.> Sometimes the presence of first-class hardware results in other hardware being treated as "second-class"
The firmware is entirely open source so it should be easy for other companies to port it to their own hardware. The MCU we use is also supported by Klipper and Marlin, so there will not have to be a decision between designing hardware for Prunt or other options. That being said, there is no existing hardware that our firmware can be ported to directly as we make extensive use of hardware timers rather than doing pulse generation/counting in software and 3D printer hardware is not generally designed with this in mind.
It should be reasonably simple to do everything in software if anyone were inclined to do so to support existing boards. Prunt itself is actually a library with a very high level API intended to make it easy to support all sorts of odd hardware: https://github.com/Prunt3D/prunt/blob/6a9dbd0a8d5edd890e4b72...
There is also an example of a very trivial implementation here that just dumps commanded positions to stdout which can be used as a starting point: https://github.com/Prunt3D/prunt_simulator/blob/master/src/p...
> especially since it sounds like the first-class hardware will eventually be much more than $100
The BOM cost is over $100, so this will be the case, however I would like to try and keep the price well under $200 for something similar to the current hardware.
> Adjustable acceleration is already an option on most systems, does editing jerk/snap/crackle actually improve my print quality or just give me more parameters to fiddle with?
In my testing I have seen less resonance artefacts with higher order limits as opposed to just limiting acceleration, however I have not done extensive comparisons to other options such as input shaping.
> Safter/faster homing seems like a niche issue- I have never had any homing issues, and how much time do I actually save if I crank the speed up? A few seconds per print?
The main issue we're solving here is guaranteeing that the switch will never move out of its allowable range when other parameters such as acceleration are changed. For most people the benefit here is likely just never having to think about what number they should put in for homing velocity.
Could you elaborate on the hardware timers? How are these different from the timers that exist in the microcontroller, and what design changes are required in hardware?
Or is your point that the outputs from these timers can't be muxed to the pins that current hardware wires up?
> Or is your point that the outputs from these timers can't be muxed to the pins that current hardware wires up?
This. As far as I'm aware, other boards are just designed in the way that makes the layout easiest. The timers we're using are also fixed to specific pins with no muxxing (HRTIM on the STM32G474 specifically).
I was both excited and disappointed reading the list of hardware features. I, admittedly, have spent the last 6 years working in (not-human-rated) aerospace. Excited because the points you make on the site are definitely things that I've been disappointed to see missing on most existing hardware, and disappointed because... I wish that that list of features wasn't special at all and everyone made more robust hardware like that :)
I'm very curious about the Ada firmware and am hoping I'll have some time around Christmas break to have a dig into it. Last time I did anything with Ada was in grad school about 15 years ago and I loved it; I'm really excited to see what the bridge between Ada and a microcontroller looks like (see above... aerospace!)
> what the bridge between Ada and a microcontroller looks like
At a high level, we're just putting records with representation clauses directly on to a UART: https://github.com/Prunt3D/prunt_board_2_software/blob/maste...
What's a "5th order motion planner"?
I don't see a reference to the term on your website and when I looked it up on Google this post was the top hit. I also found this paper [1], is this what you're talking about? https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=883...
The first 5 derivatives of the position relative to time (velocity/acceleration/jerk/snap/crackle) are bounded, meaning that what the motors are commanded to do is a better representation of what is possible in reality.
I haven't dug into any of your code or (potential) documentation. In the quadrotor world a common approach is to do minimum-snap trajectories. That derivation shakes out from the fact that the aircraft itself has non-holonomic constraints: you can control force in the local Z axis (accelerating or decelerating all four motors simultaneously), and can control attitude (roll/pitch/yaw) by accelerating a pair of motors and decelerating the other pair of motors. When you go all the way down through the derivation you eventually can show that a minimum-snap trajectory results in smooth torque (aka current) commands for the motors themselves.
Is your 5th-order model derived from something like that? Or was it more of a "everything is really smooth if we have bounded crackle" kind of situation? Either way I'm really happy to see higher-order motion control coming to open-source firmware like this that doesn't require a host like Klipper does.
Thanks! Is the 6th derivative called a pop? XP
Edit: yes, apparently it is :D
After that it goes drop, lock, slam, thump
Wow - i didn’t know that the 5th derivative was covered. Is it standard in electronic devices these days ?
There are motion planners for six axis arms that go up to 11th order.
Why would you want your printer to blend corners, when you can also just put it in the g-code while keeping the printer faithful to it.
Marlin and Klipper are not actually faithful to what is in your g-code. Both will move through corners without going down to zero velocity, this results in a point with infinite axial acceleration, which is physically impossible and will generate a somewhat rounded corner while also causing vibrations in the printer. Prunt replaces this with a small rounded corner with G5 continuity, which results in less vibration as there is bounded axial acceleration (and jerk/snap/crackle).
Klipper and Marlin do support circular arcs if they are added to the g-code by the user, but these are not quite as good as our corners as they have infinite axial jerk at the point where the arc meets a straight line, as shown in the below images:
Circular corner blending: https://prunt3d.com/images/circle_corner/
Ours: https://prunt3d.com/images/prunt_corner/
I should also note before someone else does that technically infinite pop makes our corners physically impossible too, however at the 6th derivative of position it really ceases to matter in practice.
Thanks for the explanation. I do feel that the printer should follow its instructions, so perhaps the g code would need some extensions.
Most motion control systems for machining, etc, do the same thing: they do weird things at corners that follow the toolpath within a small tolerance but don't require slowing to zero.
Changing velocity too much has its own impacts on surface quality, that can be larger than moving off the toolpath by a small distance.
G-code / RS-274 is an industry standard far beyond 3d printing and this behavior is pretty standard for controllers/implementers at this point.
There is an "exact stop" mode G61 in RS-274, but it's not often used, instead of the G64 "path blending" mode. There are also extensions that I think are pseudo-standard, like G64 Px.xx lets you set a tolerance value in many controllers.
If your machine is physically accurate to X under perfect, slow conditions, you don't lose anything by telling it to blend paths to a tolerance of 2X during periods of high acceleration.
The problem is common g-code asks for things which violate physics. No amount of engineering or materials science can turn a moving printer head at a right angle with absolutely zero deflection. Even giant many millions of dollars CNC machines do all sorts of tricks to make corners (and a million other gcode problems) handle more gracefully. Most such big systems actually read ahead in gcode dozens to hundreds of steps to modify it in flight to get the best performance from the machine.
What led you to pick Ada? What was the development experience like?
Mostly I just like Ada, but there's a few things have been very useful here:
1. GCC has built-in dimensional analysis, which has saved me from errors that would have otherwise taken hours to track down or may have just gone unnoticed multiple times. As an example of this, there's a transcription error in the below code:
https://prunt3d.com/images/hn_dimensional_analysis_1.png
This line caused a compiler error that made it trivial to track down:
https://prunt3d.com/images/hn_dimensional_analysis_2.png
https://prunt3d.com/images/hn_dimensional_analysis_3.png
2. Intertask communication in Ada is nicer to work with than any other language I am familiar with, making it easy to make both the host and MCU software multithreaded: https://learn.adacore.com/courses/Ada_For_The_CPP_Java_Devel...
3. On the firmware side on things, Ada supports preemptive multitasking and exceptions with full tracebacks on small MCUs, which made firmware development much easier. Having preconditions that throw exceptions on procedures for controlling peripherals prevents a few hard to debug issues.
4. Someone already ported Adacore's embedded runtime to the MCU we use, so that was less work for me: https://github.com/JCGobbi/Nucleo-STM32G474RE
5. Ada supports defining the exact layout of types rather than having to rely on something like protobuf to get messages between the host and the MCU. I can just set the fields in these records and stream the bytes over a UART without any extra (de)serialisation: https://github.com/Prunt3D/prunt_board_2_software/blob/maste...
Right on. It's not something I see in the wild often, and it surely piqued my interested.
Thanks for this detailed information, this is very interesting!
I got this error for your PNGs:
> Access denied > The owner of this website (prunt3d.com) does not allow hotlinking to that resource (/images/hn_dimensional_analysis_2.png).
Oops, turns out hotlink protection is on by default. Fixed now.
What's your Emacs setup for Ada?
Eglot, Ada Language Server, and Ada mode from ELPA with the following config:
(use-package ada-mode)
(add-hook 'ada-mode-hook #'lsp! 'append)
(setq-default ada-xref-backend 'eglot)
(setq-default ada-diagnostics-backend 'eglot)
(add-hook 'ada-mode-hook (lambda () (set (make-local-variable 'comment-start) "-- ")))
(custom-set-variables
'(ada-fill-comment-prefix #("-- " 0 2 (syntax-table (11))))
'(wisi-size-threshold 2))
Then for each project I have a .dir-locals.el similar to the following: ((ada-mode . ((eglot-workspace-configuration . (:ada
(:projectFile "AAA.gpr")))
(tab-width . 3)
(fill-column . 119)
(indent-tabs-mode . nil))))
Can anyone give insight on what kind of controller they're using? It would be more interesting to see _how_ they achieved it.
first link (https://github.com/Prunt3D/prunt_board_2_server/releases) on the getting started page gives a 404 page not found error
Fixed in the live version of the site, thanks, although it isn't usable without the hardware it controls.
TIL Hacker News will redirect CloudFlare pages domains to their pages.dev URL, I wasn't aware is was even possible to find this due to CNAME flattening. Actual URL is https://prunt3d.com/, but I suppose it doesn't really matter.
No, it follows the canonical URL linked in the page's <head>:
link rel="canonical" href="https://600f3559.prunt-docs.pages.dev/" itemprop="url"
Thanks. This is what I get for using these big static site generators that I don't entirely understand, turns out this was a result of setting the base URL in Hugo to $CF_PAGES_URL as recommended by the CloudFlare docs.
Thank you for investigating this - I got scared when I saw what looked like an ephemeral URL!
Comment was deleted :(
Crafted by Rajat
Source Code