eyal0 / OctoPrint-PrintTimeGenius

Use a gcode pre-analysis to provide better print time estimation
190 stars 32 forks source link

Request: Make PTG Compatible with Octolapse #184

Open SoLongSidekick opened 4 years ago

SoLongSidekick commented 4 years ago

So I've come to seriously rely on PTG; not having a somewhat accurate time to finish estimate is one of the major flaws with Octoprint. Anyways, along with PrinterStats the other main plugin I rely on is Octolapse. I just found out that PTG does not work when using Octolapse, though. While really accurate integration would be pretty complicated, I feel like adding a 1/2 second to one second to each layer in estimated time would be perfectly sufficient. The only change to normal printing behavior is after each layer is finished the print head moves to a predetermined spot in the X/Y and stays there long enough for a photo to be snapped, then the printer moves on to the next layer. It's closer to a half a second than it is a full second.

Anyways, I would be really grateful if you had the time to make these two awesome plugins compatible. Thanks.

SoLongSidekick commented 4 years ago

I recorded a video showing the time added to a layer by Octolapse. You can see it finish printing a layer, then move the printhead to the center of its travel, sit there for just a moment, then go back to printing. Please excuse the ridiculous model I happened to be printing when I recorded this: https://youtu.be/QCC7nWYlWMg.

eyal0 commented 4 years ago

Okay, I get the idea but I don't know how I would implement it. I've thought about how to handle stuff like this for a while. For example, people have filament changes where the printer sits around waiting for the next command.

I thought about having PTG look through the running commands and, like, pause the timer when it sees some command and then restart it when it see a different one...

Or maybe some sort of plug-in system where it's easy to tell PTG to pretend like certain actions take longer. For your case, maybe you'd be able to see that the new layer comment in your gcode counts as 2 seconds or something like that.

I don't own a printer at the moment so it's hard for me to work on this.

serenewaffles commented 4 years ago

It would be nice if, at the least, a person could manually input a per layer compensation for when Octolapse is set to take pictures at layer, even if PTG isn't calculating the delay.

i.e. I know Octolapse takes ~0.8 seconds to take a snap. Then I could have PTG add 0.8s/layer to the estimated time. It still won't be perfect, but it will hopefully be better than it is. This could also help with the compensation. Instead of lengthening all extrusion estimates, it should hopefully be able to judge tall (many Octolapse delays) and short (few Octolapse delays) prints properly. Currently, if you only have tall prints in your compensation history, PTG grossly overestimates short prints.

eyal0 commented 4 years ago

Yes, I understand. But how would PTG know how many layers there are?

How does the octolapse even know how many layers there are, by the way? Does the octolapse modify the gcode file and insert something in there?

serenewaffles commented 4 years ago

Octolapse does modify the gcode when it performs stabilization or to pause for a snapshot.

As for how Octolapse knows when layers change, I believe it takes a user supplied z-hop height and assumes any z moves that aren't that height to be layer changes.

eyal0 commented 4 years ago

So when you upload the gcode file, it gets modified by octolapse to add camera commands into it? If you redownload it from octoprint, are those camera commands in there?

serenewaffles commented 4 years ago

I am not 100% familiar with the inner workings of Octolapse. I believe that it monitors the gcode and edits it on the fly. If you have Octolapse set not to record timelapses, it does not make any modifications to the gcode.

For what I've suggested, the best way would probably be to make the user manually enter z-hop height, approximate Octolapse delay per layer, and whether Octolapse is enabled. Given how manual the process is, I think it should likely also be considered an advanced option, hidden by the blind.

serenewaffles commented 4 years ago

Thinking this through now, am I right in thinking that this would require PTG to reanalyze the files every time one changed whether Octolapse is enabled? If so, I'm not sure my proposed solution is worth the effort.

eyal0 commented 4 years ago

@FormerLurker what do you suggest? Marlin-calc is analyzing the file before it even prints so I need some way to figure out how many camera flashes will be in there and at what position in the file...

Is octolapse able to look at a gcode file and calculate all the positions in the file where a photo will be taken? Maybe there could be a hook in octolapse where it could report the position in the file and the instructions that will get inserted by octolapse at that position, for the whole file.

Then PTG could send a command to octolapse to request all that info. Octolapse would report it as json or something. Then PTG would make a modified version of the original gcode in temp and send that to marlin-calc.

I think that this would fix the problem for users. I'm happy to help with the octolapse code, too.

FormerLurker commented 4 years ago

