Welcome! Log In Create A New Profile

Advanced

Retract calculation in dimension plugin

Posted by garyhodgson 
Retract calculation in dimension plugin
November 03, 2011 10:40AM
Hi,

I'm currently digging through the Skeinforge/SFACT code trying to get to grips with the algorithms and I have found something a bit peculiar. It's either that I don't fully understand the algorithm (highly plausible), or it's a potential bug. This appears to affect Skeinforge (44) and SFACT (V42.4.1) versions.

[EDIT: I should clarify that so far most of my comparison has been with SFACT, largely because it's what I have been using for the past few weeks. Further testing with Skeinforge44 seems to give different results to what is shown below. The default min. retraction for travel setting of 1.0 for example means the small retraction for the Z axis movement would not happen. It also seems that the code between the two versions had diverged to such an extent and so this post may not be relevant to the original Skeinforge as such. Nevertheless, the "getDistanceToNextThread" method from both versions is almost identical, and from the code alone the potential error described here is still possibly valid.]

In the Dimension plugin, getDistanceToNextThread function, the algorithm calculates the distance from the last location (end of the last path) to the start of the next location (thread) in order to derive how much filament to retract. However, it appears to use the next G1 code it finds after(!) the extruder is active (i.e. after a M101 code is read), which would be the end of the first extruded path. Surely this means that the retraction distance is wrong? I would imagine the retraction distance should be calculated from the end of the last path to the start of the next.

As way of example, a non-filled 20mm cube I am using for testing has to retract between the Z layers only. Layer height is 0.4

SkeinforgeSFACT produces the following gcodes for the end of the boundary:

                G1 X90.2356 Y90.2356 Z0.2 F1800.0 E2.49087 ; end of path
		G1 F900.0
		G1 E1.67293 ; retract
		G1 F1800.0
		;M103
		M82
		G1 X90.2356 Y90.2356 Z0.6 F7800.0 ; start of next path
		G1 F900.0
		G1 E2.49087 ; reverse retract
		G1 F7800.0
		G92 E0
		;M101
		G1 X109.764 Y90.2356 Z0.6 F1800.0 E0.622717 ; end of first path

Retraction Distance = 0.81794
Distance between threads = 19.6

My modified test version, which uses the starting point produces:

                G1 X90.23559 Y90.235593 Z0.2 F1800.0 E2.490921 	; end of path
		G1 F900.0
		G1 E2.449254 ; retract
		G1 F1800.0
		;M103
		M82
		G1 X90.23559 Y90.235593 Z0.6 F7800.0 ; start of next path
		G1 F900.0
		G1 E0.0  ; NOTE!! My reverse retract is not currently working!
		G1 F7800.0
		G92 E0
		;M101
		G1 X109.76441 Y90.235591 Z0.6 F1800.0 E0.62273 ; end of first path

Retraction Distance = 0.041667
[EDIT: It seems this value is much lower because the SFACT version factors in the feedrate to the calculation. However the distance between threads still has a discrepancy. ]

Distance between threads = 2.0

Am I simply missing something horribly obvious, as I did with the inset plugin, or is this a potential bug?


Thanks in advance,
Gary


(To save people digging out the code I include the functions from dimension.py below.) [EDIT: I have now included both skeinforge44 and SFACT versions]

SFACT:
def getDistanceToNextThread(self, lineIndex):
	'Get the travel distance to the next thread.'
	if self.oldLocation == None:
		return None
	isActive = False
	location = self.oldLocation
	for afterIndex in xrange(lineIndex + 1, len(self.lines)):
		line = self.lines[afterIndex]
		splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line)
		firstWord = gcodec.getFirstWord(splitLine)
		if firstWord == 'G1':
			if isActive:
				location = gcodec.getLocationFromSplitLine(location, splitLine)
				#if self.repository.retractWhenCrossing.value:
				locationEnclosureIndex = self.getSmallestEnclosureIndex(location.dropAxis())
				if locationEnclosureIndex != self.getSmallestEnclosureIndex(self.oldLocation.dropAxis()):
					return None
				locationMinusOld = location - self.oldLocation
				xyTravel = abs(locationMinusOld.dropAxis())
				zTravelMultiplied = locationMinusOld.z * self.zDistanceRatio
				self.timeToNextThread = math.sqrt(xyTravel * xyTravel + zTravelMultiplied * zTravelMultiplied)/ self.feedRateMinute*60
				self.autoRetractDistance = self.timeToNextThread * abs(self.repository.oozeRate.value)/60
				return math.sqrt(xyTravel * xyTravel + zTravelMultiplied * zTravelMultiplied)
		elif firstWord == 'M101':
			isActive = True
		elif firstWord == 'M103':
			isActive = False
	return None
