# Arc Motion

286 views

### Ravi Ganesh

Dec 2, 2021, 5:45:00 AM12/2/21
to OpenPnP
Arcs are special in motion. Right from an electron in a cyclotron to a kid navigating a bicycle direction change is in circular motion (AKA arcs)

Here is a video demonstrating pick and place motion with
1. Sharp corners
2. Chamferred corners
3. Arc motion.

These are the gcodes respetively
Sharp Corners:
G01 X0 Y0 Z0 {FeedRate:F%.2f}
Z10.
X0 Y0 Z15
X100 Y100
Z0
G01 X0 Y0 Z0

45 degree edges:
G01 X0 Y0 Z0 {FeedRate:F%.2f}
Z10.
X3.5355 Y3.5355 Z15.
X96.4645 Y96.4645
X100. Y100. Z10.
Z0.
G01 X0 Y0 Z0

Arc:
G18; arc in XZ plane
G01 X0 Y0 Z0 {FeedRate:F%.2f};
G01 X0 Y0 Z10;
G4 P0 ; Bug in my 4 axis grbl?? Requires motion stop before arc execution
G03 X3.53 Z15 Y3.53  R5;
G01 X96.464 Y96.464;
G4 P0 ; ?? Bug
G03 X100 Z10 Y100 R5;
G01 Z0;
G01 X0 Y0 Z0 ;

Ravi Ganesh

### mark maker

Dec 2, 2021, 7:24:06 AM12/2/21

This won't help in the general case, because the arc is either in the XZ plane (G18) or in the YZ plane (G19). Only if you have completely orthogonal moves in X or Y would this be a smooth path. But such moves almost never happen in OpenPnP, most are at arbitrary diagonals.

Even if you were to select the closer of the two planes, you get a corner in the path, at the top. The corner angle would be blunter than 90°, so maybe it would allow going through that corner a bit faster (junction deviation), but your overall path is longer, so I don't think this will gain much.

Also note: for any smoothing to be safe when placing parts, you would have to raise your safe Z by the radius of the arc. Otherwise, when placing tall components (e.g. electrolyte caps) close together you would risk colliding them. Raising Z also makes the moves slower, so again you have to weigh up gains with losses.

The real solution is supporting something like G64:

https://linuxcnc.org/docs/2.6/html/gcode/gcode.html#sec:G64

And then calculate the blending  dynamically, i.e. large blending for long moves, only little blending for short moves.

_Mark

--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.

### surab...@gmail.com

Dec 2, 2021, 8:05:07 AM12/2/21

Mark,

IMO this gcode:

G18;

..

G03 X3 Z15 Y3  R5;

Is an arc in a plane at 45 degree to the XZ plane and orthogonal to XY.

So using G18 and G19 arc in any vertical plane is possible. (I think the video proves that)

However I have no Idea whether blending is better than arcs.

But definitely I want to ask why arc was not considered so long, when it is already available.

R

--
You received this message because you are subscribed to a topic in the Google Groups "OpenPnP" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/openpnp/PxliLkN6JBU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to openpnp+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/openpnp/f0a6e78d-b5f7-aee5-a351-bd0402fd2e6b%40makr.zone.

### Arthur Wolf

Dec 2, 2021, 8:18:46 AM12/2/21
You *could* generate the arc as a series of small gcodes (do the full 3D math in openpnp), and send that to the board, most boards will support that kind of gcode density no issue (ie if they can do delta moves or laser engraving etc...).
You wouldn't be using G2/G3 at all.
All your other objections do stand though, so I'm a bit skeptical on how much this would help.

--
`勇気とユーモア`

### bert shivaan

Dec 2, 2021, 12:29:58 PM12/2/21
to OpenPnP
Ravi, can you try taht again but with a much slower feed rate? I have watched it on youtube at .25 playback but it is still too fast. The reason I ask is because in industrial controls, you can not arc in more than 1 plane at a time. My controls will simply ignore the Y move until the arc is done, then move in y. (or ignore the x move if YZ plane is selected). It looks like your axis that runs to and from the camera moves after the arc, but I can not tell. That would make sense to me and follow the standard.

### mark maker

Dec 2, 2021, 12:35:27 PM12/2/21

> IMO this gcode: G18; G03 X3 Z15 Y3  R5; Is an arc in a plane at 45 degree to the XZ plane and orthogonal to XY.

I don't think that is an arc in the 45° plane. It is a helix (like a screw thread) with 3mm climb in the Y axis.

As the helix climb is constant per angle, this means there are even two corners, one at the base of the arc, and one at the top. Two corners means this is certainly slower than rectangular motion.

Grbl is no exception, you can see here, there's only 2D math :

and btw. what would be the point of G18 and G19 if the command could specify the plane 😉?

> You *could* generate the arc as a series of small gcodes (do the full 3D math in openpnp)

OpenPnP can do that!

See here:

https://github.com/openpnp/openpnp/wiki/Motion-Planner#motion-blending

Unfortunately, after having programmed all this, it turned out the USB serial speed of the tested controllers is not fast enough. It takes more time to send these fine-grained paths, than what it saves in motion time

😭.

In theory it all worked nicely, I'll try to find the simulated illustration.

_Mark

### Arthur Wolf

Dec 2, 2021, 1:56:41 PM12/2/21
On Thu, Dec 2, 2021 at 6:35 PM mark maker <ma...@makr.zone> wrote:

> IMO this gcode: G18; G03 X3 Z15 Y3  R5; Is an arc in a plane at 45 degree to the XZ plane and orthogonal to XY.

I don't think that is an arc in the 45° plane. It is a helix (like a screw thread) with 3mm climb in the Y axis.

As the helix climb is constant per angle, this means there are even two corners, one at the base of the arc, and one at the top. Two corners means this is certainly slower than rectangular motion.

Grbl is no exception, you can see here, there's only 2D math :

and btw. what would be the point of G18 and G19 if the command could specify the plane 😉?

> You *could* generate the arc as a series of small gcodes (do the full 3D math in openpnp)

OpenPnP can do that!

See here:

https://github.com/openpnp/openpnp/wiki/Motion-Planner#motion-blending

Unfortunately, after having programmed all this, it turned out the USB serial speed of the tested controllers is not fast enough. It takes more time to send these fine-grained paths, than what it saves in motion time

That is surprising. I've had to help companies do similar things (for example for HS liquid handling), and they were able to achieve it with proper optimization.
Could I get some sample gcode for this?

--
`勇気とユーモア`

### surab...@gmail.com

Dec 2, 2021, 9:01:22 PM12/2/21

Well said Mark. What really matters is that angle. Worst case this angle is 22.5 degree.

IMO this helix could still be considered and the practical results might be appealing compared to the development effort.

I will give this one also a try….

Sent: Thursday, December 2, 2021 11:05 PM
Subject: Re: [OpenPnP] Arc Motion

> IMO this gcode: G18; G03 X3 Z15 Y3  R5; Is an arc in a plane at 45 degree to the XZ plane and orthogonal to XY.

--
You received this message because you are subscribed to a topic in the Google Groups "OpenPnP" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/openpnp/PxliLkN6JBU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to openpnp+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/openpnp/26919260-9ccf-e9f7-fcef-75385d856b89%40makr.zone.

image003.jpg

### surab...@gmail.com

Dec 2, 2021, 9:25:00 PM12/2/21

Hi Arthur,

Here is a gcode fragment to make a diagonal pick and place from 0,0 to 100,100

using interpolated arcs.

Z plane is 15mm.

