APIs, concepts, guides, and more
PT Streaming Motion

PT motion is the simplest streaming motion requiring only Positions and Time deltas arrays.

🔹 What is PT Motion?

PT motion is the simplest streaming motion to use because it only requires an array of Positions and Time deltas. The controller is responsible for figuring out the velocity, and acceleration for each motion segment. MovePT currently supports several types of interpolation, as described in Streaming Motion.

Simple PT Interpolation Output Example

RSIMotionTypePT is good for very closely spaced points (int time) or low accelerations. It is a very simple algorithm, requiring very few calculations; therefore, it is fast. If the points are spaced too far apart, the motion will be rough like shown in the example below. The acceleration between each point is instantaneous. It is best to keep the point spacing within a few samples.

Trapezoidal move example:

p1[0] = 050; t1[0] = 1.0;

p1[1] = 400; t1[1] = 3.5;

p1[2] = 450; t1[2] = 1.0;

Note: The Position array is direction sensitive meaning you must put a (-) sign on negative numbers.

BSpline Interpolation Output Example

RSIMotionTypeBSPLINE interpolation is our recommended technique to blend transitions between segments. Use BSpline for smooth paths or systems with poor acceleration response.

Trapezoidal move example:

p[0] = 050; t[0] = 1.0;

p[1] = 400; t[1] = 3.5;

p[2] = 450; t[2] = 1.0;

Note: The Position array is direction sensitive meaning you must put a (-) sign on negative numbers.

🔹 PT Motion with Feedforward (PTF)

MovePTF extends PT motion by adding a feedforward term to each point. The feedforward value is a raw control output value applied directly to the control output, providing additional control authority beyond the PID controller.

When to Use Feedforward

Feedforward is useful when you need to compensate for known forces or apply model-based control:

  • Gravity Compensation: For vertical axes, apply a constant feedforward to counteract gravitational force
  • Friction Compensation: Add feedforward values to overcome static or dynamic friction
  • Torque Feedforward: Provide additional torque for high-performance applications or dynamic loads
  • Model-Based Control: Apply control outputs calculated from system dynamics models

Feedforward Units and Configuration

Feedforward values are raw control output values, not UserUnits:

  • Typically 16-bit signed integers for torque control (-32768 to 32767)
  • Typically 32-bit signed integers for velocity or position control
  • The axis must be configured separately for the output type and PDO mapping via demand channel configuration

Feedforward Interpolation

The feedforward values are linearly interpolated between consecutive points during multi-sample segments:

  • If a segment spans 10 firmware samples, the feedforward transitions smoothly by 10% per sample from the current point to the next
  • For single-sample segments, the feedforward changes instantly at each point

Array Structure for PTF

For single Axis:

positions[] = [p₀, p₁, p₂, ..., pₙ]
times[] = [t₀, t₁, t₂, ..., tₙ]
feedforwards[] = [f₀, f₁, f₂, ..., fₙ] // raw control output values

For MultiAxis with 3 axes:

positions[] = [X₀, Y₀, Z₀, X₁, Y₁, Z₁, ..., Xₙ, Yₙ, Zₙ]
times[] = [t₀, t₁, ..., tₙ]
feedforwards[] = [Xf₀, Yf₀, Zf₀, Xf₁, Yf₁, Zf₁, ..., Xfₙ, Yfₙ, Zfₙ]
Note
The feedforwards array size must match the positions array size.

🔹 MultiAxis PT Motion

All motion streaming methods can be used for coordinated motion on MultiAxis objects. It is important that you setup your arrays appropriately for a MultiAxis object. See the examples below on how to structure your arrays for MultiAxis PT Motion.

Example 1: Three Axis Multi-Axis XYZ with MovePT

The position data for all three axes are combined into the array. The time array is shared for all axes. This is why you need 3x as many position points than you need time points. See the example below:

p[0] = 050; t[0] = 1;
p[1] = 025;
p[2] = 012.5;
p[3] = 400; t[1] = 3.5;
p[4] = 200;
p[5] = 100;
p[6] = 450; t[2] = 1;
p[7] = 225;
p[8] = 112.5;

1st Segment 2nd Segment 3rd Segment Resulting Motion Plot
AxisX p[0] = 050;
[0] = 1;
p[2] = 400;
t[1] = 3.5;
p[4] = 450;
t[2] = 1;
Image
AxisY p[1] = 025;
t[0] = 1;
p[3] = 200;
t[1] = 3.5;
p[5] = 225;
t[2] = 1;
Image
AxisZ p[2] = 012.5;
t[0] = 1;
p[5] = 100;
t[1] = 3.5;
p[8] = 112.5;
t[2] = 1;
Image

📜 Sample Code

Basic Streaming PT Motion

Stopping Streaming PT Motion

This code demonstrates that different actions that you can take after stopping a PT Streaming motion.

  • C#

    /* Demonstrates how to handle PT streaming motion when stopping.
    Shows the difference between Stop/Resume to continue appending points,
    versus starting fresh motion after stopping.
    */
    using RSI.RapidCode; // RSI.RapidCode.dotNET;
    Console.WriteLine("📜 Axis Streaming Motion: PT While Stopping");
    // get rmp objects
    try
    {
    Helpers.CheckErrors(controller);
    // get axis
    Axis axis = controller.AxisGet(Constants.AXIS_0_INDEX);
    // configure phantom axis
    const int points = 3; // points per streaming motion call
    const int emptyCount = 2; // e-stop generated if there are this number or fewer frames loaded
    double[] first = [0.1, 0.2, 0.3]; // positions for first MovePT call
    double[] second = [0.4, 0.5, 0.6]; // positions for second MovePT call
    double[] third = [0.7, 0.8, 0.9]; // positions for third MovePT call
    double[] time1 = [0.3, 0.3, 0.3]; // time deltas for first MovePT call
    double[] time2 = [0.2, 0.2, 0.2]; // time deltas for second MovePT call
    double[] time3 = [0.25, 0.25, 0.25]; // time deltas for third MovePT call
    axis.AmpEnableSet(true);
    axis.MovePT(RSIMotionType.RSIMotionTypePT, first, time1, points, emptyCount, false, false); // start motion and stream points
    axis.MovePT(RSIMotionType.RSIMotionTypePT, second, time2, points, emptyCount, false, false); // append points
    // after Stop() on streaming motion, you can:
    // 1. Resume() to continue appending points to existing motion
    // 2. Discard previous points and start new motion
    axis.Stop(); // puts axis in STOPPED state
    // axis.EStop(); // puts axis in ERROR state (must ClearFaults() before continuing)
    // axis.Abort(); // puts axis in ERROR state and triggers AmpEnable(false) (must call AmpEnable(true) before continuing)
    axis.MotionDoneWait(); // wait for axis to stop
    axis.Resume(); // resume appends next points to existing motion, without Resume(), new points start fresh motion
    // append or start new based on Resume() call
    axis.MovePT(RSIMotionType.RSIMotionTypePT, third, time3, points, emptyCount, false, true);
    // wait for motion to complete
    Console.WriteLine($"Final position: {axis.CommandPositionGet()}");
    // cleanup
    }
    // handle errors as needed
    finally
    {
    controller.Delete(); // dispose
    }
    void Resume()
    Resume an axis.