UnderAutomation
Any question?

[email protected]

Contact us
UnderAutomation
⌘Q

Forward & Inverse Kinematics

Perform forward and inverse kinematics calculations offline for FANUC industrial robots and CRX cobots using DH parameters.

This page shows how to compute the forward and inverse kinematics of FANUC industrial arms and CRX cobots with the Fanuc SDK, offline or with the controller. Inverse kinematics (IK) and forward kinematics (FK) let you move between joint space and Cartesian space. FK computes the tool pose from known joint angles, while IK finds joint angles for a desired pose. The kinematics utilities in the Fanuc SDK are offline helpers: you can evaluate poses and joint solutions without connecting to a controller, for simulation, path validation and checks before deployment.

Industrial arms and cobots

Two solvers

The SDK has two analytical solvers and chooses the right one:

  • OPW industrial arms: Classical 6-axis Fanuc robots with an ortho-parallel base and spherical wrist, based on the paper An Analytical Solution of the Inverse Kinematics Problem of Industrial Serial Manipulators with an Ortho-parallel Basis and a Spherical Wrist by Mathias Brandstötter, Arthur Angerer, and Michael Hofbaur.
  • CRX collaborative arms: Fanuc CRX cobots that have their own closed-form solver and optional dual solutions, based on paper Geometric Approach for Inverse Kinematics of the FANUC CRX Collaborative Robot by Manel Abbes and Gérard Poisson.

Choice of the solver

KinematicsUtils.InverseKinematics() reads DhParameters.KinematicsCategory:

  • KinematicsCategory.Opw: it calls Opw.OpwKinematicsUtils.InverseKinematics (industrial robots).
  • KinematicsCategory.Crx: it calls Crx.CrxKinematicsUtils.InverseKinematics (CRX cobots).

So one entry point covers every arm.

Offline kinematics

Run forward kinematics (FK)

static void Main()
{
// Load robot geometry
var dh = DhParameters.FromArmKinematicModel(ArmKinematicModels.CRX10iA);
// Joint angles in degrees (Fanuc convention)
var jointsDeg = new JointsPosition { J1 = 0, J2 = -30, J3 = 45, J4 = 0, J5 = 60, J6 = 90 };
// Compute pose: returns XYZ + WPR
CartesianPosition pose = KinematicsUtils.ForwardKinematics(jointsDeg, dh);
}
}
Click to see the full code

Solve inverse kinematics (IK) for an OPW robot

static void Main()
{
// OPW industrial robot
var dh = DhParameters.FromArmKinematicModel(ArmKinematicModels.ARCMate120iD);
var target = new CartesianPosition { X = 800, Y = 0, Z = 450, W = 180, P = 0, R = 90 };
JointsPosition[] solutions = KinematicsUtils.InverseKinematics(target, dh);
// CRX cobot with dual solutions
var dhCrx = DhParameters.FromArmKinematicModel(ArmKinematicModels.CRX10iAL);
var targetCrx = new CartesianPosition { X = 400, Y = 250, Z = 650, W = 0, P = 90, R = 0 };
JointsPosition[] crxSolutions = CrxKinematicsUtils.InverseKinematics(
targetCrx, dhCrx,
includeDuals: true
);
}
}
Click to see the full code

Solve inverse kinematics (IK) for a CRX cobot

