So, let's recap:
We want to move our "hand" in a straight line (blue)
If we merely rotated the "elbow", we'd be able to move from the starting point to the end-point. But, the path would be circular (purple).
So, to avoid a circular-path we need to also rotate the "shoulder," as well.
As I gather, the typical approach is to calculate "paths" for both the elbow and the shoulder before the motion actually starts, then execute the motion.
Calculation of the joints' rotations is an interesting exercise, and can solve this problem, but isn't particularly easy for me to wrap my head around.
Also, computers are *excellent* at iterative calculations... doing things step-by-step over and over again... So, then, why try to "predict" (or "extrapolate"?) those equations, when they have to be executed step-by-step in the end?
For a more iterative-approach we still need to determine equation(s) for the line that our "hand" will move along...
That's not particularly-complicated, the regular ol' y=mx+b equations, or a slight modification thereof.
(TODO: Re-learn parametric-equations... is that y(t) = at+b, and x(t) = ct+d?)
(This might be approached in the same way a line of pixels would be drawn, iteratively, on a screen... more on that later).
Anyways, not particularly difficult, and required regardless of which approach is taken (this so-called "iterative-motion" approach, or using inverse-kinematics).
Now, let's iterate through this...
Just glancing at it, we can see the "hand" should move down, a bit... (we'll ignore the leftward-motion, for now).
A downward motion of the "hand" should be accomplishable by rotating the elbow counter-clockwise.
Doing-so causes an "overshoot" toward the left (along the purple path)
So, to compensate, we want to move the "hand" to the right. That can be accomplished by rotating the "shoulder" clockwise a bit.
Basically, that's it. Now repeat those steps, taking very small physical steps, numerous times until the endpoint is reached.
Thankfully, computers (or even 8-bit microcontrollers) can do that very process thousands, if not *millions* of times per second, so the amount of "overshoot" will be so small as to not even be noticed.
Taken a step further, those calculations can be performed faster than one's motors can step from one position to the next, and likely can occur more-often than even a high resolution encoder could detect. Which means no more "error" or "overshoot" would occur with this iterative method than with any other.
Further-still, the desired motion of the "hand" determines, in any case, the rotations of the "elbow" and "shoulder", so no motion-planning is necessary for each individual joint to consider acceleration, etc. If the requested-motion (the line) is possible per the limitations of the motors, the motion will occur. If not, a slower motor will delay the system until it "catches up." In the end, the motion will be as smooth as the motors can physically allow, and if the requested motion of the "hand" is within the means of the system, it will occur "on time" and with as much or as little "ramping" as requested.
One key-factor may be to iterate through each possible position on each motor, step-by-step. Rather than, say, requesting twenty steps on one motor, and one on the next, within one "loop." Instead, one might iterate through the loop ten times; the first ten loops would cause individual steps of the first motor, the next loop would advance both motors one step, and the remaining ten loops would cause ten more individual steps on the first motor.
This is similar to drawing a line of pixels on a screen. If you drew a line on a screen by using y=mx+b, iterating through each *integer* value of x, when m > 1, the line drawn would contain a bunch of disconnected points. Instead, you determine which axis requires the greatest "travel" and choose to use either y=mx+b or x=ny+c as appropriate, and, again, step through each *integer* value of x or y, respectively.
By throwing "time" into the equation (using a parametric equation, which I've forgotten how to represent), the effect is essentially that many loop-iterations may not do *anything* causing a slight delay in the stepping, and, therefore inherently controlling the *speed* of the motors, without ever having to calculate it (for each motor).
And, again, by doing-so where each loop-iteration only handles one "step" of each motor, and since the loop-iterations themselves happen *so fast* and *so often* (possibly millions of times a second), the end-effect should be motion as smooth as can be achieved with the motors (and encoders, if used), regardless of the method used to determine their "paths".
Now, more-complicated motions will, of course, slow the loop-iteration-speed... Using an equation for a line, wherein one also considers acceleration/deceleration (aka "ramping"), would mean quite a bit of calculation during each loop to determine the amount of "error" or "overshoot"... In which case, maybe the motion *of the hand* should be "pre-planned", and stored as a lookup-table, rather than recalculated during each step. This would also account for really complicated motions such as an S-curve connecting the two end-points, etc. But the end-result is the same, no "inverse" calculations are necessary. Just calculate the desired path, then allow the extremely fast trial-and-error process that computers are exceptional at to handle the rest.
At least, that's how I see it... I've tried to learn inverse-kinematics a few times, but the explanations I've found are just outside my grasp... maybe what I've described, here, *is* inverse-kinematics, and I just didn't realize it?
And, of course, with three "joints" it gets more complicated... And, further-still, when a path needs to take into consideration the other joints (such as to avoid obstacles)...