APIs, concepts, guides, and more
SampleAppsHelper.h
1
90#ifndef SAMPLE_APPS_HELPER
91#define SAMPLE_APPS_HELPER
92
93#include "rsi.h" // Import our RapidCode Library.
94#include <algorithm>
95#include <cstdlib>
96#include <iostream>
97#include <string>
98
99using namespace RSI::RapidCode; // Import the RapidCode namespace
100
107{
108 // If you want to use hardware, then follow the instructions in the README before setting this to true.
109 static constexpr bool USE_HARDWARE = false;
110
111 // Motion Controller Creation Parameters
112 static constexpr char RMP_PATH[] = "";
113 static constexpr char NIC_PRIMARY[] = "";
114 static constexpr char NODE_NAME[] = "";
115 static constexpr int CPU_AFFINITY = 0;
116
117 // Controller Initial Object Counts (Sample Apps may change these counts as needed)
118 static constexpr int AXIS_COUNT = 2;
119 static constexpr int MOTION_COUNT = AXIS_COUNT;
120 static constexpr int USER_LIMIT_COUNT = 0;
121 static constexpr int MATH_BLOCK_COUNT = 0;
122 static constexpr int RECORDER_COUNT = 0;
123
124 // Axis Configuration Constants
125 // First (x) Axis configuration parameters
126 static constexpr int AXIS_X_USER_UNITS = 1;
127 static constexpr int AXIS_X_INDEX = 0;
128
129 // Second (y) Axis configuration parameters
130 static constexpr int AXIS_Y_USER_UNITS = 1;
131 static constexpr int AXIS_Y_INDEX = 1;
132
139 static void ConfigureHardwareAxes(MotionController *controller, std::vector<Axis *> axes)
140 {
141 // If you have configured your axes using rsiconfig, RapidSetup, or RapidSetupX then you can comment out this error and return.
142 // IMPLEMENTATION REQUIRED: Configure the axes for hardware
143 throw std::runtime_error("You must implement the ConfigureHardwareAxes function (found in /include/SampleAppsHelper.h) to use hardware.");
144
145 // Simple Axis Configuration Example:
146 // (Look at the Axis: Configuration section in the RapidCode API Reference for more advanced configurations)
147 /*
148 axes[0]->UserUnitsSet(USER_UNITS);
149 axes[0]->PositionSet(0);
150 axes[0]->ErrorLimitTriggerValueSet(0.1 * USER_UNITS);
151 axes[0]->ErrorLimitActionSet(RSIAction::RSIActionABORT);
152 axes[0]->Abort();
153 axes[0]->ClearFaults();
154 */
155 }
156};
158
165{
171#if _WIN32
173{
174 // Create a controller with using defined parameters
179 return params;
180}
181#elif __linux__
183{
188 return params;
189}
190#endif
192
200static void CheckErrors(RapidCodeObject *rsiObject)
201{
202 bool hasErrors = false;
203 std::string errorStrings("");
204 while (rsiObject->ErrorLogCountGet() > 0)
205 {
206 const RsiError *err = rsiObject->ErrorLogGet();
207
208 errorStrings += err->what();
209 errorStrings += "\n";
210
211 if (!err->isWarning)
212 {
213 hasErrors = true;
214 }
215 }
216
217 if (hasErrors)
218 {
219 throw std::runtime_error(errorStrings.c_str());
220 }
221}
223
231static void StartTheNetwork(MotionController *controller)
232{
233 // Initialize the Network
234 if (controller->NetworkStateGet() != RSINetworkState::RSINetworkStateOPERATIONAL) // Check if network is started already.
235 {
236 std::cout << "Starting Network.." << std::endl;
237 controller->NetworkStart(); // If not. Initialize The Network. (This can also be done from RapidSetup Tool)
238 }
239
240 if (controller->NetworkStateGet() != RSINetworkState::RSINetworkStateOPERATIONAL) // Check if network is started again.
241 {
242 int messagesToRead = controller->NetworkLogMessageCountGet(); // Some kind of error starting the network, read the network log messages
243
244 for (int i = 0; i < messagesToRead; i++)
245 {
246 std::cout << controller->NetworkLogMessageGet(i) << std::endl; // Print all the messages to help figure out the problem
247 }
248 throw std::runtime_error("Expected OPERATIONAL state but the network did not get there.");
249 }
250 else // Else, of network is operational.
251 {
252 std::cout << "Network Started" << std::endl << std::endl;
253 }
254}
256
264static void ShutdownTheNetwork(MotionController *controller)
265{
266 // Check if the network is already shutdown
267 if (controller->NetworkStateGet() == RSINetworkState::RSINetworkStateUNINITIALIZED ||
268 controller->NetworkStateGet() == RSINetworkState::RSINetworkStateSHUTDOWN)
269 {
270 return;
271 }
272
273 // Shutdown the network
274 std::cout << "Shutting down the network.." << std::endl;
275 controller->NetworkShutdown();
276
277 if (controller->NetworkStateGet() != RSINetworkState::RSINetworkStateUNINITIALIZED &&
278 controller->NetworkStateGet() != RSINetworkState::RSINetworkStateSHUTDOWN) // Check if the network is shutdown.
279 {
280 int messagesToRead = controller->NetworkLogMessageCountGet(); // Some kind of error shutting down the network, read the network log messages
281
282 for (int i = 0; i < messagesToRead; i++)
283 {
284 std::cout << controller->NetworkLogMessageGet(i) << std::endl; // Print all the messages to help figure out the problem
285 }
286 throw std::runtime_error("Expected SHUTDOWN state but the network did not get there.");
287 }
288 else // Else, of network is shutdown.
289 {
290 std::cout << "Network Shutdown" << std::endl << std::endl;
291 }
292}
294
303static void ConfigurePhantomAxis(MotionController *controller, int axisNumber)
304{
305 // Configure the specified axis as a phantom axis
306 Axis *axis = controller->AxisGet(axisNumber); // Initialize Axis class
307 CheckErrors(axis); // [Helper Function] Check that the axis has been initialized correctly
308
309 // 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)
310 // Therefore, you must set all of their actions to "NONE".
311 axis->PositionSet(0); // Set the position to 0
312 axis->ErrorLimitActionSet(RSIAction::RSIActionNONE); // Set Error Limit Action.
313 axis->AmpFaultActionSet(RSIAction::RSIActionNONE); // Set Amp Fault Action.
314 axis->AmpFaultTriggerStateSet(1); // Set Amp Fault Trigger State.
315 axis->HardwareNegLimitActionSet(RSIAction::RSIActionNONE); // Set Hardware Negative Limit Action.
316 axis->HardwarePosLimitActionSet(RSIAction::RSIActionNONE); // Set Hardware Positive Limit Action.
317 axis->SoftwareNegLimitActionSet(RSIAction::RSIActionNONE); // Set Software Negative Limit Action.
318 axis->SoftwarePosLimitActionSet(RSIAction::RSIActionNONE); // Set Software Positive Limit Action.
319 axis->HomeActionSet(RSIAction::RSIActionNONE); // Set Home Action.
320
321 const double positionToleranceMax =
322 std::numeric_limits<double>::max() /
323 10.0; // Reduce from max slightly, so XML to string serialization and deserialization works without throwing System.OverflowException
324 axis->PositionToleranceCoarseSet(positionToleranceMax); // Set Settling Coarse Position Tolerance to max value
325 axis->PositionToleranceFineSet(positionToleranceMax
326 ); // Set Settling Fine Position Tolerance to max value (so Phantom axis will get immediate MotionDone when target is reached)
327
328 axis->MotorTypeSet(RSIMotorType::RSIMotorTypePHANTOM); // Set the MotorType to phantom
329}
331
337static void SetupController(MotionController *controller)
338{
339 // Set the axis and motion counts
345
346 // Get the axis objects and check them for errors
347 Axis *axisX = controller->AxisGet(SampleAppsConfig::AXIS_X_INDEX);
348 CheckErrors(axisX);
349
350 Axis *axisY = controller->AxisGet(SampleAppsConfig::AXIS_Y_INDEX);
351 CheckErrors(axisY);
352
353 // Check if we are using hardware or phantom axes
355 {
356 SampleAppsConfig::ConfigureHardwareAxes(controller, {axisX, axisY});
357 }
358 else
359 {
360 // Set the user units
363
364 // Configure them as phantoms
367 }
368
369 // Clear Faults
370 axisX->ClearFaults();
371 axisY->ClearFaults();
372
373 // Start or shutdown the network depending on the configuration
375 {
376 StartTheNetwork(controller);
377 }
378 else
379 {
380 if (controller->NetworkStateGet() != RSINetworkState::RSINetworkStateUNINITIALIZED &&
381 controller->NetworkStateGet() != RSINetworkState::RSINetworkStateSHUTDOWN)
382 {
383 std::cout << "The Sample Apps are configured to use Phantom Axes, but the network is not in the UNINITIALIZED or SHUTDOWN state.\n";
384 std::cout << "If you intended to run with hardware, then follow the steps in README.md and /include/SampleAppsHelper.h\n";
385 }
386 ShutdownTheNetwork(controller);
387 }
388}
390
398{
399 ShutdownTheNetwork(controller);
400 controller->Reset(); // Reset the controller to ensure it is in a known state.
401 StartTheNetwork(controller);
402}
404
412{
413 // Clear the counts
414 controller->AxisCountSet(0);
415 controller->MotionCountSet(0);
416 controller->UserLimitCountSet(0);
417}
419
428static void SetupControllerForPhantoms(MotionController *controller, int axisCount, std::vector<int> axisNums)
429{
430 ShutdownTheNetwork(controller);
431
432 ClearControllerCounts(controller);
433
434 controller->AxisCountSet(axisCount);
435 for (auto axisNum : axisNums)
436 {
437 ConfigurePhantomAxis(controller, axisNum);
438 }
439}
441
447static void PrintHeader(std::string sampleAppName)
448{
449 std::cout << "----------------------------------------------------------------------------------------------------\n";
450 std::cout << "Running " << sampleAppName << " Sample App\n";
451 std::cout << "----------------------------------------------------------------------------------------------------\n" << std::endl;
452}
454
461static void PrintFooter(std::string sampleAppName, int exitCode)
462{
463 std::cout << "\n----------------------------------------------------------------------------------------------------\n";
464 if (exitCode == 0)
465 {
466 std::cout << sampleAppName << " Sample App Completed Successfully\n";
467 }
468 else
469 {
470 std::cout << sampleAppName << " Sample App Failed with Exit Code: " << exitCode << "\n";
471 }
472 std::cout << "----------------------------------------------------------------------------------------------------\n" << std::endl;
473}
475} // namespace SampleAppsHelper
476
477#endif // SAMPLE_APPS_HELPER
void HardwareNegLimitActionSet(RSIAction action)
Set the action that will occur when the Hardware Negative Limit Event triggers.
void HardwarePosLimitActionSet(RSIAction action)
Set the action that will occur when the Hardware Positive Limit Event triggers.
void PositionToleranceCoarseSet(double tolerance)
Set the Coarse Position Tolerance for Axis settling.
void SoftwareNegLimitActionSet(RSIAction action)
Set the action that will occur when the Software Negative Limit Event triggers.
void UserUnitsSet(double countsPerUserUnit)
Sets the number of counts per User Unit.
void AmpFaultActionSet(RSIAction action)
Set the Amp Fault action.
void AmpFaultTriggerStateSet(bool state)
Set the trigger state of the Amp Fault input.
void HomeActionSet(RSIAction action)
Set the action that will occur when the Home Event triggers.
void PositionToleranceFineSet(double tolerance)
Set the Fine Position Tolerance for Axis settling.
void ErrorLimitActionSet(RSIAction action)
Set the action that will occur when the Error Limit Event triggers.
void MotorTypeSet(RSIMotorType type)
Set the motor type.
void PositionSet(double position)
Set the Command and Actual positions.
void SoftwarePosLimitActionSet(RSIAction action)
Set the action that will occur when the Software Positive Limit Event triggers.
Represents a single axis of motion control. This class provides an interface for commanding motion,...
Definition rsi.h:5518
Axis * AxisGet(int32_t axisNumber)
AxisGet returns a pointer to an Axis object and initializes its internals.
RSINetworkState NetworkStateGet()
void MathBlockCountSet(int32_t mathBlockCount)
Set the number of processed MathBlocks in the MotionController.
void Reset()
Reset the controller which stops and restarts the RMP firmware.
void MotionCountSet(int32_t motionCount)
Set the number of processed Motion Supervisors in the controller.
const char *const NetworkLogMessageGet(int32_t messageIndex)
void RecorderCountSet(int32_t recorderCount)
Set the number of processed Recorders in the controller.
void UserLimitCountSet(int32_t userLimitCount)
Set the number of processed UserLimits in the MotionController.
void AxisCountSet(int32_t axisCount)
Set the number of allocated and processed axes in the controller.
Represents the RMP soft motion controller. This class provides an interface to general controller con...
Definition rsi.h:795
void NetworkShutdown()
Shutdown the network. For EtherCAT, this will kill the RMPNetwork process.
void NetworkStart()
Start the network with RSINetworkStartupMethodNORMAL.
void ClearFaults()
Clear all faults for an Axis or MultiAxis.
const RsiError *const ErrorLogGet()
Get the next RsiError in the log.
int32_t ErrorLogCountGet()
Get the number of software errors in the error log.
The RapidCode base class. All non-error objects are derived from this class.
Definition rsi.h:179
Represents the error details thrown as an exception by all RapidCode classes. This class contains an ...
Definition rsi.h:106
bool isWarning
Whether the error is or is not a warning.
Definition rsi.h:115
const char * what() const noexcept
Returns a null terminated character sequence that may be used to identify the exception.
Definition rsi.h:168
static void SetupControllerForHardware(MotionController *controller)
Sets up the controller for hardware use by resetting it and starting the network.
static void PrintFooter(std::string sampleAppName, int exitCode)
Print a message to indicate the sample app has finished and if it was successful or not.
static void ConfigurePhantomAxis(MotionController *controller, int axisNumber)
Configures a specified axis as a phantom axis with custom settings.
static void CheckErrors(RapidCodeObject *rsiObject)
Checks for errors in the given RapidCodeObject and throws an exception if any non-warning errors are ...
static void PrintHeader(std::string sampleAppName)
Print a start message to indicate that the sample app has started.
static void ShutdownTheNetwork(MotionController *controller)
Shuts down the network communication for the given MotionController.
static void SetupControllerForPhantoms(MotionController *controller, int axisCount, std::vector< int > axisNums)
Sets up the controller for phantom axes, including configuring specified axes as phantom.
static void ClearControllerCounts(MotionController *controller)
Clears count settings for axes, motion, and user limits on the controller.
static void StartTheNetwork(MotionController *controller)
Starts the network communication for the given MotionController.
static void SetupController(MotionController *controller)
Setup the controller with user defined axis counts and configuration.
static MotionController::CreationParameters GetCreationParameters()
Returns a MotionController::CreationParameters object with user-defined parameters.
SampleAppsHelper namespace provides static methods for common tasks in RMP applications.
char NodeName[PathLengthMaximum]
[Windows/INtime] Indicate the INtime node on which the RMP and RMPNetwork processes run.
Definition rsi.h:971
char RmpPath[PathLengthMaximum]
Location of the RMP firmware executable, license, and associated binaries and resources.
Definition rsi.h:939
int32_t CpuAffinity
[Linux] Indicate the CPU core on which the RMP and RMPNetwork processes run.
Definition rsi.h:991
char NicPrimary[PathLengthMaximum]
Primary EtherCAT Network Interface (NIC) name.
Definition rsi.h:945
static constexpr uint32_t PathLengthMaximum
MotionController::CreationParameters Maximum string buffer length.
Definition rsi.h:866
CreationParameters for MotionController::Create.
Definition rsi.h:856
static void ConfigureHardwareAxes(MotionController *controller, std::vector< Axis * > axes)
Configures the hardware axes according to user specified implementation.
This struct provides static methods and constants for user configuration in RMP applications....
static constexpr int CPU_AFFINITY
(Linux only) CPU core to use. This should be an isolated core.
static constexpr int AXIS_Y_USER_UNITS
User units for the second axis.
static constexpr int AXIS_COUNT
Number of axes to configure on the controller.
static constexpr int USER_LIMIT_COUNT
Number of user limits to configure on the controller.
static constexpr int MOTION_COUNT
Number of motion objects to configure on the controller.
static constexpr char NIC_PRIMARY[]
Name of the NIC to use for the EtherCAT network (not needed for running on phantom axes)
static constexpr int AXIS_X_INDEX
Index of the first axis to use in the sample apps.
static constexpr int MATH_BLOCK_COUNT
Number of math block objects to configure on the controller.
static constexpr bool USE_HARDWARE
Flag for whether to use hardware or phantom axes.
static constexpr char RMP_PATH[]
Path to the RMP.rta file (usually the RapidSetup folder).
static constexpr int AXIS_X_USER_UNITS
User units for the first axis.
static constexpr int RECORDER_COUNT
Number of recorder objects to configure on the controller.
static constexpr char NODE_NAME[]
(Windows only) INtime node name. Use "" for default node.
static constexpr int AXIS_Y_INDEX
Index of the second axis to use in the sample apps.