skeinforge44:
def getDistanceToNextThread(self, lineIndex):
	'Get the travel distance to the next thread.'
	if self.oldLocation == None:
		return None
	isActive = False
	location = self.oldLocation
	for afterIndex in xrange(lineIndex + 1, len(self.lines)):
		line = self.lines[afterIndex]
		splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line)
		firstWord = gcodec.getFirstWord(splitLine)
		if firstWord == 'G1':
			if isActive:
				location = gcodec.getLocationFromSplitLine(location, splitLine)
				if not self.repository.retractWithinIsland.value:
					locationEnclosureIndex = self.getSmallestEnclosureIndex(location.dropAxis())
					if locationEnclosureIndex != self.getSmallestEnclosureIndex(self.oldLocation.dropAxis()):
						return None
				locationMinusOld = location - self.oldLocation
				xyTravel = abs(locationMinusOld.dropAxis())
				zTravelMultiplied = locationMinusOld.z * self.zDistanceRatio
				return math.sqrt(xyTravel * xyTravel + zTravelMultiplied * zTravelMultiplied)
		elif firstWord == 'M101':
			isActive = True
		elif firstWord == 'M103':
			isActive = False
	return None

Edited 2 time(s). Last edit at 11/03/2011 06:08PM by garyhodgson.


------------------------------------------
garyhodgson.com/reprap | reprap.development-tracker.info | thingtracker.net
Re: Retract calculation in dimension plugin
November 03, 2011 12:04PM
I don't see anything wrong with the first g-code: The one from Skeinforge before you modified it. It puts the extruder back (restart) to were it was before the retract (E2.49087) before the next extruded segment: The one you labeled "end of first path".
Re: Retract calculation in dimension plugin
November 03, 2011 12:36PM
Yeah, it puts it back to the correct position, but my concern is that it retracts too far. i.e. it's retracting as though it was moving from the end of the last line of the last path to the end of the first line of the next path, rather than the start of the next line of the next path.

The retraction speed and distances involved probably mean this doesn't really matter in most prints I guess, but, if there is a problem, it means more work for the extruder at each transition and I suppose it could result in the filament being held back too far at the start of each line, perhaps.


------------------------------------------
garyhodgson.com/reprap | reprap.development-tracker.info | thingtracker.net
Re: Retract calculation in dimension plugin
November 03, 2011 06:38PM
I've added my comments in red to the g-code from SFACT.

                G1 X90.2356 Y90.2356 Z0.2 F1800.0 E2.49087 ; end of path - Correct
		G1 F900.0
		G1 E1.67293 ; retract - Correct
		G1 F1800.0
		;M103
		M82
		G1 X90.2356 Y90.2356 Z0.6 F7800.0 ; start of next path - yes, x, y and z move but nothing extruded
		G1 F900.0
		G1 E2.49087 ; reverse retract - Restart puts it back to where it was at the end of the last path as it should to prepare for next path
		G1 F7800.0
		G92 E0    ; Resets the Extruder back to 0
		;M101
		G1 X109.764 Y90.2356 Z0.6 F1800.0 E0.622717 ; end of first path - No. This is the next path where it extrudes 0.622717 mm
Re: Retract calculation in dimension plugin
November 04, 2011 07:27AM
The Gcode produced as it stands is "correct", but I think that the retract amount is too big, i.e. in the example "G1 E1.67293" should be smaller.

My original post is probably not very clear, particularly now I edited it with "clarifications" about Skeinforge vs SFACT. Below I can show the actual figures used which I think is clearer.

So, taking the calculation from the function:

	locationMinusOld = location - self.oldLocation
	xyTravel = abs(locationMinusOld.dropAxis())
	zTravelMultiplied = locationMinusOld.z * self.zDistanceRatio
	self.timeToNextThread = math.sqrt(xyTravel * xyTravel + zTravelMultiplied * zTravelMultiplied)/ self.feedRateMinute*60
	self.autoRetractDistance = self.timeToNextThread * abs(self.repository.oozeRate.value)/60
	return math.sqrt(xyTravel * xyTravel + zTravelMultiplied * zTravelMultiplied)
