EmbroidePy / pyembroidery

pyembroidery library for reading and writing a variety of embroidery formats.
MIT License
185 stars 34 forks source link

Trims do not work in pyembroidery when written from Ink/Stitch #68

Closed MatsIBengtsson closed 4 years ago

MatsIBengtsson commented 4 years ago

I have a Husqvarna viking Topaz 50 machine, which does trims. When doing designs in inkstitch exported through pyembroidery, my trims does not work as I expect (they do not trim at all).

Free version of Premier (Husqvarna/Pfaff embroidery software), tells me there are no trims in the generated vp3 file. The free version of truesize e4, tells me there are only two trims in the vp3 file (a file with two colors).

Saving to formats like dst or pes, generates the trims as expected.

The issue is also described in Ink/Stitch ( #https://github.com/inkstitch/inkstitch/issues/495). Enclosing a zip file containing a number of files to give details outline cat face p0.0-006.zip

The files are described below, and contain information on the difference when using Premier/trueview or going through pyembroidery.

MatsIBengtsson commented 4 years ago

That means the command I have is actually wrong in that it ever provides a cut. Wilcom E4 is right. Just drag the thread at the end.

Wilcom e4 is the one rumored to know how to cut in vp3. It knows how to do it on top thread, but I expect it knew that already in e3?

It didn't cut when it rehomed at the end? I specifically removed the 0x80 0x03 TRIM command being added when END was called. It is technically correct. But, if it's dragging the uncut thread at the end, I see why it always tended to add that. Which is why I thought of it like an end, though the file doesn't actually have an END.

It dragged the thread, but it was cut somewhere beneath, I could pull it out.

Was there a stitch half way between the diamonds? The code for that file specifically says diamond, move 5mm, apply command 0x80 0x02 move 5mm more then sew another diamond. If it didn't apply the stitch at the center that's actually significant. Move to location, but do not stitch, is a JUMP command.

There is a stitch in the middle, so it stitched (diamond, long thread, stitch, new long thread, diamond

MatsIBengtsson commented 4 years ago

Thus far the info I'm getting is 80 02 is long form stitch and cannot create an implicit trim. The code that suggests a long distance there trims, is in error. And I should restore the TRIM for the END command since it only otherwise trims between color blocks and that doesn't apply to the final color block and needs the explicit trim there.

Sounds exactly right, and that is how the first file I did with InkStitch worked. Plus this thing with the starting point.

MatsIBengtsson commented 4 years ago

Not too hard to code up. I'll start on some of the next wave of checks. I'll code up them with the trim and then long_form stitch (80 01) with and without the terminal (80 01) command.

This is 80 03 80 01 xx xx 00 00 80 02 - So trim, long_form_stitch, (80 02) command.

trim01xy.zip

Did the 500 and the 150. No difference seen. There is a cut between the diamonds, which are both complete. There is no tie-off before the jump, but a tie-on and tie-off after.

This is 80 03 80 01 xx xx 00 00 - So trim, long_form_stitch, no ending 80 02 command. To see if it has some meaning in a trimmed context.

trim01xy_no_ending_02.zip

Did the 500 and the 150. There is no cut between the diamonds. There is a tie-on, but no tie-off in the end. This one has a thread in between the diamonds, not looking like TrueSizer depicts it (no thread between).

tatarize commented 4 years ago

So: 80 03 80 01 xx xx yy yy 80 02 ... == Diamond1, Trim, Jump, Tie On, Diamond2, Tie off.

And: 80 03 80 01 xx xx yy yy ... == Diamond1, Jump, Tie On, Diamond2

That's sounds kinda weird unless I'm misplacing where you are saying the tie-on and tie-offs occur or don't. But, also, if 80 03 means trim, why did not including the 80 02 element cause the trim to fail?

tatarize commented 4 years ago

I'm guessing since we want TRIM, MOVE it's pretty easy to go ahead and decide that that is that. Going with the first form solves the problem. Even without fully mapping things out. The reading and writing will be more accurate and properly reflect what will happen with the sewing.

It requires an overt trim command to trim. Long form doesn't cause a trim, ever. And omitting the 80 02 can cause the TRIM and other embroidery operations to fail.

Since the machine never autotrims, regardless whether it's actually indicated in the pattern, a TRIM command should be added at the very end so that it trims before returning to home.

It's enough that it largely settles any lingering issues. The elements can be correctly reflected as to what the machine actually does.


I mean I could feed you some more patterns, to see what they do. What if I long form all the stitches? all_long0.zip

What if I do that, but I never add an 80 02? all_long-no-02.zip

(This was intended as an example of further research, but this actually looks weird in Wilcom's preview. Apparently they say that 80 02 not only doesn't do something, but is actively part of the 80 01 command and putting a different element in there, eats it and causes the whole thing to corrupt, and go wonky. Premier seems to agree. Apparently the suffix 80 02 isn't independent and putting a distance there or a different command seems to imply those elements will not be executed)

Actually the previews seem to strongly indicate that whatever that value is, it's always irrelevant.

I made that value: 0x79 aka 121 the image didn't change. all_long-big-move.zip

(I'll change my reader accordingly).

--

But, even without some idle speculations to reverse engineer what's actually going on with the machine under the hood. I can now write out perfectly reasonable embroidery files. And load them with sufficient accuracy that when there's a long thread between elements of that cat's face, it's not because my program screwed up, but it's that if you run the file, you will actually get a long string there, so you might want to insert a trim.

tatarize commented 4 years ago

@MatsIBengtsson Taking your input into consideration.


This should do good work towards improving the reading and writing of trims with regards to VP3. Since the only way to trim is between stitchblocks or to explicitly trim, the code I had to prevent double-trim is obsoleted (since that never really happens). This should improve the accuracy. And with the exception of the alt code there, should be quite compatible with inkstitch's old version of pyembroidery.

MatsIBengtsson commented 4 years ago

So: 80 03 80 01 xx xx yy yy 80 02 ... == Diamond1, Trim, Jump, Tie On, Diamond2, Tie off.

And: 80 03 80 01 xx xx yy yy ... == Diamond1, Jump, Tie On, Diamond2

That's sounds kinda weird unless I'm misplacing where you are saying the tie-on and tie-offs occur or don't. But, also, if 80 03 means trim, why did not including the 80 02 element cause the trim to fail?

Could 80 03 mean cut and tie-off at same time?

MatsIBengtsson commented 4 years ago

@MatsIBengtsson Taking your input into consideration.

  • There is no implicit trim. The only permitted trim is explicit. Distance based trims do not exist.
  • 80 02 does nothing. The sequence 80 01 xx xx yy yy 80 02 ignores the 80 02, and any value put there has no effect. When added independently they don't do anything either.
  • Without adding a TRIM for the END, the final stitch block does not autotrim. While it doesn't appear in the file, it's appropriate to terminate with a trim.

This should do good work towards improving the reading and writing of trims with regards to VP3. Since the only way to trim is between stitchblocks or to explicitly trim, the code I had to prevent double-trim is obsoleted (since that never really happens). This should improve the accuracy. And with the exception of the alt code there, should be quite compatible with inkstitch's old version of pyembroidery.

I will try to test your files tomorrow. But until then a comment: My machine has a checkbox for automatically trimming on jumps. So it might be that we do not know how to code such jump.

tatarize commented 4 years ago

Could 80 03 mean cut and tie-off at same time?

Yes. It's entirely reasonable that a command could trigger a sequence of events. Namely at this location, do 3 stitches then trigger the trimming cutter thing. That'd be entirely doable. If that's actually what's happening I'm not sure how it affects pyembroidery. I mean I guess I call 80 03, stitch(0,0), stitch(0,0), stitch(0,0), trim(0,0) instead of just Trim. Because for accurately sake that is what it would be doing.

I will try to test your files tomorrow. But until then a comment: My machine has a checkbox for automatically trimming on jumps. So it might be that we do not know how to code such jump.

Ah, a checkbox. Those are great. You should rather rerun some of the older things I sent you with the checkbox on. The ones that concluded that no distance would cause a trim. Because apparently some distance can cause a trim if that checkbox were on. The new stuff was just examples of things that could be tested but wouldn't be that important to test.

The jump here is likely referring to 80 01 xx xx yy yy 80 02 element. I classed it as a long stitch because that's what it does. It stitches at the other end of that location, so it's not strictly speaking what I call a JUMP it moves from place to place, but properly JUMPs are not stitched at their final location. They simply move there and block the needlebar. So moving there and then stitching even if that's a really far distance is still a kind of stitch. And for consistency with the rest of the readers and writers should remain that way.

Apparently it has an option to trim a really long stitch. While that's important to know about and perfectly reasonable to map out. Explicit trims kind of make it a moot point. You don't tend to design embroidery specifically intended to be auto-trimmed if you have an option of an explicit trim. Now, there's some chance that other models don't use an explicit trim but can only auto-trim. But, I've never heard of that.

Really the important detail is at what distance does that checkbox cause an auto-trim. I have for some of the readers an option that mimics the options on the machine for the auto-trim. So when loading a pattern that was intended for that machine with those settings I can add explicit trims where the auto-trims would happen. It's highly important for machines that cannot explicit trim, but notably less important for other elements. I would gladly add that option if the distance there was known (sometimes check the box will even let you set the distance value yourself).

The auto-trim on jump might just be auto-trim on jumps of any length. So even the stuff less than 8 bits. Which would explain the Wilcom e3 interpretation of that. It would be nice to know, but knowing simply means I would add a settings option for autotrimming that would add TRIM commands where the trims would happen in a loaded file. Which would be more accurate but, to date, no software has taken those setting into account for anything. It would often be more useful for software to do that kind of trim insertion as a post process.

There's not a clean, easy, solution to the question of how to deal with optional values on the machine. When I load the file, is there a trim or not... well that depends on the settings in the machine. I usually just opt for the default settings. And add the other settings as part of the loading options. But, they'd end up being rather buried and the default will just be the machine default.

The major issues have all been settled. I've posted the latest version with stuff we mapped out here.

MatsIBengtsson commented 4 years ago

Could 80 03 mean cut and tie-off at same time?

Yes. It's entirely reasonable that a command could trigger a sequence of events. Namely at this location, do 3 stitches then trigger the trimming cutter thing. That'd be entirely doable. If that's actually what's happening I'm not sure how it affects pyembroidery. I mean I guess I call 80 03, stitch(0,0), stitch(0,0), stitch(0,0), trim(0,0) instead of just Trim. Because for accurately sake that is what it would be doing.

I does when you and wilcom provide the file. But for the file converted by Premier (see earlier entry) it instead did the 4 locking stitches side to side. Never seen that before.

I will try to test your files tomorrow. But until then a comment: My machine has a checkbox for automatically trimming on jumps. So it might be that we do not know how to code such jump.

Ah, a checkbox. Those are great. You should rather rerun some of the older things I sent you with the checkbox on. The ones that concluded that no distance would cause a trim. Because apparently some distance can cause a trim if that checkbox were on. The new stuff was just examples of things that could be tested but wouldn't be that important to test.

I have been running all tests with the checkbox on. Yet, I can turn it off and see if there is a difference if that is of interest? It could be those are active only for non-native formats (it can use most formats I have seen).

... Apparently it has an option to trim a really long stitch. While that's important to know about and perfectly reasonable to map out. Explicit trims kind of make it a moot point. You don't tend to design embroidery specifically intended to be auto-trimmed if you have an option of an explicit trim. Now, there's some chance that other models don't use an explicit trim but can only auto-trim. But, I've never heard of that.

Really the important detail is at what distance does that checkbox cause an auto-trim. I have for some of the readers an option that mimics the options on the machine for the auto-trim. So when loading a pattern that was intended for that machine with those settings I can add explicit trims where the auto-trims would happen. It's highly important for machines that cannot explicit trim, but notably less important for other elements. I would gladly add that option if the distance there was known (sometimes check the box will even let you set the distance value yourself).

My biggest frame is 360 mm, so it could be we are not using long enough distances, and it could be valid only for non-native formats.

The major issues have all been settled. I've posted the latest version with stuff we mapped out here.

Agree, but one exception: tie-ons. I was thinking of your diamond-stitches-diamond. There is no tie-on at the start. What happens if your first move to the first diamond is done by 80 01 followed by 80 02? Will it tie-on? Could you do such file?

tatarize commented 4 years ago

long-starts.zip

0: The first move is replaced with a long stitch. 1: The initial stitch is replaced with a long stitch. 2: The initial stitch is replaced with a long stitch, a trim is added before the first move towards the other diamond.

I have been running all tests with the checkbox on. Yet, I can turn it off and see if there is a difference if that is of interest?

If the lack of long stitch cuts happened with the checkbox on, then it didn't force an auto-trim in that instance. So it's of no concern. The current understanding isn't going to be altered when the checkbox is off.

It could be non-native formats of something, but if that's the case then it largely doesn't matter much. I'd only be hyper concerned about native formats for your machine, rather than your machine's interpretation of another machine's format.

tatarize commented 4 years ago

generate_vp3.zip

Here's a basic example of how I'm generating the files. In case you suddenly get an itch for some test. This will create the two diamonds with the first stitch being long stitched, and the 50, and 50 in the middle both being long stitched after the trim. Should be pretty easy to modify and rig up whatever you want. (should require any pyembroidery after I added the ALTERNATIVE flags and such).

MatsIBengtsson commented 4 years ago

long-starts.zip

0: The first move is replaced with a long stitch. 1: The initial stitch is replaced with a long stitch. 2: The initial stitch is replaced with a long stitch, a trim is added before the first move towards the other diamond.

This made differences:

MatsIBengtsson commented 4 years ago

generate_vp3.zip

Here's a basic example of how I'm generating the files. In case you suddenly get an itch for some test. This will create the two diamonds with the first stitch being long stitched, and the 50, and 50 in the middle both being long stitched after the trim. Should be pretty easy to modify and rig up whatever you want. (should require any pyembroidery after I added the ALTERNATIVE flags and such).

Thank you.

tatarize commented 4 years ago

It seems like the initial cut and tie-on is automatic. Apparently it can be prevented but, is generally fine.

The thing I don't understand are the tie-on tie-off triggers. They are done inside the machine but I'm not sure what causes them to happen. Do they always happen if the block is contiguous? Like if there's no trim in the colorblock does it always trim, tie-on, run, tie-off. Apparently long stitches don't stop that from happening but if you put in a trim basically anywhere suddenly it will have not caused a tie-on at the very beginning? Like it prescans the entire set of stitches and doesn't do a tie-on if there's a trim in it? Or is it a length thing. Like there's 4 stitches from start to trim in #2 there, and it didn't do the tie-on. So did it scan ahead a certain amount or does it scan the entire block?

Obviously the better solution is to ignore the automatic tie on, assume the thread starts trimmed, and insert proper tie-on and tie-offs as appropriate. Which is the current methodology. So long as the code stays on the beaten path it should be fine. Perform a trim and tie off, then a cut as needed and ignore this automatic one.

Even pinpointing what causes it likely won't change the methods for the VP3 format. I should actually fix that one value that I called stitches + end before I knew what I was calling an end was a TRIM. But, other than that this seems more or less finished.

I'm not exactly sure which elements would need to be ported back to inkstitch. But, some of them should. TRIM is 0x80 0x03. The final END should likely be given a TRIM value even though it's technically inaccurate. And no distance of 0x80 0x01 xx xx yy yy 0x80 0x02 ever causes a TRIM.

MatsIBengtsson commented 4 years ago

The thing I don't understand are the tie-on tie-off triggers. They are done inside the machine but I'm not sure what causes them to happen. Do they always happen if the block is contiguous? Like if there's no trim in the colorblock does it always trim, tie-on, run, tie-off. Apparently long stitches don't stop that from happening but if you put in a trim basically anywhere suddenly it will have not caused a tie-on at the very beginning? Like it prescans the entire set of stitches and doesn't do a tie-on if there's a trim in it? Or is it a length thing. Like there's 4 stitches from start to trim in #2 there, and it didn't do the tie-on. So did it scan ahead a certain amount or does it scan the entire block?

This was hard to answer. Every time there is a new colorblock, I get the chance to change thread. If I do, it means I cut the bottom thread, and it fetches thread and does tie-on. If I do not, it does not always cut the top thread, meaning it does likely not always tie-off. I need to experiment to be sure on that one. I think the tie we talk about missing in last experiment was the end tie, not the start tie. I am uncertain, I know it was loose in the middle, and thet the start thread was cut off, so the extra thread must have come from the end.

Obviously the better solution is to ignore the automatic tie on, assume the thread starts trimmed, and insert proper tie-on and tie-offs as appropriate. Which is the current methodology. So long as the code stays on the beaten path it should be fine. Perform a trim and tie off, then a cut as needed and ignore this automatic one.

Sounds good.

Even pinpointing what causes it likely won't change the methods for the VP3 format. I should actually fix that one value that I called stitches + end before I knew what I was calling an end was a TRIM. But, other than that this seems more or less finished.

Agree

I'm not exactly sure which elements would need to be ported back to inkstitch. But, some of them should. TRIM is 0x80 0x03. The final END should likely be given a TRIM value even though it's technically inaccurate. And no distance of 0x80 0x01 xx xx yy yy 0x80 0x02 ever causes a TRIM.

True. But it seem tie-on after cut of top thread, and tie-off after end without cut is unclear? Could be the 80x02 has to do with first, and 80x03 with the last?

tatarize commented 4 years ago

Failed to notice this question before.

True. But it seem tie-on after cut of top thread, and tie-off after end without cut is unclear? Could be the 80x02 has to do with first, and 80x03 with the last?

These are automatic triggers within the machine. Which means it's likely to do with something machine specific based on internal methods within the machine. So whatever the criteria is, it's outside the project more or less. If your machine is invented stitches that are not explicit in the file, other machines might invent different stitches, and the odds are good whatever the criteria are should not interfere with the file itself.

So while somewhat interesting as to why it does that and when, it's outside the scope. Clearly properly classifying a TRIM as what it is, and properly reacting to long stitch commands are highly useful corrections, as is ensuring there aren't other commands being missed. What makes it invent some other stitches might just be a setting somewhere or change with a firmware upgrade or not hold true for all files.

So, yes what causes those events is unclear. But, for functionality clarity is not a requirement.