APIs, concepts, guides, and more
HelperFunctions.cs
1
46using RSI.RapidCode.dotNET; // Import our RapidCode Library
47using System;
48using NUnit.Framework;
49
50
51
52#if DOXYGEN // RSI internal documentation use only
53using RSI.RapidCode;
55#endif
56
60public static class HelperFunctions
61{
75 public static void CheckErrors(RapidCodeObject rsiObject)
76 {
77 bool hasErrors = false;
78 System.Text.StringBuilder errorStringBuilder = new System.Text.StringBuilder();
79 while (rsiObject.ErrorLogCountGet() > 0)
80 {
81 RsiError error = rsiObject.ErrorLogGet();
82
83 if (error.isWarning)
84 {
85 errorStringBuilder.AppendLine("WARNING: " + error.Message);
86 }
87 else
88 {
89 hasErrors = true;
90 errorStringBuilder.AppendLine("ERROR: " + error.Message);
91 }
92 }
93
94 if (errorStringBuilder.Length > 0)
95 {
96 Console.WriteLine(errorStringBuilder.ToString());
97 }
98
99 if (hasErrors)
100 {
101 throw new Exception(errorStringBuilder.ToString());
102 }
103 }
106
120 public static void StartTheNetwork(MotionController controller)
121 {
122 // Initialize the Network
123 if (controller.NetworkStateGet() != RSINetworkState.RSINetworkStateOPERATIONAL) // Check if network is started already.
124 {
125 Console.WriteLine("Starting Network..");
126 controller.NetworkStart(); // If not. Initialize The Network. (This can also be done from RapidSetup Tool)
127 }
128
129 if (controller.NetworkStateGet() != RSINetworkState.RSINetworkStateOPERATIONAL) // Check if network is started again.
130 {
131 int messagesToRead = controller.NetworkLogMessageCountGet(); // Some kind of error starting the network, read the network log messages
132
133 for (int i = 0; i < messagesToRead; i++)
134 {
135 Console.WriteLine(controller.NetworkLogMessageGet(i)); // Print all the messages to help figure out the problem
136 }
137 Console.WriteLine("Expected OPERATIONAL state but the network did not get there.");
138 //throw new RsiError(); // Uncomment if you want your application to exit when the network isn't operational. (Comment when using phantom axis)
139 }
140 else // Else, of network is operational.
141 {
142 Console.WriteLine("Network Started");
143 }
144 }
147}
148
150public static class Constants
151{
152 public const int SAMPLES = 2;
153 public const int AXIS_NUMBER = 0;
154 public const int X_AXIS_NUMBER = 0;
155 public const int Y_AXIS_NUMBER = 1;
156 public const int Z_AXIS_NUMBER = 2;
157 public const int A_AXIS_NUMBER = 3;
158 public const int B_AXIS_NUMBER = 4;
159 public const int C_AXIS_NUMBER = 5;
160 public const int MAIN_AXIS_NUMBER = 0;
161 public const int DRIVEN_AXIS_NUMBER = 1;
162 public const int HOLDING_AXIS_INDEX = 0;
163 public const int MOVING_AXIS_INDEX = 1;
164 public const int AXIS_COUNT = 6;
165 public const int FIRST_AXIS_NUMBER = 0;
166 public const int SECOND_AXIS_NUMBER = 1;
167 public const int THIRD_AXIS_NUMBER = 2;
168 public const double USER_UNITS = 1;
169 public const double AKD_USER_UNITS = 1048576; // USER UNITS for an AKD drive 1 rev (the motor used in this sample app has 1048576 encoder pulses per revolution)
170
172 public const double POSITION = 2; // Specify the position to travel to.
173 public const double VELOCITY = 200; // Specify your velocity. - units: UserUnits/Sec
174 public const double ACCELERATION = 100; // Specify your acceleration. - units: UserUnits/Sec^2
175 public const double DECELERATION = 100; // Specify your deceleration. - units: UserUnits/Sec^2
176 public const double JERK_PERCENT = 50; // Specify your jerk percent (0.0 to 100.0)
178
179 public const double POSITION_A = 5;
180 public const double POSITION_B = 10;
181 public const int MAX_TEST_TIME = 3000;
182 public const int COMP_NUM_ZERO = 0;
183 public const int COMP_NUM_ONE = 1;
184 public const int COMP_NUM_TWO = 2;
185}
186
188public class TestBase
189{
190 public MotionController controller;
191 public Axis axis;
192 public Axis x_axis;
193 public Axis y_axis;
194 public Axis z_axis;
195 public Axis a_axis;
196 public Axis b_axis;
197 public Axis c_axis;
198 public Axis prime_axis;
199 public Axis main_axis;
200 public Axis driven_axis;
201 public MultiAxis jointsMultiAxis;
202 public Robot robot;
203
205 public Axis CreateAndReadyAxis(int AxisNumber)
206 {
207 Axis axis = controller.AxisGet(AxisNumber); // Initialize Axis Class. (Use RapidSetup Tool to see what is your axis number)
208 HelperFunctions.CheckErrors(axis); // [Helper Function] Check that the axis has been initialize correctly.
209 ResetAxis(axis);
210 return axis;
211 }
213
214 public void InitializeAllAxes()
215 {
216 axis = controller.AxisGet(Constants.AXIS_NUMBER); // Initialize Axis Class. (Use RapidSetup Tool to see what is your axis number)
218 x_axis = controller.AxisGet(Constants.X_AXIS_NUMBER);
220 y_axis = controller.AxisGet(Constants.Y_AXIS_NUMBER);
222 z_axis = controller.AxisGet(Constants.Z_AXIS_NUMBER);
224 a_axis = controller.AxisGet(Constants.A_AXIS_NUMBER);
226 b_axis = controller.AxisGet(Constants.B_AXIS_NUMBER);
228 c_axis = controller.AxisGet(Constants.C_AXIS_NUMBER);
230 main_axis = controller.AxisGet(Constants.MAIN_AXIS_NUMBER);
231 HelperFunctions.CheckErrors(main_axis);
232 driven_axis = controller.AxisGet(Constants.DRIVEN_AXIS_NUMBER);
233 HelperFunctions.CheckErrors(driven_axis);
234 jointsMultiAxis = controller.MultiAxisGet(Constants.AXIS_COUNT);
235 HelperFunctions.CheckErrors(jointsMultiAxis);
236 }
237
238 public void DisableAllAxes()
239 {
240 for (int i = 0; i < controller.AxisCountGet(); i++)
241 {
242 Axis axis = controller.AxisGet(i);
244 axis.Abort();
245 axis.AmpEnableSet(false);
246 }
247 }
248
250 public void ResetAxis(Axis myAxis)
251 {
252 myAxis.ErrorLimitTriggerValueSet(1000);
253 myAxis.UserUnitsSet(Constants.USER_UNITS); // Specify the counts per Unit.
254 myAxis.PositionSet(0); // Sets the current position as 0 effectively 'homing' it.
255 myAxis.Abort(); // If there is any motion happening, abort it (creates a fault).
256 myAxis.DefaultAccelerationSet(Constants.ACCELERATION);
257 myAxis.DefaultDecelerationSet(Constants.ACCELERATION);
258 myAxis.DefaultVelocitySet(Constants.VELOCITY);
259
260 EnableAmp(myAxis);
261 }
263
265 public void EnableAmp(Axis myAxis)
266 {
267 myAxis.ClearFaults(); // To enable after an abort faults must be cleared.
268 myAxis.AmpEnableSet(true); // Enable the motor.
269 }
271
272 public void TearDownFixture()
273 {
274 DisableAllAxes();
275 controller.Shutdown();
276 controller.Delete();
277 }
278}
279
281public class SampleAppTestBase : TestBase
282{
283 [SetUp]
284 public void SetUp()
285 {
286 for (int i = 0; i < controller.AxisCountGet(); i++)
287 {
288 //@[AxisGet]
289 Axis axis = controller.AxisGet(i);
291 //@[AxisGet]
292 ResetAxis(axis);
293 }
294 }
295
296 [OneTimeSetUp]
297 public void OneTimeSetUp()
298 {
299 controller = MotionController.CreateFromSoftware(TestContext.CurrentContext.TestDirectory);// Insert the path location of the RMP.rta (usually the RapidSetup folder)
300 HelperFunctions.CheckErrors(controller); // [Helper Function] Check that the controller has been initialize correctly.
301 controller.AxisCountSet(Constants.AXIS_COUNT);
302 controller.MotionCountSet(Constants.AXIS_COUNT + 1); // Create a MultiAxis
303
304 InitializeAllAxes();
305 }
306
307 [TearDown]
308 public void TearDown()
309 {
310 DisableAllAxes();
311 }
312
313 [OneTimeTearDown]
314 public void OneTimeTearDown()
315 {
316 controller.Shutdown();
317 controller.Delete();
318 }
319}
320
322[TestFixture]
323[Category("Software")]
324public class StaticMemoryTestBase : TestBase
325{
326 [OneTimeSetUp]
327 public void OneTimeSetUp()
328 {
329 //@[ControllerReset]
330 controller = MotionController.CreateFromSoftware(TestContext.CurrentContext.TestDirectory);
331 controller.Reset(); // reboot the RMP controller firmware
332 //@[ControllerReset]
333 }
334
335 [SetUp]
336 public void Setup()
337 {
338 controller = MotionController.CreateFromSoftware(TestContext.CurrentContext.TestDirectory);
339 HelperFunctions.CheckErrors(controller);
340 }
341
342 [TearDown]
343 public void TearDown()
344 {
345 TearDownFixture(); // Teardown the entire fixture every time as the controller needs to be restarted between different static memory allocations
346 }
347}
348
350[TestFixture]
351[Category("Software")]
352public class HelperFunctionsTests : SampleAppTestBase
353 {
354 [Test]
355 public void CheckErrorsTest()
356 {
357 string expectedErrorSubstring = "Motion: MPIStateERROR"; // we expect this to be in the message
358 axis.ThrowExceptions(false); // exceptions will be logged, not thrown
359 axis.Abort(); // put into RSIStateERROR
360 axis.MoveSCurve(1); // command a move while in ERROR state - this will log an exception
361 Assert.Throws(Is.TypeOf<Exception>().And.Message.Contains(expectedErrorSubstring), () => HelperFunctions.CheckErrors(axis));
362 }
363
364 [Test]
365 public void CheckErrorsWarningTest()
366 {
367 const int BAD_AXIS_NUMBER = 777;
368 Axis badAxis = controller.AxisGet(BAD_AXIS_NUMBER); // try to get an illegal axis
369 Assert.Throws(Is.TypeOf<Exception>().And.Message.Contains(BAD_AXIS_NUMBER.ToString()), () => HelperFunctions.CheckErrors(badAxis));
370 }
371 }
static void CheckErrors(RapidCodeObject rsiObject)
Check if the RapidCodeObject has any errors.
static void StartTheNetwork(MotionController controller)
Start the controller communication/network.
Helper Functions for checking logged creation errors, starting the network, etc.
void UserUnitsSet(double countsPerUserUnit)
Sets the number of counts per User Unit.
void ErrorLimitTriggerValueSet(double triggerValue)
Set the Position Error Limit trigger value.
void PositionSet(double position)
Set the Command and Actual positions.
void MoveSCurve(double position, double vel, double accel, double decel, double jerkPct)
Command a point-to-point S-Curve motion.
Represents a single axis of motion control. This class provides an interface for commanding motion,...
Definition rsi.h:5518
void DefaultVelocitySet(double velocity)
Set the default velocity in UserUnits.
void DefaultAccelerationSet(double acceleration)
Set the default acceleration in UserUnits.
void DefaultDecelerationSet(double deceleration)
Set the default deceleration in UserUnits.
Represents a collection of joints in Cartesian space with forward and inverse kinematics....
Axis * AxisGet(int32_t axisNumber)
AxisGet returns a pointer to an Axis object and initializes its internals.
RSINetworkState NetworkStateGet()
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)
static MotionController * CreateFromSoftware()
Initialize and start the RMP EtherCAT controller.
void Delete(void)
Delete the MotionController and all its objects.
void Shutdown()
Shutdown the controller.
MultiAxis * MultiAxisGet(int32_t motionSupervisorNumber)
MultiAxisGet returns a pointer to a MultiAxis object and initializes its internals.
int32_t AxisCountGet()
Get the number of axes processing.
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 NetworkStart()
Start the network with RSINetworkStartupMethodNORMAL.
Represents multiple axes of motion control, allows you to map two or more Axis objects together for e...
Definition rsi.h:10213
void ClearFaults()
Clear all faults for an Axis or MultiAxis.
void AmpEnableSet(bool enable)
Enable all amplifiers.
void Abort()
Abort an axis.
void ThrowExceptions(bool state)
Configure a class to throw exceptions.
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
RSINetworkState
State of network.
Definition rsienums.h:565
The Cartesian namespace.