UnderAutomation
질문이요?

[email protected]

문의하기
UnderAutomation
⌘Q
Fanuc SDK documentation
RMI overview
Documentation home

Motion commands

Send linear, joint, and circular motion commands with configurable speed, termination type, and acceleration via RMI.

RMI lets you send TP-equivalent motion instructions to the robot. Each call to SendTpInstruction() returns an RmiInstructionResponse that tracks the instruction through its execution lifecycle.

Linear motion

Move the robot in a straight line to a Cartesian target:

// Linear motion to a Cartesian target (tool 1, frame 0)
var move = new LinearMotionTpInstruction
{
SpeedType = RmiLinearSpeedType.MmSec,
Speed = 100,
TermType = RmiTerminationType.Fine,
Target = new CartesianPositionWithUserFrame(500, 200, 300, 0, 90, 0, tool: 1, frame: 0)
};
robot.Rmi.SendTpInstruction(move).WaitForCompletion();
// Incremental linear motion (delta from current position)
var inc = new LinearRelativeTpInstruction
{
SpeedType = RmiLinearSpeedType.MmSec,
Speed = 50,
TermType = RmiTerminationType.Fine,
Target = new CartesianPositionWithUserFrame(0, 0, -50, 0, 0, 0, 1, 0)
};
robot.Rmi.SendTpInstruction(inc).WaitForCompletion();
// Linear motion with joint-angle target representation
var jrep = new LinearMotionJRepTpInstruction
{
SpeedType = RmiLinearSpeedType.MmSec,
Speed = 80,
TermType = RmiTerminationType.Fine,
Joints = new JointsPosition(10, -20, 30, 0, 60, 0)
};
robot.Rmi.SendTpInstruction(jrep).WaitForCompletion();
// CNT blending: chain motions without stopping
var p1 = new LinearMotionTpInstruction
{
SpeedType = RmiLinearSpeedType.MmSec,
Speed = 200,
TermType = RmiTerminationType.Cnt,
TermValue = 100,
Target = new CartesianPositionWithUserFrame(600, 0, 400, 0, 90, 0, 1, 0)
};
var p2 = new LinearMotionTpInstruction
{
SpeedType = RmiLinearSpeedType.MmSec,
Speed = 200,
TermType = RmiTerminationType.Fine, // last motion must be Fine (or NoBlend = true)
Target = new CartesianPositionWithUserFrame(700, 0, 350, 0, 90, 0, 1, 0)
};
robot.Rmi.SendTpInstruction(p1);
robot.Rmi.SendTpInstruction(p2).WaitForCompletion();

Speed types for linear motion

RmiLinearSpeedTypeDescription
MmSecMillimeters per second.
InchMinInches per minute (0.1 in/min units).
TimeDuration in 0.1-second steps.
MSecDuration in milliseconds.

Termination types

RmiTerminationTypeDescription
FineStop precisely at the target.
CntContinuous blending with the next motion (value 1-100). The last motion sent must be Fine unless NoBlend = true.
CrCorner region (requires Advanced Constant Path option).

Joint motion

Move using joint interpolation (Cartesian target or joint-angle target):

// Joint motion with Cartesian target, percent speed
var cart = new JointMotionTpInstruction
{
SpeedType = RmiJointSpeedType.Percent,
Speed = 10,
TermType = RmiTerminationType.Fine,
Target = new CartesianPositionWithUserFrame(500, 200, 300, 0, 90, 0, tool: 1, frame: 0)
};
robot.Rmi.SendTpInstruction(cart).WaitForCompletion();
// Joint motion with joint-angle target representation
var jrep = new JointMotionJRepTpInstruction
{
SpeedType = RmiJointSpeedType.Percent,
Speed = 5,
TermType = RmiTerminationType.Fine,
Joints = new JointsPosition(10, -20, 30, 0, 60, 0)
};
robot.Rmi.SendTpInstruction(jrep).WaitForCompletion();
// Incremental joint motion (joint-angle delta)
var relJrep = new JointRelativeJRepTpInstruction
{
SpeedType = RmiJointSpeedType.Percent,
Speed = 5,
TermType = RmiTerminationType.Fine,
Joints = new JointsPosition(0, 0, 0, 0, 5, 0) // rotate J5 by 5 degrees
};
robot.Rmi.SendTpInstruction(relJrep).WaitForCompletion();