Safe height is 10mm (i.e the minimum height the head retracts up before making any horizontal component move.

G01 X0 Y0 Z0 F10000

Z10.

X0.0141 Y0.0141 Z10.4467

X0.0564 Y0.0564 Z10.8897

X0.1265 Y0.1265 Z11.3257

X0.2239 Y0.2239 Z11.7511

X0.3478 Y0.3478 Z12.1624

X0.4971 Y0.4971 Z12.5565

X0.6707 Y0.6707 Z12.9302

X0.8673 Y0.8673 Z13.2804

X1.0851 Y1.0851 Z13.6043

X1.3226 Y1.3226 Z13.8995

X1.5778 Y1.5778 Z14.1635

X1.8486 Y1.8486 Z14.3941

X2.1329 Y2.1329 Z14.5897

X2.4284 Y2.4284 Z14.7485

X2.7328 Y2.7328 Z14.8694

X3.0436 Y3.0436 Z14.9514

X3.3583 Y3.3583 Z14.9937

X3.5355 Y3.5355 Z15.

X6.9773 Y6.9773

X96.4645 Y96.4645

X96.6417 Y96.6417 Z14.9937

X96.9564 Y96.9564 Z14.9514

X97.2672 Y97.2672 Z14.8694

X97.5716 Y97.5716 Z14.7485

X97.8671 Y97.8671 Z14.5897

X98.1514 Y98.1514 Z14.3941

X98.4222 Y98.4222 Z14.1635

X98.6774 Y98.6774 Z13.8995

X98.9149 Y98.9149 Z13.6043

X99.1327 Y99.1327 Z13.2804

X99.3293 Y99.3293 Z12.9302

X99.5029 Y99.5029 Z12.5565

X99.6522 Y99.6522 Z12.1624

X99.7761 Y99.7761 Z11.7511

X99.8735 Y99.8735 Z11.3257

X99.9436 Y99.9436 Z10.8897

X99.9859 Y99.9859 Z10.4467

X100. Y100. Z10.

Z0.

arc.txt

### Arthur Wolf

Dec 2, 2021, 9:27:51 PM12/2/21
I'm really surprised this wouldn't be sent/interpreted fast enough. I've seen data denser than this interpolated fast enough, even at 10k speeds. Was this sent over UART or USB/ACM?
You could reduce data volume by 20-30% by removing the spaces, moving in relative mode, and removing at least one, maybe two trailing digits (you don't need that much resolution).

--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.

--
`勇気とユーモア`

### mark maker

Dec 3, 2021, 4:59:04 AM12/3/21

> Could I get some sample gcode for this?

First let me tell you that Grbl hardly has a planner queue that is long enough, even the 32bit controller like Smoothie and Duet are quite challenged by that (RAM-wise, and processing wise). Grbl will not be able to look ahead until the end of the segment sequence and therefore it will conservatively decelerate way too early. You will get very strange, stuttery moves!

Furthermore: this only works if you have an acceleration control command like M204.

But just to get the G-code as an academic exercise,  enable the feature in OpenPnP as follows. Please take the time to really follow this carefully step by step (however no guarantee that I didn't miss something):

https://github.com/openpnp/openpnp/wiki/Motion-Planner#motion-blending
2. Convert the GcodeDriver to the GcodeAsyncDriver if you haven't already. You need to proceed all the way to the Advanced Milestone of Issues & Solution to get the suggestion for automatic conversion.
https://github.com/openpnp/openpnp/wiki/GcodeAsyncDriver#for-existing-gcodedrivers
3. Set the Simulated3rdOrderControl in the driver.
https://github.com/openpnp/openpnp/wiki/GcodeAsyncDriver#gcodedriver-new-settings
4. Set the interpolation settings:
https://github.com/openpnp/openpnp/wiki/GcodeAsyncDriver#interpolation
5. Enable Location Confirmation on the driver.
6. For the academic interest: set the Log G-code option on the driver. It will log the pure G-code, separate from the usual log.
7. Like in step (2), convert the NullPlanner to the ReferenceAdvancedMotionPlanner with Issues & Solutions.
8. Set the Motion Planner to Allow continuous motion and to Allow uncoordinated:
https://github.com/openpnp/openpnp/wiki/Motion-Planner#settings
9. You need a Safe Z Zone that is not zero, i.e. the headroom for the curves a.k.a. Z overshoots. Set the Safe Zone Low and Safe Zone High limits on the Z axis. It will optimize the curve size (small curves on short moves, large curves on long moves, limited by the head-room of the Safe Z Zone):
https://github.com/openpnp/openpnp/wiki/Machine-Axes#kinematic-settings--axis-limits

Then try it 😎

_Mark

--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.

### mark maker

Dec 3, 2021, 8:06:51 AM12/3/21

I have to be more specific:

1. For Smoothieware the USB speed seems good enough, but the planner queue is too small for long moves with large curves. For short moves it works, see the two animations:

2. For Duet, the queue can be made large enough (lots of RAM) but the USB serial speed (although it was much improved) is still not good enough.

I have to say that I don't know if Smoothie would be performant enough (in terms of processing power) to handle a larger queue, even if the RAM was large enough.

When does Smoothie 2 finally come out? 😛

_Mark

### Arthur Wolf

Dec 3, 2021, 8:13:03 AM12/3/21
On v1, you can make the queue longer, I've seen people do 4x on it (not on 3D printers, those have modules that use too much RAM), which at 0.1mm/block is 25.6mm, which should be plenty enough for this use case.  It depends on how much RAM you're using for other modules/uses etc. Processing power is definitely not a limiting factor here, the vast majority of the processing on v1 goes to actual step generation.
About v2, we've been constrained by the chip shortages, but we finally have a proto going to the devs this week. We upgraded to a much more powerful chip by the way (with lots more RAM), see the upgrade on Kickstarter :

--
`勇気とユーモア`
d9db20fcbb5de77c9b81201a7daa44bf_original.webp

### mark maker

Dec 3, 2021, 8:34:06 AM12/3/21

> Could I get some sample gcode for this?

Sorry just saw that it is you who is asking, Arthur, not Ravi.

_Mark

### Jan

Dec 6, 2021, 7:53:28 PM12/6/21
Hi All!
May I summersise this thread, draw some conclusing and kindly ask for
- For motion blending the controller should be able to quickly accept
and queue many smal segmens for gcode.
- For controllers with serial links the gcode should be compressed by
removing unnesseary spaces and reducing the presicion. (1/100mm and
1/10° is probably fine for all kinds of PnP requirements)
- Smoothieware V1 can provide and handle very long queues limited by the
available memory only.
- On Smoothieware V1 the queue can be adjusted via planner_queue_size
- http://smoothieware.org/configuration-options says that
planner_queue_size can be adjusted until smoothieware runs out of RAM.
- https://smoothieware.org/troubleshooting says that running out of
memory means that the mem-command reports less then 2k free space.
- on my CHM-T36VA with criegels enhanced smoothieware on STM32F407
(https://github.com/c-riegel/Smoothieware-CHMT) "mem" says "Total Free
RAM: 67348 bytes", "Free AHB0: 11192" and "Block size: 92 byte" (This
firmware has planner_queue_size set to 48).
- If I understand the source code correctly, "planner_queue_size" is
evaluated in Conveyor.cpp (Conveyor::on_module_loaded()) which is then
used to resize the queue via BlockQueue::resize() in BlockQueue.cpp
which requests memory from AHB0 pool. I guess further that each element
is of size "Block size" which is 92 byte for me.
- If I keep 2k of AHB0 free, there would be space for 99 more queue
elements summing to a total of 147. Without the 2k it would be 121 more
for a total of 169. As there is plenty of space in other pools free, it
shall be possible to provide an even larger queue.
- If I take this gcode fragment (from arc.txt) "X99.9859 Y99.9859
Z10.4467" and compress it to "X99.96Y99.96Z10.45" it contains 18
characters + new-line. 19 characters transfered at 115200 baud with 8N1
would require 1.65ms. At 1000mm/s feedrate each segment would be 1.65mm
long. At slower speeds the segments would be shorted. (This could be
even made 10% faster with 7N1 transfer)
Would that provide enough speed and space for smooth motion blending?

Jan

On 03.12.2021 14:12, Arthur Wolf wrote:
> On v1, you can make the queue longer, I've seen people do 4x on it (not
> on 3D printers, those have modules that use too much RAM), which at
> 0.1mm/block is 25.6mm, which should be plenty enough for this use case.
> It depends on how much RAM you're using for other modules/uses etc.
> Processing power is definitely not a limiting factor here, the vast
> majority of the processing on v1 goes to actual step generation.
> About v2, we've been constrained by the chip shortages, but we finally
> have a proto going to the devs this week. We upgraded to a much more
> powerful chip by the way (with lots more RAM), see the upgrade on
> Kickstarter :
>
> Screenshot from 2021-12-03 14-12-21.png
>
>
>
>
> On Fri, Dec 3, 2021 at 2:06 PM mark maker <ma...@makr.zone> wrote:
>
> I have to be more specific:
>
> 1. For Smoothieware the USB speed seems good enough, but the
> planner queue is/too small/ for long moves with large curves.
> For short moves it works, see the two animations:
>
> 2. For Duet, the queue can be made large enough (lots of RAM) but
>>
>>
>>
>> --
>>
>> 勇気とユーモア
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "OpenPnP" group.
>> To unsubscribe from this group and stop receiving emails from it,
>> send an email to openpnp+u...@googlegroups.com
>> To view this discussion on the web visit
>
> --
> You received this message because you are subscribed to the Google
> Groups "OpenPnP" group.
> To unsubscribe from this group and stop receiving emails from it,
> send an email to openpnp+u...@googlegroups.com
> To view this discussion on the web visit
>
>
>
> --
>
> 勇気とユーモア
>
> --
> You received this message because you are subscribed to the Google
> Groups "OpenPnP" group.
> To unsubscribe from this group and stop receiving emails from it, send
> To view this discussion on the web visit

### Arthur Wolf

Dec 6, 2021, 8:30:39 PM12/6/21
That's some impressive research :)
Note you can save a few more characters in your gcode by using relative mode instead of absolute mode (so instead of saying X123.45 then X123.47, you say X0.02 again and again)

To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.

--
`勇気とユーモア`

### mark maker

Dec 7, 2021, 4:24:57 AM12/7/21

Hi Jan

OpenPnP can already compress the Gcode:

2. Remove whitespace and unnecessary trailing digits
https://github.com/openpnp/openpnp/wiki/GcodeAsyncDriver#gcodedriver-new-settings
3. You can set the resolution on the Axis, i.e. if you set it to 0.01 and adapt the format of the MOVE_TO_COMMAND (%.2f instead of %.4f), you get what you describe.

All this was used in my tests with regular Smoothie and Duet 3 to no avail.

There is currently no support for relative motion. That would probably help a bit here, but create other problems.

Regular Smoothie has not enough RAM, I was able to increase the queue to 48 before it stopped working. But that's not enough. For fully smoothed operation you probably need 100-300 segments. Regular Smoothie has very fast native USB serial and flow control, but I still don't know whether it would be fast enough.

> 19 characters transfered at 115200 baud with 8N1 would require 1.65ms.
>
Would that provide enough speed and space for smooth motion blending?

The CHM-T36VA serial bridge to the STM32F407 is slow and shaky, flow control seemed not to work properly. Experiments, I think done by Nélio, did not work. Maybe there would be an option to connect native USB serial?

Duet 3 seems to have enough RAM, but its serial USB serial, while being improved lately, is still way too slow. The last experiments (I think by Wolfgang) did not really work out.

One problem is also to let the planner wait until it has received the whole sequence for look-ahead planning. If the planner starts planning/executing motion too quickly, it will rush into premature deceleration, not yet seeing the sequence to the end. We added some new grace period support to Duet, i.e. it would wait longer, or until an M400 is received, which typically signals the end of a sequence. I'm not sure we tested the latest incarnation of that. Any controller supporting such paths would have a grace period+release feature too.

Here is a simulations with the OpenPnP Motion Planner (dual nozzle machine, i.e. see the nozzle switch in the back row, showing as inverted Z moves):

The gains are moderate (-16.6% time). All that planning as true 3rd order motion also requires solving time (in Java). Add to that the serial communication time and the gains were gone. 😭

I'm now quite convinced that controller side support for smoothing is the way to go.

_Mark

### Jan

Dec 7, 2021, 5:04:52 PM12/7/21
Hi Mark!
Many thanks for your detailed response.
I'm aware that compression is available as well as the option to
coordinates are not send if not needed.
The CHM-T36VA controller board has just a two-wire serial interface.
RTS/CTS for hardware flow control are not connected. Anyhow, this is -
to my understanding - only needed, if the queue is to short. If the
queue is large and the planner can respect a maximum number of slices
per segment (until it needs to wait for a move to finish) flow-control
is not needed.
The STM32F407 provides a USB full-speed device controller and phy. The
pins are accessible at the CAN connector, which is unpopulated. I guess
two series resistors and a pullup would be all thats needed to make the
physical connection. I've two concerns with this option:
a) I've read that USB interfaces might cause trouble because of ground
loops. Yes, USB isolators are easy to add.
b) Fitting USB-serial into the existing firmware would be some work and
- to my understanding - only make sense if we would gain significant
benefits.
I've started this response to gain more insights for the second point.
In software development I'd use a profiler and carefully generate
testcases to find the place where optimization would be most efficient.
I've identified some places in the past that are all addresses so far:
the criegel firmware operates the CHM-T36VA with an unbelievable speed.
As you wrote in one of your early blog posts, acceleration is all that
matters for the total speed... I'd add that optimizing move distances is
the second as hardware inertia is a bigger limit then computer speed.
If you think, that changing the way the controller handles the queue is
an efficient way to proceed, why not just do it. You already made a few
modification to smoothieware - which to my knowledge where not accepted
due to limited used for the community. If think, that a larger queue is
an other way to step forward, why not try to optimize the queue/memory
layout...

