The RMP Motion Controller APIs
HelperFunctions.cs
1
42using RSI.RapidCode.dotNET; // Import our RapidCode Library
43using System;
44using NUnit.Framework;
45
46
47
48#if DOXYGEN // RSI internal documentation use only
49using RSI.RapidCode;
51#endif
52
56public static class HelperFunctions
57{
71 public static void CheckErrors(RapidCodeObject rsiObject)
72 {
73 bool hasErrors = false;
74 System.Text.StringBuilder errorStringBuilder = new System.Text.StringBuilder();
75 while (rsiObject.ErrorLogCountGet() > 0)
76 {
77 RsiError error = rsiObject.ErrorLogGet();
78
79 if (error.isWarning)
80 {
81 errorStringBuilder.AppendLine("WARNING: " + error.Message);
82 }
83 else
84 {
85 hasErrors = true;
86 errorStringBuilder.AppendLine("ERROR: " + error.Message);
87 }
88 }
89
90 if (errorStringBuilder.Length > 0)
91 {
92 Console.WriteLine(errorStringBuilder.ToString());
93 }
94
95 if (hasErrors)
96 {
97 throw new Exception(errorStringBuilder.ToString());
98 }
99 }
102
116 public static void StartTheNetwork(MotionController controller)
117 {
118 // Initialize the Network
119 if (controller.NetworkStateGet() != RSINetworkState.RSINetworkStateOPERATIONAL) // Check if network is started already.
120 {
121 Console.WriteLine("Starting Network..");
122 controller.NetworkStart(); // If not. Initialize The Network. (This can also be done from RapidSetup Tool)
123 }
124
125 if (controller.NetworkStateGet() != RSINetworkState.RSINetworkStateOPERATIONAL) // Check if network is started again.
126 {
127 int messagesToRead = controller.NetworkLogMessageCountGet(); // Some kind of error starting the network, read the network log messages
128
129 for (int i = 0; i < messagesToRead; i++)
130 {
131 Console.WriteLine(controller.NetworkLogMessageGet(i)); // Print all the messages to help figure out the problem
132 }
133 Console.WriteLine("Expected OPERATIONAL state but the network did not get there.");
134 //throw new RsiError(); // Uncomment if you want your application to exit when the network isn't operational. (Comment when using phantom axis)
135 }
136 else // Else, of network is operational.
137 {
138 Console.WriteLine("Network Started");
139 }
140 }
143}
144
146public static class Constants
147{
148 public const int SAMPLES = 2;
149 public const int AXIS_NUMBER = 0;
150 public const int X_AXIS_NUMBER = 0;
151 public const int Y_AXIS_NUMBER = 1;
152 public const int Z_AXIS_NUMBER = 2;
153 public const int A_AXIS_NUMBER = 3;
154 public const int B_AXIS_NUMBER = 4;
155 public const int C_AXIS_NUMBER = 5;
156 public const int MAIN_AXIS_NUMBER = 0;
157 public const int DRIVEN_AXIS_NUMBER = 1;
158 public const int HOLDING_AXIS_INDEX = 0;
159 public const int MOVING_AXIS_INDEX = 1;
160 public const int AXIS_COUNT = 6;
161 public const int FIRST_AXIS_NUMBER = 0;
162 public const int SECOND_AXIS_NUMBER = 1;
163 public const int THIRD_AXIS_NUMBER = 2;
164 public const double USER_UNITS = 1;
165 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)
166
168 public const double POSITION = 2; // Specify the position to travel to.
169 public const double VELOCITY = 200; // Specify your velocity. - units: UserUnits/Sec
170 public const double ACCELERATION = 100; // Specify your acceleration. - units: UserUnits/Sec^2
171 public const double DECELERATION = 100; // Specify your deceleration. - units: UserUnits/Sec^2
172 public const double JERK_PERCENT = 50; // Specify your jerk percent (0.0 to 100.0)
174
175 public const double POSITION_A = 5;
176 public const double POSITION_B = 10;
177 public const int MAX_TEST_TIME = 3000;
178 public const int COMP_NUM_ZERO = 0;
179 public const int COMP_NUM_ONE = 1;
180 public const int COMP_NUM_TWO = 2;
181}
182
184public class TestBase
185{
186 public MotionController controller;
187 public Axis axis;
188 public Axis x_axis;
189 public Axis y_axis;
190 public Axis z_axis;
191 public Axis a_axis;
192 public Axis b_axis;
193 public Axis c_axis;
194 public Axis prime_axis;
195 public Axis main_axis;
196 public Axis driven_axis;
197 public MultiAxis jointsMultiAxis;
198 public Robot robot;
199
201 public Axis CreateAndReadyAxis(int AxisNumber)
202 {
203 Axis axis = controller.AxisGet(AxisNumber); // Initialize Axis Class. (Use RapidSetup Tool to see what is your axis number)
204 HelperFunctions.CheckErrors(axis); // [Helper Function] Check that the axis has been initialize correctly.
205 ResetAxis(axis);
206 return axis;
207 }
209
210 public void InitializeAllAxes()
211 {
212 axis = controller.AxisGet(Constants.AXIS_NUMBER); // Initialize Axis Class. (Use RapidSetup Tool to see what is your axis number)
214 x_axis = controller.AxisGet(Constants.X_AXIS_NUMBER);
216 y_axis = controller.AxisGet(Constants.Y_AXIS_NUMBER);
218 z_axis = controller.AxisGet(Constants.Z_AXIS_NUMBER);
220 a_axis = controller.AxisGet(Constants.A_AXIS_NUMBER);
222 b_axis = controller.AxisGet(Constants.B_AXIS_NUMBER);
224 c_axis = controller.AxisGet(Constants.C_AXIS_NUMBER);
226 main_axis = controller.AxisGet(Constants.MAIN_AXIS_NUMBER);
227 HelperFunctions.CheckErrors(main_axis);
228 driven_axis = controller.AxisGet(Constants.DRIVEN_AXIS_NUMBER);
229 HelperFunctions.CheckErrors(driven_axis);
230 jointsMultiAxis = controller.MultiAxisGet(Constants.AXIS_COUNT);
231 HelperFunctions.CheckErrors(jointsMultiAxis);
232 }
233
234 public void DisableAllAxes()
235 {
236 for (int i = 0; i < controller.AxisCountGet(); i++)
237 {
238 Axis axis = controller.AxisGet(i);
240 axis.Abort();
241 axis.AmpEnableSet(false);
242 }
243 }
244
246 public void ResetAxis(Axis myAxis)
247 {
248 myAxis.ErrorLimitTriggerValueSet(1000);
249 myAxis.UserUnitsSet(Constants.USER_UNITS); // Specify the counts per Unit.
250 myAxis.PositionSet(0); // Sets the current position as 0 effectively 'homing' it.
251 myAxis.Abort(); // If there is any motion happening, abort it (creates a fault).
252 myAxis.DefaultAccelerationSet(Constants.ACCELERATION);
253 myAxis.DefaultDecelerationSet(Constants.ACCELERATION);
254 myAxis.DefaultVelocitySet(Constants.VELOCITY);
255
256 EnableAmp(myAxis);
257 }
259
261 public void EnableAmp(Axis myAxis)
262 {
263 myAxis.ClearFaults(); // To enable after an abort faults must be cleared.
264 myAxis.AmpEnableSet(true); // Enable the motor.
265 }
267
268 public void TearDownFixture()
269 {
270 DisableAllAxes();
271 controller.Shutdown();
272 controller.Delete();
273 }
274}
275
277public class SampleAppTestBase : TestBase
278{
279 [SetUp]
280 public void SetUp()
281 {
282 for (int i = 0; i < controller.AxisCountGet(); i++)
283 {
284 //@[AxisGet]
285 Axis axis = controller.AxisGet(i);
287 //@[AxisGet]
288 ResetAxis(axis);
289 }
290 }
291
292 [OneTimeSetUp]
293 public void OneTimeSetUp()
294 {
295 controller = MotionController.CreateFromSoftware(TestContext.CurrentContext.TestDirectory);// Insert the path location of the RMP.rta (usually the RapidSetup folder)
296 HelperFunctions.CheckErrors(controller); // [Helper Function] Check that the controller has been initialize correctly.
297 controller.AxisCountSet(Constants.AXIS_COUNT);
298 controller.MotionCountSet(Constants.AXIS_COUNT + 1); // Create a MultiAxis
299
300 InitializeAllAxes();
301 }
302
303 [TearDown]
304 public void TearDown()
305 {
306 DisableAllAxes();
307 }
308
309 [OneTimeTearDown]
310 public void OneTimeTearDown()
311 {
312 controller.Shutdown();
313 controller.Delete();
314 }
315}
316
318[TestFixture]
319[Category("Software")]
320public class StaticMemoryTestBase : TestBase
321{
322 [OneTimeSetUp]
323 public void OneTimeSetUp()
324 {
325 //@[ControllerReset]
326 controller = MotionController.CreateFromSoftware(TestContext.CurrentContext.TestDirectory);
327 controller.Reset(); // reboot the RMP controller firmware
328 //@[ControllerReset]
329 }
330
331 [SetUp]
332 public void Setup()
333 {
334 controller = MotionController.CreateFromSoftware(TestContext.CurrentContext.TestDirectory);
335 HelperFunctions.CheckErrors(controller);
336 }
337
338 [TearDown]
339 public void TearDown()
340 {
341 TearDownFixture(); // Teardown the entire fixture every time as the controller needs to be restarted between different static memory allocations
342 }
343}
344
346[TestFixture]
347[Category("Software")]
348public class HelperFunctionsTests : SampleAppTestBase
349 {
350 [Test]
351 public void CheckErrorsTest()
352 {
353 string expectedErrorSubstring = "Motion: MPIStateERROR"; // we expect this to be in the message
354 axis.ThrowExceptions(false); // exceptions will be logged, not thrown
355 axis.Abort(); // put into RSIStateERROR
356 axis.MoveSCurve(1); // command a move while in ERROR state - this will log an exception
357 Assert.Throws(Is.TypeOf<Exception>().And.Message.Contains(expectedErrorSubstring), () => HelperFunctions.CheckErrors(axis));
358 }
359
360 [Test]
361 public void CheckErrorsWarningTest()
362 {
363 const int BAD_AXIS_NUMBER = 777;
364 Axis badAxis = controller.AxisGet(BAD_AXIS_NUMBER); // try to get an illegal axis
365 Assert.Throws(Is.TypeOf<Exception>().And.Message.Contains(BAD_AXIS_NUMBER.ToString()), () => HelperFunctions.CheckErrors(badAxis));
366 }
367 }
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:5664
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:762
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:10564
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:178
Represents the error details thrown as an exception by all RapidCode classes. This class contains an ...
Definition rsi.h:105
bool isWarning
Whether the error is or is not a warning.
Definition rsi.h:114
RSINetworkState
State of network.
Definition rsienums.h:557
The Cartesian namespace.