UnderAutomation
Eine Frage?

[email protected]

Kontakt
UnderAutomation
⌘Q
Fanuc SDK documentation
Motion commands
Documentation home

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.

// Basic status: servo, TP mode, RMI running, override
RmiControllerStatusResponse 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 clamp
RmiExtendedControllerStatusResponse 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 state
Console.WriteLine("In HOLD: " + robot.Rmi.IsInHoldState);

Admin commands

// Set speed override (1-100 %)
robot.Rmi.SetOverride(50);
// Pause and resume the motion program
robot.Rmi.Pause();
robot.Rmi.Continue();
// Reset controller errors and exit the HOLD state
robot.Rmi.Reset();
// Resynchronize the sequence ID counter
robot.Rmi.AutoSetNextSequenceId();
// Get/set current UFRAME and UTOOL numbers
var ut = robot.Rmi.GetUFrameUTool();
System.Console.WriteLine("Frame: " + ut.Frame + ", Tool: " + ut.Tool);
robot.Rmi.SetUFrameUTool(uframe: 1, utool: 2);
// Abort the RMI_MOVE program
robot.Rmi.Abort();

Position reading

Read the current robot position and TCP speed. On firmware MajorVersion >= 6, the position reflects actual encoder counts.

// 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 angles
RmiJointAnglesSampleResponse 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");

User frames and tools

Read and write user frames (UFrame) and tools (UTool):

// Read UFRAME 1
RmiIndexedFrameResponse 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 1
robot.Rmi.WriteUFrame(1, new XYZWPRPosition { X = 100, Y = 0, Z = 0, W = 0, P = 0, R = 0 });
// Read UTOOL 1
RmiIndexedFrameResponse 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 1
robot.Rmi.WriteUTool(1, new XYZWPRPosition { X = 0, Y = 0, Z = 200, W = 0, P = 0, R = 0 });
// Get current UFRAME and UTOOL numbers
RmiUFrameUToolNumbersResponse current = robot.Rmi.GetUFrameUTool();
Console.WriteLine($"Active UFRAME={current.Frame} UTOOL={current.Tool}");
// Set the active UFRAME and UTOOL
robot.Rmi.SetUFrameUTool(uframe: 1, utool: 2);

Digital I/O

// 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);

Generic I/O ports

ReadIOPort and WriteIOPort work with any port type (DI, DO, AI, AO, GO, RO, FLAG, RI, UI, UO):

// Read any IO port type: DI, DO, AI, AO, GO, RO, FLAG, RI, UI, UO
RmiIoPortValueResponse 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.5
robot.Rmi.WriteIOPort(RmiIoPortType.AO, 1, 2.5);
// Write GO[1] = 7
robot.Rmi.WriteIOPort(RmiIoPortType.GO, 1, 7);
// Write FLAG[5] = 1
robot.Rmi.WriteIOPort(RmiIoPortType.FLAG, 5, 1);

Position registers

// 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 value
robot.Rmi.WritePositionRegisterCartesian(2,
new CartesianPositionWithUserFrame(500, 200, 300, 0, 90, 0, tool: 1, frame: 0));

Numeric registers and system variables

// 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 variable
robot.Rmi.WriteVariableAsInteger("$MCR.$GENOVERRIDE", 80);

Payload

Define payload mass, center of gravity, and inertia for a schedule. You can also send a SetPayloadTpInstruction as a motion-sequence instruction.

// Define payload for schedule 1: 5 kg, center of gravity offset 0.1 m in Z
robot.Rmi.SetPayloadValue(
scheduleNumber: 1,
massKg: 5.0f,
cgXm: 0f, cgYm: 0f, cgZm: 0.1f);
// Include inertia values
robot.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 compensation
robot.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);

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.

// 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}");
};

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 ready
var status = robot.Rmi.GetStatus();
if (!status.ServoReady || status.TPEnabled)
{
Console.WriteLine("Controller not ready for RMI.");
return;
}
// Read current position before moving
var pos = robot.Rmi.ReadCartesianPosition();
Console.WriteLine($"Start: X={pos.Position.X:F1} Y={pos.Position.Y:F1} Z={pos.Position.Z:F1}");
// Read UFrame 1
var 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 motion
robot.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] ON
robot.Rmi.WriteDOUT(1, RmiOnOff.ON);
// Read TCP speed
var tcp = robot.Rmi.ReadTcpSpeed();
Console.WriteLine($"TCP speed: {tcp.Speed:F1} mm/s");
robot.Rmi.Abort();
robot.Disconnect();
}
}

