SNPX
SNPX is a protocol that allows you to fast read and write data on the robot (registers, variables, alarms, IOs, etc.)
Overview
SNPX (Also known as RobotIF, Robot Interface, or SRTP) allows for quick reading and writing of data on the robot, including:
- Registers (Position, number, and string)
- Variables
- Signals (UI, UO, GI, GO, ...)
- Clear and read alarms
- Read the status programs
TCP port Robot IF Server (by default 60008) should be accessible on your controller.
Differences with official Fanuc Robot Interface
Fanuc also provides a Robot Interface client implementation (FRRJIF.DLL) and here are the main differences:
| UnderAutomation.Fanuc.dll | FRRJIF.DLL | |
|---|---|---|
| Editor | UnderAutomation | Fanuc Ltd. |
| Technology | 100% managed .NET assembly | native ActiveX / COM |
| Portability | No dependencies, the DLL can be moved | Requires installation with a setup program, especially for license management |
| Read/write command execution time | 2 ms | 30 ms |
| Pricing and conditions | Pay once at an affordable price, forever, with no recurring charges No matter :
|
Contact Fanuc to find out your terms of use |
Robot options
To enable SNPX on your robot, you need one of the following option :
- If R650 FRA params is selected (Option "FANUC America Corp." in "Advanced" tab of ROBOGUIDE "Worcell creation wizard - Step 7 Robot options"), R553 "HMI Device SNPX" is needed.
- If R651 FRL params is selected (Option "FANUC Ltd." in this "Advanced" tab), no option is needed.
Performances
SNPX is a fast protocol, allowing you to read and write data in less than 2 ms.
Benchmarks show that regardless of the amount of data transported in a command, it takes the same amount of time to execute. For example, you can read 80 position registers or write a variable in a few milliseconds.
This protocol is obviously not real-time or deterministic; execution time depends on the CPU load of your robot controller, network load, and computer performance.
When used on a robot simulated with ROBOGUIDE, execution times of less than 1 ms can even be achieved.
Features
Read current position
Here's how to read the current position of the main robot arm or another group driven by the controller.
Note: The current position is that of the current tool.
World current position
Method CurrentPosition.ReadWorldPosition returns the current position of the robot in the world coordinate system.
using UnderAutomation.Fanuc;using UnderAutomation.Fanuc.Common;public class SnpxCurrentWorldPosition{static void Main(){// Create a new Fanuc robot instanceFanucRobot robot = new FanucRobot();// Set connection parametersConnectionParameters parameters = new ConnectionParameters("192.168.0.1");parameters.Snpx.Enable = true;// Connect to the robotrobot.Connect(parameters);/**/// Read a current world positionPosition worldPosition = robot.Snpx.CurrentPosition.ReadWorldPosition();// Access the Cartesian positiondouble x = worldPosition.CartesianPosition.X;// Access the user tool at this cartesian positionshort usertTool = worldPosition.UserTool;// Access the joint positionsdouble j1 = worldPosition.JointsPosition.J1;// Read a current world position of group 2Position worldPositionG2 = robot.Snpx.CurrentPosition.ReadWorldPosition(2);/**/}}
User frame current position
Method CurrentPosition.ReadUserFramePosition returns the current position of the robot in the specified user frame.
Note: if you use user frame 15, the selected user frame in the pendant is used.
using UnderAutomation.Fanuc;using UnderAutomation.Fanuc.Common;public class SnpxCurrentUserFramePosition{static void Main(){// Create a new Fanuc robot instanceFanucRobot robot = new FanucRobot();// Set connection parametersConnectionParameters parameters = new ConnectionParameters("192.168.0.1");parameters.Snpx.Enable = true;// Connect to the robotrobot.Connect(parameters);/**/// Read user frame 2 positionPosition userFrame = robot.Snpx.CurrentPosition.ReadUserFramePosition(1);// Access the Cartesian positiondouble x = userFrame.CartesianPosition.X;// Access the user tool at this cartesian positionshort usertTool = userFrame.UserTool;// Access the user frame idshort usertFrame = userFrame.UserFrame;// Access the joint positionsdouble j1 = userFrame.JointsPosition.J1;// Read a current world position of group 2Position userFrameG2 = robot.Snpx.CurrentPosition.ReadWorldPosition(2);/**/}}
Read/write IOs, registers and Variables
You can read and write position registers, numeric registers, string registers, and system variables.
Intermediate objects (NumericRegisters, PositionRegisters, ..., SDI, SO, ..., PositionSystemVariables, ...) contain Read and Write methods that take the ID or name of the data to be read or written as a parameter.
Note 1: For position-type objects, two additional methods are available to specifically write the position in joint or Cartesian coordinates.
Note 2: you can read and write Karel program variables by using the variable name $[KarelProgram]KarelVariable.
using UnderAutomation.Fanuc;using UnderAutomation.Fanuc.Common;public class Snpx{static void Main(){// Create a new Fanuc robot instanceFanucRobot robot = new FanucRobot();// Set connection parametersConnectionParameters parameters = new ConnectionParameters("192.168.0.1");parameters.Snpx.Enable = true;// Connect to the robotrobot.Connect(parameters);/**/// Read a registerPosition posReg1 = robot.Snpx.PositionRegisters.Read(1);float numReg5 = robot.Snpx.NumericRegisters.Read(5);string strReg10 = robot.Snpx.StringRegisters.Read(10);// Write a registerposReg1.CartesianPosition.X = 100;robot.Snpx.PositionRegisters.Write(1, posReg1);robot.Snpx.NumericRegisters.Write(2, 123.45f);robot.Snpx.StringRegisters.Write(3, "Hello, world!");// Read a variableint rmtMaster = robot.Snpx.IntegerSystemVariables.Read("$RMT_MASTER");string lastAlm = robot.Snpx.StringSystemVariables.Read("$ALM_IF.$LAST_ALM");Position cellFloor = robot.Snpx.PositionSystemVariables.Read("$CELL_FLOOR");// Write a system variablerobot.Snpx.IntegerSystemVariables.Write("$RMT_MASTER", 1);robot.Snpx.StringSystemVariables.Write("$ALM_IF.$LAST_ALM", "No alarms");robot.Snpx.PositionSystemVariables.Write("$CELL_FLOOR", cellFloor);// Write a Karel program variablerobot.Snpx.IntegerSystemVariables.Write("$[KarelProgram]KarelVariable", 1);// Read and Write I/O (SDI,SDO,RDI,RDO,UI,UO,SI,SO,WI,WO,WSI,PMC_K,PMC_R)robot.Snpx.RDO.Write(1, true);ushort ai5 = robot.Snpx.AI.Read(5);// Read and Write analogs (AI,AO,GI,GO,PMC_D)robot.Snpx.AO.Write(2, 5);ushort ao3 = robot.Snpx.AO.Read(3);// Clear alarmsrobot.Snpx.ClearAlarms();/**/}}
Read in batch
To improve the read speed of a group of registers or variables, you can create a custom assignment to read this set in a single command rather than one read command per register.
For each type of register or variable, a CreateBatchAssignment method allows you to create this custom assignment by specifying the list of variables or registers to read, or the range of data to read (start index and size).
Then, a Read() method on the returned object triggers the batch reading of this data.
// Create a batch read assignmentprivate NumericRegistersBatchAssignment _NumericRegistersBatchAssignment;public void Setup(){_NumericRegistersBatchAssignment = _robot.Snpx.NumericRegisters.CreateBatchAssignment(NumericRegisterStartIndex, BlockSize);}public void ReadNumericRegisters(){float[] values = _NumericRegistersBatchAssignment.Read();}
Acknowledge alarms
You can acknowledge alarms by using the ClearAlarms method.
Check if SNPX is available
By FTP, you can check if SNPX is available on the robot controller by checking the installed features.
// Get all installed featuresFeatures features = _robot.Ftp.GetSummaryDiagnostic().Features;// Check if SNPX is availablebool isSnpxAvailable = features.HasSnpx;
Demonstration
You can take a look at the Winforms Desktop project source which implements all these features. I can be downloaded here.

API reference
Snpx Client
Members of Snpx.SnpxClient :public class SnpxClient : SnpxClientBase {public SnpxClient()public void Connect(string ip, int port = 60008)}
public class SnpxClientBase {// Analog Inputspublic NumericIO AI { get; }// Analog Outputspublic NumericIO AO { get; }// Current active alarmspublic AlarmAccess ActiveAlarm { get; }// Alarm historypublic AlarmAccess AlarmHistory { get; }// Clear all active alarmspublic void ClearAlarms()// Clear all assignmentspublic void ClearAssignments()protected void ConnectInternal(string ip, int port = 60008)public bool Connected { get; }// Current position in world or user framepublic CurrentPosition CurrentPosition { get; }// List of all digital signal accessors (SDI, SDO, RDI, RDO, ...)public DigitalSignals[] DigitalSignals { get; }// Disconnect from the robotpublic void Disconnect()// Group Inputspublic NumericIO GI { get; }// Group Outputspublic NumericIO GO { get; }public Assignment[] GetAssignments()// Integer variablespublic IntegerSystemVariables IntegerSystemVariables { get; }public string Ip { get; }// List of all Numeric IOs accessors (GI, GO, AI, AO, ...)public NumericIO[] NumericIOs { get; }// Number registerspublic NumericRegisters NumericRegisters { get; }// Programmable Machine Controller Datapublic NumericIO PMC_D { get; }// Programmable Machine Controller Constantspublic DigitalSignals PMC_K { get; }// Programmable Machine Controller Relayspublic DigitalSignals PMC_R { get; }// Position registerspublic PositionRegisters PositionRegisters { get; }// Position variablespublic PositionSystemVariables PositionSystemVariables { get; }// Remote Digital Inputspublic DigitalSignals RDI { get; }// Remote Digital Outputspublic DigitalSignals RDO { get; }// Real variablespublic RealSystemVariables RealSystemVariables { get; }// Safety Digital Inputspublic DigitalSignals SDI { get; }// Safety Digital Outputspublic DigitalSignals SDO { get; }// System Inputspublic DigitalSignals SI { get; }// System Outputspublic DigitalSignals SO { get; }// Set boolean variable without assignmentspublic void SetVariable(string name, bool value)// Set double variable without assignmentspublic void SetVariable(string name, double value)// Set integer variable without assignmentspublic void SetVariable(string name, int value)// Set string variable without assignmentspublic void SetVariable(string name, string value)// String registerspublic StringRegisters StringRegisters { get; }// String variablespublic StringSystemVariables StringSystemVariables { get; }// User Inputspublic DigitalSignals UI { get; }// User Outputspublic DigitalSignals UO { get; }// Weld Inputspublic DigitalSignals WI { get; }// Weld Outputspublic DigitalSignals WO { get; }// Weld System Inputspublic DigitalSignals WSI { get; }}
Inputs and Outputs
Members of Snpx.Internal.DigitalSignals :public class DigitalSignals : SnpxElements<bool, int> {public override bool Read(int index)public bool[] Read(int firstIndex, ushort count)public SegmentName SegmentName { get; }public SegmentOffset SegmentOffset { get; }public SegmentSelector SegmentSelector { get; }public void Write(int index, bool value)public void Write(int firstIndex, bool[] values)}
public class NumericIO : SnpxElements<ushort, int> {public override ushort Read(int index)public ushort[] Read(int firstIndex, ushort count)public SegmentName SegmentName { get; }public SegmentOffset SegmentOffset { get; }public SegmentSelector SegmentSelector { get; }public void Write(int index, ushort value)public void Write(int firstIndex, ushort[] values)}
Registers
Members of Snpx.Internal.NumericRegisters :public class NumericRegisters : SnpxWritableAssignableElements<float, int, NumericRegistersBatchAssignment> {protected override int AssignmentSize { get; }public NumericRegistersBatchAssignment CreateBatchAssignment(int startIndex, int count)protected override string GetAssignmentName(int index)protected override string GetAssignmentTarget(int index)protected override float ReadFromClient(int offset)protected override void WriteInClient(int offset, float value)}
public class PositionRegisters : SnpxWritableAssignableElements<Position, int, PositionRegistersBatchAssignment> {protected override int AssignmentSize { get; }public PositionRegistersBatchAssignment CreateBatchAssignment(int startIndex, int count)protected override string GetAssignmentName(int index)protected override string GetAssignmentTarget(int index)protected override Position ReadFromClient(int offset)public void Write(int index, CartesianPosition cartesianPosition)public void Write(int index, ExtendedCartesianPosition extendedCartesianPosition)public void Write(int index, JointsPosition jointsPosition)protected override void WriteInClient(int offset, Position value)}
Position
Members of Common.Position :public class Position {public Position()public Position(short userFrame, short userTool, JointsPosition jointsPosition, ExtendedCartesianPosition cartesianPosition)public ExtendedCartesianPosition CartesianPosition { get; set; }public JointsPosition JointsPosition { get; set; }public short UserFrame { get; set; }public short UserTool { get; set; }}
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 valuepublic static bool IsNear(JointsPosition j1, JointsPosition j2, double degreesTolerance)public double this[int i] { get; set; }// Joint 1 in degreespublic double J1 { get; set; }// Joint 2 in degreespublic double J2 { get; set; }// Joint 3 in degreespublic double J3 { get; set; }// Joint 4 in degreespublic double J4 { get; set; }// Joint 5 in degreespublic double J5 { get; set; }// Joint 6 in degreespublic double J6 { get; set; }// Joint 7 in degreespublic double J7 { get; set; }// Joint 8 in degreespublic double J8 { get; set; }// Joint 9 in degreespublic double J9 { get; set; }public override string ToString()// Numeric values for each jointspublic double[] Values { get; }}
public class ExtendedCartesianPosition : CartesianPosition {public ExtendedCartesianPosition()public ExtendedCartesianPosition(double x, double y, double z, double w, double p, double r, double e1, double e2, double e3)public double E1 { get; set; }public double E2 { get; set; }public double E3 { get; set; }}
public class CartesianPosition : XYZPosition {// Default constructorpublic CartesianPosition()// Constructor with position and rotationspublic 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 configurationpublic Configuration Configuration { get; }// Create a CartesianPosition with unknow configuration from a homogeneous rotation and translation 4x4 matrixpublic static CartesianPosition FromHomogeneousMatrix(double[,] R)// Check if two Cartesian positions are near each other within specified tolerancespublic 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 matrixpublic double[,] ToHomogeneousMatrix()public override string ToString()// W rotation in degrees (Rx)public double W { get; set; }}
public class XYZPosition {public XYZPosition()public XYZPosition(double x, double y, double z)public override string ToString()// X coordinate in millimeterspublic double X { get; set; }// Y coordinate in millimeterspublic double Y { get; set; }// Z coordinate in millimeterspublic double Z { get; set; }}
Variables
Members of Snpx.Internal.PositionSystemVariables :public class PositionSystemVariables : SnpxWritableAssignableElements<Position, string, PositionSystemVariablesBatchAssignment> {protected override int AssignmentSize { get; }protected override string GetAssignmentName(string index)protected override string GetAssignmentTarget(string index)protected override Position ReadFromClient(int offset)public void Write(string variable, CartesianPosition cartesianPosition)public void Write(string variable, ExtendedCartesianPosition extendedCartesianPosition)public void Write(string variable, JointsPosition jointsPosition)protected override void WriteInClient(int offset, Position value)}
public class StringRegisters : SnpxWritableAssignableElements<string, int, StringRegistersBatchAssignment> {protected override int AssignmentSize { get; }public StringRegistersBatchAssignment CreateBatchAssignment(int startIndex, int count)protected override string GetAssignmentName(int index)protected override string GetAssignmentTarget(int index)protected override string ReadFromClient(int offset)protected override void WriteInClient(int offset, string value)}
public class StringSystemVariables : SnpxWritableAssignableElements<string, string, StringSystemVariablesBatchAssignment> {protected override int AssignmentSize { get; }protected override string GetAssignmentName(string index)protected override string GetAssignmentTarget(string index)protected override string ReadFromClient(int offset)protected override void WriteInClient(int offset, string value)}