adafruit / Adafruit_CircuitPython_turtle

left! right! forward! turtle power!
MIT License
8 stars 12 forks source link

turtle location is wrong after several moves #41

Open ricknun opened 2 weeks ago

ricknun commented 2 weeks ago

Turtle command "forward(self, distance: float)" (and likely other commands) truncate turtle location to an integer value after each move. This can accumulate up to a 1 pixel error per turtle move. I would expect that the turtle location be maintained to floating point resolution and then be plotted to the nearest pixel each move. The attached program for a Circuit Playground Bluefruit + TFT Gizmo shows the problem. For example, 105 moves forward of 1.904762 pixels moves 105 pixels, not 105*1.904762 ~= 200. I am using CircuitPython v9.1.4. An image of running the attached .py program is attached too. It's possible this issue goes deeper than just Turtle Graphics -- I don't know what its underlying graphics system is. turtle_truncate.txt 20241105_141322

ricknun commented 2 weeks ago

This problem was found in a more complicated turtle graphics program and reduced to the attached turtle_truncate.py.

ricknun commented 2 weeks ago

I checked Python v3.13 turtle graphics (see https://docs.python.org/3/library/turtle.html) on my Windows 10 PC. As expected, the result there is that the attached code produces 3 lines each 200 pixels long. There, turtle location is maintained with floating point numbers. With many plot points Adafruit turtle graphics leaves the turtle significantly far from where it should be. The attached .py file also mentions another problem with Adafruit turtle graphics, described in issue #40.

turtle_truncate.txt

ricknun commented 2 weeks ago

I changed the issue title to better indicate impact to the end user. As another example, here is Adafruit's own example code "turtle_overlayed_koch.py" running on CPB + TFT Gizmo. Notice the yellow many-move Koch snowflake overlays the others correctly in the upper-left but is way off to the lower-right. Any turtle image with many small moves ends up being significantly off from where it should be.

TurtleIntegerTruncateBug

dhalbert commented 2 weeks ago

Can you see a straightforward fix for this, like always storing the actual location, and doing int rounding/truncation only when doing display? A PR would be welcome.

ricknun commented 2 weeks ago

I tried to understand adafruit_turtle.py enough to suggest a fix but couldn't do so. It seems important that the overlaid Koch program (and example code in issue #40) used to work well -- It should be possible to back-rev adafruit_turtle.py and other files involved to find who broke the code when, but I don't know how to do that. If the person that broke it is still around I'd get them involved. If not, at least I'd know what they were trying to do and where they went wrong.

dhalbert commented 2 weeks ago

Can you give a really simple example that shows the problem? Then we can try versions in systematic way and get to the exact change that caused the issue.

ricknun commented 2 weeks ago

In the original post see turtle_truncate.txt (and rename it to .py). See comments in the file.

dhalbert commented 2 weeks ago

Did we have a discussion already about .mode("standard") vs .mode("logo")? "logo" appears to be the default. Did you try switching modes to "standard"? That changes the default heading orientation (you noted a difference in your example).

ricknun commented 1 week ago

turtle.mode("standard") and "logo" has to do with issue #40 and is discussed there -- I think mode "standard" was default in the past and someone changed it to "logo", breaking the 4 example files sited in that issue. The issue here doesn't change between "standard" and "logo" modes. In the provided turtle_truncate.py program you can add turtle.mode("standard") and comment out the turtle.setheading(90) line, to get the same image as shown in the original post.