evildmp / BrachioGraph

BrachioGraph is an ultra-cheap (total cost of materials: €14) plotter that can be built with minimal skills.
https://www.brachiograph.art
MIT License
680 stars 114 forks source link

`ValueError: math domain error` triggered in drive_xy #51

Closed willprice closed 4 years ago

willprice commented 4 years ago

Using the following testing script

from brachiograph import BrachioGraph
from time import sleep

# The servo_x_degree_ms signs need flipping as my motors
# go in the opposite direction to those in the article
plotter = BrachioGraph(
  inner_arm=8.2,
  outer_arm=8.85,
  servo_1_degree_ms=10,
  servo_2_degree_ms=-10,
)
print("Resetting arm position")
plotter.set_angles(angle_1=-90, angle_2=90)
print("Set up complete")

plotter.drive_xy()

and moving around with a,d,l,k I can consistently trigger a math domain error. I think this happens when the hypotenuse becomes very small or perhaps negative?

Here's the stack trace

Traceback (most recent call last):
File "test.py", line 23, in <module>
plotter.drive_xy()
File "/home/pi/branchiograph/brachiograph.py", line 698, in drive_xy
self.xy(self.current_x, self.current_y)
File "/home/pi/branchiograph/brachiograph.py", line 434, in xy
(angle_1, angle_2) = self.xy_to_angles(x, y)
File "/home/pi/branchiograph/brachiograph.py", line 590, in xy_to_angles
(hypotenuse**2+self.INNER_ARM**2-self.OUTER_ARM**2)/(2*hypotenuse*self.INNER_ARM)
ValueError: math domain error

and here are the values printed during driving the plotter

Resetting arm position
Set up complete
-9.2 8.85
-10.2 8.85
-11.2 8.85
-12.2 8.85
-13.2 8.85
-14.2 8.85
-13.2 8.85
-12.2 8.85
-11.2 8.85
-12.2 8.85
-13.2 8.85
-14.2 8.85
-13.2 8.85
-12.2 8.85
-11.2 8.85
-11.2 9.85
-11.2 10.85
-11.2 11.85
-11.2 12.85
-11.2 13.85
moe5k commented 4 years ago

I have the same problem. Did you solved it?

willprice commented 4 years ago

@moe5k, well I think the idea is that you use bg.drive_xy() to figure out the min/max x/y values before this is triggered, although I'm not certain about that. I've not had much success yet, as when I try the bg.box() test, the plotter draws nothing like a box! It's more like two squashed circles.

moe5k commented 4 years ago

@willprice i thought using bg.drive_xy() for define the physical limits of the hardware. At least bg.box() should drive along these points. I got also a similar behavior while starting bg.box().

willprice commented 4 years ago

@moe5k Yes, I think you're probably right. It doesn't seem particularly user friendly for the app to crash, instead, an error should be raised. I've not quite pinned down the cause of the issue. At first, I thought it was when the hypotenuse went to 0 causing a div by 0 error, but I tried to catch this issue but still observed the domain error. I think I need to log the values going to the trigonometric functions as this is where I suspect the exception is being raised.

willprice commented 4 years ago

OK, figured out why this happens. When (hypotenuse**2+self.INNER_ARM**2-self.OUTER_ARM**2)/(2*hypotenuse*self.INNER_ARM) (derived from the cosine rule) is less than -1 or greater than 1 then arccos will throw a math domain error since cos can only produce values in the range [-1, 1]. I need to think about this a bit more, but my intuition is that it's not possible to produce a triangle with its tip at (x, y) given the inner and outer arm lengths.

evildmp commented 4 years ago

This looks reasonable to me.

>>> import math
>>> math.sqrt(11.2 **2  + 13.85 **2) < (8.2 + 8.85)
False

The distance to the point is further than arms can reach.

A better message would be useful though.

willprice commented 4 years ago

I've added a bit of code to catch this issue and inform the user. https://github.com/willprice/BrachioGraph/commit/c8d764d3d50916e7ea4408d3d27ce832a613a0e8 In that branch I've turned all the return str messages into exceptions too.

evildmp commented 4 years ago

In the better-turtle-graphics branch (in development) we can get useful output like:

Screenshot 2019-12-08 21 38 40

that helps visualise this better.

willprice commented 4 years ago

That looks super useful. Thanks @evildmp, I'll check it out.