Speed types for joint motion

RmiJointSpeedTypeDescription
PercentPercentage of maximum joint speed (1-100).
TimeDuration in 0.1-second steps.
MSecDuration in milliseconds.

Circular motion

Circular motion requires a via point and a destination:

// Circular motion: define a via-point and a destination
var arc = new CircularMotionTpInstruction
{
SpeedType = RmiLinearSpeedType.MmSec,
Speed = 80,
TermType = RmiTerminationType.Fine,
Via = new CartesianPositionWithUserFrame(600, 100, 350, 0, 90, 0, tool: 1, frame: 0),
Target = new CartesianPositionWithUserFrame(700, 0, 300, 0, 90, 0, tool: 1, frame: 0)
};
robot.Rmi.SendTpInstruction(arc).WaitForCompletion();
// Incremental circular motion (via and target are deltas)
var arcRel = new CircularRelativeTpInstruction
{
SpeedType = RmiLinearSpeedType.MmSec,
Speed = 60,
TermType = RmiTerminationType.Fine,
Via = new CartesianPositionWithUserFrame(50, 50, 0, 0, 0, 0, 1, 0),
Target = new CartesianPositionWithUserFrame(100, 0, 0, 0, 0, 0, 1, 0)
};
robot.Rmi.SendTpInstruction(arcRel).WaitForCompletion();

Spline motion

Spline motion requires firmware MajorVersion >= 7 (V9.40P/54 or later). The controller needs at least one more spline instruction after the first to start executing the segment.

// Spline motion requires MajorVersion >= 7 (firmware V9.40P/54 or later).
// The controller will not execute the first spline segment until it receives
// a second instruction (motion or non-motion) after the last spline point.
robot.Rmi.SendTpInstruction(new SplineMotionTpInstruction
{
SpeedType = RmiLinearSpeedType.MmSec,
Speed = 200,
TermType = RmiTerminationType.Cnt,
TermValue = 100,
Target = new CartesianPositionWithUserFrame(500, 100, 300, 0, 90, 0, 1, 0)
});
robot.Rmi.SendTpInstruction(new SplineMotionTpInstruction
{
SpeedType = RmiLinearSpeedType.MmSec,
Speed = 200,
TermType = RmiTerminationType.Cnt,
TermValue = 100,
Target = new CartesianPositionWithUserFrame(550, 200, 320, 0, 90, 0, 1, 0)
});
robot.Rmi.SendTpInstruction(new SplineMotionTpInstruction
{
SpeedType = RmiLinearSpeedType.MmSec,
Speed = 200,
TermType = RmiTerminationType.Fine,
Target = new CartesianPositionWithUserFrame(600, 100, 300, 0, 90, 0, 1, 0)
});
// Send a non-spline instruction to flush the spline buffer and trigger execution
robot.Rmi.SendTpInstruction(new WaitTimeTpInstruction { Seconds = 0.1 })
.WaitForCompletion();
// Spline with joint-angle representation
robot.Rmi.SendTpInstruction(new SplineMotionJRepTpInstruction
{
SpeedType = RmiJointSpeedType.Percent,
Speed = 50,
TermType = RmiTerminationType.Cnt,
TermValue = 100,
Joints = new JointsPosition(10, -20, 30, 0, 60, 0)
});
robot.Rmi.SendTpInstruction(new SplineMotionJRepTpInstruction
{
SpeedType = RmiJointSpeedType.Percent,
Speed = 50,
TermType = RmiTerminationType.Fine,
Joints = new JointsPosition(15, -15, 35, 5, 55, 5)
});
robot.Rmi.SendTpInstruction(new WaitTimeTpInstruction { Seconds = 0.1 })
.WaitForCompletion();

Relative (incremental) motions

All motion types have incremental variants. The position is a delta from the current robot position:

AbsoluteIncremental
LinearMotionTpInstructionLinearRelativeTpInstruction
JointMotionTpInstructionJointRelativeTpInstruction
CircularMotionTpInstructionCircularRelativeTpInstruction
LinearMotionJRepTpInstructionLinearRelativeJRepTpInstruction
JointMotionJRepTpInstructionJointRelativeJRepTpInstruction

