APIs, concepts, guides, and more
Path Motion

Define complex 3D paths using lines and arcs for moving an end effector in Cartesian space.

🔹 What is Path Motion?

Path Motion allows complex 3D paths to be specified using simple geometric elements (arcs and lines) in order to define the desired path. Path motion is useful for applications that need to move an end effector in 3D cartesian space on a machine with an arbitrary kinematic model.

🔹 Classes for representing location in 3D space (Pose, Vector, Quaternion)

Class Composed of notes
RobotPosition Pose, RapidVector of Free Axis positions when a Robot has non-kinematic joints
Pose Vector3d, Quaternion Made of a Vector and a Quaternion
Vector3d X, Y, Z or R, P, Y 3 64-bit floating point double values
Quaternion W, X, Y, Z 4 64-bit floating point double values
RapidVector wrapped STL vector similar to std::vector

🔹 Lines

Lines are defined by an endpoint. The start point will either be the end point of the previously appended motion (For the first move it will be the current position).

🔹 Arcs

Arcs are defined by a rotation direction, endpoint, and center.
Alternatively, the can be defined by an endpoint and radius but must then only take place on a specified plane.

Warning
Currently, all arcs must take place on the XY, YZ, or XZ plane.

🔹 Relative/Absolute

Lines and arcs can be programmed as either relative or absolute.
Absolute moves will be relative to the origin point of your kinematic space. Relative moves will be relative to the start point(end point of previous move)

🔹 Examples of Basic Cartesian Lines and Arcs

CartesianRobot.PathLine(Pose(1000,1000,0));
Image

CartesianRobot.PathArc(RSIRotationDirection.Clockwise,Pose(1000,1000,0), Vector(0,1000,0)); Image

CartesianRobot.PathArcXY(RSIRotationDirection.Clockwise,1000,1000,1000);
Image

Note
This Path Motion feature is not the same as legacy path motion (methods on the MultiAxis class)

📜 Sample Code

Basic Path Motion

Gantry Prime Axis

Setup model with 1:1 geared axis.

  • C#

    /* This sample demonstrates how to set up a kinematic model with a gantry prime axis.
    Shows how to configure a 1:1 geared axis system where two physical axes work together
    to control the same cartesian coordinate.
    */
    using RSI.RapidCode; // RSI.RapidCode.dotNET;
    Console.WriteLine("📜 Motion: Path Gantry");
    // get rmp objects
    try
    {
    Helpers.CheckErrors(controller);
    // set robot axis labels
    const string xLabel = "X-Axis";
    const string yLabel = "Y-Axis";
    const string yPrimeLabel = "Y-Prime";
    // get the 3 axis needed for XY_Yp robot
    Axis xAxis = controller.AxisGet(Constants.AXIS_0_INDEX);
    Axis yAxis = controller.AxisGet(Constants.AXIS_1_INDEX);
    Axis primeAxis = controller.AxisGet(Constants.AXIS_2_INDEX);
    Helpers.CheckErrors(primeAxis);
    // configure phantom axes
    // set the expected labels for each axis
    xAxis.UserLabelSet(xLabel);
    yAxis.UserLabelSet(yLabel);
    primeAxis.UserLabelSet(yPrimeLabel);
    // the joint index of each axis is the index within the MultiAxis object
    // "X-Axis" has joint index 0
    // "Y-Axis" has joint index 1
    // "Y-Prime" has joint index 2
    MultiAxis jointsMultiAxis = controller.MultiAxisGet(0);
    Axis[] axes = [xAxis, yAxis, primeAxis];
    jointsMultiAxis.AxesAdd(axes, axes.Length);
    const LinearUnits units = LinearUnits.Millimeters;
    const string modelName = "RSI_XY_Yp";
    const double scaling = 1.0, offset = 0.0;
    LinearModelBuilder builder = new(modelName);
    builder.UnitsSet(units);
    builder.JointAdd(new LinearJointMapping(0, CartesianAxis.X) { ExpectedLabel = xLabel, Scaling = scaling, Offset = offset });
    builder.JointAdd(new LinearJointMapping(1, CartesianAxis.Y) { ExpectedLabel = yLabel, Scaling = scaling, Offset = offset });
    builder.JointAdd(new LinearJointMapping(2, CartesianAxis.Y) { ExpectedLabel = yPrimeLabel, Scaling = scaling, Offset = offset });
    // create Robot object where the y and y prime will be geared 1:1
    const int motionFrameBufferSize = 50; // this is the minimum valid motion frame buffer size
    Robot robot = Robot.RobotCreate(controller, jointsMultiAxis, builder, motionFrameBufferSize);
    Console.WriteLine($"Model name: {robot.ModelGet().NameGet()}");
    Console.WriteLine($"Model units: {robot.ModelGet().UnitsGet()}");
    Console.WriteLine("Gantry configuration: Y-axis and Y-Prime axis are geared 1:1");
    // cleanup
    Robot.RobotDelete(controller, robot);
    }
    // handle errors as needed
    finally
    {
    controller.Delete(); // dispose
    }