This isn't possible in v0.3.4, or when using the classic triggers in v0.4, but it should be possible for the smart triggers to some extent.

There are some things that would be difficult to account for, like using a dslr, where it can take anywhere between 1 and 10 seconds to acquire an image. But the estimate could be closer. It might even be possible to average out the snapshot time while the print progresses.

I could create a hook that sends all of the gcode used to create the snapshots (only for smart triggers where they are precalculated), along with the starting position. You could include a variable for each snapshot for the variance due to image capture and processing time maybe? I am just brainstorming atm, but let me know what you think.

FormerLurker commented 4 years ago

So, I've been thinking more about this. I think I need to add two things to Octolapse to make this work:

  1. A hook that you can use to get an array of gcode used to take all of the snapshots. I don't think recreating an entire file with the new gcodes inserted isn't ideal since the preprocessing has to happen before every print (I can explain this if you want), and outputting a new gcode file every time will increase processing time that is already too high. However, it should be possible to run each snapshot through your Marlin-calc function and sum up the time, no?
  2. Another hook that gets called after each snapshot is taken that report how long it took to acquire the images. I will probably add additional info that could be useful for other plugins too. This would include only the snapshot time and not any time involved in the moving to/from the snapshot position. Using this you could create a running average of the snapshot time (or any other method you want) to adjust the print time accordingly.

How does that sound?

serenewaffles commented 4 years ago

At least on my printer (Monoprice MP10), the M400 commands necessary to determine snapshots ruin prints.

FormerLurker commented 4 years ago

@serenewaffles, sorry, but I don't know of any other way to accomplish the stabilization without adding manual wait times, which must be guessed, and thus add even more time to the prints. V0.4 is a bit better because the new smart triggers prefer to take snapshots over infill. Anyway, this isn't a PTG issue, so if you want to open an issue in the Octolapse github page feel free.

eyal0 commented 4 years ago

@FormerLurker no need to send the entire gcode file, for sure! It would be enough to just send just the diff in whatever format. If octolapse is only ever inserting instructions then just send byte positions and strings to insert into the gcode file.

How PTG would use this is another question. I can run marlin-calc as much as I want and store the timing analysis both with and without octolapse. But running marlin-calc is pretty slow, I wouldn't want to have to double the effort. And it's hard to run each one separately and just add up the results because the time to take a photo depends on the location of the print head before the photo, right?

I'm fine with us assuming that whatever settings octolapse has at the time of upload will be close enough to whatever settings it'll have when it's finally printing.

So my real difficulty is figuring out how to compute the time to print without running marlin-calc twice. I'll have to think on it.

Maybe I'll start with profiling marlin-calc. Maybe the slowness is actually something that could be mitigated so that two runs, both with and without octolapse, could be done in parallel?

FormerLurker commented 4 years ago

The snapshot scripts are only maybe 10 lines long at the most. I can provide the exact starting location too. Maybe you can run marlin calc on just those lines, and the resulting time to the final print time estimate? You'd have to be able to 'transport' the printhead between each snapshot to the starting location. I'm also guessing marlin calc requires a file ATM, though it wouldn't take much time to keep overwriting a single file with new gcode from each snapshot.

I'll start on this once V0.4 is out the door. I had to scrub my planned release this weekend due to a few major bug fixes. I just dropped RC3, and am hoping to get enough confirmation on the fixes to release this weekend.

eyal0 commented 4 years ago

marlin-calc can process a file but changing that to a stream would be easy, too.

The transporting of the printhead is what makes it difficult to have an accurate answer. Because the transport time is probably variable. The rest is probably constant.

As a first step, I could just take an average and use that for each photo. The transport time is probably just a small piece of each photo. That would at least get us closer.

FormerLurker commented 4 years ago

When i say transport, I mean instantaneous transport (0 time). I think this will make much more sense when you see the gcode. Perhaps G92 could be used to trick marlin?

eyal0 commented 4 years ago

I guess that I need to see the gcode to understand. I assume that was octolapse does it, while the printing is going on, it look for gcode that indicates that it is time to take a photo. For example, maybe whenever the Z height increases by anything other than the retraction Z-hop amount. And then, I guess that octolapse inserts some commands like a G0 or G1 to get out of the way, then M400 to wait for everything to finish, then something to make the camera take a photo, like some octoprint URL? And then move back to wherever the printhead was to continue where we left off.

