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)
    {
    var hasErrors = false;
    var errorStrBuilder = new System.Text.StringBuilder();
    while (rsiObject.ErrorLogCountGet() > 0)
    {
    // get error
    RsiError rsiError = rsiObject.ErrorLogGet();
    // get message
    var errorMsg = rsiError.isWarning ? $"WARNING: {rsiError.Message}" : $"ERROR: {rsiError.Message}";
    errorStrBuilder.AppendLine(errorMsg);
    // set flag
    hasErrors = !rsiError.isWarning;
    }
    if (hasErrors)
    throw new Exception(errorStrBuilder.ToString());
    }

    *Network Start:**

    Start the network and print any errors encountered.

    public static void NetworkStart(MotionController controller)
    {
    // check if network is started already
    if (controller.NetworkStateGet() != RSINetworkState.RSINetworkStateOPERATIONAL)
    {
    Console.WriteLine("Starting Network..");
    // if not started, initialize the network
    controller.NetworkStart();
    }
    // check if network is started again
    if (controller.NetworkStateGet() != RSINetworkState.RSINetworkStateOPERATIONAL)
    {
    // read network log messages
    int messagesToRead = controller.NetworkLogMessageCountGet();
    // print all the messages to help figure out the problem
    for (int i = 0; i < messagesToRead; i++)
    Console.WriteLine(controller.NetworkLogMessageGet(i));
    throw new SystemException("Expected OPERATIONAL state but the network did not get there.");
    }
    else
    {
    Console.WriteLine("Network Started");
    }
    }

    *Network Shutdown:**

    Shutdown the network and print any errors encountered.

    public static void NetworkShutdown(MotionController controller)
    {
    // check if the network is already shutdown
    if (controller.NetworkStateGet() == RSINetworkState.RSINetworkStateUNINITIALIZED ||
    controller.NetworkStateGet() == RSINetworkState.RSINetworkStateSHUTDOWN)
    return;
    // shutdown the network
    Console.WriteLine("Shutting down the network..");
    controller.NetworkShutdown();
    // check if the network is shutdown
    var networkState = controller.NetworkStateGet();
    if (networkState != RSINetworkState.RSINetworkStateUNINITIALIZED &&
    networkState != RSINetworkState.RSINetworkStateSHUTDOWN)
    {
    // some kind of error shutting down the network, read the network log messages
    int messagesToRead = controller.NetworkLogMessageCountGet();
    // print all the messages to help figure out the problem
    for (int i = 0; i < messagesToRead; i++)
    Console.WriteLine(controller.NetworkLogMessageGet(i));
    throw new SystemException("Expected SHUTDOWN state but the network did not get there.");
    }
    else
    {
    Console.WriteLine("Network Shutdown");
    }
    }

    *Controller Setup:**

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

    public static void ControllerSetup(MotionController controller)
    {
    NetworkShutdown(controller);
    // reset the controller to ensure it is in a known state
    controller.Reset();
    NetworkStart(controller);
    }

    *Phantom Axis Reset:**

    Resets a phantom axis to a known state by disabling limits, setting tolerances, and clearing faults.

    public static void PhantomAxisReset(Axis phantomAxis)
    {
    if (phantomAxis.MotorTypeGet() != RSIMotorType.RSIMotorTypePHANTOM)
    {
    throw new Exception(@$"Axis {phantomAxis.NumberGet()} is not configured as a phantom axis.
    Please ensure the axis is set to phantom before calling PhantomAxisConfigure.");
    }
    // abort any motion
    AbortMotionObject(phantomAxis);
    // disable all limits (not used for phantom axes)
    phantomAxis.ErrorLimitActionSet(RSIAction.RSIActionNONE);
    phantomAxis.HardwareNegLimitActionSet(RSIAction.RSIActionNONE);
    phantomAxis.HardwarePosLimitActionSet(RSIAction.RSIActionNONE);
    phantomAxis.HomeActionSet(RSIAction.RSIActionNONE);
    phantomAxis.SoftwareNegLimitActionSet(RSIAction.RSIActionNONE);
    phantomAxis.SoftwarePosLimitActionSet(RSIAction.RSIActionNONE);
    // set position tolerances to max value for immediate MotionDone
    double POSITION_TOLERANCE_MAX = Double.MaxValue / 10.0;
    phantomAxis.PositionToleranceCoarseSet(POSITION_TOLERANCE_MAX);
    phantomAxis.PositionToleranceFineSet(POSITION_TOLERANCE_MAX);
    // set sample apps default motion parameters
    phantomAxis.UserUnitsSet(1);
    phantomAxis.DefaultVelocitySet(100);
    phantomAxis.DefaultAccelerationSet(1000);
    phantomAxis.DefaultDecelerationSet(1000);
    phantomAxis.DefaultJerkPercentSet(0);
    phantomAxis.PositionSet(0);
    }

  • 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.

    {
    // 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;
    // If you want to use hardware, then follow the instructions in the README before setting this to true.
    static constexpr bool USE_HARDWARE = false;
    static void ConfigureHardwareAxes(MotionController *controller)
    {
    // 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
    std::ostringstream message;
    message << "You must implement the " << __func__ << " function (found in " << __FILE__ << " line " << __LINE__ << ") to use hardware.";
    throw std::runtime_error(message.str().c_str());
    // Simple Axis Configuration Example:
    // (Look at the Axis: Configuration section in the RapidCode API Reference for more advanced configurations)
    /*
    const int USER_UNITS = 1048576; // example for 20-bit encoder, 2^20 = 1048576
    Axis *axis = controller->AxisGet(0);
    axis->UserUnitsSet(USER_UNITS);
    axis->PositionSet(0);
    axis->ErrorLimitTriggerValueSet(0.1 * USER_UNITS);
    axis->ErrorLimitActionSet(RSIAction::RSIActionABORT);
    axis->Abort();
    axis->ClearFaults();
    */
    }
    };

    *Get Creation Parameters:**

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

    #if _WIN32
    static MotionController::CreationParameters GetCreationParameters()
    {
    // Create a controller with using defined parameters
    MotionController::CreationParameters params;
    return params;
    }
    #elif __linux__
    static MotionController::CreationParameters GetCreationParameters()
    {
    MotionController::CreationParameters params;
    return params;
    }
    #endif

    *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, int numAxes = 0)
    {
    // Start or shutdown the network depending on the configuration
    {
    StartTheNetwork(controller);
    }
    else if (controller->NetworkStateGet() != RSINetworkState::RSINetworkStateUNINITIALIZED &&
    controller->NetworkStateGet() != RSINetworkState::RSINetworkStateSHUTDOWN)
    {
    std::ostringstream message;
    message << "The Sample Apps are configured to use Phantom Axes, but the network is not in the UNINITIALIZED or SHUTDOWN state.\n"
    << "If you intended to run with hardware, then follow the steps in README.md and /src/SampleAppsHelper.h\n"
    << "Otherwise, shutdown the network before running the sample apps with phantom axes.";
    throw std::runtime_error(message.str().c_str());
    }
    // Check if we are using hardware or phantom axes
    {
    // Let the user defined function configure the axes
    // Check that there are enough axes configured
    int axisCount = controller->AxisCountGet();
    if (axisCount < numAxes)
    {
    std::ostringstream message;
    message << "Error! Not enough axes configured. Expected " << numAxes << " axes but only found " << axisCount << " axes."
    << "Please configure the axes in the SampleAppsConfig::ConfigureHardwareAxes function.";
    throw std::runtime_error(message.str().c_str());
    }
    }
    else
    {
    // Record the initial object counts to restore later
    initialAxisCount = controller->AxisCountGet();
    // Add phantom axes for the sample app if needed
    if (numAxes > initialAxisCount)
    {
    controller->AxisCountSet(numAxes);
    }
    for (int i = 0; i < numAxes; i++)
    {
    ConfigurePhantomAxis(controller, i);
    }
    }
    }

    *Setup-Controller-For-Hardware-cpp:**

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

    static void SetupControllerForHardware(MotionController *controller)
    {
    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;
    }