APIs, concepts, guides, and more
Helper Functions

Streamline code and ensure proper initialization of projects with custom helper functions designed to simplify common setup tasks. controller.

🔹 What are Helper Functions?

Helper functions are functions/methods that were created by us (RSI) to reduce the amount of code that goes into our sample apps. They are not included in our RapidCode API. But you are free to replicate these functions on your projects.

Explore our sample apps to see how they are being used!

📜 Sample Code

  • C#

    Check Errors:

    Check the RSIError log for any logged errors. Read and print all the errors. Ignore warnings.

    public static void CheckErrors(RapidCodeObject rsiObject)
    {
    bool hasErrors = false;
    System.Text.StringBuilder errorStringBuilder = new System.Text.StringBuilder();
    while (rsiObject.ErrorLogCountGet() > 0)
    {
    RsiError error = rsiObject.ErrorLogGet();
    if (error.isWarning)
    {
    errorStringBuilder.AppendLine("WARNING: " + error.Message);
    }
    else
    {
    hasErrors = true;
    errorStringBuilder.AppendLine("ERROR: " + error.Message);
    }
    }
    if (errorStringBuilder.Length > 0)
    {
    Console.WriteLine(errorStringBuilder.ToString());
    }
    if (hasErrors)
    {
    throw new Exception(errorStringBuilder.ToString());
    }
    }

    Start the Network:

    Start the network and print any errors encountered.

    public static void StartTheNetwork(MotionController controller)
    {
    // Initialize the Network
    if (controller.NetworkStateGet() != RSINetworkState.RSINetworkStateOPERATIONAL) // Check if network is started already.
    {
    Console.WriteLine("Starting Network..");
    controller.NetworkStart(); // If not. Initialize The Network. (This can also be done from RapidSetup Tool)
    }
    if (controller.NetworkStateGet() != RSINetworkState.RSINetworkStateOPERATIONAL) // Check if network is started again.
    {
    int messagesToRead = controller.NetworkLogMessageCountGet(); // Some kind of error starting the network, read the network log messages
    for (int i = 0; i < messagesToRead; i++)
    {
    Console.WriteLine(controller.NetworkLogMessageGet(i)); // Print all the messages to help figure out the problem
    }
    Console.WriteLine("Expected OPERATIONAL state but the network did not get there.");
    //throw new RsiError(); // Uncomment if you want your application to exit when the network isn't operational. (Comment when using phantom axis)
    }
    else // Else, of network is operational.
    {
    Console.WriteLine("Network Started");
    }
    }

    Create and Ready Axis:

    public Axis CreateAndReadyAxis(int AxisNumber)
    {
    Axis axis = controller.AxisGet(AxisNumber); // Initialize Axis Class. (Use RapidSetup Tool to see what is your axis number)
    HelperFunctions.CheckErrors(axis); // [Helper Function] Check that the axis has been initialize correctly.
    ResetAxis(axis);
    return axis;
    }

    Reset Axis:

    public void ResetAxis(Axis myAxis)
    {
    myAxis.UserUnitsSet(Constants.USER_UNITS); // Specify the counts per Unit.
    myAxis.PositionSet(0); // Sets the current position as 0 effectively 'homing' it.
    myAxis.Abort(); // If there is any motion happening, abort it (creates a fault).
    myAxis.DefaultAccelerationSet(Constants.ACCELERATION);
    myAxis.DefaultDecelerationSet(Constants.ACCELERATION);
    myAxis.DefaultVelocitySet(Constants.VELOCITY);
    EnableAmp(myAxis);
    }

    Enable Amp:

    public void EnableAmp(Axis myAxis)
    {
    myAxis.ClearFaults(); // To enable after an abort faults must be cleared.
    myAxis.AmpEnableSet(true); // Enable the motor.
    }

  • C++

    Sample Apps Config:

    This struct provides static methods and constants for user configuration in RMP applications. Everything in this struct is expected to be modifed by the user.

    {
    // If you want to use hardware, then follow the instructions in the README before setting this to true.
    static constexpr bool USE_HARDWARE = false;
    // Motion Controller Creation Parameters
    static constexpr char RMP_PATH[] = "";
    static constexpr char NIC_PRIMARY[] = "";
    static constexpr char NODE_NAME[] = "";
    static constexpr int CPU_AFFINITY = 0;
    // Controller Initial Object Counts (Sample Apps may change these counts as needed)
    static constexpr int AXIS_COUNT = 2;
    static constexpr int MOTION_COUNT = AXIS_COUNT;
    static constexpr int USER_LIMIT_COUNT = 0;
    static constexpr int MATH_BLOCK_COUNT = 0;
    static constexpr int RECORDER_COUNT = 0;
    // Axis Configuration Constants
    // First (x) Axis configuration parameters
    static constexpr int AXIS_X_USER_UNITS = 1;
    static constexpr int AXIS_X_INDEX = 0;
    // Second (y) Axis configuration parameters
    static constexpr int AXIS_Y_USER_UNITS = 1;
    static constexpr int AXIS_Y_INDEX = 1;
    static void ConfigureHardwareAxes(MotionController *controller, std::vector<Axis *> axes)
    {
    // If you have configured your axes using rsiconfig, RapidSetup, or RapidSetupX then you can comment out this error and return.
    // IMPLEMENTATION REQUIRED: Configure the axes for hardware
    throw std::runtime_error("You must implement the ConfigureHardwareAxes function (found in /include/SampleAppsHelper.h) to use hardware.");
    // Simple Axis Configuration Example:
    // (Look at the Axis: Configuration section in the RapidCode API Reference for more advanced configurations)
    /*
    axes[0]->UserUnitsSet(USER_UNITS);
    axes[0]->PositionSet(0);
    axes[0]->ErrorLimitTriggerValueSet(0.1 * USER_UNITS);
    axes[0]->ErrorLimitActionSet(RSIAction::RSIActionABORT);
    axes[0]->Abort();
    axes[0]->ClearFaults();
    */
    }
    };

    Get Creation Parameters:

    Returns a MotionController::CreationParameters object with user-defined parameters.

    Check Errors:

    Check the RSIError log for any logged errors. Read and print all the errors. Ignore warnings.

    static void CheckErrors(RapidCodeObject *rsiObject)
    {
    bool hasErrors = false;
    std::string errorStrings("");
    while (rsiObject->ErrorLogCountGet() > 0)
    {
    const RsiError *err = rsiObject->ErrorLogGet();
    errorStrings += err->what();
    errorStrings += "\n";
    if (!err->isWarning)
    {
    hasErrors = true;
    }
    }
    if (hasErrors)
    {
    throw std::runtime_error(errorStrings.c_str());
    }
    }

    Start-The-Network-cpp:

    Start the network and print any errors encountered.

    static void StartTheNetwork(MotionController *controller)
    {
    // Initialize the Network
    if (controller->NetworkStateGet() != RSINetworkState::RSINetworkStateOPERATIONAL) // Check if network is started already.
    {
    std::cout << "Starting Network.." << std::endl;
    controller->NetworkStart(); // If not. Initialize The Network. (This can also be done from RapidSetup Tool)
    }
    if (controller->NetworkStateGet() != RSINetworkState::RSINetworkStateOPERATIONAL) // Check if network is started again.
    {
    int messagesToRead = controller->NetworkLogMessageCountGet(); // Some kind of error starting the network, read the network log messages
    for (int i = 0; i < messagesToRead; i++)
    {
    std::cout << controller->NetworkLogMessageGet(i) << std::endl; // Print all the messages to help figure out the problem
    }
    throw std::runtime_error("Expected OPERATIONAL state but the network did not get there.");
    }
    else // Else, of network is operational.
    {
    std::cout << "Network Started" << std::endl << std::endl;
    }
    }

    Shutdown-The-Network-cpp:

    Shutdown the network and print any errors encountered.

    static void ShutdownTheNetwork(MotionController *controller)
    {
    // Check if the network is already shutdown
    if (controller->NetworkStateGet() == RSINetworkState::RSINetworkStateUNINITIALIZED ||
    controller->NetworkStateGet() == RSINetworkState::RSINetworkStateSHUTDOWN)
    {
    return;
    }
    // Shutdown the network
    std::cout << "Shutting down the network.." << std::endl;
    controller->NetworkShutdown();
    if (controller->NetworkStateGet() != RSINetworkState::RSINetworkStateUNINITIALIZED &&
    controller->NetworkStateGet() != RSINetworkState::RSINetworkStateSHUTDOWN) // Check if the network is shutdown.
    {
    int messagesToRead = controller->NetworkLogMessageCountGet(); // Some kind of error shutting down the network, read the network log messages
    for (int i = 0; i < messagesToRead; i++)
    {
    std::cout << controller->NetworkLogMessageGet(i) << std::endl; // Print all the messages to help figure out the problem
    }
    throw std::runtime_error("Expected SHUTDOWN state but the network did not get there.");
    }
    else // Else, of network is shutdown.
    {
    std::cout << "Network Shutdown" << std::endl << std::endl;
    }
    }

    Configure-Phantom-Axis-cpp:

    Configures a specified axis as a phantom axis with custom settings.

    static void ConfigurePhantomAxis(MotionController *controller, int axisNumber)
    {
    // Configure the specified axis as a phantom axis
    Axis *axis = controller->AxisGet(axisNumber); // Initialize Axis class
    CheckErrors(axis); // [Helper Function] Check that the axis has been initialized correctly
    // These limits are not meaningful for a Phantom Axis (e.g., a phantom axis has no actual position so a position error trigger is not necessary)
    // Therefore, you must set all of their actions to "NONE".
    axis->PositionSet(0); // Set the position to 0
    axis->ErrorLimitActionSet(RSIAction::RSIActionNONE); // Set Error Limit Action.
    axis->AmpFaultActionSet(RSIAction::RSIActionNONE); // Set Amp Fault Action.
    axis->AmpFaultTriggerStateSet(1); // Set Amp Fault Trigger State.
    axis->HardwareNegLimitActionSet(RSIAction::RSIActionNONE); // Set Hardware Negative Limit Action.
    axis->HardwarePosLimitActionSet(RSIAction::RSIActionNONE); // Set Hardware Positive Limit Action.
    axis->SoftwareNegLimitActionSet(RSIAction::RSIActionNONE); // Set Software Negative Limit Action.
    axis->SoftwarePosLimitActionSet(RSIAction::RSIActionNONE); // Set Software Positive Limit Action.
    axis->HomeActionSet(RSIAction::RSIActionNONE); // Set Home Action.
    const double positionToleranceMax =
    std::numeric_limits<double>::max() /
    10.0; // Reduce from max slightly, so XML to string serialization and deserialization works without throwing System.OverflowException
    axis->PositionToleranceCoarseSet(positionToleranceMax); // Set Settling Coarse Position Tolerance to max value
    axis->PositionToleranceFineSet(positionToleranceMax
    ); // Set Settling Fine Position Tolerance to max value (so Phantom axis will get immediate MotionDone when target is reached)
    axis->MotorTypeSet(RSIMotorType::RSIMotorTypePHANTOM); // Set the MotorType to phantom
    }

    Setup-Controller-cpp:

    Setup the controller with user defined axis counts and configuration.

    static void SetupController(MotionController *controller)
    {
    // Set the axis and motion counts
    // Get the axis objects and check them for errors
    CheckErrors(axisX);
    CheckErrors(axisY);
    // Check if we are using hardware or phantom axes
    {
    SampleAppsConfig::ConfigureHardwareAxes(controller, {axisX, axisY});
    }
    else
    {
    // Set the user units
    // Configure them as phantoms
    }
    // Clear Faults
    axisX->ClearFaults();
    axisY->ClearFaults();
    // Start or shutdown the network depending on the configuration
    {
    StartTheNetwork(controller);
    }
    else
    {
    if (controller->NetworkStateGet() != RSINetworkState::RSINetworkStateUNINITIALIZED &&
    controller->NetworkStateGet() != RSINetworkState::RSINetworkStateSHUTDOWN)
    {
    std::cout << "The Sample Apps are configured to use Phantom Axes, but the network is not in the UNINITIALIZED or SHUTDOWN state.\n";
    std::cout << "If you intended to run with hardware, then follow the steps in README.md and /include/SampleAppsHelper.h\n";
    }
    ShutdownTheNetwork(controller);
    }
    }

    Setup-Controller-For-Hardware-cpp:

    Sets up the controller for hardware use by resetting it and starting the network.

    {
    ShutdownTheNetwork(controller);
    controller->Reset(); // Reset the controller to ensure it is in a known state.
    StartTheNetwork(controller);
    }

    Clear-Controller-Counts-cpp:

    Clears count settings for axes, motion, and user limits on the controller.

    static void ClearControllerCounts(MotionController *controller)
    {
    // Clear the counts
    controller->AxisCountSet(0);
    controller->MotionCountSet(0);
    controller->UserLimitCountSet(0);
    }

    Setup-Controller-For-Phantoms-cpp:

    Sets up the controller for phantom axes, including configuring specified axes as phantom.

    static void SetupControllerForPhantoms(MotionController *controller, int axisCount, std::vector<int> axisNums)
    {
    ShutdownTheNetwork(controller);
    ClearControllerCounts(controller);
    controller->AxisCountSet(axisCount);
    for (auto axisNum : axisNums)
    {
    ConfigurePhantomAxis(controller, axisNum);
    }
    }

    Print-Header-cpp:

    Print a start message to indicate that the sample app has started.

    static void PrintHeader(std::string sampleAppName)
    {
    std::cout << "----------------------------------------------------------------------------------------------------\n";
    std::cout << "Running " << sampleAppName << " Sample App\n";
    std::cout << "----------------------------------------------------------------------------------------------------\n" << std::endl;
    }

    Print-Footer-cpp:

    Print a message to indicate the sample app has finished and if it was successful or not.

    static void PrintFooter(std::string sampleAppName, int exitCode)
    {
    std::cout << "\n----------------------------------------------------------------------------------------------------\n";
    if (exitCode == 0)
    {
    std::cout << sampleAppName << " Sample App Completed Successfully\n";
    }
    else
    {
    std::cout << sampleAppName << " Sample App Failed with Exit Code: " << exitCode << "\n";
    }
    std::cout << "----------------------------------------------------------------------------------------------------\n" << std::endl;
    }