<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: David</title>
    <description>The latest articles on Forem by David (@dslower).</description>
    <link>https://forem.com/dslower</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3271952%2Feae73483-4a1a-421c-a2b0-ab07cb567bca.png</url>
      <title>Forem: David</title>
      <link>https://forem.com/dslower</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dslower"/>
    <language>en</language>
    <item>
      <title>Inverse Kinematics Solver using the Fabrik method</title>
      <dc:creator>David</dc:creator>
      <pubDate>Sun, 22 Jun 2025 17:34:35 +0000</pubDate>
      <link>https://forem.com/dslower/inverse-kinematics-solver-using-the-fabrik-method-1m92</link>
      <guid>https://forem.com/dslower/inverse-kinematics-solver-using-the-fabrik-method-1m92</guid>
      <description>&lt;p&gt;Want to learn how to implement an Inverse Kinematics(Ik) solver in Miniscript? In this post I'll teach you how.&lt;/p&gt;

&lt;p&gt;Final Result:&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/Fm1dM0IwzDA"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Ik is one of the coolest things in programming. It can make animations look more realistic and can help achieving complex behaviors from simple rules. In this tutorial we'll be using a method called Fabrik which stands for “Forward And Backward Reaching Inverse Kinematics”. We are going to make a robot arm that tries to reach the mouse. Let's code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Boot up MiniMicro, make a folder called “ik” with the command: &lt;code&gt;mkdir “ik”&lt;/code&gt; and hit enter, navigate the folder by typing: &lt;code&gt;cd “ik”&lt;/code&gt;. Note that the argument past to the command has to be between quotation marks. Now let's create our MiniScript file with: &lt;code&gt;save “main”&lt;/code&gt;, and start editing by typing &lt;code&gt;edit&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting Code
&lt;/h2&gt;

&lt;p&gt;We'll start by clearing the screen with: &lt;code&gt;clear&lt;/code&gt;. Now we define some variables, &lt;code&gt;distance&lt;/code&gt; is the distance between joints, and &lt;code&gt;points&lt;/code&gt; is a list in which we store joints so we can loop through them easily. The current code should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clear

distance = 64
points = []
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's create a custom class that extend the &lt;code&gt;Sprite&lt;/code&gt; to add a handy function and avoid repeating complex code. Also let's load a basic image to see the points, and scale it up a little.&lt;/p&gt;

&lt;p&gt;Download this sample &lt;a href="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mlgio10pix1722vovcmy.png" rel="noopener noreferrer"&gt;image&lt;/a&gt;, rename it to "point.png" and place it next to your "main.ms" file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Point = new Sprite
Point.image = file.loadImage("point.png")
Point.scale = 6
Point.normalize = function
    length = sqrt(self.x * self.x + self.y * self.y)
    if length != 0 then
        self.x /= length
        self.y /= length
    else
        self.x = 0
        self.y = 0
    end if
end function
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't worry if you don't understand this code, just know that it converts the x and y values to arrange between 0 and 1. We make use of the &lt;a href="https://en.wikipedia.org/wiki/Pythagorean_theorem" rel="noopener noreferrer"&gt;Pythagorean theorem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ok, so now we add 3 items to the ‘points’ list. For that we use a basic for loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for i in range(2)
    p = new Point
    display(4).sprites.push p
    points.push p
end for
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, let's add a variable named &lt;code&gt;anchor&lt;/code&gt; which will be the anchor point of the arm, let's set it to the center of the screen, and &lt;code&gt;dir&lt;/code&gt;, which will store the direction from one point no another.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;anchor = new Point
anchor.x = 480
anchor.y = 320

dir = new Point
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The whole script should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clear

distance = 64
points = []

Point = new Sprite
Point.image = file.loadImage("bone.png")
Point.scale = 6
Point.normalize = function
    length = sqrt(self.x * self.x + self.y * self.y)
    if length != 0 then
        self.x /= length
        self.y /= length
    else
        self.x = 0
        self.y = 0
    end if
end function

for i in range(2)
    p = new Point
    display(4).sprites.push p
    points.push p
end for

anchor = new Point
anchor.x = 480
anchor.y = 320

dir = new Point
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Fun Part
&lt;/h2&gt;

&lt;p&gt;Now that we got everything ready it's time to code the “ik” solver. Let's start a &lt;code&gt;while&lt;/code&gt; loop and clear the screen to a white color.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;while true
    gfx.clear color.white

        // Next will go here...

    yield
