APIs, concepts, guides, and more
Compensator.cs
Attention
See the following Concept pages for a detailed explanation of this sample: Compensator.
Warning
This is a sample program to assist in the integration of the RMP motion controller with your application. It may not contain all of the logic and safety features that your application requires. We recommend that you wire an external hardware emergency stop (e-stop) button for safety when using our code sample apps. Doing so will help ensure the safety of you and those around you and will prevent potential injury or damage.

The sample apps assume that the system (network, axes, I/O) are configured prior to running the code featured in the sample app. See the Configuration page for more information.
using RSI.RapidCode.dotNET; // Import our RapidCode Library.
using NUnit.Framework;
using System;
[TestFixture]
[Category("Software")]
class Compensator : StaticMemoryTestBase
{
//[Test, Timeout(Constants.MAX_TEST_TIME)]
[Test]
public void Compensator1D()
{
// To use a compensator space in memory must be reserved before creating axis objects. For this sample app we will create two overlapping compensation tables.
controller.CompensatorCountSet(2);
// To know how much memory will be required for the compensator table you must first know your MIN, MAX, and DELTA. See our compensator topic page for more information.
const int MIN = 0; // The smallest value in counts on the input axis where a table will be applied to the output axis.
const int MAX = 200; // The largest value in counts on the input axis where a table will be applied to the output axis.
const int DELTA = 10; // The number of encoder counts on the input axis between values in the table.
const int POINTS = ((MAX - MIN) / DELTA) + 1; // The space required in memory for the table to be held. (21)
// Compensator table values use Axis COUNTS NOT user units to be applied to the output axis.
double[] TABLE0 = new double[POINTS] { 0, 1000, -5000, -10000, 10000, 5000, -5000, 2500, 0, 2500, 5000, 7500, 1000, 1250, 1000, 7500, 5000, 2500, 0, -2500, -1000 };
double[] TABLE1 = new double[POINTS] { 0, 500, 0, 0, 0, 0, 0, 0, 0, 0, 1000, -5000, -1000, 1000, 5000, -5000, 2500, 0, -1000, 0, 0 };
// Reserve space in memory for the compensator tables.
controller.CompensatorPointCountSet(Constants.COMP_NUM_ZERO, TABLE0.Length);
controller.CompensatorPointCountSet(Constants.COMP_NUM_ONE, TABLE1.Length);
controller.AxisCountSet(2);
Axis moving_axis = CreateAndReadyAxis(Constants.MAIN_AXIS_NUMBER); // Helper function to setup an axis
Axis follower_axis = CreateAndReadyAxis(Constants.DRIVEN_AXIS_NUMBER); // Helper function to setup an axis
// NOTE the three following values must be equal before a compensator can be configured. Otherwise an error will be thrown. See topic page for more info.
if (controller.CompensatorPointCountGet(Constants.COMP_NUM_ZERO) == TABLE0.Length && POINTS == TABLE0.Length)
{
// Initalize the Compensator
controller.CompensatorConfigSet(Constants.COMP_NUM_ZERO, moving_axis, RSIAxisMasterType.RSIAxisMasterTypeAXIS_ACTUAL_POSITION, MIN, MAX, DELTA, follower_axis, RSICompensatorOutputType.RSICompensatorOutputTypeSINGLE, TABLE0);
// You can also configure multiple overlaping compensation tables. Note the first compensator remains in SINGLE mode but the second is set to ADDITIVE
controller.CompensatorConfigSet(Constants.COMP_NUM_ONE, moving_axis, RSIAxisMasterType.RSIAxisMasterTypeAXIS_ACTUAL_POSITION, MIN, MAX, DELTA, follower_axis, RSICompensatorOutputType.RSICompensatorOutputTypeADDITIVE, TABLE1);
}
// NOTE the three following values must be equal before a compensator can be configured. Otherwise an error will be thrown. See topic page for more info.
Assert.That(controller.CompensatorPointCountGet(Constants.COMP_NUM_ZERO), Is.EqualTo(TABLE0.Length));
Assert.That(TABLE0.Length, Is.EqualTo(POINTS));
//---TEST ASSERT---
moving_axis.PositionSet(DELTA);//We move one index into the compensation table
Assert.That(follower_axis.CompensationPositionGet(), Is.EqualTo(TABLE0[1] + TABLE1[1]));
}
[Test]
public void Compensator2D()
{
// Constants
const int X_MIN = 0;
const int X_MAX = 500;
const int X_DELTA = 100;
const int Y_MIN = 0;
const int Y_MAX = 500;
const int Y_DELTA = 100;
const int COMPENSATOR_X_POINTS = ((X_MAX - X_MIN) / X_DELTA) + 1;
const int COMPENSATOR_Y_POINTS = ((Y_MAX - Y_MIN) / Y_DELTA) + 1;
const int POINTS = (COMPENSATOR_X_POINTS) * (COMPENSATOR_Y_POINTS);
// Compensator uses Axis COUNTS NOT user units
double[] TABLE = new double[POINTS] {
0, 0, 0, 0, 0, 0,
100, 200, -200, 10, 300, 0,
100, 200, -500, 400, 500, 0,
0, 0, 0, 0, 0, 0,
-300, 300, -300, -300, -300, 0,
0, 0, 0, 0, 0, 0,
};
// To use a compensator space in memory must be reserved before creating axis objects. For this sample app we will create two overlapping compensation tables.
controller.CompensatorCountSet(1);
controller.CompensatorPointCountSet(Constants.COMP_NUM_ZERO, TABLE.Length);
// Initialize Axes. (Use RapidSetup Tool to see what is your axis number)
controller.AxisCountSet(3);
Axis x = CreateAndReadyAxis(Constants.X_AXIS_NUMBER);
Axis y = CreateAndReadyAxis(Constants.Y_AXIS_NUMBER);
Axis z = CreateAndReadyAxis(Constants.Z_AXIS_NUMBER);
z.ErrorLimitTriggerValueSet(1); // Specify the position error limit trigger. (Learn more about this on our support page)
// Initalize the Compensator
controller.CompensatorConfigSet(Constants.COMP_NUM_ZERO, x, RSIAxisMasterType.RSIAxisMasterTypeAXIS_ACTUAL_POSITION, X_MIN, X_MAX, X_DELTA, y, RSIAxisMasterType.RSIAxisMasterTypeAXIS_ACTUAL_POSITION, Y_MIN, Y_MAX, Y_DELTA, z, RSICompensatorOutputType.RSICompensatorOutputTypeSINGLE, TABLE);
//---TEST ASSERT---
// Test first row first col
x.PositionSet(0);
y.PositionSet(0);
Assert.That(z.CompensationPositionGet(), Is.EqualTo(TABLE[0]));
// Test second row second col
x.PositionSet(X_DELTA);
y.PositionSet(Y_DELTA);
Assert.That(z.CompensationPositionGet(), Is.EqualTo(TABLE[7]));
// Test Third row third col
x.PositionSet(X_DELTA * 2);
y.PositionSet(Y_DELTA * 2);
Assert.That(z.CompensationPositionGet(), Is.EqualTo(TABLE[14]));
}
[Test]
public void CompensatorSingleAxis()
{
Console.WriteLine("Start SompensatorSingleAxis");
// Constants
const int MIN = 10;
const int MAX = 210;
const int DELTA = 10;
const int POINTS = ((MAX - MIN) / DELTA) + 1; //21
// Compensator uses Axis COUNTS NOT user units
double[] TABLE = new double[POINTS] { 0, 2, -3, -5, -3, 2, -3, 0, 2, -3, -5, -3, 2, -3, 0, 2, -3, -5, -3, 2, -3 };
// Setup memory space for the compensator
controller.CompensatorCountSet(1);
controller.CompensatorPointCountSet(Constants.COMP_NUM_ZERO, TABLE.Length);
// Initialize Axes. (Use RapidSetup Tool to see what is your axis number)
controller.AxisCountSet(1);
Axis axis = CreateAndReadyAxis(Constants.AXIS_NUMBER);
// NOTE the three following values must be equal before a compensator can be configured. Otherwise an error will be thrown. See topic page for more info.
if (controller.CompensatorPointCountGet(Constants.COMP_NUM_ZERO) == TABLE.Length && POINTS == TABLE.Length)
{
controller.CompensatorConfigSet(Constants.COMP_NUM_ZERO, axis, RSIAxisMasterType.RSIAxisMasterTypeAXIS_COMMAND_POSITION, MIN, MAX, DELTA, axis, RSICompensatorOutputType.RSICompensatorOutputTypeSINGLE, TABLE);
axis.MoveSCurve(DELTA * 2); // Note multiply by to to get to index because min=delta
axis.MotionDoneWait();
controller.SampleWait(Constants.SAMPLES);
}
// NOTE the three following values must be equal before a compensator can be configured. Otherwise an error will be thrown. See topic page for more info.
Assert.That(controller.CompensatorPointCountGet(Constants.COMP_NUM_ZERO), Is.EqualTo(TABLE.Length));
Assert.That(TABLE.Length, Is.EqualTo(POINTS));
Assert.That(axis.CompensationPositionGet(), Is.EqualTo(TABLE[1]));
Console.WriteLine("End SompensatorSingleAxis");
}
}
int32_t CompensatorPointCountGet(int32_t compensatorNumber)
Get the number of points for use with a Compensator.
void CompensatorPointCountSet(int32_t compensatorNumber, int32_t pointCount)
Set the number of points for use with a Compensator.
void SampleWait(uint32_t samples)
Wait for controller firmware to execute samples.
void CompensatorCountSet(int32_t compensatorCount)
Set the number of Compensators available in the firmware.
void CompensatorConfigSet(int32_t compensatorNumber, int32_t firstInputAxisNumber, RSIAxisMasterType firstInputAxisType, double firstInputAxisMinimum, double firstInputAxisMaximum, double firstInputAxisDelta, int32_t secondInputAxisNumber, RSIAxisMasterType secondInputAxisType, double secondInputAxisMinimum, double secondInputAxisMaximum, double secondInputAxisDelta, int32_t outputAxisNumber, RSICompensatorOutputType outputType, const double *const table)
Configure a 2D compensator.
void AxisCountSet(int32_t axisCount)
Set the number of allocated and processed axes in the controller.