Motion options

Most instruction classes expose optional motion modifiers:

PropertyTypeDescription
Accbyte?Acceleration override (20-100 %).
OffsetPrNumbershort?Offset position register number.
ToolOffsetPrNumbershort?Tool offset PR number (MajorVersion >= 4).
VisionPrNumbershort?Vision offset register number.
WristJointboolEnable wrist-joint mode (linear and circular only).
MrotboolMROT option — requires WristJoint and R640 option.
NoBlendboolAllow CNT motion to execute without waiting for the next instruction (MajorVersion >= 5).
Alimint?Acceleration limit in mm/s² (MajorVersion >= 5, R921 option).
AlimRegshort?Register-based acceleration limit (MajorVersion >= 5, R921 option).
LcbTypestringLocal Condition Block type: "TB", "TA", or "DB".
LcbValueshort?LCB value (ms for TA/TB, 0.01 mm for DB).
PortTypeRmiPortType?Output port type (DOUT or ROUT) triggered by LCB.
PortNumbershort?LCB output port number.
PortValueRmiOnOff?LCB output port value (ON or OFF).

Non-motion instructions

Insert wait conditions, frame changes, and program calls between motions:

// Wait for digital input DI[1] to turn ON before continuing
robot.Rmi.SendTpInstruction(new WaitDinTpInstruction
{
PortNumber = 1,
Value = RmiOnOff.ON
});
// Wait 0.5 seconds
robot.Rmi.SendTpInstruction(new WaitTimeTpInstruction { Seconds = 0.5 });
// Switch to UFRAME 2 for the next motions
robot.Rmi.SendTpInstruction(new SetUFrameTpInstruction { FrameNumber = 2 });
// Switch to UTOOL 3
robot.Rmi.SendTpInstruction(new SetUToolTpInstruction { ToolNumber = 3 });
// Activate payload schedule 1
robot.Rmi.SendTpInstruction(new SetPayloadTpInstruction { ScheduleNumber = 1 });
// Call a TP program (requires MajorVersion >= 4)
robot.Rmi.SendTpInstruction(new CallProgramTpInstruction { ProgramName = "GRIPPER_OPEN" })
.WaitForCompletion();

Tracking instruction status

// Send several instructions. Each returns immediately.
for (int i = 0; i < 5; i++)
{
var instr = new LinearMotionTpInstruction
{
SpeedType = RmiLinearSpeedType.MmSec,
Speed = 100,
TermType = RmiTerminationType.Fine,
Target = new CartesianPositionWithUserFrame(500 + i * 20, 200, 300, 0, 90, 0, 1, 0)
};
RmiInstructionResponse r = robot.Rmi.SendTpInstruction(instr);
// Subscribe to status changes
r.StatusChanged += status =>
Console.WriteLine($" Seq {r.SequenceId}: {status}");
}
// Wait for all instructions to complete
foreach (RmiInstructionResponse r in robot.Rmi.Instructions)
r.WaitForCompletion();
// Print final results
foreach (RmiInstructionResponse r in robot.Rmi.Instructions)
{
if (r.Status == RmiInstructionStatus.Error)
Console.WriteLine($" Seq {r.SequenceId} failed: {r.ErrorText}");
else
Console.WriteLine($" Seq {r.SequenceId} completed OK");
}
// Remove completed instructions from the tracking list
robot.Rmi.ClearCompletedInstructions();

Complete example

