The RMP Motion Controller APIs
HelperFunctions.cs
using RSI.RapidCode.dotNET; // Import our RapidCode Library
using System;
using NUnit.Framework;
#if DOXYGEN // RSI internal documentation use only
#endif
public static class HelperFunctions
{
public static void CheckErrors(RapidCodeObject rsiObject)
{
bool hasErrors = false;
System.Text.StringBuilder errorStringBuilder = new System.Text.StringBuilder();
while (rsiObject.ErrorLogCountGet() > 0)
{
RsiError error = rsiObject.ErrorLogGet();
if (error.isWarning)
{
errorStringBuilder.AppendLine("WARNING: " + error.Message);
}
else
{
hasErrors = true;
errorStringBuilder.AppendLine("ERROR: " + error.Message);
}
}
if (errorStringBuilder.Length > 0)
{
Console.WriteLine(errorStringBuilder.ToString());
}
if (hasErrors)
{
throw new Exception(errorStringBuilder.ToString());
}
}
public static void StartTheNetwork(MotionController controller)
{
// Initialize the Network
if (controller.NetworkStateGet() != RSINetworkState.RSINetworkStateOPERATIONAL) // Check if network is started already.
{
Console.WriteLine("Starting Network..");
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++)
{
Console.WriteLine(controller.NetworkLogMessageGet(i)); // Print all the messages to help figure out the problem
}
Console.WriteLine("Expected OPERATIONAL state but the network did not get there.");
//throw new RsiError(); // Uncomment if you want your application to exit when the network isn't operational. (Comment when using phantom axis)
}
else // Else, of network is operational.
{
Console.WriteLine("Network Started");
}
}
}
public static class Constants
{
public const int SAMPLES = 2;
public const int AXIS_NUMBER = 0;
public const int X_AXIS_NUMBER = 0;
public const int Y_AXIS_NUMBER = 1;
public const int Z_AXIS_NUMBER = 2;
public const int A_AXIS_NUMBER = 3;
public const int B_AXIS_NUMBER = 4;
public const int C_AXIS_NUMBER = 5;
public const int MAIN_AXIS_NUMBER = 0;
public const int DRIVEN_AXIS_NUMBER = 1;
public const int HOLDING_AXIS_INDEX = 0;
public const int MOVING_AXIS_INDEX = 1;
public const int AXIS_COUNT = 6;
public const int FIRST_AXIS_NUMBER = 0;
public const int SECOND_AXIS_NUMBER = 1;
public const int THIRD_AXIS_NUMBER = 2;
public const double USER_UNITS = 1;
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)
public const double POSITION = 2; // Specify the position to travel to.
public const double VELOCITY = 200; // Specify your velocity. - units: UserUnits/Sec
public const double ACCELERATION = 100; // Specify your acceleration. - units: UserUnits/Sec^2
public const double DECELERATION = 100; // Specify your deceleration. - units: UserUnits/Sec^2
public const double JERK_PERCENT = 50; // Specify your jerk percent (0.0 to 100.0)
public const double POSITION_A = 5;
public const double POSITION_B = 10;
public const int MAX_TEST_TIME = 3000;
public const int COMP_NUM_ZERO = 0;
public const int COMP_NUM_ONE = 1;
public const int COMP_NUM_TWO = 2;
}
public class TestBase
{
public MotionController controller;
public Axis axis;
public Axis x_axis;
public Axis y_axis;
public Axis z_axis;
public Axis a_axis;
public Axis b_axis;
public Axis c_axis;
public Axis prime_axis;
public Axis main_axis;
public Axis driven_axis;
public MultiAxis jointsMultiAxis;
public Robot robot;
public Axis CreateAndReadyAxis(int AxisNumber)
{
Axis axis = controller.AxisGet(AxisNumber); // Initialize Axis Class. (Use RapidSetup Tool to see what is your axis number)
HelperFunctions.CheckErrors(axis); // [Helper Function] Check that the axis has been initialize correctly.
ResetAxis(axis);
return axis;
}
public void InitializeAllAxes()
{
axis = controller.AxisGet(Constants.AXIS_NUMBER); // Initialize Axis Class. (Use RapidSetup Tool to see what is your axis number)
x_axis = controller.AxisGet(Constants.X_AXIS_NUMBER);
y_axis = controller.AxisGet(Constants.Y_AXIS_NUMBER);
z_axis = controller.AxisGet(Constants.Z_AXIS_NUMBER);
a_axis = controller.AxisGet(Constants.A_AXIS_NUMBER);
b_axis = controller.AxisGet(Constants.B_AXIS_NUMBER);
c_axis = controller.AxisGet(Constants.C_AXIS_NUMBER);
main_axis = controller.AxisGet(Constants.MAIN_AXIS_NUMBER);
driven_axis = controller.AxisGet(Constants.DRIVEN_AXIS_NUMBER);
jointsMultiAxis = controller.MultiAxisGet(Constants.AXIS_COUNT);
HelperFunctions.CheckErrors(jointsMultiAxis);
}
public void DisableAllAxes()
{
for (int i = 0; i < controller.AxisCountGet(); i++)
{
Axis axis = controller.AxisGet(i);
axis.Abort();
axis.AmpEnableSet(false);
}
}
public void ResetAxis(Axis myAxis)
{
myAxis.UserUnitsSet(Constants.USER_UNITS); // Specify the counts per Unit.
myAxis.PositionSet(0); // Sets the current position as 0 effectively 'homing' it.
myAxis.Abort(); // If there is any motion happening, abort it (creates a fault).
myAxis.DefaultAccelerationSet(Constants.ACCELERATION);
myAxis.DefaultDecelerationSet(Constants.ACCELERATION);
myAxis.DefaultVelocitySet(Constants.VELOCITY);
EnableAmp(myAxis);
}
public void EnableAmp(Axis myAxis)
{
myAxis.ClearFaults(); // To enable after an abort faults must be cleared.
myAxis.AmpEnableSet(true); // Enable the motor.
}
public void TearDownFixture()
{
DisableAllAxes();
controller.Shutdown();
controller.Delete();
}
}
public class SampleAppTestBase : TestBase
{
[SetUp]
public void SetUp()
{
for (int i = 0; i < controller.AxisCountGet(); i++)
{
//@[AxisGet]
Axis axis = controller.AxisGet(i);
//@[AxisGet]
ResetAxis(axis);
}
}
[OneTimeSetUp]
public void OneTimeSetUp()
{
controller = MotionController.CreateFromSoftware(TestContext.CurrentContext.TestDirectory);// Insert the path location of the RMP.rta (usually the RapidSetup folder)
HelperFunctions.CheckErrors(controller); // [Helper Function] Check that the controller has been initialize correctly.
controller.AxisCountSet(Constants.AXIS_COUNT);
controller.MotionCountSet(Constants.AXIS_COUNT + 1); // Create a MultiAxis
InitializeAllAxes();
}
[TearDown]
public void TearDown()
{
DisableAllAxes();
}
[OneTimeTearDown]
public void OneTimeTearDown()
{
controller.Shutdown();
controller.Delete();
}
}
[TestFixture]
[Category("Software")]
public class StaticMemoryTestBase : TestBase
{
[OneTimeSetUp]
public void OneTimeSetUp()
{
//@[ControllerReset]
controller = MotionController.CreateFromSoftware(TestContext.CurrentContext.TestDirectory);
controller.Reset(); // reboot the RMP controller firmware
//@[ControllerReset]
}
[SetUp]
public void Setup()
{
controller = MotionController.CreateFromSoftware(TestContext.CurrentContext.TestDirectory);
}
[TearDown]
public void TearDown()
{
TearDownFixture(); // Teardown the entire fixture every time as the controller needs to be restarted between different static memory allocations
}
}
[TestFixture]
[Category("Software")]
public class HelperFunctionsTests : SampleAppTestBase
{
[Test]
public void CheckErrorsTest()
{
string expectedErrorSubstring = "Motion: MPIStateERROR"; // we expect this to be in the message
axis.ThrowExceptions(false); // exceptions will be logged, not thrown
axis.Abort(); // put into RSIStateERROR
axis.MoveSCurve(1); // command a move while in ERROR state - this will log an exception
Assert.Throws(Is.TypeOf<Exception>().And.Message.Contains(expectedErrorSubstring), () => HelperFunctions.CheckErrors(axis));
}
[Test]
public void CheckErrorsWarningTest()
{
const int BAD_AXIS_NUMBER = 777;
Axis badAxis = controller.AxisGet(BAD_AXIS_NUMBER); // try to get an illegal axis
Assert.Throws(Is.TypeOf<Exception>().And.Message.Contains(BAD_AXIS_NUMBER.ToString()), () => HelperFunctions.CheckErrors(badAxis));
}
}
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.