I've found that as I give the annealer more variables to mess with, the better the result it produces. However, the results - while good - show that there is still more work to be done. I've already given it almost every variable I can think of, except for one: Tower lean. The firmware assumes each tower is exactly perpendicular (90 degrees) relative to the build surface, but unless your printer was assembled by robots, this is probably not the case. Furthermore, the lean, even if small, can have a significant impact on positional accuracy. If you move the effector out from the center to the edge, all the carriages have to move, and one may have to move as much as ~140mm. Multiply that by the lean of the towers, and even if the lean is small, you're still multiplying that by up to 140mm just on one tower! Your carriages may wind up some percent of a millimeter off from where the printer thinks they are. Therefore, tower lean seems like the logical choice for the next variable type to add to the annealer. If there are improvements to be found by compensating for tower lean, doing so should help significantly.
That brings us to the trig part!
The idea I had was to store a unit vector containing the lean of the tower relative to its origin, which is one of its endpoints (either the bottom or the top of the tower). To get the true { x, y, z } of the carriage, you take its elevation (distance from its origin), multiply that by the unit vector, and you get your true coordinates. That's pretty simple, and it works fine for the forward kinematics (effector X,Y,Z given carriage elevations) because we already have the elevations.
However, it doesn't work for the inverse kinematics (carriage elevations given effector X,Y,Z) because you have to already know the elevation (distance from the carriage's origin) before you can get the carriage's true XYZ. In fact, it throws off the whole equation pretty soundly.
Here's the regular version, without any math for tower lean:
Code: Select all
.<--- Carriage
|\
| \
| \ AL = Arm Length
| \ | = Elevation = Vertical distance from effector's hinge to carriage's hinge (the vertical axis in this diagram)
| \
.-----.<--- Effector
Dist
Because of an old dude named Pythagoras, we know the following:
Elev = sqrt(AL^2 + Dist^2)
AL = sqrt(Dist^2 + Elev^2)
Dist = sqrt(Elev^2 + AL^2)
Dist^2 = (X - twr[X])^2 + (Y - twr[Y])^2 = AL^2 - Elev^2
Elev = sqrt( AL^2 - (cartesian[X]-twr[X])^2 - (cartesian[Y]-twr[Y])^2 ) + cartesian[Z]
In the real world, the triangle may be either right or scalene. Moreover, unless your printer was built by an expensive robot with perfect accuracy, it is scalene. The plane of the triangle is not perpendicular to the build surface. Additionally, the trick of only calculating the carriage positions for the { X, Y } coordinates, and then adding Z to all three carriage positions, no longer works because the towers aren't exactly vertical. You might add 100mm of Z, but only get (for example) 98.8mm above the surface, because the tower just isn't straight up and down!
In the diagram above, the Dist variable is measured from the carriage if it was at the effector's height, to the effector. This works because a towers's XY is always the same, at every elevation. To do this properly in a robot where the tower's XY changes with elevation because of lean, we can make no assumption about whether the carriage is at the same XY at effector height that it would be at carriage height. Therefore, we would instead have to measure Dist as the horizontal distance between the carriage's elevation on the tower to the effector, and use a different variable to describe the true vertical distance from the carriage hinge to the effector hinge, which I call ZTrue:
Code: Select all
v--- Carriage
.----- <--- Dist
\ |
\ |
\ | \ = AL
\ | | = ZTrue
\|
. <--- Effector
I don't know how to continue, and I've been researching this for most of the last 12 hours, so my brain is totally fried. What's the next step? How do I find the elevation of a sphere along an arbitrarily leaning tower, such that the distance from the center of the sphere to a point at radius AL (arm length) is equal to the horizontal distance between the sphere center and the desired effector hinge location? (Is that even the right question?)