Jan

On 07.12.2021 10:24, mark maker wrote:
> Hi Jan
>
> OpenPnP can already compress the Gcode:
>
> 2. Remove whitespace and unnecessary trailing digits
> https://github.com/openpnp/openpnp/wiki/GcodeAsyncDriver#gcodedriver-new-settings
> 3. You can set the resolution on the Axis, i.e. if you set it to 0.01
> and adapt the format of the MOVE_TO_COMMAND (%.2f instead of %.4f),
> you get what you describe.
>
> All this was used in my tests with regular Smoothie and Duet 3 to no avail.
>
> There is currently no support for relative motion. That would probably
> help a bit here, but create other problems.
>
> Regular Smoothie has not enough RAM, I was able to increase the queue to
> 48 before it stopped working. But that's not enough. For fully smoothed
> operation you probably need 100-300 segments. Regular Smoothie has very
> fast native USB serial and flow control, but I still don't know whether
> it would be fast enough.
>
> /> //19 characters transfered at 115200 baud with 8N1 would require 1.65ms.
> > //Would that provide enough speed and space for smooth motion blending?/
>
> The CHM-T36VA serial bridge to the STM32F407 is slow and shaky, flow
> control seemed not to work properly. Experiments, I think done by Nélio,
> did not work. Maybe there would be an option to connect native USB serial?
>
> Duet 3 seems to have enough RAM, but its serial USB serial, while being
> improved lately, is still way too slow. The last experiments (I think by
> Wolfgang) did not really work out.
>
> One problem is also to let the planner wait until it has received the
> whole sequence for look-ahead planning. If the planner starts
> planning/executing motion too quickly, it will rush into premature
> deceleration, not yet seeing the sequence to the end. We added some new
> grace period support to Duet, i.e. it would wait longer, or until an
> M400 is received, which typically signals the end of a sequence. I'm not
> sure we tested the latest incarnation of that. Any controller supporting
> such paths would have a grace period+release feature too.
>
> Here is a simulations with the OpenPnP Motion Planner (dual nozzle
> machine, i.e. see the nozzle switch in the back row, showing as inverted
> Z moves):
>
>
>
>> >>         To view this discussion on the web visit
>> >>
>> >>
>> >>
>> >>
>> >>
>> >>     --
>> >>
>> >>         勇気とユーモア
>> >>
>> >>     --
>> >>     You received this message because you are subscribed to the
>> >>     Groups "OpenPnP" group.
>> >>     To unsubscribe from this group and stop receiving emails
>> from it,
>> >>     send an email to openpnp+u...@googlegroups.com
>> >>     To view this discussion on the web visit
>> >>
>> >>
>> >
>> >     --
>> >     You received this message because you are subscribed to the
>> >     Groups "OpenPnP" group.
>> >     To unsubscribe from this group and stop receiving emails
>> from it,
>> >     send an email to openpnp+u...@googlegroups.com
>> >     To view this discussion on the web visit
>> >
>> >
>> >
>> >
>> >
>> > --
>> >
>> >     勇気とユーモア
>> >
>> > --
>> > You received this message because you are subscribed to the Google
>> > Groups "OpenPnP" group.
>> > To unsubscribe from this group and stop receiving emails from
>> it, send
>> > an email to openpnp+u...@googlegroups.com
>> To view this discussion on the web visit
>>
>>
>>
>> --
>>
>> 勇気とユーモア
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "OpenPnP" group.
>> To unsubscribe from this group and stop receiving emails from it, send
>> To view this discussion on the web visit
>
> --
> You received this message because you are subscribed to the Google
> Groups "OpenPnP" group.
> To unsubscribe from this group and stop receiving emails from it, send
> To view this discussion on the web visit

### mark maker

Dec 8, 2021, 2:29:36 AM12/8/21

> flow-control is not needed.

This is not usually true. It takes considerable time to interpret the G-code, put the motion segments in the queue, and plan the ramps. These controllers are usually simple in that they always re-plan everything after receiving a new motion segment. Also there is usually no such thing as multi-threading and/or smart queue locking, this stuff is done in interrupt handlers that do one whole thing at a time. This means that locking/blocking times are large, the serial receive buffer can overflow and it must be flow controlled.

And that is also what was observed on every controller so far: unless flow control is done right, you get erratic behaviour or even hangs.

> a) I've read that USB interfaces might cause trouble because of ground loops.

That's the same for serial. It won't work without either isolation or grounding.

> Yes, USB isolators are easy to add.

Yes, and IMHO they are a MUST for any fast NC machine. My Azteeg Smoothie clone controller has one built-in, as it should.

> b) Fitting USB-serial into the existing firmware would be some work and - to my understanding - only make sense if we would gain significant benefits.

These gains would certainly be significant. We're talking a whole different category of performance!

> why not try to optimize the queue/memory layout...

Improving the comms speed or enlarging the queue is just treating the symptoms. Like I said: the real solution IMHO lays in supporting that stuff natively on the controller. Support motion blending (G64) and true 7-segment 3rd order control. But I would go for a more performant MCU, like the Teensy 4.1 and a separate driver board, like @billsef did:

_Mark

### Jan

Dec 10, 2021, 5:35:55 PM12/10/21
Hi Mark!

On 08.12.2021 08:29, mark maker wrote:
[...]
> /> //why not try to optimize the queue/memory layout... /
>
> Improving the comms speed or enlarging the queue is just treating the
> symptoms. Like I said: the real solution IMHO lays in supporting that
> stuff natively on the controller. Support motion blending (G64) and true
> 7-segment 3rd order control. But I would go for a more performant MCU,
> like the Teensy 4.1 and a separate driver board, like @billsef did:
>