The CRX solver uses a closed-form geometric approach and returns all valid joint solutions directly. No seed position is required. Pass includeDuals: true (C#) or include_duals=True (Python) to also include the dual configurations defined by the CRX kinematics.

using UnderAutomation.Fanuc.Common;
using UnderAutomation.Fanuc.Kinematics;
using UnderAutomation.Fanuc.Kinematics.Crx;
public class KinematicsIK
{
static void Main()
{
// OPW industrial robot
var dh = DhParameters.FromArmKinematicModel(ArmKinematicModels.ARCMate120iD);
var target = new CartesianPosition { X = 800, Y = 0, Z = 450, W = 180, P = 0, R = 90 };
JointsPosition[] solutions = KinematicsUtils.InverseKinematics(target, dh);
// CRX cobot with dual solutions
var dhCrx = DhParameters.FromArmKinematicModel(ArmKinematicModels.CRX10iAL);
var targetCrx = new CartesianPosition { X = 400, Y = 250, Z = 650, W = 0, P = 90, R = 0 };
JointsPosition[] crxSolutions = CrxKinematicsUtils.InverseKinematics(
targetCrx, dhCrx,
includeDuals: true
);
}
}

Build DH parameters from multiple sources

  • Built-in catalog: DhParameters.FromArmKinematicModel(ArmKinematicModels model) gives the geometry of many Fanuc arms and cobots.
  • ROBOGUIDE library: DhParameters.FromDefFile(path) parses robot definitions in ProgramData/FANUC/ROBOGUIDE/Robot Library.
  • Controller variables: DhParameters.FromSymotnFile and DhParameters.FromMrrGrp convert live $MRR_GRP or symotn.va data to reusable DH structures.
  • OPW data: DhParameters.FromOpwParameters maps OPW parameters (meters) to Fanuc-style DH while keeping the kinematics category consistent.

Tips

  • Offline: the solvers need no controller and no connection.
  • Pose normalization: OpwKinematicsUtils.InverseKinematics normalizes angles to (-180, 180] to match Fanuc expectations.
  • CRX dual solutions: Pass includeDuals: true to CrxKinematicsUtils.InverseKinematics to include the additional configurations defined by the CRX kinematics model.
  • Matrix helpers: KinematicsUtils.Mul multiplies 2D matrices if you need to compose transforms manually.

Kinematics on the controller

With a connection, the controller can compute the kinematics, without DH parameters. The controller keeps the joint and the Cartesian form of every position register. Write a position in one form with SNPX, then read the same register back to get the other form.

Forward kinematics using SNPX position registers

Write joint angles and read back the Cartesian pose:

FanucRobot _robot = new FanucRobot();
_robot.Connect("192.168.0.1");
// Forward kinematics via SNPX: joints → Cartesian
JointsPosition jointsPosition = new JointsPosition(10, 12, 50, 20, 12, 16);
_robot.Snpx.PositionRegisters.Write(1, jointsPosition);
CartesianPosition cartesianPosition = _robot.Snpx.PositionRegisters.Read(1).CartesianPosition;
// Inverse kinematics via SNPX: Cartesian → joints
CartesianPosition targetPosition = new CartesianPosition() { X = 100, Y = 100, Z = 100 };
targetPosition.Configuration.WristFlip = WristFlip.Flip;
targetPosition.Configuration.ArmUpDown = ArmUpDown.Down;
targetPosition.Configuration.ArmLeftRight = ArmLeftRight.Left;
_robot.Snpx.PositionRegisters.Write(1, targetPosition);
JointsPosition resultJoints = _robot.Snpx.PositionRegisters.Read(1).JointsPosition;
}
}
Click to see the full code

Inverse kinematics using SNPX position registers

Write a Cartesian pose and read back the joint angles. There is only one solution, because the Cartesian position contains the configuration.

Demonstration

Online 3D tool

fanuc-kinematics.underautomation.com is a 3D page to try the forward and inverse kinematics of the FANUC arms and cobots.

Fanuc Robot Simulator

Demo application

Everything on this page can be tried without writing code, in the Forward & Invert Kinematics page of the demo application.

Forward & Invert Kinematics page of the Fanuc SDK demo application

The demo application is open source. The C# source of this page is KinematicsControl.cs.

Reference

Class
KinematicsUtils
C#Python

Kinematics utilities

MemberTypeDescription
ForwardKinematics(double[], DhParameters)
Method
static
CartesianPosition
Compute FK for given joint angles (rad) and DH parameters
ForwardKinematics(JointsPosition, DhParameters)
Method
static
CartesianPosition
Compute FK for given joint angles (deg) and DH parameters
InverseKinematics(CartesianPosition, DhParameters)
Method
static
JointsPosition[]
Compute all inverse kinematics solutions for a desired end effector pose.
  • position : Target Cartesian position.
  • parameters : DH parameters of the robot.
Mul(double[,], double[,])
Method
static
double[,]
Multiply two 4x4 homogeneous transformation matrices.
  • A : Left matrix.
  • B : Right matrix.
Class
DhParameters
C#Python

Denavit-Hartenberg parameters for a 6-axis robot arm.

MemberTypeDescription
DhParameters()
Constructor
Initializes a new empty instance of DhParameters.
DhParameters(double, double, double, double, double, double)
Constructor
Initializes a new instance of DhParameters with the specified values.
  • d4 : DH parameter D4 (mm).
  • d5 : DH parameter D5 (mm).
  • d6 : DH parameter D6 (mm).
  • a1 : DH parameter A1 (mm).
  • a2 : DH parameter A2 (mm).
  • a3 : DH parameter A3 (mm).
DhParameters(IDhParameters)
Constructor
Initializes a new instance of DhParameters by copying from an existing IDhParameters.
  • parameters : The source parameters to copy.