using System;
using UnderAutomation.Fanuc;
using UnderAutomation.Fanuc.Common;
using UnderAutomation.Fanuc.Rmi.Data;
using UnderAutomation.Fanuc.Rmi.TpInstructions;
public class RmiMotion
{
static void Main()
{
FanucRobot robot = new FanucRobot();
ConnectionParameters parameters = new ConnectionParameters("192.168.0.1");
parameters.Rmi.Enable = true;
robot.Connect(parameters);
// Check status
RmiControllerStatusResponse status = robot.Rmi.GetStatus();
if (status.TPEnabled)
{
Console.WriteLine("Turn off the teach pendant before proceeding.");
return;
}
if (!status.ServoReady)
{
Console.WriteLine("Servos are not ready.");
return;
}
// Initialize RMI_MOVE
robot.Rmi.Initialize();
// Set speed override
robot.Rmi.SetOverride(80);
// Move to a start position
robot.Rmi.SendTpInstruction(new JointMotionJRepTpInstruction
{
SpeedType = RmiJointSpeedType.Percent,
Speed = 10,
TermType = RmiTerminationType.Fine,
Joints = new JointsPosition(0, 0, 0, 0, 0, 0)
}).WaitForCompletion();
// Approach
robot.Rmi.SendTpInstruction(new LinearMotionTpInstruction
{
SpeedType = RmiLinearSpeedType.MmSec,
Speed = 200,
TermType = RmiTerminationType.Cnt,
TermValue = 50,
Target = new CartesianPositionWithUserFrame(500, 200, 350, 0, 90, 0, 1, 0)
});
// Descend to pick position
robot.Rmi.SendTpInstruction(new LinearMotionTpInstruction
{
SpeedType = RmiLinearSpeedType.MmSec,
Speed = 50,
TermType = RmiTerminationType.Fine,
Target = new CartesianPositionWithUserFrame(500, 200, 300, 0, 90, 0, 1, 0)
}).WaitForCompletion();
// Activate gripper
robot.Rmi.SendTpInstruction(new CallProgramTpInstruction { ProgramName = "GRIP_ON" })
.WaitForCompletion();
// Retract
robot.Rmi.SendTpInstruction(new LinearMotionTpInstruction
{
SpeedType = RmiLinearSpeedType.MmSec,
Speed = 100,
TermType = RmiTerminationType.Fine,
Target = new CartesianPositionWithUserFrame(500, 200, 400, 0, 90, 0, 1, 0)
}).WaitForCompletion();
// Check HOLD state
if (robot.Rmi.IsInHoldState)
{
Console.WriteLine("Controller in HOLD. Calling Reset...");
robot.Rmi.Reset();
}
robot.Rmi.Abort();
robot.Disconnect();
}
}

API reference