a) I've tried to change the memory layout to make space for a large
queue. Unfortunately I got stuck. After changing the memory layout (to
free AHB0 as much as possible) I had to change MemoryPool.cpp to allow
Soothieware to handle pools larger then 64k. How I've 128k AHB0 pool,
but can't get the queue large because there is still more memory
consumped on the heap per queue element the on AHB0. Would anybody
please solve the puzzle for me:
- planner_queue_size is evaluated in Conveyor.cpp (line 75) and hand
over (in line 83) to BlockQueue::resize() (line 157).
- In BlockQueue::resize() memory for the queue is allocated at line 184
on AHB0 pool and then used to create "newring".
- If I change planner_queue_size by 1, I can see that AHB0 usage
increases by "Block size". In addition I see, that the heap usage
increases by 400 byte. Why?

b) I've studied the Nist RS274 Version 3 specification and found
(section 4.3.5.3) that Smoothieware currently seems to use mode
CANON_EXACT_PATH. G64 would switch to mode CANON_CONTINUOUS. If I
understand the specification correctely this would mean, that corners
are rounded to a configurable max. deviation. Together with my
understanding for junction_deviation this sound to me as if mode
CANON_CONTINUOUS could be implemented by providing a second
junction_deviation parameter. For CANON_CONTINUOUS we use a larger (eg.
5mm) junction deviation and for CANON_EXACT_PATH the current small one.
I'm I missing something?

c) implementing 7-segment 3rd order control would be an other (separate)

Jan

[...]

### mark maker

Dec 11, 2021, 4:50:33 AM12/11/21

junction_deviation that is currently Grbl is not to be confused with real curving. The Grbl junction_deviation pretends that there is a "virtual" curve, but does not actually make one. This is an optimization so the machine does not have to decelerate to zero velocity in junctions, instead it pretends there is a curve and therefore can move through the corner at speed. This is only tolerable because the machine and the motors (electromagnetic fields) are flexible to a degree, they will just be banged through. AFAIK, for stepper motors it can only tolerate deviations that don't threaten to lose steps, i.e. in the order of a half-step, typically sub-millimeter.

https://onehossshay.wordpress.com/2011/09/24/improving_grbl_cornering_algorithm/

"Lastly, keep in mind this method is a virtual path deviation that is only used for robustly computing the junction speed and does not actually mean there is a physical path deviation in your CNC machine."

To plan true physical curves would be an altogether different matter.

_Mark

### Arthur Wolf

Dec 11, 2021, 7:43:02 AM12/11/21
On Sat, Dec 11, 2021 at 10:50 AM mark maker <ma...@makr.zone> wrote:

junction_deviation that is currently Grbl is not to be confused with real curving. The Grbl junction_deviation pretends that there is a "virtual" curve, but does not actually make one. This is an optimization so the machine does not have to decelerate to zero velocity in junctions, instead it pretends there is a curve and therefore can move through the corner at speed. This is only tolerable because the machine and the motors (electromagnetic fields) are flexible to a degree, they will just be banged through. AFAIK, for stepper motors it can only tolerate deviations that don't threaten to lose steps, i.e. in the order of a half-step, typically sub-millimeter.

One way to think about this, is the less you slow down (in a corner or otherwise), the more inertia from the movement is transformed into kinetic energy, that has to be absorbed by the system (motors, frame, slack in belts, springs, etc)
This is obvious if you have a flimsy machine, high acceleration and strong junction deviation, you'll see the machine "rock" as the inertia from the movement is transferred to the frame.
If however your machine is very sturdy, that energy is transformed in other ways: heat, sound etc. This is one reason why more expensive machines tend to be heavier/have sturdier frames: it allows for higher speeds/accelerations/jd without the machine shaking all around (loosing precision).

I had actually started work on a planner for Smoothie that limits acceleration/jd in terms of explicit energy, so you'd say something like "my frame can take 0.1 joules per second", and it'd limit changes in speed/direction to accommodate that. I hope I'll finish that someday.

--
`勇気とユーモア`

### mark maker

Dec 11, 2021, 8:28:16 AM12/11/21

> This is obvious if you have a flimsy machine, high acceleration and strong junction deviation, you'll see the machine "rock" as the inertia from the movement is transferred to the frame.

> If however your machine is very sturdy, that energy is transformed in other ways: heat, sound etc. This is one reason why more expensive machines tend to be heavier/have sturdier frames

I do agree that heavier, stiffer machines with the corresponding much more powerful motors to drive the heavier rig, do allow for higher accelerations, while retaining positioning accuracy.

But I'm not sure it is actually an advantage in terms of allowable pretend junction deviation: If the machine does not give way, this means that exceedingly higher accelerations (and jerk etc.) will take place. Acceleration/jerk are obtained by essentially dividing the momentum by the flex, i.e. a machine with near zero flex would have near infinite acceleration/jerk, i.e. no motor can hold that! Of course, if you have closed loop servos, it will correct any deviation after the fact, but then your stiffness and accuracy is effectively gone too, and you might get ringing, again due to the stiffness.

A flimsier/softer machine might take these deviations more "naturally". It will just give way and ride through the bumps like on suspension, with a lot of damping too. Even with open loop steppers it remains practicable. Every cheap but still damn good 3D printer is a testimony of that balance, that after years of tuning may be "just right". This sometimes becomes visible, such as when Thomas Sanladerer "upgrades" his PRUSA with linear rails, making it much stiffer, and then sees how the prints get worse, not better. I'm sure that true motion blending (instead of just pretend junction deviation) could make that ringing go away.

So I would say that a stiffer machine does not necessarily benefit less from advanced motion control (like true motion blending), it may sometimes even be the other way around.

_Mark

### Harjit Singh

Dec 11, 2021, 12:24:20 PM12/11/21
@Mark - been meaning to ask you about the 3rd order i.e. jerk constrained path. I've followed your work and emails but there are a couple of aspects I haven't worked out.

When generating the motion parameters, you try to move all axes simultaneously - this is shown in the beautiful 3D diagram (motion-planning-optimized.png).

1. Do you start at the end of the motion and generate the motion parameters from there? The reason is that the end of the motion has to have a zero velocity. If you plan from where the nozzle is, you could end up with a non-zero velocity at the location you want to stop. Or you can end up with sub-optimal velocity along the path.

2. I believe you move all three (or four) axes X, Y, Z (and C). The scenario is - imagine there is a tall component directly in the path. Then, you have to move the Z-axis to get the vertical clearance and then move the X/Y axes. I say "Z and then X and Y" and it sounds sequential. The question isdo you only move Z and not move X and Y axes until the Z is clear or do you move X and Y but very slowly and guarantee no collision. And then, as soon as the Z axis is clear, change the X and Y motion parameters to move much more quickly?

You've mentioned that the right thing to do is have the motor controller/driver generate the complete motion based on the high level motion parameters. This makes sense. What code can I read to get an idea of the complexity for just the execution portion i.e. the portion that would need to be on the motor controller/driver.

Thank you!

### mark maker

Dec 11, 2021, 12:54:45 PM12/11/21

Hi Harjit,

The way I did it in OpenPnP is linked below. The idea is somewhat described in the comment here.

But today/in a controller I would probably do it differently. Rather than "overshoot" into an uncoordinated move at Safe Z, I would follow the G64 idea/NIST standard, to smooth one motion into the next, i.e. not necessarily reach the corner point.

Code parts:

Single Motion (interface to use):

https://github.com/openpnp/openpnp/blob/develop/src/main/java/org/openpnp/model/Motion.java

Single Motion Profile (3rd order ramps, uncoordinated moves etc.). That's the hardest part:

https://github.com/openpnp/openpnp/blob/develop/src/main/java/org/openpnp/model/MotionProfile.java

Motion Path (Handling multiple Motions, putting things together):

https://github.com/openpnp/openpnp/blob/develop/src/main/java/org/openpnp/model/AbstractMotionPath.java

Motion Planner (interface to use the whole thing):

https://github.com/openpnp/openpnp/blob/develop/src/main/java/org/openpnp/machine/reference/driver/AbstractMotionPlanner.java

_Mark

### Jarosław Karwik

