Frames, I/O & status
Manage user frames and tools, read/write I/O, read positions, set speed override, and get controller status via RMI.
RMI provides access to controller status, user frames and tools, digital and generic I/O, position reading, registers, system variables, payload, and TCP speed.
Controller status
GetStatus() returns the full controller state. Use it before Initialize() to verify the controller is ready.
parameters.Rmi.Enable = true;robot.Connect(parameters);// Basic status: servo, TP mode, RMI running, overrideRmiControllerStatusResponse status = robot.Rmi.GetStatus();Console.WriteLine("Servo ready: " + status.ServoReady);Console.WriteLine("TP enabled: " + status.TPEnabled);Console.WriteLine("RMI running: " + status.RmiMotionStatus);Console.WriteLine("Program state: " + status.ProgramStatus);Console.WriteLine("Override: " + status.SpeedOverride + "%");Console.WriteLine("UFrame count: " + status.NumberUFrame);Console.WriteLine("UTool count: " + status.NumberUTool);// Extended status: drive power, control mode, speed clampRmiExtendedControllerStatusResponse ext = robot.Rmi.GetExtendedStatus();Console.WriteLine("Drives on: " + ext.DrivesPowered);Console.WriteLine("In motion: " + ext.InMotion);// Read last controller error (up to 5 at once)RmiControllerErrorTextResponse errors = robot.Rmi.ReadError(count: 3);foreach (string entry in errors.ErrorDataEntries)Console.WriteLine("Error: " + entry);// HOLD stateConsole.WriteLine("In HOLD: " + robot.Rmi.IsInHoldState);robot.Disconnect();}
Admin commands
robot.Connect(parameters);robot.Rmi.Initialize();// Set speed override (1-100 %)robot.Rmi.SetOverride(50);// Pause and resume the motion programrobot.Rmi.Pause();robot.Rmi.Continue();// Reset controller errors and exit the HOLD staterobot.Rmi.Reset();// Resynchronize the sequence ID counterrobot.Rmi.AutoSetNextSequenceId();// Get/set current UFRAME and UTOOL numbersvar ut = robot.Rmi.GetUFrameUTool();System.Console.WriteLine("Frame: " + ut.Frame + ", Tool: " + ut.Tool);robot.Rmi.SetUFrameUTool(uframe: 1, utool: 2);// Abort the RMI_MOVE programrobot.Rmi.Abort();robot.Disconnect();}
Position reading
Read the current robot position and TCP speed. On firmware MajorVersion >= 6, the position reflects actual encoder counts.
parameters.Rmi.Enable = true;robot.Connect(parameters);// Read current Cartesian position.// On MajorVersion >= 6, returns actual encoder position.RmiCartesianPositionResponse cart = robot.Rmi.ReadCartesianPosition();Console.WriteLine($"X={cart.Position.X:F1} Y={cart.Position.Y:F1} Z={cart.Position.Z:F1}");Console.WriteLine($"W={cart.Position.W:F1} P={cart.Position.P:F1} R={cart.Position.R:F1}");Console.WriteLine($"Tool={cart.Position.Tool} Frame={cart.Position.Frame}");Console.WriteLine($"Timestamp={cart.TimeTag}");// Read current joint anglesRmiJointAnglesSampleResponse joints = robot.Rmi.ReadJointAngles();Console.WriteLine($"J1={joints.JointAngle.J1:F2} J2={joints.JointAngle.J2:F2} J3={joints.JointAngle.J3:F2}");Console.WriteLine($"J4={joints.JointAngle.J4:F2} J5={joints.JointAngle.J5:F2} J6={joints.JointAngle.J6:F2}");// Read TCP speed (mm/s)RmiTcpSpeedResponse speed = robot.Rmi.ReadTcpSpeed();Console.WriteLine($"TCP speed={speed.Speed:F2} mm/s");robot.Disconnect();}
User frames and tools
Read and write user frames (UFrame) and tools (UTool):
parameters.Rmi.Enable = true;robot.Connect(parameters);// Read UFRAME 1RmiIndexedFrameResponse uf = robot.Rmi.ReadUFrame(1);Console.WriteLine($"UFrame 1: X={uf.Frame.X:F1} Y={uf.Frame.Y:F1} Z={uf.Frame.Z:F1}");// Write UFRAME 1robot.Rmi.WriteUFrame(1, new XYZWPRPosition { X = 100, Y = 0, Z = 0, W = 0, P = 0, R = 0 });// Read UTOOL 1RmiIndexedFrameResponse ut = robot.Rmi.ReadUTool(1);Console.WriteLine($"UTool 1: X={ut.Frame.X:F1} Y={ut.Frame.Y:F1} Z={ut.Frame.Z:F1}");// Write UTOOL 1robot.Rmi.WriteUTool(1, new XYZWPRPosition { X = 0, Y = 0, Z = 200, W = 0, P = 0, R = 0 });// Get current UFRAME and UTOOL numbersRmiUFrameUToolNumbersResponse current = robot.Rmi.GetUFrameUTool();Console.WriteLine($"Active UFRAME={current.Frame} UTOOL={current.Tool}");// Set the active UFRAME and UTOOLrobot.Rmi.SetUFrameUTool(uframe: 1, utool: 2);robot.Disconnect();}
Digital I/O
parameters.Rmi.Enable = true;robot.Connect(parameters);// Read digital input DI[2]RmiDigitalInputValueResponse din = robot.Rmi.ReadDIN(2);Console.WriteLine($"DI[2] = {din.PortValue}");// Write digital output DO[1]robot.Rmi.WriteDOUT(1, RmiOnOff.ON);robot.Rmi.WriteDOUT(1, RmiOnOff.OFF);robot.Disconnect();}
Generic I/O ports
ReadIOPort and WriteIOPort work with any port type (DI, DO, AI, AO, GO, RO, FLAG, RI, UI, UO):
parameters.Rmi.Enable = true;robot.Connect(parameters);// Read any IO port type: DI, DO, AI, AO, GO, RO, FLAG, RI, UI, UORmiIoPortValueResponse di = robot.Rmi.ReadIOPort(RmiIoPortType.DI, 1);Console.WriteLine($"DI[1] = {di.Value}");RmiIoPortValueResponse ai = robot.Rmi.ReadIOPort(RmiIoPortType.AI, 1);Console.WriteLine($"AI[1] = {ai.Value}");RmiIoPortValueResponse flag = robot.Rmi.ReadIOPort(RmiIoPortType.FLAG, 5);Console.WriteLine($"FLAG[5] = {flag.Value}");// Write AO[1] = 2.5robot.Rmi.WriteIOPort(RmiIoPortType.AO, 1, 2.5);// Write GO[1] = 7robot.Rmi.WriteIOPort(RmiIoPortType.GO, 1, 7);// Write FLAG[5] = 1robot.Rmi.WriteIOPort(RmiIoPortType.FLAG, 5, 1);robot.Disconnect();}
Position registers
parameters.Rmi.Enable = true;robot.Connect(parameters);// Read position register PR[1]RmiPositionRegisterDataResponse pr = robot.Rmi.ReadPositionRegister(1);Console.WriteLine($"PR[1]: X={pr.CartesianPosition.X:F1} Y={pr.CartesianPosition.Y:F1} Z={pr.CartesianPosition.Z:F1}");// Write position register PR[2] with a Cartesian valuerobot.Rmi.WritePositionRegisterCartesian(2,new CartesianPositionWithUserFrame(500, 200, 300, 0, 90, 0, tool: 1, frame: 0));robot.Disconnect();}
Numeric registers and system variables
parameters.Rmi.Enable = true;robot.Connect(parameters);// Read numeric register R[1]RmiNumericRegisterValueResponse r1 = robot.Rmi.ReadNumericRegister(1);Console.WriteLine($"R[1] IsInteger={r1.Value.IsInteger} Value={r1.Value.RealValue}");// Write integer value to R[1]robot.Rmi.WriteNumericRegisterAsInteger(1, 42);// Write float value to R[2]robot.Rmi.WriteNumericRegisterAsDouble(2, 3.14);// Read system variable $MCR.$GENOVERRIDE (include the leading $)RmiVariableValueResponse var = robot.Rmi.ReadVariable("$MCR.$GENOVERRIDE");Console.WriteLine($"Speed override = {var.RealValue}");// Write system variablerobot.Rmi.WriteVariableAsInteger("$MCR.$GENOVERRIDE", 80);robot.Disconnect();}
Payload
Define payload mass, center of gravity, and inertia for a schedule. You can also send a SetPayloadTpInstruction as a motion-sequence instruction.
parameters.Rmi.Enable = true;robot.Connect(parameters);// Define payload for schedule 1: 5 kg, center of gravity offset 0.1 m in Zrobot.Rmi.SetPayloadValue(scheduleNumber: 1,massKg: 5.0f,cgXm: 0f, cgYm: 0f, cgZm: 0.1f);// Include inertia valuesrobot.Rmi.SetPayloadValue(scheduleNumber: 2,massKg: 3.0f,cgXm: 0.05f, cgYm: 0f, cgZm: 0.08f,inertiaXkgm2: 0.002f, inertiaYkgm2: 0.002f, inertiaZkgm2: 0.001f);// Define payload compensationrobot.Rmi.SetPayloadCompensation(scheduleNumber: 1,massKg: 1.0f,cgXm: 0f, cgYm: 0f, cgZm: 0.05f,inertiaXkgm2: 0.001f, inertiaYkgm2: 0.001f, inertiaZkgm2: 0.0005f);// Activate schedule 1 immediately (command, not a TP instruction)robot.Rmi.SetPayloadSchedule(1);robot.Disconnect();}
Position recording
The RMI Position Record menu (UTILITIES on the teach pendant) lets an operator jog the robot to a position and press Record. The controller sends the position back to the connected remote device as a packet. Subscribe to RecordedCartesianPositionReceived or RecordedJointPositionReceived to receive these positions.
The position ID is assigned by the controller and increments with each recorded position. Use it to correlate incoming positions with your application data.
parameters.Rmi.Enable = true;robot.Connect(parameters);// Subscribe before connecting to the RMI session.// The controller fires these events when the operator uses the// RMI Position Record menu on the teach pendant (UTILITIES > RMI Position Record)// and presses the Record key.robot.Rmi.RecordedCartesianPositionReceived += (RmiRecordedCartesianPosition rec) =>{Console.WriteLine($"Recorded Cartesian pos {rec.PositionId}:");Console.WriteLine($" X={rec.Position.X:F1} Y={rec.Position.Y:F1} Z={rec.Position.Z:F1}");Console.WriteLine($" W={rec.Position.W:F1} P={rec.Position.P:F1} R={rec.Position.R:F1}");Console.WriteLine($" Tool={rec.Position.Tool} Frame={rec.Position.Frame}");};robot.Rmi.RecordedJointPositionReceived += (RmiRecordedJointPosition rec) =>{Console.WriteLine($"Recorded joint pos {rec.PositionId}:");Console.WriteLine($" J1={rec.Joints.J1:F2} J2={rec.Joints.J2:F2} J3={rec.Joints.J3:F2}");Console.WriteLine($" J4={rec.Joints.J4:F2} J5={rec.Joints.J5:F2} J6={rec.Joints.J6:F2}");};// Keep the application alive while the operator records positionsConsole.WriteLine("Waiting for positions. Press ENTER to exit.");
Complete example
using System;using UnderAutomation.Fanuc;using UnderAutomation.Fanuc.Common;using UnderAutomation.Fanuc.Rmi.Data;using UnderAutomation.Fanuc.Rmi.TpInstructions;public class RmiFramesIo{static void Main(){FanucRobot robot = new FanucRobot();ConnectionParameters parameters = new ConnectionParameters("192.168.0.1");parameters.Rmi.Enable = true;robot.Connect(parameters);Console.WriteLine("Protocol version: " + robot.Rmi.MajorVersion + "." + robot.Rmi.MinorVersion);// Verify the controller is readyvar status = robot.Rmi.GetStatus();if (!status.ServoReady || status.TPEnabled){Console.WriteLine("Controller not ready for RMI.");return;}// Read current position before movingvar pos = robot.Rmi.ReadCartesianPosition();Console.WriteLine($"Start: X={pos.Position.X:F1} Y={pos.Position.Y:F1} Z={pos.Position.Z:F1}");// Read UFrame 1var uf = robot.Rmi.ReadUFrame(1);Console.WriteLine($"UFrame 1 origin: X={uf.Frame.X:F1}");// Read DI[1]var din = robot.Rmi.ReadDIN(1);Console.WriteLine($"DI[1] = {din.PortValue}");// Read R[1]var r1 = robot.Rmi.ReadNumericRegister(1);Console.WriteLine($"R[1] = {r1.Value.RealValue}");// Initialize and send some motionrobot.Rmi.Initialize();robot.Rmi.SetOverride(50);robot.Rmi.SendTpInstruction(new LinearMotionTpInstruction{SpeedType = RmiLinearSpeedType.MmSec,Speed = 100,TermType = RmiTerminationType.Fine,Target = new CartesianPositionWithUserFrame(500, 200, 300, 0, 90, 0, 1, 0)}).WaitForCompletion();// Write DO[1] ONrobot.Rmi.WriteDOUT(1, RmiOnOff.ON);// Read TCP speedvar tcp = robot.Rmi.ReadTcpSpeed();Console.WriteLine($"TCP speed: {tcp.Speed:F1} mm/s");robot.Rmi.Abort();robot.Disconnect();}}
API reference
Status snapshot returned by FRC_GetStatus.
| Member | Type | Description |
|---|---|---|
RmiControllerStatusResponse() Constructor | ||
CheckSequenceId Property read only | bool | Indicates the value of $RMI_CFG.$Chk_seqID, which is the configuration value that determines whether the controller checks valid incremented sequence IDs on incoming instructions. |
NextSequenceId Property | int? | The next valid sequence ID. This key is only valid if the system variable $RMI_CFG.$Chk_seqID = TRUE |
NumberUFrame Property | byte | Number of user frames available in the robot controller |
NumberUTool Property | byte | Number of user tools available in the robot controller |
ProgramStatus Property | TaskStatus | RMI_MOVE program status |
RmiMotionStatus Property | bool | The Remote Motion Interface is running |
ServoReady Property | bool | The robot controller is ready for motion |
SingleStepMode Property | bool | Single step mode |
SpeedOverride Property | byte | The current speed override setting (1–100). |
TPEnabled Property | bool | Teach Pendant Enabled (Switch on position ON) The Remote Motion interface only works when the teach pendant is disabled |
Equals(object) Method | bool | |
GetHashCode() Method | int | |
ToString() Method | string |
Extended controller status returned by FRC_GetExtStatus.
| Member | Type | Description |
|---|---|---|
RmiExtendedControllerStatusResponse() Constructor | ||
ControlMode Property | string | Active control mode string (e.g. "AUTO"), or null when unavailable. |
DrivesPowered Property | bool | Whether the servo drives are powered on. |
ErrorCode Property | string | Last reported error code text, or null when no error is active. |
GenOverride Property | int | General speed override percentage. |
InMotion Property | bool | Whether the robot is currently executing a motion. |
SpeedClampLimit Property | double? | Speed clamp limit in mm/s, or null when not configured. |
ToString() Method | string |
Current UFRAME and UTOOL numbers, optionally scoped to a motion group.
| Member | Type | Description |
|---|---|---|
RmiUFrameUToolNumbersResponse() Constructor | ||
Frame Property | byte | Current user frame number. |
Group Property | byte? | Motion group number, or null when not applicable. |
Tool Property | byte | Current user tool number. |
Equals(object) Method | bool | |
GetHashCode() Method | int | |
ToString() Method | string |
Cartesian frame data paired with an index (UFRAME or UTOOL number).
| Member | Type | Description |
|---|---|---|
RmiIndexedFrameResponse() Constructor | ||
Frame Property | XYZWPRPosition | Frame data. |
Index Property | byte | Index (UFRAME or UTOOL number). |
Equals(object) Method | bool | |
GetHashCode() Method | int | |
ToString() Method | string |
Result of reading a digital input.
| Member | Type | Description |
|---|---|---|
RmiDigitalInputValueResponse() Constructor | ||
PortNumber Property | short | Port number. |
PortValue Property | RmiOnOff | Port value |
Equals(object) Method | bool | |
GetHashCode() Method | int | |
ToString() Method | string |
Result of reading a generic IO port.
| Member | Type | Description |
|---|---|---|
RmiIoPortValueResponse() Constructor | ||
PortNumber Property | int | Port number. |
PortType Property | RmiIoPortType | Port type (DI, DO, AI, AO, GO, etc.). |
Value Property | double | Current port value. |
ToString() Method | string |
Result of reading the current Cartesian position.
| Member | Type | Description |
|---|---|---|
RmiCartesianPositionResponse() Constructor | ||
Position Property | CartesianPositionWithUserFrame | Current TCP position including configuration and active frame/tool numbers. |
Equals(object) Method | bool | |
GetHashCode() Method | int | |
ToString() Method | string |
Result of reading the current joint angles.
| Member | Type | Description |
|---|---|---|
RmiJointAnglesSampleResponse() Constructor | ||
JointAngle Property | JointsPosition | Joint angle set in degrees. |
Equals(object) Method | bool | |
GetHashCode() Method | int | |
ToString() Method | string |
Position register data paired with its register number.
| Member | Type | Description |
|---|---|---|
RmiPositionRegisterDataResponse() Constructor | ||
CartesianPosition Property | CartesianPositionWithUserFrame | Position register value. |
RegisterNumber Property | short | Register number |
Equals(object) Method | bool | |
GetHashCode() Method | int | |
ToString() Method | string |
Result of reading a numeric register.
| Member | Type | Description |
|---|---|---|
RmiNumericRegisterValueResponse() Constructor | ||
RegisterNumber Property | int | Register number. |
Value Property | NumericRegister | Register value. |
ToString() Method | string |
Result of reading a system variable.
| Member | Type | Description |
|---|---|---|
RmiVariableValueResponse() Constructor | ||
IntegerValue Property | int | Gets or sets the value as an integer. Internally stored as a double. |
IsInteger Property | bool | Whether the variable holds a floating-point value. |
Name Property | string | Variable name, including the leading $ character. |
RealValue Property | double | Gets or sets the value as a double-precision floating-point number. |
ToString() Method | string |
Result of reading TCP speed.
| Member | Type | Description |
|---|---|---|
RmiTcpSpeedResponse() Constructor | ||
Speed Property | double | Current tool center point speed in mm/s. |
Equals(object) Method | bool | |
GetHashCode() Method | int | |
ToString() Method | string |
Parameters for defining payload mass, center of gravity, and optionally inertia for a payload schedule. Used by SetPayloadValue(RmiSetPayloadParameters). All positional values are in meters; mass in kg; inertia in kg·m².
| Member | Type | Description |
|---|---|---|
RmiSetPayloadParameters() Constructor | ||
CgXm Property | float | Center-of-gravity X offset in meters. |
CgYm Property | float | Center-of-gravity Y offset in meters. |
CgZm Property | float | Center-of-gravity Z offset in meters. |
Group Property | byte? | Optional motion group number. null uses the active group. |
InertiaXkgm2 Property | float? | Inertia around the X axis in kg·m². null omits this field from the command. |
InertiaYkgm2 Property | float? | Inertia around the Y axis in kg·m². null omits this field from the command. |
InertiaZkgm2 Property | float? | Inertia around the Z axis in kg·m². null omits this field from the command. |
MassKg Property | float | Payload mass in kilograms. |
ScheduleNumber Property | byte | Payload schedule number to configure. |
Parameters for defining payload compensation for a payload schedule. Used by SetPayloadCompensation(RmiSetPayloadCompensationParameters). All positional values are in meters; mass in kg; inertia in kg·m².
| Member | Type | Description |
|---|---|---|
RmiSetPayloadCompensationParameters() Constructor | ||
CgXm Property | float | Center-of-gravity X offset in meters. |
CgYm Property | float | Center-of-gravity Y offset in meters. |
CgZm Property | float | Center-of-gravity Z offset in meters. |
Group Property | byte? | Optional motion group number. null uses the active group. |
InertiaXkgm2 Property | float | Inertia around the X axis in kg·m². |
InertiaYkgm2 Property | float | Inertia around the Y axis in kg·m². |
InertiaZkgm2 Property | float | Inertia around the Z axis in kg·m². |
MassKg Property | float | Payload mass in kilograms. |
ScheduleNumber Property | byte | Payload schedule number to configure. |
Cartesian position received from the controller via the RMI Position Record menu (TouchUp).
| Member | Type | Description |
|---|---|---|
RmiRecordedCartesianPosition() Constructor | ||
Position Property | CartesianPositionWithUserFrame | Recorded Cartesian position including arm configuration and active frame/tool numbers. |
PositionId Property | ushort | Position identifier assigned by the controller. |
ToString() Method | string |
Joint position received from the controller via the RMI Position Record menu (TouchUp).
| Member | Type | Description |
|---|---|---|
RmiRecordedJointPosition() Constructor | ||
Joints Property | JointsPosition | Recorded joint angles in degrees. |
PositionId Property | ushort | Position identifier assigned by the controller. |
ToString() Method | string |