API reference

Members of Rmi.Data.RmiControllerStatusResponse :
public class RmiControllerStatusResponse : RmiResponseBase {
public RmiControllerStatusResponse()
// 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.
public bool CheckSequenceId { get; }
public override bool Equals(object obj)
public override int GetHashCode()
// The next valid sequence ID. This key is only valid if the system variable $RMI_CFG.$Chk_seqID = TRUE
public int? NextSequenceId { get; set; }
// Number of user frames available in the robot controller
public byte NumberUFrame { get; set; }
// Number of user tools available in the robot controller
public byte NumberUTool { get; set; }
// RMI_MOVE program status
public TaskStatus ProgramStatus { get; set; }
// The Remote Motion Interface is running
public bool RmiMotionStatus { get; set; }
// The robot controller is ready for motion
public bool ServoReady { get; set; }
// Single step mode
public bool SingleStepMode { get; set; }
// The current speed override setting (1–100).
public byte SpeedOverride { get; set; }
// Teach Pendant Enabled (Switch on position ON) The Remote Motion interface only works when the teach pendant is disabled
public bool TPEnabled { get; set; }
public override string ToString()
}
Members of Rmi.Data.RmiExtendedControllerStatusResponse :
public class RmiExtendedControllerStatusResponse : RmiResponseBase {
public RmiExtendedControllerStatusResponse()
// Active control mode string (e.g. "AUTO"), or null when unavailable.
public string ControlMode { get; set; }
// Whether the servo drives are powered on.
public bool DrivesPowered { get; set; }
// Last reported error code text, or null when no error is active.
public string ErrorCode { get; set; }
// General speed override percentage.
public int GenOverride { get; set; }
// Whether the robot is currently executing a motion.
public bool InMotion { get; set; }
// Speed clamp limit in mm/s, or null when not configured.
public double? SpeedClampLimit { get; set; }
public override string ToString()
}
Members of Rmi.Data.RmiUFrameUToolNumbersResponse :
public class RmiUFrameUToolNumbersResponse : RmiResponseBase {
public RmiUFrameUToolNumbersResponse()
public override bool Equals(object obj)
// Current user frame number.
public byte Frame { get; set; }
public override int GetHashCode()
// Motion group number, or null when not applicable.
public byte? Group { get; set; }
public override string ToString()
// Current user tool number.
public byte Tool { get; set; }
}
Members of Rmi.Data.RmiIndexedFrameResponse :
public class RmiIndexedFrameResponse : RmiResponseBase {
public RmiIndexedFrameResponse()
public override bool Equals(object obj)
// Frame data.
public XYZWPRPosition Frame { get; set; }
public override int GetHashCode()
// Index (UFRAME or UTOOL number).
public byte Index { get; set; }
public override string ToString()
}
Members of Rmi.Data.RmiDigitalInputValueResponse :
public class RmiDigitalInputValueResponse : RmiResponseBase {
public RmiDigitalInputValueResponse()
public override bool Equals(object obj)
public override int GetHashCode()
// Port number.
public short PortNumber { get; set; }
// Port value
public RmiOnOff PortValue { get; set; }
public override string ToString()
}
Members of Rmi.Data.RmiIoPortValueResponse :
public class RmiIoPortValueResponse : RmiResponseBase {
public RmiIoPortValueResponse()
// Port number.
public int PortNumber { get; set; }
// Port type (DI, DO, AI, AO, GO, etc.).
public RmiIoPortType PortType { get; set; }
public override string ToString()
// Current port value.
public double Value { get; set; }
}
Members of Rmi.Data.RmiCartesianPositionResponse :
public class RmiCartesianPositionResponse : RmiTimedResponse {
public RmiCartesianPositionResponse()
public override bool Equals(object obj)
public override int GetHashCode()
// Current TCP position including configuration and active frame/tool numbers.
public CartesianPositionWithUserFrame Position { get; set; }
public override string ToString()
}
Members of Rmi.Data.RmiJointAnglesSampleResponse :
public class RmiJointAnglesSampleResponse : RmiTimedResponse {
public RmiJointAnglesSampleResponse()
public override bool Equals(object obj)
public override int GetHashCode()
// Joint angle set in degrees.
public JointsPosition JointAngle { get; set; }
public override string ToString()
}
Members of Rmi.Data.RmiPositionRegisterDataResponse :
public class RmiPositionRegisterDataResponse : RmiResponseBase {
public RmiPositionRegisterDataResponse()
// Position register value.
public CartesianPositionWithUserFrame CartesianPosition { get; set; }
public override bool Equals(object obj)
public override int GetHashCode()
// Register number
public short RegisterNumber { get; set; }
public override string ToString()
}
Members of Rmi.Data.RmiNumericRegisterValueResponse :
public class RmiNumericRegisterValueResponse : RmiResponseBase {
public RmiNumericRegisterValueResponse()
// Register number.
public int RegisterNumber { get; set; }
public override string ToString()
// Register value.
public NumericRegister Value { get; set; }
}
Members of Rmi.Data.RmiVariableValueResponse :
public class RmiVariableValueResponse : RmiResponseBase {
public RmiVariableValueResponse()
// Gets or sets the value as an integer. Internally stored as a double.
public int IntegerValue { get; set; }
// Whether the variable holds a floating-point value.
public bool IsInteger { get; set; }
// Variable name, including the leading <code>$</code> character.
public string Name { get; set; }
// Gets or sets the value as a double-precision floating-point number.
public double RealValue { get; set; }
public override string ToString()
}
Members of Rmi.Data.RmiTcpSpeedResponse :
public class RmiTcpSpeedResponse : RmiTimedResponse {
public RmiTcpSpeedResponse()
public override bool Equals(object obj)
public override int GetHashCode()
// Current tool center point speed in mm/s.
public double Speed { get; set; }
public override string ToString()
}
Members of Rmi.Data.RmiSetPayloadParameters :
public class RmiSetPayloadParameters {
public RmiSetPayloadParameters()
// Center-of-gravity X offset in meters.
public float CgXm { get; set; }
// Center-of-gravity Y offset in meters.
public float CgYm { get; set; }
// Center-of-gravity Z offset in meters.
public float CgZm { get; set; }
// Optional motion group number. <code>null</code> uses the active group.
public byte? Group { get; set; }
// Inertia around the X axis in kg·m². <code>null</code> omits this field from the command.
public float? InertiaXkgm2 { get; set; }
// Inertia around the Y axis in kg·m². <code>null</code> omits this field from the command.
public float? InertiaYkgm2 { get; set; }
// Inertia around the Z axis in kg·m². <code>null</code> omits this field from the command.
public float? InertiaZkgm2 { get; set; }
// Payload mass in kilograms.
public float MassKg { get; set; }
// Payload schedule number to configure.
public byte ScheduleNumber { get; set; }
}
Members of Rmi.Data.RmiSetPayloadCompensationParameters :
public class RmiSetPayloadCompensationParameters {
public RmiSetPayloadCompensationParameters()
// Center-of-gravity X offset in meters.
public float CgXm { get; set; }
// Center-of-gravity Y offset in meters.
public float CgYm { get; set; }
// Center-of-gravity Z offset in meters.
public float CgZm { get; set; }
// Optional motion group number. <code>null</code> uses the active group.
public byte? Group { get; set; }
// Inertia around the X axis in kg·m².
public float InertiaXkgm2 { get; set; }
// Inertia around the Y axis in kg·m².
public float InertiaYkgm2 { get; set; }
// Inertia around the Z axis in kg·m².
public float InertiaZkgm2 { get; set; }
// Payload mass in kilograms.
public float MassKg { get; set; }
// Payload schedule number to configure.
public byte ScheduleNumber { get; set; }
}
Members of Rmi.Data.RmiRecordedCartesianPosition :
public class RmiRecordedCartesianPosition {
public RmiRecordedCartesianPosition()
// Recorded Cartesian position including arm configuration and active frame/tool numbers.
public CartesianPositionWithUserFrame Position { get; set; }
// Position identifier assigned by the controller.
public ushort PositionId { get; set; }
public override string ToString()
}
Members of Rmi.Data.RmiRecordedJointPosition :
public class RmiRecordedJointPosition {
public RmiRecordedJointPosition()
// Recorded joint angles in degrees.
public JointsPosition Joints { get; set; }
// Position identifier assigned by the controller.
public ushort PositionId { get; set; }
public override string ToString()
}
View as Markdown

Integrieren Sie Roboter von Universal Robots, Fanuc, Yaskawa, ABB oder Staubli ganz einfach in Ihre .NET-, Python-, LabVIEW- oder Matlab-Anwendungen

UnderAutomation
KontaktLegal

© All rights reserved.