Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved placement of MESH comments (combing/wipes) #1369

Open
paukstelis opened this issue Nov 29, 2020 · 7 comments
Open

Improved placement of MESH comments (combing/wipes) #1369

paukstelis opened this issue Nov 29, 2020 · 7 comments
Labels
Status: Deferred Not for now, but we could find the time or need to do this later.

Comments

@paukstelis
Copy link
Contributor

paukstelis commented Nov 29, 2020

Application Version
4.7+ (at least)

The incorporation of MESH comments is designed to delineate moves associated with each object on the build plate.
Current versions of Cura like to include additional moves on a previous object after it places the MESH comment. I have two cubes on the build plate separated far apart (around ~X35, Y24 and the other at ~X190, Y140) so the coordinate differences are easy to see. Note the transition around the change to cube 2:

G1 F1800 X35.535 Y24.427 E0.06879
M204 S2000
G0 F7200 X34.969 Y24.427
M204 S1000
G1 F1800 X34.56 Y24.836 E0.02886
M204 S2000
G1 F2100 E-0.4
;MESH:20mm_cube.stl(2)
G0 F7200 X52.253 Y42.119
G0 X53.557 Y42.119
G0 X193.204 Y143.365
G0 X194.508 Y143.365

The first two moves after the MESH comment are still related to the previous object. If using OctoPrint cancelobjects or M486 in Marlin, and the previous object (X35) is cancelled, there is an extra travel move. Also, if wipes are enabled these wipes happen here as well.

It actually gets worse if you look after it completes the last object in the list and moves to NONMESH:

G1 F1800 X196.147 Y144.394 E0.04311
M204 S2000
G1 F2100 E-0.4
;MESH:NONMESH
G0 F600 X196.147 Y144.394 Z0.8
G0 F7200 X194.508 Y143.365
G0 X193.204 Y143.365
G0 X53.557 Y42.119
G0 X52.253 Y42.119
G0 X51.817 Y41.683

While it totally makes sense to have the layer change in NONMESH, if you cancel the object before NONMESH, the first thing that will happen is an F600 move across the build plate. This was brought up as recent issue: paukstelis/Octoprint-Cancelobject#62

It seems like the layer change Z move should not be tied to any X and Y moves, and when at all possible.
It seems that most of this is a result of combing, as the moves to get out of an object mostly disappear (with the exception of NONMESH) when combing is turned off.

@Ghostkeeper
Copy link
Collaborator

The logic behind what happens is that Cura finishes printing one object at the end of the last extruded line. From there it's either finished with the layer, or it needs to print more objects. When it prints the next object, it just starts from whichever state the printer was left in: probably somewhere inside another mesh, but it doesn't know and doesn't care. It just travels to the start location of the new object in whichever way it deems necessary.

Sometimes this travel move may need to go through other parts. In particular, if the infill is printed after the walls it'll probably end up on the last infill line. But it may also need to go through completely unrelated parts, for instance if printing several concentric rings and it needs to travel from the innermost ring to the outermost ring (passing through several intermediate rings). Note that this doesn't just happen for the first travel move going towards the seam position, but also for travel moves within the same part if combing is not possible (e.g. if combing is set to Infill Only but there is no infill on that layer, or if combing is disabled altogether).

Beyond the current behaviour, it is theoretically possible to use a ;MESH comment for travel moves passing through other objects. There are a few practical concerns for the implementation though:

  • A single travel move command may pass through multiple objects. This is not your concern for the Cancel Object functionality, but it is to get the behaviour consistent if this becomes a new requirement.
  • When combing, Cura doesn't know which object's walls it's avoiding. It is only printing one mesh at a time, and so only tracks the currently printing mesh, which is a problem in our software architecture then. What's more, combing avoids a single complex polygon containing the shape of the entire layer, not separated by which parts of which simple polygon belong to which mesh. The polygon is offset by the Travel Avoid Distance which makes the shapes of multiple close-together meshes merge into one shape, so that would always lose any relationship between combing outline and the mesh name. For travel moves inside a mesh this can be avoided, but that's again an architectural problem with how the algorithm works now.

Considering the magnitude of the changes required, and the minority of the issues it causes (a few seconds extra printing time), I think this is not something we should consider implementing in the near future. I'll defer this until there is a more pressing need to get the ;MESH comments more accurate for travel moves through other meshes.

@Ghostkeeper Ghostkeeper added the Status: Deferred Not for now, but we could find the time or need to do this later. label Dec 1, 2020
@paukstelis
Copy link
Contributor Author

I agree it is a minor inconvenience, except when it is in the last object before NONMESH layer change moves. The F600 movement that includes X and Y coordinates will mean a very slow movement that lets filament ooze considerably. There is clearly no advantage to having those X and Y coords as they are exactly the same as the previous coordinates (in all the examples I looked at).