Dec 12, 2021, 4:26:20 AM12/12/21
to OpenPnP
This may be helpfull for you:
( original source:

If you want to play with 3rd order 7 segments curves in python:

Same in C:

### Jan

Dec 14, 2021, 10:53:19 AM12/14/21
Hi Mark! Hi Arthur!
I'm sorry, I still don't get it.
Mark, you asked for controller-wise motion blending and referred to
G64. Section 3.5.14 of the NIST specification version 3 says, that G64
"put the machining center into [..] continuous mode". Continuous mode is
explained in Section 4.3.5.3 as "In CANON_CONTINUOUS mode, the control
tries to keep the feed rate constant and does not try to keep the
controlled point exactly on the path at all times.". In addition is
specifies that "There is a maximum allowable deviation at such
junctures, and the control should never allow that to be exceeded;
acceleration and deceleration may be performed if necessary to do this."
I've studies the (smoothieware) code and Sonny's paper you mentioned.
To my understanding the math is ok and the assumption, that the junction
is a cycle even if it its not, holds true. (Calculating the difference
would be a nice homework for graduates.)
I also don't see why inertia, machine friction and step loosing is
always argued against junction_deviation. To my understanding
junction_deviation, as proposed by Sonny and implemented in
smoothieware, tries to join two segments of a movement by starting the
second while the first it still ongoing by respecting a maximum
allowable path deviation. Each segment follows its own rules with
respect to target position, max. speed and max. acceleration (and
potential other parameters). Suppose the implementation is correct, no
motor is ever operated outside its specified limits. However, in such
junctions, two or more motors may operate in parallel hence the net
acceleration (at the nozzle tip in the PnP case) is larger. (for a
square machine - as we usually use for PnP - this is sqrt(a_x^2 + a_y^2
+ a_z^2) where a_i is the acceleration on the respective axis).
If you don't like the way the machine drives thru junctions, you're
free to ask if the acceleration profile in junctions could be made
different from the one used to stop the motor. At present the
(smoothieware) implementation uses constant ac-/deceleration. I guess
thats what you meant by 7-segment motion control. That would probably
change the way, the machine drives thru corners, but will not give a
circular motion (sin/cos)... If you don't like the effect of the net
acceleration it should be straight forward to reduce the configured
acceleration per axis in corners. However, this would be beyond the
scope the the NIST specification.
To my understanding, with junction_deviation enabled the machine runs
in continuous mode. You would then need G61 to switch the machine to
exact path mode or G61.1 for exact stop mode to force the machine to
reach certain points exactly. Btw: did you ever observed, that the
nozzle did not touch down enough (on feeders or the PCB)? With
junction_deviation > 0 and nozzle-down and nozzle-up segments both in
the queue, the machine would be allowed to only lower the nozzle by
target-Z - junction_deviation (remember continuous mode: "There is a
maximum allowable deviation at such junctures"). So I would say, we need
a way to put the controller into exact path mode where application and
use junction_deviation every where else. We could then reduce jerk by
modifying the acceleration/deceleration functions in the controller.
Maybe S-shape using sin/cos would be a way to go, thats not so difficult
the implement. Unfortunately it only provides a single parameters as we
currently have. So acceleration would be converted into angular velocity.

Jan

On 11.12.2021 14:28, mark maker wrote:
> /> This is obvious if you have a flimsy machine, high acceleration and
> strong junction deviation, you'll see the machine "rock" as the inertia
> from the movement is transferred to the frame./
>
> />//If however your machine is very sturdy, that energy is transformed
> in other ways: heat, sound etc. This is one reason why more expensive
> machines tend to be heavier/have sturdier frames/
>
> I do agree that heavier, stiffer machines with the corresponding much
> more powerful motors to drive the heavier rig, do allow for higher
> accelerations, while retaining positioning accuracy.
>
> But I'm not sure it is actually an advantage in terms of allowable
> /pretend /junction deviation: If the machine does not give way, this
> means that exceedingly higher accelerations (and jerk etc.) will take
> place. Acceleration/jerk are obtained by essentially /dividing/ the
> momentum by the flex, i.e. a machine with near zero flex would have near
> infinite acceleration/jerk, i.e. no motor can hold that! Of course, if
> you have closed loop servos, it will correct any deviation after the
> fact, but then your stiffness and accuracy is /effectively/ gone too,
> and you might get ringing, again due to the stiffness.
>
> A flimsier/softer machine might take these deviations more "naturally".
> It will just give way and ride through the bumps like on suspension,
> with a lot of damping too. Even with open loop steppers it remains
> practicable. Every cheap but still damn good 3D printer is a testimony
> of that balance, that after years of tuning may be "just right". This
> PRUSA with linear rails, making it much stiffer, and then sees how the
> prints get worse, not better <https://youtu.be/J_RcgixLbAI>. I'm sure
> that true motion blending (instead of just /pretend/ junction deviation)
> could make that ringing go away.
>
> So I would say that a stiffer machine does not necessarily benefit
> /less/ from advanced motion control (like true motion blending), it may
> sometimes even be the other way around.
>
> _Mark
>
> On 11.12.21 13:42, Arthur Wolf wrote:
>>
>>
>> On Sat, Dec 11, 2021 at 10:50 AM mark maker <ma...@makr.zone> wrote:
>>
>> *junction_deviation* that is currently Grbl is not to be confused
>> with real curving. The Grbl *junction_deviation* /pretends/ that
>> there is a "virtual" curve, but does not actually make one. This
>> is an optimization so the machine does not have to decelerate to
>> zero velocity in junctions, instead it /pretends/ there is a curve
>> and therefore can move through the corner at speed. This is only
>> tolerable because the machine and the motors (electromagnetic
>> fields) are flexible to a degree, they will just be banged
>> through. AFAIK, for stepper motors it can only tolerate deviations
>> that don't threaten to lose steps, i.e. in the order of a
>> half-step, typically sub-millimeter.
>>
>>
>> One way to think about this, is the less you slow down (in a corner or
>> otherwise), the more inertia from the movement is transformed into
>> kinetic energy, that has to be absorbed by the system (motors, frame,
>> slack in belts, springs, etc)
>> This is obvious if you have a flimsy machine, high acceleration and
>> strong junction deviation, you'll see the machine "rock" as the
>> inertia from the movement is transferred to the frame.
>> If however your machine is very sturdy, that energy is transformed in
>> other ways: heat, sound etc. This is one reason why more expensive
>> machines tend to be heavier/have sturdier frames: it allows for higher
>> speeds/accelerations/jd without the machine shaking all around
>> (loosing precision).
>>
>> I had actually started work on a planner for Smoothie that limits
>> acceleration/jd in terms of explicit energy, so you'd say something
>> like "my frame can take 0.1 joules per second", and it'd limit changes
>> in speed/direction to accommodate that. I hope I'll finish that someday.
>>
>> https://onehossshay.wordpress.com/2011/09/24/improving_grbl_cornering_algorithm/
>>
>> /"//Lastly, keep in mind this method is a //*virtual*// path
>> deviation that is only used for robustly computing the junction
>> speed and does not actually mean there is a physical path
>> deviation in your CNC machine."/
>>>>>>>     >>         To view this discussion on the web visit
>>>>>>>     >>
>>>>>>>
>>>>>>>     >>
>>>>>>>
>>>>>>>     >>
>>>>>>>     >>
>>>>>>>     >>
>>>>>>>     >>     --
>>>>>>>     >>
>>>>>>>     >>         勇気とユーモア
>>>>>>>     >>
>>>>>>>     >>     --
>>>>>>>     >>     You received this message because you are
>>>>>>> subscribed to the
>>>>>>>     >>     Groups "OpenPnP" group.
>>>>>>>     >>     To unsubscribe from this group and stop receiving
>>>>>>> emails
>>>>>>>     from it,
>>>>>>>     >>     send an email to openpnp+u...@googlegroups.com
>>>>>>>     >>     To view this discussion on the web visit
>>>>>>>     >>
>>>>>>>
>>>>>>>     >>
>>>>>>>
>>>>>>>     >
>>>>>>>     >     --
>>>>>>>     >     You received this message because you are
>>>>>>> subscribed to the
>>>>>>>     >     Groups "OpenPnP" group.
>>>>>>>     >     To unsubscribe from this group and stop receiving
>>>>>>> emails
>>>>>>>     from it,
>>>>>>>     >     send an email to openpnp+u...@googlegroups.com
>>>>>>>     >     To view this discussion on the web visit
>>>>>>>     >
>>>>>>>
>>>>>>>     >
>>>>>>>
>>>>>>>     >
>>>>>>>     >
>>>>>>>     >
>>>>>>>     > --
>>>>>>>     >
>>>>>>>     >     勇気とユーモア
>>>>>>>     >
>>>>>>>     > --
>>>>>>>     > You received this message because you are subscribed to
>>>>>>>     > Groups "OpenPnP" group.
>>>>>>>     > To unsubscribe from this group and stop receiving
>>>>>>> emails from
>>>>>>>     it, send
>>>>>>>     > an email to openpnp+u...@googlegroups.com
>>
>>
>>
>> --
>>
>> 勇気とユーモア
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "OpenPnP" group.
>> To unsubscribe from this group and stop receiving emails from it, send
>> To view this discussion on the web visit
>
> --
> You received this message because you are subscribed to the Google
> Groups "OpenPnP" group.
> To unsubscribe from this group and stop receiving emails from it, send
> To view this discussion on the web visit

### mark maker

Dec 14, 2021, 12:08:23 PM12/14/21

Hi Jan

Sorry, what you are describing is not what junction_deviation does in Grbl and descendants, including Smoothie.

These controllers are only capable of planning straight lines. Even if you send them G2, G3 arcs, they internally break it up into a polygon. The planner can only handle straight segments.

Now imagine sitting in one of these small mining rail cars. You are driving at speed through a curve in the rails. Now imagine the rails are not smooth but approximated by a polygon. Certainly you can now "feel" the jerks and bumps in your imagination 😁

When driving over a polygon corner, even at a very shallow angle, the rail car would need to change its velocity (vector) in zero time. Due to inertia, that is physically impossible. Instead everything in and on it will flex, including you. Ouch, right?!

The remove all jerking and bumping, you would need to decelerate to zero velocity before the corner. Then re-accelerate again after the corner. Obviously this is very slow and unacceptable for many NC application. You'd burn a mill's drill bit, shoot big holes with a laser, or make blobs with a 3D printer.

So these controllers make a compromise. They pretend there is a curve through the corner. Then they calculate what speed would be acceptable to go through the corner, if there were such a curve (limited by the acceleration). The shallower the corner angle, the faster they can go through. Then they calculate the segment entry/exit speeds according to that speed. But they still drive the steppers in straight lines (red vectors). This junction_deviation does not remove the "jerk or bump" when going through the corner, it only limits it to a tolerable amount!

That's why these are called virtual curves. They are not real!

In reality the machine will not move along that dark blue virtual curve, instead it will move something like the orange curve here, i.e. overshoot and then settle back onto the exit vector. It's all in the flex and dampening of the machine:

Obviously it would be much less extreme on a shallow angle, and that's what interpolation, including OpenPnP's tries to do. This is OK for many applications, on the sub-millimeter scale and with mostly shallow polygon angles, but it is in no way motion path smoothing or G64.

Therefore, unfortunately what you are describing in the rest of your text "does not compute". 😬

If you don't believe me: set your Smoothie junction_deviation to some multi-millimeter value:

https://smoothieware.org/configuration-options

 junction_deviation 0.05 Similar to the old “max_jerk”, in millimeters. Defines how much the machine slows down when decelerating proportional to the vector angle of change of direction. See here and here. Lower values mean being more careful, higher values means being faster and have more jerk

Try running a simple two-legged angled move. But no guarantees as to the survival of your machine!!!

_Mark

### Jan

Dec 20, 2021, 11:28:27 AM12/20/21
Hi Mark!
Many thanks for putting so much effort in OpenPnP and in responding to
my questions.
explanations and I now understand where I was wrong: the Block class
describes a linear movement of all motors together. So if two blocks are
joined, the code can only control the speed at the junction. And thats
where it might violate the acceleration limits per axis which would
introduce additional jerk and potentially result in loss of steps.
I've also found the place, there the slicing of arcs into line segments
is done.
Overall, it seems that adding mode CANON_CONTINUOUS (motion blending)
would be quite some work and probably would require making some
fundamental changes. As you wrote earlier, according to your simulations
the benefit of such modification is only limited (and you already have a
solutions with PC wise motion blending), I'll put my efforts rather into
the job optimization topic we discussed as well.

Jan

On 14.12.2021 18:08, mark maker wrote:
> Hi Jan
>
> Sorry, what you are describing is not what *junction_deviation *does in
> Grbl and descendants, including Smoothie.
>
> These controllers are only capable of planning straight lines. Even if
> you send them G2, G3 arcs, they internally break it up into a polygon.
> *The planner can only handle straight segments.*
>
> Now imagine sitting in one of these small mining rail cars. You are
> driving at speed through a curve in the rails. Now imagine the rails are
> not smooth but approximated by a polygon. Certainly you can now "feel"
> the jerks and bumps in your imagination 😁
>
> When driving over a polygon corner, even at a very shallow angle, the
> rail car would need to change its velocity (vector) in zero time. Due to
> inertia, that is *physically impossible*. Instead everything in and on
> it will flex, including you. *Ouch*, right?!
>
> The remove all jerking and bumping, you would need to decelerate to zero
> velocity before the corner. Then re-accelerate again after the corner.
> Obviously this is very slow and unacceptable for many NC application.
> You'd burn a mill's drill bit, shoot big holes with a laser, or make
> blobs with a 3D printer.
>
> So these controllers make a compromise. They *pretend *there is a curve
> through the corner. Then they calculate what speed would be acceptable
> to go through the corner, if there were such a curve (limited by the
> acceleration). The shallower the corner angle, the faster they can go
> through. Then they calculate the segment entry/exit speeds according to
> that speed. *But they still drive the steppers in straight lines (red
> vectors). *This *junction_deviation* does *not remove* the "jerk or
> bump" when going through the corner, it *only limits it to a tolerable
> amount*!
>
> That's why these are called *virtual curves*. They are *not real!*
>
> **
>
> https://onehossshay.wordpress.com/2011/09/24/improving_grbl_cornering_algorithm/
>
> In reality the machine will not move along that*dark blue **virtual
> **curve*, instead it will move something like the *orange **curve* here,
> i.e. overshoot and then settle back onto the exit vector. It's all in
> the flex and dampening of the machine:
>
> Obviously it would be much less extreme on a shallow angle, and that's
> what *interpolation*, including OpenPnP's tries to do. This is OK for
> many applications, on the sub-millimeter scale and with mostly shallow
> polygon angles, *but it is in no way motion path smoothing or G64. *
>
> Therefore, unfortunately what you are describing in the rest of your
> text "does not compute". 😬
>
> If you don't believe me: set your Smoothie *junction_deviation *to some
> multi-millimeter value:
>
> https://smoothieware.org/configuration-options
>
> junction_deviation 0.05 Similar to the old “max_jerk”, in millimeters.
> Defines how much the machine slows down when decelerating proportional
> to the vector angle of change of direction. See here
> <https://github.com/grbl/grbl/blob/master/planner.c> and here
> <https://github.com/grbl/grbl/wiki/Configuring-Grbl-v0.8>. Lower values
> mean being more careful, higher values means being faster and have more
> jerk
>
> Try running a simple two-legged angled move. *But no guarantees as to
> the survival of your machine!!! *

### dc42

Dec 20, 2021, 4:52:56 PM12/20/21
to OpenPnP
Perhaps what's needed is a new GCode command that means "Go from the present position to (xyz) in a smooth manner, reaching a maximum height of (h)". It would do something like this:

1. If the starting Z is lower than the ending Z, go straight up to reach the ending Z.
2. Describe a stretched arc from this position to the end XY position, reaching the specified maximum height.
3. If the required end Z is lower than the starting/current Z, go straight down.

### bert shivaan

Dec 20, 2021, 8:26:41 PM12/20/21
to OpenPnP
Thats actually how some of my 20+ year old machines work, If the end point Z is higher then the start point, Z is raised then X/Y move. If the end point Z is lower than the current, it will move X/Y first then lower Z.

But that is not what Mark is trying to do, He wants to blend the corner which doesn't seem like any boards do that yet.

### mark maker

Dec 21, 2021, 11:35:23 AM12/21/21

Hi dc42 / all,

this topic had me thinking for quite some time now. The solution could be something like the following:

1. Working assumption: only two subsequent segments can be blended. A more general, but also much more complicated discussion could take N blended segments into consideration, but is beyond the scope here. However, see (16).
2. Start by planning the segments as today but no "junction_deviation" applied (needed modifications are explained below).
3. Instead of executing the motion planner segments one by one, execute them slightly overlapping in time. See the animation below. Blending is achieved by simply adding the relative displacement of the second segment to the absolute displacement of the first.
4. The effects of the overlap (literally, "the cutting of corners") would have to be limited by the maximum deviation allowed by G64, as described in the NIST standard. See how LinuxCNC documents it: http://www.linuxcnc.org/docs/2.6/html/gcode/gcode.html#sec:G64.
5. Different accelerations limits on the segments must be taken into consideration, i.e. the point in time where the path is nearest the corner can become very asymmetric (see the demo at the end).
6. The overlap time obtained from (4) is only the theoretical maximum, it will be further constrained below.
7. For very blunt angles this can give large allowable overlap times.
8. Next we need to make sure, the blending still respects the feed-rate and acceleration limits. This is certainly true for angles of 90°, nothing is adding up either way.
9. For blunter angles, if you take the minimum of the first segment deceleration ramp time and the second segment acceleration ramp time as the allowable maximum overlap time, then the limits should still always be respected (assuming we allow for the limits to be blended too!). As one segment ramps down, the other ramps up. The "corner case" is a sum-zero game, where any deceleration is compensated by same acceleration, i.e. where the velocity stays constant. This happens when we blend nearly co-linear segments (with the same rate limits) together, i.e. we get exactly what we want: no deceleration in near-straight junctions.
10. The limitation to acceleration/deceleration ramp times also makes sure we always only blend two segments together. It cannot reach beyond.
11. For acute angles, it is more complicated: Deceleration (which is negative acceleration) and acceleration going in the opposite direction, get the same sign, i.e. they add up. The axis acceleration limit could be violated, i.e. the allowable blending time would be zero.
12. But we could alter the segments i.e. limit their deceleration/acceleration, so that the sum remains within the axis limit. The most challenged axis would then give the allowable maximum deceleration/acceleration for the segments.
13. Like (9) we limit the overlap to the smaller ramp time.
14. Unfortunately similar to (9), the ramp times can be different in the two segments. So the optimal planner would have to plan with two deceleration or acceleration ramp phases, one that is constrained by overlap and one that is not. I guess that would actually be the most difficult part of the whole impementation. Especially for 3rd order (jerk) control.
15. The above steps were explained in a logical order. But in reality, they would have to be done in a different order, i.e. steps (12) through (14) would have to precede step (2).
16. Corner case: We assume (2) optimizes co-linear segments as it already does in typical planners today. More specifically, we assume its makes sure the ramp of (at least) one co-linear segment becomes one-sided. Because there is no ramp time, (9) and (13) will naturally disallow blending of co-linear segments. These are not generally OK for blending, because they have entry/exit velocity that is non-zero. By excluding those, we only have to deal with segments that decelerate/accelerate to/from still-stand, so what was said in (9) still holds true. Furthermore, this co-linear segment optimization covers N subsequent segments, unlike the blending we discuss here (1). It follows that blending is no generalization, i.e. no valid replacement for that optimization (as I was hoping for some time).

See the animation (click to open):

It has a higher acceleration on the second segment to demonstrate that G64 calculation is not trivial (5). But note that the demo simply has the same overlap time for all the examples, i.e. there is no "real G64" applied.

_Mark

### mark maker

Dec 21, 2021, 12:33:59 PM12/21/21

Added both symmetric and asymmetric acceleration for better illustration:

### John Plocher

Dec 21, 2021, 7:29:19 PM12/21/21
Mark,

Just a quick FYI (or maybe FYA)...

I had a lunch time conversation with a Mech Engineer friend about your OpenPnP work, and he pointed me at Klipper, which is doing many things that sound similar to your work, but in the 3D printing world.

The starting point is replacing the G-Code on the printer controller with custom code, and offloading the planner/optimizer (in this case, to a raspi)...

Looks like an interesting perspective, especially as it removes the limitations inherent in depending on a 3rd-party GCode interpreter's implementation limits.

-John
FYA ... Amusement :-)

High precision stepper movement. Klipper utilizes an application processor (such as a low-cost Raspberry Pi) when calculating printer movements. The application processor determines when to step each stepper motor, it compresses those events, transmits them to the micro-controller, and then the micro-controller executes each event at the requested time. Each stepper event is scheduled with a precision of 25 micro-seconds or better. The software does not use kinematic estimations (such as the Bresenham algorithm) - instead it calculates precise step times based on the physics of acceleration and the physics of the machine kinematics. More precise stepper movement translates to quieter and more stable printer operation.

Klipper uses an "iterative solver" to calculate precise step times from simple kinematic equations. This makes porting Klipper to new types of robots easier and it keeps timing precise even with complex kinematics (no "line segmentation" is needed).

### Jarosław Karwik

Dec 22, 2021, 2:20:18 AM12/22/21
to OpenPnP
Well Klipper does magic. They also add accelerometer to the head and measure vibrations to compensate for it ( in my Voron 2.4)

But you  ended up in solution which mark already presented - calculation of movement sectors on PC and sending it to PC - sadly Smoothie could not take it.

Now, once the water is frozen ( I deal with electric boats) I have more time for my controller - I should be able to finally finish it and take more then Smoothie.

However one thing came out during preliminary testing -  FDCAN, while powerful,  is still limited in bandwidth for a system with dual controllers ( second one on the head).
I had to split some of calculations and leave them for the remote head - it introduces 1-2ms latency.
Anyway - for such taske more suitable would be single powerfull controller and only SerSes on the head ( https://en.wikipedia.org/wiki/SerDes#:~:text=A%20Serializer%2FDeserializer%20(SerDes%20pronounced,parallel%20interfaces%20in%20each%20direction.)

### mark maker

Dec 22, 2021, 3:09:12 AM12/22/21

Hi John,

Conceptually, this is certainly a possible approach.

I don't know if Klipper specifically is a valid approach for OpenPnP, because it seems to address use cases that are different. In 3D Printing or CNC Milling etc. you have a NC-Program that is prepared from beginning to end. It then statically runs for hours.

This means that latency is of no concern whatsoever.

However, in OpenPnP we have a highly interactive system: Vision, Vacuum Sensing, Contact Probing, Drag-pin sensing, Feeder sensing etc. are all sensory inputs that are interpreted by OpenPnP, and subsequent G-code can only be generated with the knowledge obtained from that sensory input. Because of that, OpenPnP runs in close step-by-step synchronization with the controller. I improved that a bit by introducing the GcodeAsyncDriver, but at least in case of vision, the round-trip time is still very important.

There has been talk about Klipper before. A user said it has 100ms latency, which would not be catastrophic but still bad. Unfortunately, that conversation was deleted by the user.

_Mark

--
You received this message because you are subscribed to the Google Groups "OpenPnP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openpnp+u...@googlegroups.com.

### mark maker

Dec 22, 2021, 3:37:52 AM12/22/21

Just FIY, I found some mistakes in my reasoning.

Assertions in (8) and (9) about 90° and blunter angles are wrong in terms of axis limits. For axis limits, the angle is irrelevant, it is the axis motion flipping its sign between the two segments that is the relevant criteria.

The angular reasoning is valid for toolpath limits, and would have to be treated too, similar to what I said before, but applicable to the toolpath instead of the axis

_Mark

### John Plocher

Dec 22, 2021, 11:27:57 AM12/22/21
The architectural concept that klipper raised for me was replacing the complex and limiting g-code interpreter on the machine with something simpler…

That is, if the existing controllers (smoothie, marlin, …) all have limits that preclude taking full advantage of your jerk reduction (etc) work, is there any advantage to putting effort into creating/ modifying the controller firmware to optimize it specifically for PnP?  More buffers, less unneeded cnc/3D constraints, tighter coupling to the assumptions you are making about safe-z and the like,…?

I too don’t think klipper itself is directly usable here, but rather that the  klipper team is solving a similar class of problems as you are, and that they decided to jettison generic gcode interpretation…

John

### Harjit Singh

Dec 22, 2021, 1:26:42 PM12/22/21
@mark - to simplify the discussion:

Instead of doing the "upside down U moves" that you have shown, imagine Z axis goes up and down with X and Y at zero velocity i.e. "rectangular" moves.
a) Then compute the time for the X and the Y movement.
b) Then slow down the faster axis to finish at the same time as the slower one by reducing the maximum velocity. This means, we get a movement in a straight line with both axes moving at the same time.

