UnderAutomation
    • ホームページ
  • 製品
    • Universal Robots SDK
    • Fanuc SDK
      • 概要
      • ダウンロード
      • ドキュメント
        • Overview
        • Get started with .NET
        • Get started with Python
        • Get started with LabVIEW
        • Licensing
        • Enable TELNET on your robot
        • Overview of TELNET interface
        • Read and decode files
        • SNPX
        • Inverse and Forward Kinematics
        • Reading & Writing Registers
        • TP editor with breakpoints
        • Move robot with mouse
    • Yaskawa SDK
    • Staubli SDK
    • お見積り・ご注文
    • ライセンス
質問ですか?

[email protected]

お問い合わせ
UnderAutomation
  • ホームページ
  • 製品
      • 概要
      • ダウンロード
      • ドキュメント
      • 概要
      • ダウンロード
      • ドキュメント
      • 概要
      • ダウンロード
      • ドキュメント
      • 概要
      • ダウンロード
      • ドキュメント
  • お見積り・ご注文
  • お問い合わせ
⌘Q
This page is only available in English.
Fanuc SDK documentation
SNPX
Documentation home
Reading & Writing Registers

Inverse and Forward Kinematics

Perform forward and inverse kinematics calculations for FANUC robots and cobots using the UnderAutomation Fanuc SDK. Calculate end-effector positions from joint angles and vice versa from DH parameters.

  • Why this matters for both industrial arms and cobots
  • Typical workflows
    • Run forward kinematics (FK)
    • Solve inverse kinematics (IK) for an OPW robot
    • Solve inverse kinematics (IK) for a CRX cobot with dual solutions
    • Build DH parameters from multiple sources
  • Practical tips
  • Demonstration
    • Core types at a glance

Inverse kinematics (IK) and forward kinematics (FK) let you move between joint space and Cartesian space. FK computes the tool p ose from known joint angles, while IK finds joint angles for a desired pose. The kinematics utilities in the Fanuc SDK are off line helpers: you can evaluate poses and joint solutions without connecting to a controller, making them perfect for simulatio n, path validation, and pre-deployment checks.

Why this matters for both industrial arms and cobots

The SDK ships with two analytical solvers and automatically chooses the right one for you:

  • 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.

When you call KinematicsUtils.InverseKinematics(), it inspects DhParameters.KinematicsCategory:

  • KinematicsCategory.Opw 👉 dispatches to Opw.OpwKinematicsUtils.InverseKinematics (industrial robots).
  • KinematicsCategory.Crx 👉 dispatches to Crx.CrxKinematicsUtils.InverseKinematics (CRX cobots).

That means you can rely on a single entry point and let the SDK route the request appropriately. 🚦

Typical workflows

Run forward kinematics (FK)

using Common;
using Kinematics;
// Load robot geometry (pick from the ArmKinematicModels enum or from a .def file)
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 in controller-friendly format
CartesianPosition pose = KinematicsUtils.ForwardKinematics(jointsDeg, dh);

Solve inverse kinematics (IK) for an OPW robot

using Common;
using Kinematics;
var dh = DhParameters.FromArmKinematicModel(ArmKinematicModels.ARCMate120iD);
// Desired pose in millimeters + WPR degrees
var target = new CartesianPosition { X = 800, Y = 0, Z = 450, W = 180, P = 0, R = 90 };
// Automatically routed to Opw.OpwKinematicsUtils.InverseKinematics
JointsPosition[] solutions = KinematicsUtils.InverseKinematics(target, dh);

Solve inverse kinematics (IK) for a CRX cobot with dual solutions

using Common;
using Kinematics;
var dh = DhParameters.FromArmKinematicModel(ArmKinematicModels.CRX10iAL);
var target = new CartesianPosition { X = 400, Y = 250, Z = 650, W = 0, P = 90, R = 0 };
// includeDuals=true surfaces the mirrored wrist/elbow poses
JointsPosition[] crxSolutions = Crx.CrxKinematicsUtils.InverseKinematics(
target,
dh,
includeDuals: true,
seedJoints: new double[] { 0, -20, 40, 0, 60, 0 }
);

Build DH parameters from multiple sources

  • Built-in catalog: DhParameters.FromArmKinematicModel(ArmKinematicModels model) gives you ready-to-use geometry for 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 d ata to reusable DH structures.
  • OPW data: DhParameters.FromOpwParameters maps OPW parameters (meters) to Fanuc-style DH while keeping the kinematics cat egory consistent.

Practical tips ✨

  • Offline safety: Because all solvers are offline, you can iterate quickly without touching a robot controller.
  • Pose normalization: OpwKinematicsUtils.InverseKinematics normalizes angles to (-180, 180] to match Fanuc expectations.
  • Seeding CRX searches: Pass seedJoints to CrxKinematicsUtils.InverseKinematics to bias solutions near a known posture.
  • Matrix helpers: KinematicsUtils.Mul multiplies 2D matrices if you need to compose transforms manually.

Happy path-planning! 🛠️

Demonstration

You can take a look at the Winforms Desktop project source which implements all these features. I can be downloaded here.

IK FK

Core types at a glance