I do think in the larger scheme of things, as long as gcode remains the standard for 3D printing, having well-defined object/movement delineation should be a goal, as the ability to distinguish objects during a print can alleviate some of the bigger headaches associated with printing (single object failing and taking out entire build plate).

I need to look further, but if you put the ;MESH comments just before the first extrusion move of an object, rather than at the end of the previous object, this could fix the problem?

@Ghostkeeper
Copy link
Collaborator

Putting the ;MESH comment just before the first extrusion will just shift the problem. If your Cancel Object functionality removes everything after the ;MESH comment it will not remove the travel moves leading up to the removed object then.

There is currently just not enough information in the g-code. This information shortage comes from the inside of CuraEngine where the combing routine doesn't know which meshes it is crossing.

@paukstelis
Copy link
Contributor Author

I think it is still important to remove the X Y coordinates from the F600 move. It is not needed and it destroys the functionality.

@paukstelis
Copy link
Contributor Author

paukstelis commented Dec 22, 2020

I feel like I'm closing in on a solution (work around?) that would provide a fix for this.

  1. Setup a flag (bool) that indicates that the mesh_id has changed
  2. Move the "MESH" comment export to after the final travel move. This puts the MESH statement after the final travel moves for the previous mesh:
                for(unsigned int point_idx = 0; point_idx < path.points.size(); point_idx++)
                {
                    gcode.writeTravel(path.points[point_idx], speed);
                }
               
                if (path.mesh_id != current_mesh)
                {
                    current_mesh = path.mesh_id;
                    newmesh = true;
                    std::stringstream ss;
                    ss << "MESH:" << current_mesh;
                    gcode.writeComment(ss.str());
                }
                continue;
  1. Now the part that makes sense but is giving me trouble, write a travel move to the current XY position . This just ensures that the starting position for the newest mesh is correct after the MESH statement. If there is no object cancellation, there is no movement, if there is object cancellation you go to the correct XY position. You can use the newmesh flag to detect that it is on a new mesh (then reset). The problem I am seeing and don't understand is that I can't write an XY travel move here. It only allows me to write an XYZ travel move. If I try to do gcode.writeTravel(getPositionXY(), speed); nothing is output, but gcode.writeTravel(getPosition(), speed); works but includes the z_hop on Z. I get that this is a travel movement that is outside the path planning, but it is really intended to be just a positional reset. If this last bit could be sorted it would achieve a clean delineation between mesh objects in the gcode. Something along these lines:
            if (newmesh)
            {
                gcode.writeComment("NEWSTART");
                gcode.writeTravel(gcode.getPositionXY(), path.config->getSpeed());
                newmesh = false;
                gcode.writeComment("NEWEND");
            }

@Ghostkeeper
Copy link
Collaborator

I don't really know where those snippets of code are coming from or where they'd be positioned in CuraEngine.

The GcodeExport class tracks the current position of the nozzle to prevent move commands being made to the same position. If that's what you mean to adjust (because for some reason the nozzle is not actually in the position that GcodeExport thinks it is) then you can adjust that in the currentPosition field.

currentPosition = Point3(x, y, currentPosition.z);

Note that this doesn't actually cause the nozzle to move. It's just an internal tracker.

GcodeExport::writeTravel(Point, Velocity) simply refers on to GcodeExport::writeTravel(Point3, Velocity) with current_layer_z as the Z coordinate of the 3D point. Note that current_layer_z can be different from currentPosition.z if the nozzle is not on the layer's Z coordinate (e.g. Z hops or pausing for too small layers with Lift Head enabled). These travel moves also update the current position automatically.

I would expect gcode.writeTravel(getPosition(), speed) to not do anything at all unless Z hopped. After all, the first thing written in that function is to return immediately if already at the specified position.

I'm not entirely sure what you're trying to edit there. But hopefully this answers your immediate questions and helps in the endeavours you're trying to fix this for yourself or your users. The problem for us that I described earlier remains though. We will not merge a solution for your plug-in if that affects other features negatively or increases the code complexity too much.

@paukstelis
Copy link
Contributor Author

I'm simply trying to improve the delineation of individual objects in the gcode, and I think this is should be possible with very minor changes. This isn't something that is strictly for me or my plugin. Any integration of M486 commands (which I believe is under consideration: Ultimaker/Cura#7014) will also benefit from having these more accurately represented in the gcode.

shinmai added a commit to shinmai/cura-M486 that referenced this issue Jan 27, 2022
added a setting that if enabled will attempt to remove X and Y components from NONMESH z-hop moves to avoid a slow travel move across the bed

for details see Ultimaker/CuraEngine#1369 (comment) and paukstelis/Octoprint-Cancelobject#62
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Deferred Not for now, but we could find the time or need to do this later.
Projects
None yet
Development

No branches or pull requests

2 participants