# Inverse Kinematics Module

What is inverse kinematics? It is that cool arm robot from iron man.

In computer animation and robotics, inverse kinematics is the mathematical process of calculating the variable joint parameters needed to place the end of a kinematic chain, such as a robot manipulator or animation character’s skeleton, in a given position and orientation relative to the start of the chain. (straight off wikipedia)

process of obtaining joint angles from known coordinates of end effector.
(OPEN SOURCE)

This module uses FABRIK (Forward and Backward Reaching Inverse Kinematics) You can enable 2D or 3D.

In the future I will add constraints to it. Meaning certain points can turn only at a certain angle.
I might add more stuff to the module in the future.

Kinematics.lua (5.2 KB)
ExamplePlace.rbxl (56.4 KB)

Preview 2D

Preview 3D

Code Documentation (its short so ill put it here)
Create IK 3D

``````local Kinematics = require(game:GetService("ServerScriptService").Kinematics).new{
Type = "2D", -- Create a 2D type. it only accepts "2D" or "3D"
Arm = {7, 5, 3}  -- Create our arm of lengths. Add as much arms you want
-- First arm is 7 Studs, second arm is 5 studs, third are is 3 studs
}

local originPosition = workspace.Origin.Position -- get start position in workspace
local targetPosition = workspace.End.Position -- get target position in workspace

local success = Kinematics:FABRIK{ -- use FABRIK (Forward and Backward Reaching Inverse Kinematics)
Origin = originPosition, -- give it start position
Target = targetPosition, -- give it target position

Tolerance = 0.1, -- Optional doesnt need to be here unless you want manual settings
MaxIterations = 100 -- Optional doesnt need to be here unless you want manual settings
}

local cframes = Kinematics:GetPartCFrames(originPosition, targetPosition) -- get the cframes so we can display and show
for armIndex = 1, #cframes do -- loop through them numerical loop cuz fast and cool
local cframe = cframes[armIndex] -- get the cframe

local arm = workspace[`Arm{armIndex}`] -- get the part in workspace that we are gonna apply cframe to
arm.CFrame = cframe -- set the part cframe and done.
end -- do other stuff
end
``````

All the stuff you can do

``````local Kinematics = require(game:GetService("ServerScriptService").Kinematics)

-- Create new Kinematic Solver
local solver = Kinematics.new{
Type = "3D", -- what type? "2D" or "3D"
Arm = { 3, 3 } -- lengths of arms, can have as much arms as you want and as much lengths
}

local success = solver:FABRIK{ -- use FABRIK, forwa and bawa reac ivner kinema
Origin = Vector3.new(2, 5, 6), -- start position
Target = Vector3.new(2, 2, 2), -- end position

Tolerance = 0.2, -- not needed since its automatically set but tolerance meaning how close it needs to be for to be success
MaxIterations = 25, -- max amount it'll do forwrad and back if not reached tolerance
} -- success means if it reached the target position within the tolerance and maxInterations

local armsData = solver:GetArmsData() -- gets all the data of each arm, gets points and length
-- returns { { position: Vector3, length: number, constraint: not used } }

local positions = solver:GetPositions() -- gets position of all points
-- it returns and array of positions so { Vector3, Vector3, Vector3 }

local cframes = solver:GetPartCFrames() -- gets cframes of all points similar to points but it gets the cframe directly and positions them in the middle
-- it returns and array of cframes so { CFrame, CFrame, CFrame }
``````

Check out my machine learning (VERY COOL AI) library

18 Likes

But, doesn’t Roblox already support this by using IKControl Instance?

1 Like

Yes you’re right. IKControl are used for Humanoids/Characters. This module is mainly on parts without
Humanoids or Animation Controllers.
So you could probably use this for making a Robot Arm

Or you could make the Legs of an AT-ST Walker

1 Like

Cool, maybe in your example place, have comments in that code also…

also what is the difference between using the 2D or 3D parameter ?

What stuff have you created with this?

And how can I get it to have constraints, so that if I am moving it in an arc, it does not bend out sideways, and instead bends in an arc like a rope would?

2D locks one of its axis and has it where it only faces you.
3D makes it so all of its axis are unlocked and each joint can face a different direction.

If you moved the arm side to side with 2D all the parts would move to keep it locked on one of its axis.
If you moved the arm side to side with 3D the last part would move because it can change directions of the other parts

I have created this walking robot.

I plan to add constraints in the future, I just haven’t created it yet.

2 Likes

So IKControl doesn’t work for stuff other than Humanoids?
Also:
Docs says:

IKControls must be a child of a Humanoid or AnimationController with an Animator

So we can simply add AnimationController with an Animator inside that.

Why not use AnimationControllers?

IKControl does work for nonhumanoids yes. This module provides more support and manipulation for non-rigged parts.

The IK module will provide you direct access to all information stored.

Oh, This is great and a pros of this module, I would certainly use that and experiment with it.

1 Like

This is great and I’m gald i could use this!
But sadly I cant use models for the arms, I’m gonna try and make it to be abe to handle models but I’m not sure if it will succeed!
(Yes I will give a copy of the edited version)

edit: Ok so i got it to work, Ill send the code:

``````--serverscriptstorage
local module = script.Parent
local serverstor = game.ServerStorage
local models = serverstor.STORAGE.TentacleModels
local signals = serverstor.SIGNALS
signals.MakeArms.Event:Connect(function(Name, Folder, ListLengths)
local get1 = Folder
local get2 = models:FindFirstChild(Name)
if get1 and get2 then
for N, Length in ipairs(ListLengths) do
--loop trough lenghts to create all parts

local clone = get2:Clone()
if clone.ClassName == "Model" then
local m = clone:FindFirstChild("inner")
if m then
m.Size = Vector3.new(m.Size.X, m.Size.Y, Length)
else
warn("INVALID MODEL IN STORAGE!")
end
elseif clone.ClassName == "Part" then
clone.Size = Vector3.new(clone.Size.X, clone.Size.Y, Length)
end
clone.Name = "Arm"..N
clone.Parent = get1
local b = clone:FindFirstChildOfClass("Script")
if b then
b.Enabled = true
end
end
print("succes!")
else
warn("invalid tentacle information given, expect errors!")
end
end)
``````
``````local serverscrip = game:GetService("ServerScriptService")
local serverstora = game:GetService("ServerStorage")
local signals = serverstora:WaitForChild("SIGNALS")
local tents = workspace:WaitForChild("Visuals"):WaitForChild("Tentacles")
local base = script.Parent.Base
--functions
local function createTentacle(Lengths)
local Arms = Instance.new("Folder")
Arms.Name = "Test"..(#tents:GetChildren()+1)
Arms.Parent = tents
signals.MakeArms:Fire("Model1", Arms, Lengths)
return Arms
end

local function RefreshTentacle(folder)
local Kinematics = require(serverscrip.Kinematics).new{Type = "3D", Arm = lengths}
local success = Kinematics:FABRIK{
Origin = script.Parent.Base.Position,
Target = script.Parent.Player.Position
}
local cframes = Kinematics:GetPartCFrames(originPosition, targetPosition)
for armIndex = 1, #cframes do
local cframe = cframes[armIndex]
local arm = folder[`Arm{armIndex}`]
if arm.ClassName == "Model" then
arm:PivotTo(cframe)
else
arm.CFrame = cframe
end
end
end

--start
wait(1)
local f = createTentacle(lengths)
wait(0.2)