The current controllers that have jerk limited motion can support this. This is slower in that the Z axis motion and the X and Y axis motions aren't blended.

Where I haven't formed a full mental model is around the Z axis blending. I keep thinking, the motion needs to be broken into three segments for the general case:
A) Raise Z to safe Z and accelerate X and Y while ensuring the nozzle/component doesn't crash into an obstruction. At the end of this move, Z will have zero velocity but X and Y will be non-zero.
B) Move X and Y at new motion parameters (max. acceleration, max. velocity and distance).
C) Lower Z to target Z and decelerate X and Y to zero while ensuring the nozzle/component doesn't crash into an obstruction. At the end of this move, X, Y and Z will have zero velocity.

Steps #1 and #3 need a 3D path solution. I looked at the code you pointed me to but I got lost because I don't have a mental model of the architecture.

1) Do you compute a "safe Z for when X and Y can start moving" - corresponds to "A" and a "safe Z for when X and Y must not be moving" corresponds to "C"?

### mark maker

Dec 23, 2021, 3:10:29 AM12/23/21

Hi Harjit,

I assume that the Safe Z promise must be kept. So the curve can only begin at Safe Z, the path must still overshoot into the Safe Z Zone.

The motion planner in OpenPnP would have to determine what the optimal curve is, given the distance in X, Y and the available headroom in the Safe Z Zone. For shorter distances in X, Y only a small overshoot is optimal, i.e. the limit is given by the ramps of the X/Y move, which then becomes one fluid curve. For large X, Y moves, you would probably use the full Z head-room, i.e. there are two curves on either side of a straight move . If the head-room is large, it also depends on how far down the Z started, i.e. how fast (and for 3rd order motion, how accelerated) the nozzle is, when it crosses Safe Z, i.e. how much head-room it needs to (jerk and) decelerate to still-stand, i.e. the limit is then given by the Z off-ramp.