Where:
self.zDistanceRatio = 5.0 (Hardcoded - I'm not sure what the significance of this number is.)
self.repository.oozeRate.value = 75.0
self.feedRateMinute = 1800.0

For SFACT produces the following figures:
	self.oldLocation (90.2356, 90.2356, 0.2)
	location (109.764, 90.2356, 0.6)
	locationMinusOld (19.5284, 0.0, 0.4)
	xyTravel 19.5284
	zTravelMultiplied 2.0
	self.timeToNextThread 0.654351593021
	self.autoRetractDistance 0.817939491276
	dist 19.6305477906

and so, E2.49087 minus 0.817939491276 = E1.67293

Note that the xyTravel is 19.5284, even though the nozzle is only moving 0.4mm on the Z axis.


My test harness version produces the following figures:
	self.oldLocation (90.235590035, 90.2355929961, 0.2)
	location (90.2355900343, 90.2355930354, 0.6)
	locationMinusOld (-7.0680528097e-10, 3.92932406612e-08, 0.4)
	xyTravel 3.929959714e-08
	zTravelMultiplied 2.0
	timeToNextThread 0.0333333333333
	retractionExtrusionDistance 0.0416666666667
	dist 2.0

and so, E2.49087 minus 0.0416666666667 = E2.449254


Does this sufficiently explain the potential problem?

Edited 1 time(s). Last edit at 11/04/2011 07:30AM by garyhodgson.


------------------------------------------
garyhodgson.com/reprap | reprap.development-tracker.info | thingtracker.net
Re: Retract calculation in dimension plugin
November 04, 2011 07:43AM
Quote
garyhodgson
In the Dimension plugin, getDistanceToNextThread function, the algorithm calculates the distance from the last location (end of the last path) to the start of the next location (thread) in order to derive how much filament to retract. However, it appears to use the next G1 code it finds after(!) the extruder is active (i.e. after a M101 code is read), which would be the end of the first extruded path. Surely this means that the retraction distance is wrong? I would imagine the retraction distance should be calculated from the end of the last path to the start of the next.

I understand that in Skeinforge, the filament is retracted by the same amount (retract parameter in Dimension) regardless of the distance from the end of the last thread to the beginning of the next one. In your Skeinforge example, I assume that your retract parameter is set to 2.49087-1.67293. I don't know about SFACT since I don't use it.
Re: Retract calculation in dimension plugin
November 04, 2011 09:00AM
I believe you are correct - Skeinforge uses a static retraction amount.

When I realised the difference between the versions I was tempted to kill this thread and perhaps re-raise it as an SFACT issue (which I will probably still do).

However Skeinforge still uses the getDistanceToNextThread calculation to determine the retraction ratio.

In the example above, because the getDistanceToNextThread returns ~20mm the retraction ratio is 1.0, and therefore the filament is retracted whatever amount is configured. If getDistanceToNextThread returned a value that fell under the defined minimum travel for retraction setting (1.0mm), as I would expect it to, then the retraction would not take place.

To verify this I just ran the numbers through the skeinforge44 algorithm to check that the distance value falls under the trigger amount. However, it seems that things are a bit more complicated due to the zDistanceRatio value. This turns out to be travelFeedRatePerSecond / maximumZTravelFeedRatePerSecond, which on my test was 16.0. This yields a zTravelMultiplied of 6.39 which, when plugged into the distance calculation returns the same:

	dist = math.sqrt(xyTravel * xyTravel + zTravelMultiplied * zTravelMultiplied)

	dist = math.sqrt(3.9306238598970684e-08 * 3.9306238598970684e-08 + 6.3999999999999995 * 6.3999999999999995)
	or, dist = math.sqrt(0.00000003930623859897 * 0.00000003930623859897 + 6.3999999999999995 * 6.3999999999999995)

	dist = 6.3999999999999995

Therefore the distance to next thread value triggers the retraction.

Given the zDistanceRatio is involved I suspect that retraction is always triggered when moving between layers. Perhaps this is a desired feature?

My concern, specifically for skeinforge44, is twofold:
1. The function "getDistanceToNextThread" returns a value that is not actually the distance to the next thread, but rather a weighted value which is used to determine if retraction should take place.
2. The basis of this weighted figure is incorrect because it includes the length of the immediate proceeding extruded path, rather than the position at the start of theat path.

Of course we're talking about some real edge cases here, the effects of which are probably negligible. Still, I think it's worth discussing.


------------------------------------------
garyhodgson.com/reprap | reprap.development-tracker.info | thingtracker.net
Re: Retract calculation in dimension plugin
November 04, 2011 10:18AM
Hi All,
I havent inspected/compared yet but what Gary seems to be right. I had that observation myself but did not try to figure out the reason...
That issue especially becomes problematic when you have a fill with clipped ends. If it is a large piece it will assume that it needs to retract a lot...
Although it could ommit it.. I will try to correct this in sfact. But I think (quite sure actually) Enrique reads the forums and he will check that himself...

I will look at it later tonite I hope...


IRC: #reprap on freenode.net (Action68)
[github.com]
Re: Retract calculation in dimension plugin
November 04, 2011 04:05PM
Just to update - I got word from Enrique that the following fix will be applied to Skeinforge. It replaces the existing "if isActive" statement in the getDistanceToNextThread function.

				if isActive:
					if not self.repository.retractWithinIsland.value:
						locationEnclosureIndex = self.getSmallestEnclosureIndex(location.dropAxis())
						if locationEnclosureIndex != self.getSmallestEnclosureIndex(self.oldLocation.dropAxis()):
							return None
					locationMinusOld = location - self.oldLocation
					xyTravel = abs(locationMinusOld.dropAxis())
					zTravelMultiplied = locationMinusOld.z * self.zDistanceRatio
					return math.sqrt(xyTravel * xyTravel + zTravelMultiplied * zTravelMultiplied)
				else:
					location = gcodec.getLocationFromSplitLine(location, splitLine)

Ahmet, I think this would work for you too. Give me a shout if I can be of any further help.

Cheers guys.


------------------------------------------
garyhodgson.com/reprap | reprap.development-tracker.info | thingtracker.net
Re: Retract calculation in dimension plugin
November 04, 2011 06:23PM
Gary: Thats great, it works.
I also believe that we should start seperating travel moves by coding G0 for them instead of checking whether an E move is included in the move..
If you want to compare sfact to sf the daily branch is based on the 15.10.11 release of the beanshell. So it should be easier.
ın daily I also deleted all the flow calculations in the different plugins. It is now carried over to the dimension plugin basically as 1 (factor for flow =feed) in dimension the volumetry is added according to the distance per move. Avoiding the loop over the flowrate and calculating back to volume....

I have no support for DC extruders but it still can be factored in.. Then probably even the calibration module would work for DC extruders..

Once again thanks for a heads up on one of the major problems in 3d printing...


IRC: #reprap on freenode.net (Action68)
[github.com]
Re: Retract calculation in dimension plugin
November 17, 2011 06:58PM
Hi Gary,
another problem that if you have comb oro cool with orbit enabled, it will just calculate the first move.
Also is tehre a way to read the feedrate of that upcoming move?


IRC: #reprap on freenode.net (Action68)
[github.com]
Re: Retract calculation in dimension plugin
November 18, 2011 07:02AM
Hi Ahmet,

You're correct in that the serial nature of Skeinforge means that working out the summation of a series of moves is not so straightforward. Off the top of my head perhaps an accumulator could be used. The following is only pseudocode as I haven't got time at the moment to try it out...
	
	# Earlier....
	xyTravel = 0
	zTravel = 0
	...

	if isActive:
	
		if not self.repository.retractWithinIsland.value:
			locationEnclosureIndex = self.getSmallestEnclosureIndex(location.dropAxis())
			if locationEnclosureIndex != self.getSmallestEnclosureIndex(self.oldLocation.dropAxis()):
				return None
		
		zTravelMultiplied = zTravel * self.zDistanceRatio
		return math.sqrt(xyTravel * xyTravel + zTravelMultiplied * zTravelMultiplied)

	else:

		location = gcodec.getLocationFromSplitLine(location, splitLine)
		locationMinusOld = location - self.oldLocation
		xyTravel += abs(locationMinusOld.dropAxis())
		zTravel += locationMinusOld.z

		...

		self.oldLocation = location

Regarding the feedrate I think the "gcodec.getDoubleFromCharacterSplitLineValue(character, splitLine, value)" function would work, searching for the "F" value. At least for volumetric extruders.


------------------------------------------
garyhodgson.com/reprap | reprap.development-tracker.info | thingtracker.net
Re: Retract calculation in dimension plugin
November 18, 2011 09:35AM
Thanks a lot. If we can calculate the time until it feeds again correct we can use Orbit cool for nicer prints...
The adaptive retract would then just retract all the way up to the limit.
I can simulate that with searching for the layer code (cool) and acting accordingly or so but then the ifs get so nested....sad smiley

Currently the sfact daily branch is updated to SF45 code. The adaptive retraction there works really nice...
[picasaweb.google.com]

SFACT daily is here: [github.com]

Edited 1 time(s). Last edit at 11/18/2011 09:41AM by ahmetcemturan.


IRC: #reprap on freenode.net (Action68)
[github.com]
Re: Retract calculation in dimension plugin
November 18, 2011 11:12AM
---

Edited 1 time(s). Last edit at 11/18/2011 11:12AM by brnrd.
Sorry, only registered users may post in this forum.

Click here to login