Is it like that? It's the camera-out-of-the-way part that depends on the current position. That's what I thought that you meant by transport. All the rest of it, I figure that it's basically a constant time for each printer. Though different printers will have a different constant.

Does it work like that?

FormerLurker commented 4 years ago

Yes, that's pretty close. There are two basic categories of triggers:

  1. Classic Triggers - These are real time, and watch the gcode stream for layer changes. Octolapse defines a layer change as the first time plastic is extruded higher than it was before. There are also some restrictions you can place on exactly when snapshots are allowed. For example, you can force Octolapse to only take a snapshot when the extruder is retracted and lifted. In this case, after Octolapse sees a layer change it will wait until all of the restrictions are met, and then it will initiate a snapshot. Additionally there are timer and gcode based triggers. These function in the same way except that the initial trigger is not based on a layer change.
  2. Smart Triggers - These triggers create snapshot plans before the print starts by examining the entire gcode file. Each plan contains an initial point, a snapshot point (or multiple snapshot points, though this isn't used yet), and a return position. I have a routine that takes the current state of the printer and a snapshot plan and converts this into gcode necessary to move the printer into position and return it to the final position. Note that the starting position isn't necessarily the same as the ending position. If Octolapse triggers during a travel move it will return to the target of the travel move in order to save a bit of time.

When Octolapse determines it's time to take a snapshot it first sends some initialization code. This might switch axis modes, lift the extruder, retract, or change the feedrate depending on the state of the printer and the settings being used. Then it sends a G1 to move into the snapshot position (or not if the user is running a Snap to Print trigger) followed by an M400 and an M114. When Octolapse sees a response from the M114 it knows the print moves are finished, and it captures snapshots for all enabled cameras. Once that is finished, it sends a return G1 (or not in the case of the Snap to Print trigger) and restores the printer to the original state, potentially by lowering Z, deretracting, and changing the feedrate, and altering the axis modes. Finally, it continues with the print and waits for the next snapshot.

I'm wondering if it would be possible to loop over all of the gcode, assuming the printer is already in the starting position, and calculate the time it would take the printer to execute the moves, then sum them all up and add in the time to the total print time. I realize this wouldn't be 100% accurate since the final return move may alter the acceleration of subsequent gcodes, but it should be pretty close, no?

eyal0 commented 4 years ago

marlin-calc computes the time to execute each line, not just the total. This is so that the time to print can be made more accurate along the way.

So what do you suggest? The current input to marlin-calc is just the gcode file. Would we execute marlin-calc again? Which which gcode?

FormerLurker commented 4 years ago

computes the time to execute each line

That definitely complicates things, but I should have realized it would work that way. Let me think about it for a while and I'll get back to you.

eyal0 commented 4 years ago

Like I said, if I know which gcode will be inserted into the file and where in the file, I can process that. Maybe that would be close enough?

About how much time is spent on each snapshot? How much is motion versus photo or whatever else?

FormerLurker commented 4 years ago

Like I said, if I know which gcode will be inserted into the file and where in the file, I can process that. Maybe that would be close enough?

Perhaps. Would that mess up anything related to line numbers? I'm not sure how PTG uses those within OctoPrint.

About how much time is spent on each snapshot? How much is motion versus photo or whatever else?

It depends so much on settings and the print file that this has no simple answer. If one is using the snap to print trigger, there will be no travel time, but there could be lift + retract. Webcam acquisition usually takes between 50 and 250MS. DSLR acquisition can take between 1 and 10 seconds depending on a lot of stuff. The snapshot acquisition happens in a thread, so if there are multiple cameras it will take as long as the slowest camera to acquire the image.

If the user is stabilizing far away from the initial point (say traveling halfway across the bed), and using a webcam, the travel time will far outweigh the snapshot acquisition time.

eyal0 commented 4 years ago

Yes, it would mess with the line numbers but I could compensate for that. Instead of sending in the gcode, I could send an array where each element is the line of gcode and some extra data, like the original line number and whether this is from octolapse or not, etc.

I don't want you to waste your time implementing your side of it so let me work on marlin-calc first and then we can go from there.

minding-myown-business commented 6 months ago

Hello, I've encountered the same issue and noticed the last comment was in 2020. @eyal0, are there any ongoing efforts to address this? The reason it's a concern for me is that PTG's ETA tends to be off by up to half an hour, particularly with larger prints. Any updates would be appreciated.

SoLongSidekick commented 6 months ago

Woah blast from the past. I'd be interested in a fix for this too still, obviously.