Note: if the lifting of Z at the start is not the same as lowering of Z at the target, the Z overshoot will become asymmetric. This is especially the case, when we have a dual nozzle shared Z axis machine, an the other nozzle is lowered at the target. The Z overshoot is then inverted from the top of the Safe Z Zone, the resulting move is wave-shaped, instead of inverted-U-shaped. Is like with the previous method in the demo's back two rows:

Once the OpenPnP motion planner has the Z overshoot, it can form the curve as follows:

• Sets G64 to zero.
• Moves Z up to Safe Z (first segment).
• Sets G64 to a very large value allowing arbitrary curvature.
• Moves Z further up to start side Z overshoot height (second  segment).
• Moves X, Y to target, at target side Z overshoot height (third segment)
• Moves Z down to Safe Z (fourth segment).
• Sets G64 to zero.
• Moves Z down to target Z (fifth segment).

With the rules (1) and (9)/(13) from my previous post, the blending/curve can only be between the ramps of two segments. So breaking up the Z moves, we can make sure that's the case, without any difficult "reverse G64" calculations on the OpenPnP side.

Overall, this system is much, much simpler than what I've (only partially!) implemented before, i.e. allowing overshoot into uncoordinated moves. Plus, this system seems to conform to the NIST G-code standard. The down side is that the driving system now needs to calculate the overshoot target points. But that's simple in the case of PnP.

