The RMP Motion Controller APIs
Multiple Sequencers

Learn to use multiple sequencers at the same time.

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.


📜 Running Multiple Sequencers
The code below demonstrates how to use two sequencers to run two tasks simultaneously and poll the global variable in each RapidScript program.

// Create two RapidSequencer instances
RSI.RapidSequencer.RapidSequencer sequencer1 = RSI.RapidSequencer.RapidSequencerFactory.Create(this._platform, _nodeName, _rmpNodeName, workingDir, port, $"Sequencer-{port}", timeoutMs);
RSI.RapidSequencer.RapidSequencer sequencer2 = RSI.RapidSequencer.RapidSequencerFactory.Create(this._platform, _nodeName, _rmpNodeName, workingDir, port + 1, $"Sequencer-{port + 1}", timeoutMs);
// Call EngineStart() on both sequencers before performing any other actions.
string rmpPath = TestContext.CurrentContext.TestDirectory;
sequencer1.EngineStart(this._rmpNodeName, rmpPath);
sequencer2.EngineStart(this._rmpNodeName, rmpPath);
// Compile the same RapidScript program, but with different entry points.
sequencer1.Compile(multipleTasksSampleFile, "RunEverySample");
sequencer2.Compile(multipleTasksSampleFile, "RunEvery50Samples");
// Start both tasks and run them asynchronously.
string runEverySampleTaskId = sequencer1.RunAsync();
string runEvery50SamplesTaskId = sequencer2.RunAsync();
// Wait a little. These tasks run forever. Dont want to wait for them to finish.
Thread.Sleep(1000);
for (int i = 0; i < GLOBAL_TEST_LOOPS; i++)
{
// Get the values of the global variables.
RSI.RapidSequencer.SequencerGlobal loopCout = sequencer1.GlobalVariableGet("loopCounterDelta");
RSI.RapidSequencer.SequencerGlobal loopCout50 = sequencer2.GlobalVariableGet("loopCounterDelta50");
// Perform some checks on the values of the global variables.
// These asserts are just for demonstration and testing purposes, and are not be necessary in an actual application.
Assert.That(loopCout.Type, Is.EqualTo(RSI.RapidSequencer.SequencerGlobal.DataType.Int32), "Loop counter for every sample must be int32");
Assert.That(loopCout.Value, Is.EqualTo(1), "This must be 1 if the program is running every sample. Failed on loop " + i);
Assert.That(loopCout50.Type, Is.EqualTo(RSI.RapidSequencer.SequencerGlobal.DataType.Int32), "Loop counter for every 50 samples must be int32");
Assert.That(loopCout50.Value, Is.EqualTo(50), "This must be 50 if the program is running every 50 samples. Failed on loop " + i);
Thread.Sleep(2); // wait a couple samples so the values are updated
}
// Force the tasks to stop
sequencer1.TaskStop(runEverySampleTaskId);
sequencer2.TaskStop(runEvery50SamplesTaskId);


📜 Multiple Tasks in RapidScript
The code below is an example RapidScript program that continuously loops while keeping track of the number of motion controller samples that have elapsed during each iteration.

global bool runEverySample = true; // global, so we can set it true or false int RapidSetup. set to false to stop the program.
global int32 loopCounterDelta = 0; // allows us to view how many RMP samples have elapsed since the previous loop.
global int32 currentSampleCounter; // allows us to see the counter counting when we view globals in RapidSetup
void RunEverySample()
{
int32 lastSampleCounter = ControllerSampleCounterGet();
while(runEverySample)
{
currentSampleCounter = ControllerSampleCounterGet();
loopCounterDelta = currentSampleCounter - lastSampleCounter;
YourFastCyclicCodeGoesHere();
RMPSampleWait(1, currentSampleCounter);
lastSampleCounter = currentSampleCounter;
}
print("Done.");
}
global bool runEvery50Samples = true; // global, so we can set it true or false int RapidSetup. set to false to stop the program.
global int32 loopCounterDelta50; // allows us to view how many RMP samples have elapsed since the previous loop.
global int32 currentSampleCounter50;
void RunEvery50Samples()
{
int32 lastSampleCounter = ControllerSampleCounterGet();
while(runEvery50Samples)
{
currentSampleCounter50 = ControllerSampleCounterGet();
loopCounterDelta50 = currentSampleCounter50 - lastSampleCounter;
YourSlowCyclicCodeGoesHere();
RMPSampleWait(50, currentSampleCounter50); // wait 50 samples
lastSampleCounter = currentSampleCounter50;
}
print("Done.");
}
void RMPSampleWait(int32 samplesToWait, int32 startingSampleCounter)
{
while(ControllerSampleCounterGet() < (startingSampleCounter + samplesToWait))
{
wait(0); // yield to other tasks
}
}
void YourFastCyclicCodeGoesHere()
{
return;
}
void YourSlowCyclicCodeGoesHere()
{
ControllerSampleWait(25); // simulate doing something that takes 25ms to execute
}