APIs, concepts, guides, and more
SampleAppsHelper.h
1#ifndef SAMPLE_APPS_HELPER
2#define SAMPLE_APPS_HELPER
3
4#include "rsi.h" // Import our RapidCode Library.
5#include <algorithm>
6#include <cstdlib>
7#include <iostream>
8#include <string>
9#include <sstream>
10
11using namespace RSI::RapidCode; // Import the RapidCode namespace
12
19{
20 // Motion Controller Creation Parameters
21 static constexpr char RMP_PATH[] = "";
22 static constexpr char NIC_PRIMARY[] = "";
23 static constexpr char NODE_NAME[] = "";
24 static constexpr int CPU_AFFINITY = 0;
25
26 // If you want to use hardware, then follow the instructions in the README before setting this to true.
27 static constexpr bool USE_HARDWARE = false;
28
34 static void ConfigureHardwareAxes(MotionController *controller)
35 {
36 // If you have configured your axes using rsiconfig, RapidSetup, or RapidSetupX then you can comment out this error and return.
37 // IMPLEMENTATION REQUIRED: Configure the axes for hardware
38 std::ostringstream message;
39 message << "You must implement the " << __func__ << " function (found in " << __FILE__ << " line " << __LINE__ << ") to use hardware.";
40 throw std::runtime_error(message.str().c_str());
41
42 // Simple Axis Configuration Example:
43 // (Look at the Axis: Configuration section in the RapidCode API Reference for more advanced configurations)
44 /*
45 const int USER_UNITS = 1048576; // example for 20-bit encoder, 2^20 = 1048576
46 Axis *axis = controller->AxisGet(0);
47 axis->UserUnitsSet(USER_UNITS);
48 axis->PositionSet(0);
49 axis->ErrorLimitTriggerValueSet(0.1 * USER_UNITS);
50 axis->ErrorLimitActionSet(RSIAction::RSIActionABORT);
51 axis->Abort();
52 axis->ClearFaults();
53 */
54 }
55};
56
57
64{
70#if _WIN32
72{
73 // Create a controller with using defined parameters
78 return params;
79}
80#elif __linux__
82{
87 return params;
88}
89#endif
91
99static void CheckErrors(RapidCodeObject *rsiObject)
100{
101 bool hasErrors = false;
102 std::string errorStrings("");
103 while (rsiObject->ErrorLogCountGet() > 0)
104 {
105 const RsiError *err = rsiObject->ErrorLogGet();
106
107 errorStrings += err->what();
108 errorStrings += "\n";
109
110 if (!err->isWarning)
111 {
112 hasErrors = true;
113 }
114 }
115
116 if (hasErrors)
117 {
118 throw std::runtime_error(errorStrings.c_str());
119 }
120}
121
122
130static void StartTheNetwork(MotionController *controller)
131{
132 // Initialize the Network
133 if (controller->NetworkStateGet() != RSINetworkState::RSINetworkStateOPERATIONAL) // Check if network is started already.
134 {
135 std::cout << "Starting Network.." << std::endl;
136 controller->NetworkStart(); // If not. Initialize The Network. (This can also be done from RapidSetup Tool)
137 }
138
139 if (controller->NetworkStateGet() != RSINetworkState::RSINetworkStateOPERATIONAL) // Check if network is started again.
140 {
141 int messagesToRead = controller->NetworkLogMessageCountGet(); // Some kind of error starting the network, read the network log messages
142
143 for (int i = 0; i < messagesToRead; i++)
144 {
145 std::cout << controller->NetworkLogMessageGet(i) << std::endl; // Print all the messages to help figure out the problem
146 }
147 throw std::runtime_error("Expected OPERATIONAL state but the network did not get there.");
148 }
149 else // Else, of network is operational.
150 {
151 std::cout << "Network Started" << std::endl << std::endl;
152 }
153}
154
155
163static void ShutdownTheNetwork(MotionController *controller)
164{
165 // Check if the network is already shutdown
166 if (controller->NetworkStateGet() == RSINetworkState::RSINetworkStateUNINITIALIZED ||
167 controller->NetworkStateGet() == RSINetworkState::RSINetworkStateSHUTDOWN)
168 {
169 return;
170 }
171
172 // Shutdown the network
173 std::cout << "Shutting down the network.." << std::endl;
174 controller->NetworkShutdown();
175
176 if (controller->NetworkStateGet() != RSINetworkState::RSINetworkStateUNINITIALIZED &&
177 controller->NetworkStateGet() != RSINetworkState::RSINetworkStateSHUTDOWN) // Check if the network is shutdown.
178 {
179 int messagesToRead = controller->NetworkLogMessageCountGet(); // Some kind of error shutting down the network, read the network log messages
180
181 for (int i = 0; i < messagesToRead; i++)
182 {
183 std::cout << controller->NetworkLogMessageGet(i) << std::endl; // Print all the messages to help figure out the problem
184 }
185 throw std::runtime_error("Expected SHUTDOWN state but the network did not get there.");
186 }
187 else // Else, of network is shutdown.
188 {
189 std::cout << "Network Shutdown" << std::endl << std::endl;
190 }
191}
192
193
202static void ConfigurePhantomAxis(MotionController *controller, int axisNumber)
203{
204 // Configure the specified axis as a phantom axis
205 Axis *axis = controller->AxisGet(axisNumber); // Initialize Axis class
206 CheckErrors(axis); // [Helper Function] Check that the axis has been initialized correctly
207
208 // 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)
209 // Therefore, you must set all of their actions to "NONE".
210 axis->PositionSet(0); // Set the position to 0
211 axis->ErrorLimitActionSet(RSIAction::RSIActionNONE); // Set Error Limit Action.
212 axis->AmpFaultActionSet(RSIAction::RSIActionNONE); // Set Amp Fault Action.
213 axis->AmpFaultTriggerStateSet(1); // Set Amp Fault Trigger State.
214 axis->HardwareNegLimitActionSet(RSIAction::RSIActionNONE); // Set Hardware Negative Limit Action.
215 axis->HardwarePosLimitActionSet(RSIAction::RSIActionNONE); // Set Hardware Positive Limit Action.
216 axis->SoftwareNegLimitActionSet(RSIAction::RSIActionNONE); // Set Software Negative Limit Action.
217 axis->SoftwarePosLimitActionSet(RSIAction::RSIActionNONE); // Set Software Positive Limit Action.
218 axis->HomeActionSet(RSIAction::RSIActionNONE); // Set Home Action.
219
220 const double positionToleranceMax =
221 std::numeric_limits<double>::max() /
222 10.0; // Reduce from max slightly, so XML to string serialization and deserialization works without throwing System.OverflowException
223 axis->PositionToleranceCoarseSet(positionToleranceMax); // Set Settling Coarse Position Tolerance to max value
224 axis->PositionToleranceFineSet(positionToleranceMax
225 ); // Set Settling Fine Position Tolerance to max value (so Phantom axis will get immediate MotionDone when target is reached)
226
227 axis->MotorTypeSet(RSIMotorType::RSIMotorTypePHANTOM); // Set the MotorType to phantom
228}
229
230
231static int initialAxisCount = -1;
232static int initialMotionCount = -1;
233
239static void SetupController(MotionController *controller, int numAxes = 0)
240 {
241 // Start or shutdown the network depending on the configuration
243 {
244 StartTheNetwork(controller);
245 }
246 else if (controller->NetworkStateGet() != RSINetworkState::RSINetworkStateUNINITIALIZED &&
247 controller->NetworkStateGet() != RSINetworkState::RSINetworkStateSHUTDOWN)
248 {
249 std::ostringstream message;
250 message << "The Sample Apps are configured to use Phantom Axes, but the network is not in the UNINITIALIZED or SHUTDOWN state.\n"
251 << "If you intended to run with hardware, then follow the steps in README.md and /src/SampleAppsHelper.h\n"
252 << "Otherwise, shutdown the network before running the sample apps with phantom axes.";
253
254 throw std::runtime_error(message.str().c_str());
255 }
256
257 // Check if we are using hardware or phantom axes
259 {
260 // Let the user defined function configure the axes
262
263 // Check that there are enough axes configured
264 int axisCount = controller->AxisCountGet();
265 if (axisCount < numAxes)
266 {
267 std::ostringstream message;
268 message << "Error! Not enough axes configured. Expected " << numAxes << " axes but only found " << axisCount << " axes."
269 << "Please configure the axes in the SampleAppsConfig::ConfigureHardwareAxes function.";
270 throw std::runtime_error(message.str().c_str());
271 }
272 }
273 else
274 {
275 // Record the initial object counts to restore later
276 initialAxisCount = controller->AxisCountGet();
277 initialMotionCount = controller->MotionCountGet();
278
279 // Add phantom axes for the sample app if needed
280 if (numAxes > initialAxisCount)
281 {
282 controller->AxisCountSet(numAxes);
283 }
284
285 for (int i = 0; i < numAxes; i++)
286 {
287 ConfigurePhantomAxis(controller, i);
288 }
289 }
290 }
291
292
298static void Cleanup(MotionController* controller)
299{
300 // Restore the object counts to the original values
301 if (initialAxisCount != -1) { controller->AxisCountSet(initialAxisCount); }
302 if (initialMotionCount != -1) { controller->MotionCountSet(initialMotionCount); }
303
304 // Reset the object counts
305 initialAxisCount = -1;
307}
308
309
317{
318 ShutdownTheNetwork(controller);
319 controller->Reset(); // Reset the controller to ensure it is in a known state.
320 StartTheNetwork(controller);
321}
322
323
331{
332 // Clear the counts
333 controller->AxisCountSet(0);
334 controller->MotionCountSet(0);
335 controller->UserLimitCountSet(0);
336}
337
338
347static void SetupControllerForPhantoms(MotionController *controller, int axisCount, std::vector<int> axisNums)
348{
349 ShutdownTheNetwork(controller);
350
351 ClearControllerCounts(controller);
352
353 controller->AxisCountSet(axisCount);
354 for (auto axisNum : axisNums)
355 {
356 ConfigurePhantomAxis(controller, axisNum);
357 }
358}
359
360
366static void PrintHeader(std::string sampleAppName)
367{
368 std::cout << "----------------------------------------------------------------------------------------------------\n";
369 std::cout << "Running " << sampleAppName << " Sample App\n";
370 std::cout << "----------------------------------------------------------------------------------------------------\n" << std::endl;
371}
372
373
380static void PrintFooter(std::string sampleAppName, int exitCode)
381{
382 std::cout << "\n----------------------------------------------------------------------------------------------------\n";
383 if (exitCode == 0)
384 {
385 std::cout << sampleAppName << " Sample App Completed Successfully\n";
386 }
387 else
388 {
389 std::cout << sampleAppName << " Sample App Failed with Exit Code: " << exitCode << "\n";
390 }
391 std::cout << "----------------------------------------------------------------------------------------------------\n" << std::endl;
392}
393
394} // namespace SampleAppsHelper
395
396#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 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:5863
Represents the RMP soft motion controller. This class provides an interface to general controller con...
Definition rsi.h:800
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:184
Represents the error details thrown as an exception by all RapidCode classes. This class contains an ...
Definition rsi.h:111
bool isWarning
Whether the error is or is not a warning.
Definition rsi.h:120
const char * what() const noexcept
Returns a null terminated character sequence that may be used to identify the exception.
Definition rsi.h:173
@ RSINetworkStateSHUTDOWN
EtherCAT was shutdown or stopped, must restart.
Definition rsienums.h:575
@ RSINetworkStateOPERATIONAL
EtherCAT operational, good state.
Definition rsienums.h:573
@ RSINetworkStateUNINITIALIZED
EtherCAT not yet started.
Definition rsienums.h:569
@ RSIActionNONE
None - do not perform any action.
Definition rsienums.h:1116
@ RSIMotorTypePHANTOM
Phantom motor (nothing physically connected).
Definition rsienums.h:1314
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 Cleanup(MotionController *controller)
Cleanup the controller and restore the object counts to the original values.
static MotionController::CreationParameters GetCreationParameters()
Returns a MotionController::CreationParameters object with user-defined parameters.
static void SetupController(MotionController *controller, int numAxes=0)
Setup the controller with user defined axis counts and configuration.
SampleAppsHelper namespace provides static methods for common tasks in RMP applications.
static int initialAxisCount
Initial axis count to restore later (-1 indicates it has not been set).
static int initialMotionCount
Initial motion count to restore later (-1 indicates it has not been set).
char NodeName[PathLengthMaximum]
[Windows/INtime] Indicate the INtime node on which the RMP and RMPNetwork processes run.
Definition rsi.h:994
char RmpPath[PathLengthMaximum]
Location of the RMP firmware executable, license, and associated binaries and resources.
Definition rsi.h:962
int32_t CpuAffinity
[Linux] Indicate the CPU core on which the RMP and RMPNetwork processes run.
Definition rsi.h:1014
char NicPrimary[PathLengthMaximum]
Primary EtherCAT Network Interface (NIC) name.
Definition rsi.h:968
static constexpr uint32_t PathLengthMaximum
MotionController::CreationParameters Maximum string buffer length.
Definition rsi.h:882
CreationParameters for MotionController::Create.
Definition rsi.h:866
static void ConfigureHardwareAxes(MotionController *controller)
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 char NIC_PRIMARY[]
Name of the NIC to use for the EtherCAT network (not needed for running on phantom axes).
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 char NODE_NAME[]
(Windows only) INtime node name. Use "" for default node.