https://makr.zone/motion_blending_animation.html

_Mark

On 22.12.21 19:26, Harjit Singh wrote:
@mark - to simplify the discussion:

Instead of doing the "upside down U moves" that you have shown, imagine Z axis goes up and down with X and Y at zero velocity i.e. "rectangular" moves.
a) Then compute the time for the X and the Y movement.
b) Then slow down the faster axis to finish at the same time as the slower one by reducing the maximum velocity. This means, we get a movement in a straight line with both axes moving at the same time.

The current controllers that have jerk limited motion can support this. This is slower in that the Z axis motion and the X and Y axis motions aren't blended.

Where I haven't formed a full mental model is around the Z axis blending. I keep thinking, the motion needs to be broken into three segments for the general case:
A) Raise Z to safe Z and accelerate X and Y while ensuring the nozzle/component doesn't crash into an obstruction. At the end of this move, Z will have zero velocity but X and Y will be non-zero.
B) Move X and Y at new motion parameters (max. acceleration, max. velocity and distance).
C) Lower Z to target Z and decelerate X and Y to zero while ensuring the nozzle/component doesn't crash into an obstruction. At the end of this move, X, Y and Z will have zero velocity.

Steps #1 and #3 need a 3D path solution. I looked at the code you pointed me to but I got lost because I don't have a mental model of the architecture.

1) Do you compute a "safe Z for when X and Y can start moving" - corresponds to "A" and a "safe Z for when X and Y must not be moving" corresponds to "C"?

____

### Jan

Dec 23, 2021, 5:09:57 PM12/23/21
Hi Mark!

On 23.12.2021 09:10, mark maker wrote:
[...]
>
> Once the OpenPnP motion planner has the Z overshoot, it can form the
> curve as follows:
>
> * Sets G64 to zero.
> * Moves Z up to Safe Z (first segment).
> * Sets G64 to a very large value allowing arbitrary curvature.
> * Moves Z further up to start side Z overshoot height (second segment).
> * Moves X, Y to target, at target side Z overshoot height (third segment)
> * Moves Z down to Safe Z (fourth segment).
> * Sets G64 to zero.
> * Moves Z down to target Z (fifth segment).

It looks to me that there is a slight misunderstanding in
CANON_CONTINUOUS mode, which is enabled by G64: According to NIST
standard, "In CANON_CONTINUOUS mode, the control tries to keep the feed
rate constant and does not try to keep the controlled point exactly on
the path at all times" (section 4.3.5.3). It further says, that "There
is a maximum allowable deviation at such junctures" and "Currently,
there is no function to set the maximum deviation allowable in
CANON_CONTINUOUS mode."

1) configure mode CANON_EXACT_PATH (G61)
2) move to Save Z
3) switch to mode CANON_CONTINUOUS (G64)
4) move to target position (X, Y, Save Z)
5) switch to mode CANON_EXACT_PATH (G61)
6) move Z down to target Z.

The controller should then use what ever path is short, fast and does
not violate "maximum allowable deviation" to go to (X, Y, Save Z).
Implementation wise smoothy/grbl uses a "block" to describe a single
segment of a path. Within this block any motors can be first
accelerated, then run at constant speed and finally decelerate. Hence
the first step would be to break up this schema and allow individual
motor to skip one or more of this steps. This would allow to accelerate
one motor while the other decelerates, which is a basic requirement for
motion blending.
Arthur and others seem to follow a different approach with smoothie2:
provide more space for the motion segment queue, more cpu power for
faster block to block interaction calculation and usb/Ethernet
interfaces for faster communication with OpenPnP. I'm not sure they also
cover the accelerate-one-motor-and-in-parallel-decelerate-an-other
problem which we need for motion blending.

Jan
>> 1. Working assumption: only two subsequent segments can be blended. A
>> more general, but also much more complicated discussion /could/
>> take N blended segments into consideration, but is beyond the
>> scope here. However, see (16).
>> 2. Start by planning the segments as today but no
>> "junction_deviation" applied (needed modifications are explained
>> below).
>> 3. Instead of executing the motion planner segments one by one,
>> execute them slightly overlapping in time. See the animation
>> below. Blending is achieved by simply adding the /relative
>> displacement/ of the second segment to the /absolute displacement/
>> of the first.
>> 4. The effects of the overlap (literally, "the cutting of corners")
>> would have to be limited by the maximum deviation allowed by G64,
>> as described in the NIST standard. See how LinuxCNC documents it:
>> http://www.linuxcnc.org/docs/2.6/html/gcode/gcode.html#sec:G64.
>> 5. Different accelerations limits on the segments must be taken into
>> consideration, i.e. the point in time where the path is nearest
>> the corner can become very asymmetric (see the demo at the end).
>> 6. The overlap time obtained from (4) is only the theoretical
>> maximum, it will be further constrained below.
>> 7. For very blunt angles this can give large allowable overlap times.
>> 8. Next we need to make sure, the blending still respects the
>> feed-rate and acceleration limits. This is certainly true for
>> angles of 90°, nothing is adding up either way.
>> 9. For blunter angles, if you take the /minimum /of the first segment
>> /deceleration/ ramp time and the second segment /acceleration/
>> ramp time as the allowable maximum overlap time, then the limits
>> should still always be respected (assuming we allow for the
>> /limits/ to be blended too!). As one segment ramps down, the other
>> ramps up. The "corner case" is a sum-zero game, where any
>> deceleration is compensated by same acceleration, i.e. where the
>> velocity stays constant. This happens when we blend /nearly/
>> co-linear segments (with the same rate limits) together, i.e. we
>> get exactly what we want: no deceleration in near-straight junctions.
>> 10. The limitation to acceleration/deceleration ramp times also makes
>> sure we always only blend /two/ segments together. It cannot reach
>> beyond.
>> 11. For acute angles, it is more complicated: Deceleration (which is
>> negative acceleration) and acceleration going in the opposite
>> direction, get the same sign, i.e. they add up. The axis
>> acceleration limit could be violated, i.e. the allowable blending
>> time would be zero.
>> 12. But we could alter the segments i.e. limit their
>> deceleration/acceleration, so that the sum remains within the axis
>> limit. The most challenged axis would then give the allowable
>> maximum deceleration/acceleration for the segments.
>> 13. Like (9) we limit the overlap to the smaller ramp time.
>> 14. Unfortunately similar to (9), the ramp times can be different in
>> the two segments. So the /optimal/ planner would have to plan with
>> /two/ deceleration or acceleration ramp phases, one that is
>> constrained by overlap and one that is not. /I guess that would
>> actually be the most difficult part of the whole impementation.
>> Especially for 3rd order (jerk) control./
>> 15. The above steps were explained in a logical order. But in reality,
>> they would have to be done in a different order, i.e. steps (12)
>> through (14) would have to precede step (2).
>> 16. Corner case: We assume (2) optimizes co-linear segments as it
>> already does in typical planners today. More specifically, we
>> assume its makes sure the ramp of (at least) one co-linear segment
>> becomes one-sided. Because there is no ramp time, (9) and (13)
>> will naturally /disallow/ blending of co-linear segments. These
>> are not generally OK for blending, because they have entry/exit
>> velocity that is non-zero. By excluding those, we only have to
>> deal with segments that decelerate/accelerate to/from still-stand,
>> so what was said in (9) still holds true. Furthermore, this
>> co-linear segment optimization /covers/ N subsequent segments,
>> unlike the blending we discuss here (1). It follows that blending
>> is no generalization, i.e. no valid replacement for that
>> optimization (as I was hoping for some time).
>>
>> See the animation (click to open):
>>
>> <https://makr.zone/motion_blending_animation.html>
>>
>> https://makr.zone/motion_blending_animation.html
>>
>> It has a higher acceleration on the second segment to demonstrate that
>> G64 calculation is not trivial (5). But note that the demo simply has
>> the same overlap time for all the examples, i.e. there is no "real
>> G64" applied.
>>
>> _Mark
>>
> --
> You received this message because you are subscribed to the Google
> Groups "OpenPnP" group.
> To unsubscribe from this group and stop receiving emails from it, send
> To view this discussion on the web visit

### Ravi Ganesh

Dec 23, 2021, 9:53:32 PM12/23/21
to OpenPnP
Hi Mark,
Turning G64 on and off looks like a great idea. I would call this realtime variable motion blending.
Here is a voltage-at-motors waveform to  illustrate the concept.

### mark maker

Dec 24, 2021, 2:44:27 AM12/24/21

"Currently, there is no function to set the maximum deviation allowable in CANON_CONTINUOUS mode."

That section of the report does not describe G-code per se, but a possible "canonical" implementation of a controller. It is based on code they apparently wrote (not very clear, see 4.1.2.). IMHO that sentence is just describing  shortcoming of their implementation at the time of the report. It does not mean there must not be such a function.

I think we should lean on LinuxCNC here:

http://www.linuxcnc.org/docs/2.6/html/gcode/gcode.html#sec:G64

_Mark