A1
Property
double
DH parameter A1 (mm).
A2
Property
double
DH parameter A2 (mm).
A3
Property
double
DH parameter A3 (mm).
D4
Property
double
DH parameter D4 (mm).
D5
Property
double
DH parameter D5 (mm).
D6
Property
double
DH parameter D6 (mm).
KinematicsCategory
Property
read only
KinematicsCategory
Gets the kinematics category determined from the DH parameter values.
Tag
Field
object
User-defined tag for associating additional data with this instance.
Equals(object)
Method
bool
FromArmKinematicModel(string)
Method
static
DhParameters
Returns DH parameters from a known Arm Kinematic Model name. Returns null if not found in enum ArmKinematicModels.
FromArmKinematicModel(ArmKinematicModels)
Method
static
DhParameters
Returns DH parameters from a known Arm Kinematic Model.
FromDefFile(string)
Method
static
DhParameters[]
Loads DH parameters of each robots described in a ROBOGUIDE definition file (*.def). By default, this file is located in "C:\ProgramData\FANUC\ROBOGUIDE\Robot Library".
FromDefFile(XDocument)
Method
static
DhParameters[]
Loads DH parameters of each robots described in a ROBOGUIDE definition file (*.def). By default, this file is located in "C:\ProgramData\FANUC\ROBOGUIDE\Robot Library".
FromMrrGrp(MrrGrpVariableType)
Method
static
DhParameters
Loads DH parameters from parsed variable $MRR_GRP located in symotn.va.
FromOpwParameters(double, double, double, double, double)
Method
static
DhParameters
Creates DH parameters from OPW parameters (in meters) C1 and B are ignored because B is always 0 and C1 is not used in the DH representation.
  • a1 : OPW A1 parameter in meters
  • a2 : OPW A2 parameter in meters
  • c2 : OPW C2 parameter in meters
  • c3 : OPW C3 parameter in meters
  • c4 : OPW C4 parameter in meters
FromSymotnFile(SymotnFile)
Method
static
DhParameters[]
Loads DH parameters of each group from a parsed symotn.va file.
GetHashCode()
Method
int
ToString()
Method
string
Enum
KinematicsCategory
C#Python

Category of kinematics model for a robot arm.

NameValueDescription
Crx
1
CRX collaborative robot kinematics.
Invalid
0
Invalid or unsupported kinematics configuration.
Opw
2
OPW (ortho-parallel wrist) kinematics for standard industrial robots.
Interface
IDhParameters
C#Python

Interface defining the Denavit-Hartenberg parameters for a 6-axis robot arm.

MemberTypeDescription
A1
Property
read only
double
DH parameter A1 (mm).
A2
Property
read only
double
DH parameter A2 (mm).
A3
Property
read only
double
DH parameter A3 (mm).
D4
Property
read only
double
DH parameter D4 (mm).
D5
Property
read only
double
DH parameter D5 (mm).
D6
Property
read only
double
DH parameter D6 (mm).
Class
JointsPosition
C#Python

Joints position in degrees

MemberTypeDescription
JointsPosition()
Constructor
Default constructor
JointsPosition(double, double, double, double, double, double)
Constructor
Constructor with 6 joint values in degrees
JointsPosition(double, double, double, double, double, double, double, double, double)
Constructor
Constructor with 9 joint values in degrees
JointsPosition(double[])
Constructor
Constructor from an array of joint values in degrees
this[int]
Property
double
Gets or sets the joint value at the specified index
J1
Property
double
Joint 1 in degrees
J2
Property
double
Joint 2 in degrees
J3
Property
double
Joint 3 in degrees
J4
Property
double
Joint 4 in degrees
J5
Property
double
Joint 5 in degrees
J6
Property
double
Joint 6 in degrees
J7
Property
double
Joint 7 in degrees
J8
Property
double
Joint 8 in degrees
J9
Property
double
Joint 9 in degrees
Values
Property
read only
double[]
Numeric values for each joints
Equals(object)
Method
bool
GetHashCode()
Method
int
IsNear(JointsPosition, JointsPosition, double)
Method
static
bool
Check if joints position is near to expected joints position with a tolerance value
ToString()
Method
string
Class
CartesianPositioninherits XYZWPRPosition
C#Python

Fanuc cartesian position and rotations

MemberTypeDescription
CartesianPosition()
Constructor
Default constructor
CartesianPosition(double, double, double, double, double, double)
Constructor
Constructor with position and rotations
CartesianPosition(double, double, double, double, double, double, Configuration)
Constructor
Constructor with position, rotations and configuration
CartesianPosition(CartesianPosition)
Constructor
Copy constructor
CartesianPosition(XYZPosition, double, double, double)
Constructor
Constructor from an XYZ position with rotations
Configuration
Property
Configuration
Position configuration
Equals(object)
Method
bool
FromHomogeneousMatrix(double[,])
Method
static
CartesianPosition
Create a CartesianPosition with unknow configuration from a homogeneous rotation and translation 4x4 matrix
  • R : Homogeneous 4x4 matrix
GetHashCode()
Method
int
IsNear(CartesianPosition, CartesianPosition, double, double)
Method
static
bool
Check if two Cartesian positions are near each other within specified tolerances
NormalizeAngle(double)
Method
static
double
Normalize an angle to the range ]-180, 180]
NormalizeAngles(CartesianPosition)
Method
static
void
Normalize the W, P, R angles to the range ]-180, 180]
ToString()
Method
string

Easily integrate Universal Robots, Fanuc, Yaskawa, ABB or Staubli robots into your .NET, Python, LabVIEW or Matlab applications

UnderAutomation
Contact usLegal

© All rights reserved.