Members of Kinematics.KinematicsUtils :
public static class KinematicsUtils {
// Compute FK for given joint angles (rad) and DH parameters
public static CartesianPosition ForwardKinematics(double[] jointAnglesRad, DhParameters dhParameters)
// Compute FK for given joint angles (deg) and DH parameters
public static CartesianPosition ForwardKinematics(JointsPosition jointAnglesDeg, DhParameters parameters)
public static JointsPosition[] InverseKinematics(CartesianPosition position, DhParameters parameters)
public static double[,] Mul(double[,] A, double[,] B)
}
Members of Kinematics.DhParameters :
public class DhParameters : IDhParameters {
public DhParameters()
public DhParameters(double d4, double d5, double d6, double a1, double a2, double a3)
public DhParameters(IDhParameters parameters)
public double A1 { get; set; }
public double A2 { get; set; }
public double A3 { get; set; }
public double D4 { get; set; }
public double D5 { get; set; }
public double D6 { get; set; }
// Returns DH parameters from a known Arm Kinematic Model name. Returns null if not found in enum ArmKinematicModels.
public static DhParameters FromArmKinematicModel(string modelName)
// Returns DH parameters from a known Arm Kinematic Model.
public static DhParameters FromArmKinematicModel(ArmKinematicModels model)
// 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".
public static DhParameters[] FromDefFile(string path)
// 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".
public static DhParameters[] FromDefFile(XDocument doc)
// Loads DH parameters from parsed variable $MRR_GRP located in symotn.va.
public static DhParameters FromMrrGrp(MrrGrpVariableType mrrGrp)
// 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.
public static DhParameters FromOpwParameters(double a1, double a2, double c2, double c3, double c4)
// Loads DH parameters of each group from a parsed symotn.va file.
public static DhParameters[] FromSymotnFile(SymotnFile file)
public KinematicsCategory KinematicsCategory { get; }
public object Tag
}
Members of Kinematics.KinematicsCategory :
public enum KinematicsCategory {
Crx = 1
Invalid = 0
Opw = 2
}
Members of Kinematics.IDhParameters :
public interface IDhParameters {
double A1 { get; }
double A2 { get; }
double A3 { get; }
double D4 { get; }
double D5 { get; }
double D6 { get; }
}
Members of Common.JointsPosition :
public class JointsPosition {
public JointsPosition()
public JointsPosition(double j1Deg, double j2Deg, double j3Deg, double j4Deg, double j5Deg, double j6Deg)
public JointsPosition(double j1Deg, double j2Deg, double j3Deg, double j4Deg, double j5Deg, double j6Deg, double j7Deg, double j8Deg, double j9Deg)
public JointsPosition(double[] values)
// Check if joints position is near to expected joints position with a tolerance value
public static bool IsNear(JointsPosition j1, JointsPosition j2, double degreesTolerance)
public double this[int i] { get; set; }
// Joint 1 in degrees
public double J1 { get; set; }
// Joint 2 in degrees
public double J2 { get; set; }
// Joint 3 in degrees
public double J3 { get; set; }
// Joint 4 in degrees
public double J4 { get; set; }
// Joint 5 in degrees
public double J5 { get; set; }
// Joint 6 in degrees
public double J6 { get; set; }
// Joint 7 in degrees
public double J7 { get; set; }
// Joint 8 in degrees
public double J8 { get; set; }
// Joint 9 in degrees
public double J9 { get; set; }
public override string ToString()
// Numeric values for each joints
public double[] Values { get; }
}
Members of Common.CartesianPosition :
public class CartesianPosition : XYZPosition {
// Default constructor
public CartesianPosition()
// Constructor with position and rotations
public CartesianPosition(double x, double y, double z, double w, double p, double r)
public CartesianPosition(double x, double y, double z, double w, double p, double r, Configuration configuration)
public CartesianPosition(CartesianPosition position)
public CartesianPosition(XYZPosition position, double w, double p, double r)
// Position configuration
public Configuration Configuration { get; }
// Create a CartesianPosition with unknow configuration from a homogeneous rotation and translation 4x4 matrix
public static CartesianPosition FromHomogeneousMatrix(double[,] R)
// Check if two Cartesian positions are near each other within specified tolerances
public static bool IsNear(CartesianPosition a, CartesianPosition b, double mmTolerance, double degreesTolerance)
// Normalize an angle to the range ]-180, 180]
public static double NormalizeAngle(double angle)
// Normalize the W, P, R angles to the range ]-180, 180]
public static void NormalizeAngles(CartesianPosition pose)
// P rotation in degrees (Ry)
public double P { get; set; }
// R rotation in degrees (Rz)
public double R { get; set; }
// Convert position to a homogeneous rotation and translation 4x4 matrix
public double[,] ToHomogeneousMatrix()
public override string ToString()
// W rotation in degrees (Rx)
public double W { get; set; }
}
SNPX
Documentation home
Reading & Writing Registers

Universal Robots、Fanuc、Yaskawa、Staubli ロボットを .NET、Python、LabVIEW、または Matlab アプリケーションに簡単に統合

UnderAutomation
お問い合わせLegal
製品
Universal Robots SDKFanuc SDKYaskawa SDKStaubli SDK
enEnglish
frFrançais
deDeutsch
esEspañol
zh中文
ja日本語
ko한국어

© All rights reserved.