Members of Rmi.TpInstructions.LinearMotionTpInstruction :
public class LinearMotionTpInstruction : CartesianMotionTpInstructionBase {
public LinearMotionTpInstruction()
// Acceleration limit value. <code>null</code> uses the controller default. Requires MajorVersion &gt;= 5 and the R921 option.
public int? Alim { get; set; }
// Acceleration limit register number. <code>null</code> disables register-based limit. Requires MajorVersion &gt;= 5 and the R921 option.
public short? AlimReg { get; set; }
// When <code>true</code>, enables coordinated motion (MROT).
public bool Mrot { get; set; }
// When <code>true</code>, disables blending with the next instruction. Requires MajorVersion &gt;= 5.
public bool NoBlend { get; set; }
// Speed unit (mm/s, inch/min, or time).
public RmiLinearSpeedType SpeedType { get; set; }
// When <code>true</code>, enables wrist-joint mode for this motion.
public bool WristJoint { get; set; }
}
Members of Rmi.TpInstructions.JointMotionTpInstruction :
public class JointMotionTpInstruction : CartesianMotionTpInstructionBase {
public JointMotionTpInstruction()
// When <code>true</code>, enables coordinated motion (MROT).
public bool Mrot { get; set; }
// When <code>true</code>, disables blending with the next instruction.
public bool NoBlend { get; set; }
// Speed unit (percent override or time).
public RmiJointSpeedType SpeedType { get; set; }
}
Members of Rmi.TpInstructions.JointMotionJRepTpInstruction :
public class JointMotionJRepTpInstruction : JRepMotionTpInstructionBase {
public JointMotionJRepTpInstruction()
// When <code>true</code>, enables coordinated motion (MROT).
public bool Mrot { get; set; }
// When <code>true</code>, disables blending with the next instruction.
public bool NoBlend { get; set; }
// Speed unit (percent override or time).
public RmiJointSpeedType SpeedType { get; set; }
}
Members of Rmi.TpInstructions.CircularMotionTpInstruction :
public class CircularMotionTpInstruction : CartesianMotionTpInstructionBase {
public CircularMotionTpInstruction()
// When <code>true</code>, enables coordinated motion (MROT).
public bool Mrot { get; set; }
// When <code>true</code>, disables blending with the next instruction.
public bool NoBlend { get; set; }
// Speed unit (mm/s, inch/min, or time).
public RmiLinearSpeedType SpeedType { get; set; }
// Via-point Cartesian position that defines the arc.
public CartesianPositionWithUserFrame Via { get; set; }
// When <code>true</code>, enables wrist-joint mode for this motion.
public bool WristJoint { get; set; }
}
Members of Rmi.TpInstructions.SplineMotionTpInstruction :
public class SplineMotionTpInstruction : CartesianMotionTpInstructionBase {
public SplineMotionTpInstruction()
// Speed unit (mm/s, inch/min, or time).
public RmiLinearSpeedType SpeedType { get; set; }
}
Members of Rmi.TpInstructions.FullMotionTpInstructionBase :
public abstract class FullMotionTpInstructionBase : MotionTpInstructionBase {
protected FullMotionTpInstructionBase()
// Optional acceleration override (1-100 %). <code>null</code> uses the controller default.
public byte? Acc { get; set; }
// Lock-and-continue (LCB) condition type string. <code>null</code> disables LCB.
public string LcbType { get; set; }
// Lock-and-continue (LCB) condition value. Required when <xref href="UnderAutomation.Fanuc.Rmi.TpInstructions.FullMotionTpInstructionBase.LcbType" data-throw-if-not-resolved="false"></xref> is set.
public short? LcbValue { get; set; }
// Offset position register number. <code>null</code> disables offset.
public short? OffsetPrNumber { get; set; }
// Digital output port number. Required when <xref href="UnderAutomation.Fanuc.Rmi.TpInstructions.FullMotionTpInstructionBase.PortType" data-throw-if-not-resolved="false"></xref> is set.
public short? PortNumber { get; set; }
// Digital output port type to trigger at the end of this motion. <code>null</code> disables output.
public RmiPortType? PortType { get; set; }
// Digital output port value. Required when <xref href="UnderAutomation.Fanuc.Rmi.TpInstructions.FullMotionTpInstructionBase.PortType" data-throw-if-not-resolved="false"></xref> is set.
public RmiOnOff? PortValue { get; set; }
// Tool-offset position register number. <code>null</code> disables tool offset. Requires MajorVersion &gt;= 4.
public short? ToolOffsetPrNumber { get; set; }
// Vision offset position register number. <code>null</code> disables vision offset.
public short? VisionPrNumber { get; set; }
}
Members of Rmi.Data.RmiInstructionResponse :
public class RmiInstructionResponse : RmiResponseBase {
public RmiInstructionResponse()
public override bool Equals(object obj)
public override int GetHashCode()
// Sent instruction
public RmiInstructionBase Instruction { get; }
// Sequence identifier assigned to this instruction. 0 until the instruction has been dispatched to the controller.
public int SequenceId { get; }
// Current execution state of the instruction.
public RmiInstructionStatus Status { get; }
// Fired each time <xref href="UnderAutomation.Fanuc.Rmi.Data.RmiInstructionResponse.Status" data-throw-if-not-resolved="false"></xref> changes. The argument is the new status value.
// This event may be raised from a background thread.
public event Action<RmiInstructionStatus> StatusChanged
public override string ToString()
// Blocks the calling thread until the instruction reaches a terminal state
// (<xref href="UnderAutomation.Fanuc.Rmi.Data.RmiInstructionStatus.Completed" data-throw-if-not-resolved="false"></xref> or <xref href="UnderAutomation.Fanuc.Rmi.Data.RmiInstructionStatus.Error" data-throw-if-not-resolved="false"></xref>),
// or until <code class="paramref">timeoutMs</code> milliseconds have elapsed.
// Pass -1 (or omit) to wait indefinitely.
public bool WaitForCompletion(int timeoutMs = -1)
}
View as Markdown

Universal Robots, Fanuc, Yaskawa, ABB 또는 Staubli 로봇을 .NET, Python, LabVIEW 또는 Matlab 애플리케이션에 쉽게 통합

UnderAutomation
문의하기Legal

© All rights reserved.