APIs, concepts, guides, and more
Helper Functions

This namespace includes the source code of all our SampleAppsCPP helper functions.

Helper functions were created to reduce code. Please note that if you would like to use this classes on your personal project you will have to replicate this class.

Precondition
This sample code presumes that the user has set the tuning paramters(PID, PIV, etc.) prior to running this program so that the motor can rotate in a stable manner.
Warning
This is a sample program to assist in the integration of the RMP motion controller with your application. It may not contain all of the logic and safety features that your application requires.

📜 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
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
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
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
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
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
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
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
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
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;
}