3D Rendering

Get points in 3D space for rendering them.

  • C#

    /* This sample demonstrates how to get 3D path points for rendering visualization.
    Shows how to retrieve planned positions from a Robot path for use with 3D graphics libraries
    or visualization tools.
    */
    using RSI.RapidCode; // RSI.RapidCode.dotNET;
    Console.WriteLine("📜 Motion: Path 3D Rendering");
    // get rmp objects
    try
    {
    Helpers.CheckErrors(controller);
    // set robot axis labels
    const string xLabel = "X-Axis";
    const string yLabel = "Y-Axis";
    const string zLabel = "Z-Axis";
    // get the 3 axis needed for XYZ robot
    Axis xAxis = controller.AxisGet(Constants.AXIS_0_INDEX);
    Axis yAxis = controller.AxisGet(Constants.AXIS_1_INDEX);
    Axis zAxis = controller.AxisGet(Constants.AXIS_2_INDEX);
    // configure phantom axes
    // set axis labels
    xAxis.UserLabelSet(xLabel);
    yAxis.UserLabelSet(yLabel);
    zAxis.UserLabelSet(zLabel);
    // create multi-axis object for joints
    MultiAxis jointsMultiAxis = controller.MultiAxisGet(0);
    Axis[] axes = [xAxis, yAxis, zAxis];
    jointsMultiAxis.AxesAdd(axes, axes.Length);
    // create simple 3-axis kinematic model
    const string modelName = "RSI_XYZ";
    const double scaling = 1.0;
    const double offset = 0.0;
    LinearModelBuilder builder = new(modelName);
    builder.UnitsSet(LinearUnits.Millimeters);
    builder.JointAdd(new LinearJointMapping(0, CartesianAxis.X) { ExpectedLabel = xLabel, Scaling = scaling, Offset = offset });
    builder.JointAdd(new LinearJointMapping(1, CartesianAxis.Y) { ExpectedLabel = yLabel, Scaling = scaling, Offset = offset });
    builder.JointAdd(new LinearJointMapping(2, CartesianAxis.Z) { ExpectedLabel = zLabel, Scaling = scaling, Offset = offset });
    // create Robot object
    Robot robot = Robot.RobotCreate(controller, jointsMultiAxis, builder, MotionController.AxisFrameBufferSizeDefault);
    // set path motion parameters
    robot.PathAccelerationSet(100);
    robot.PathVelocitySet(50);
    // program path motion
    robot.PathProgrammingModeSet(PathMode.Absolute);
    robot.PathLine(target: new Pose(1, 1, 1));
    robot.PathArc(
    target: new Pose(0, 2, 1),
    center: new Vector3d(0, 1, 1),
    direction: RotationDirection.Clockwise);
    // process the path to build trajectory
    robot.PathProcessLoadedMoves();
    // get path points for 3D rendering
    Console.WriteLine("Retrieving 3D path points for rendering:");
    const ulong frameCount = 500;
    ulong startFrame = 0;
    int totalPointCount = 0;
    ulong retrievedFrames;
    do
    {
    RapidVectorRobotPosition positions = robot.PathPlannedPositionsGet(startFrame, frameCount);
    retrievedFrames = positions.Size();
    foreach (RobotPosition position in positions.ToArray())
    {
    Vector3d spatial = position.Pose.Position;
    // print first 4 points as example
    if (totalPointCount < 4)
    {
    Console.WriteLine($"Point {totalPointCount}: X={spatial.X:F2}, Y={spatial.Y:F2}, Z={spatial.Z:F2}");
    }
    totalPointCount++;
    // add code here to create rendering with your preferred 3D library
    // examples:
    // vector3 = new Vector3D(spatial.X, spatial.Y, spatial.Z);
    // linePositions.Add(vector3);
    // scene.AddPoint(spatial.X, spatial.Y, spatial.Z);
    }
    startFrame += retrievedFrames;
    }
    while (retrievedFrames == frameCount);
    // print total points retrieved
    Console.WriteLine($"Total 3D points retrieved: {totalPointCount}");
    // cleanup
    Robot.RobotDelete(controller, robot);
    }
    // handle errors as needed
    finally
    {
    controller.Delete(); // dispose
    }