end while
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A quick detail, the Fabrik method is done in two steps. We start from the last point, move it to the target position and then adjust all other points accordingly. In the second step we start from the first point, move it to the origin position and adjust all other points. That's why this method is called Fabrik, because we move forward and backwards, in the process, all points move to the best possible position in which they don't overlap, and the distance between each position is the one we desired.&lt;/p&gt;

&lt;p&gt;With that said, let's code. First let's move all the points towards the target position, in our case, the coordinates of the mouse. Let's set the last point (the tip of the arm) to mouse position.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// forward iteration
points[points.len - 1].x = mouse.x
points[points.len - 1].y = mouse.y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we loop through the points left, starting from the penultimate. We calculate the direction to the next point and adjust the position of the current point using the direction multiplied by the length and subtracting that vector to the next point position.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for i in range(points.len-2, 0)
    dir.x = points[i + 1].x - points[i].x
    dir.y = points[i + 1].y - points[i].y
    dir.normalize

    points[i].x = points[i + 1].x - dir.x * distance
    points[i].y = points[i + 1].y - dir.y * distance
end for
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last step is very similar to the previous one, except we go in reverse. Let's set the first point (the arm anchor) to the origin position.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//backwards iteration
points[0].x = anchor.x
points[0].y = anchor.y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we loop again but skipping the first point since we already set it's position. We calculate the direction, this time with the previous point and adjust it's position.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for i in range(1, points.len - 1)
    dir.x = points[i - 1].x - points[i].x
    dir.y = points[i - 1].y - points[i].y
    dir.normalize

    points[i].x = points[i - 1].x - dir.x * distance
    points[i].y = points[i - 1].y - dir.y * distance
end for
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we finish the loop let's draw a line that connects all points. We do that using the ‘gfx.line’ function, it takes from 4 to 6 arguments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for i in range(1, points.len - 1)
    dir.x = points[i - 1].x - points[i].x
    dir.y = points[i - 1].y - points[i].y
    dir.normalize

    points[i].x = points[i - 1].x - dir.x * distance
    points[i].y = points[i - 1].y - dir.y * distance

    // Draw line
    gfx.line(
      points[i].x, // start x
      points[i].y, // start y
      points[i-1].x, // end x
      points[i-1].y, // end y
      color.gray,  // color
      16) // line width
end for
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete script should be something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clear

distance = 64
points = []

Point = new Sprite
Point.image = file.loadImage("bone.png")
Point.scale = 6
Point.normalize = function
    length = sqrt(self.x * self.x + self.y * self.y)
    if length != 0 then
        self.x /= length
        self.y /= length
    else
        self.x = 0
        self.y = 0
    end if
end function

for i in range(2)
    p = new Point
    display(4).sprites.push p
    points.push p
end for

anchor = new Point
anchor.x = 480
anchor.y = 320

dir = new Point

while true
        gfx.clear color.white

        // forward iteration
    points[points.len - 1].x = mouse.x
    points[points.len - 1].y = mouse.y

    for i in range(points.len-2, 0)
        dir.x = points[i + 1].x - points[i].x
        dir.y = points[i + 1].y - points[i].y
        dir.normalize

        points[i].x = points[i + 1].x - dir.x * distance
        points[i].y = points[i + 1].y - dir.y * distance
    end for

        // backwards iteration
    points[0].x = anchor.x
    points[0].y = anchor.y

    for i in range(1, points.len - 1)
        dir.x = points[i - 1].x - points[i].x
        dir.y = points[i - 1].y - points[i].y
        dir.normalize

        points[i].x = points[i - 1].x - dir.x * distance
        points[i].y = points[i - 1].y - dir.y * distance

                //Draw line
        gfx.line(
          points[i].x,
          points[i].y,
          points[i-1].x,
          points[i-1].y,
          color.gray,
          16)  
    end for

    yield
end while
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done! Hit F5 and move the mouse around, you'll see the robot arm trying to reach it and flex if it's in range. &lt;/p&gt;

&lt;p&gt;This is a simple example but it can be adapted to more complex ones with some additions. Want to see how? Wait for the next tutorial to find out.&lt;/p&gt;

&lt;p&gt;That's it for now, hope you enjoyed it and find it useful! If you have any questions feel free to leave a comment. Thanks for reading!! &lt;/p&gt;

</description>
      <category>miniscript</category>
      <category>minimicro</category>
      <category>programming</category>
      <category>inversekinematics</category>
    </item>
  </channel>
</rss>
