3 using System.Threading;
4 using System.Threading.Tasks;
7 using System.Diagnostics;
13 [Category(
"Software")]
14 class RapidSequencerAPIExample : SampleAppTestBase
17 static string samplesDirectory = TestContext.CurrentContext.TestDirectory +
@"\examples\rapidsequencer\";
19 static string samplesDirectory = TestContext.CurrentContext.TestDirectory +
@"\..\examples\rapidsequencer\";
22 string multipleTasksSampleFile = samplesDirectory +
"MultipleTasks.sq";
24 int GLOBAL_TEST_LOOPS;
26 public String _nodeName;
27 public String _rmpNodeName;
30 public String workingDir = TestContext.CurrentContext.TestDirectory;
33 public ulong timeoutMs;
35 private void ShutdownSequencers()
45 string runShell(
string cmd,
string cmdArgs)
47 Process cliProcess =
new Process()
49 StartInfo =
new ProcessStartInfo(cmd, cmdArgs)
51 UseShellExecute =
false,
52 RedirectStandardOutput =
true
56 string cliOut = cliProcess.StandardOutput.ReadToEnd();
57 cliProcess.WaitForExit();
63 bool hasValipIP(
string ifconfigOutput)
65 string[] invalidIPs = {
"0.0.0.0",
"127.0.0.1" };
66 System.Text.RegularExpressions.Regex ipv4Regex =
new System.Text.RegularExpressions.Regex(
@"inet\s+\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b");
68 System.Text.RegularExpressions.Match ipv4Match = ipv4Regex.Match(ifconfigOutput);
70 while (ipv4Match.Success)
72 string ipv4String = ipv4Match.Groups[1].Value;
73 if (!invalidIPs.Contains(ipv4String))
78 ipv4Match = ipv4Match.NextMatch();
83 void ConfigureINtimeNetworkStack()
85 string intime_base = Environment.ExpandEnvironmentVariables(
"%intime%");
86 string piperta = intime_base +
"bin\\piperta";
87 string ifconfig =
"-node " + this._nodeName +
" \"" + intime_base +
"network7\\ifconfig\"";
88 string netload =
"-node " + this._nodeName +
" \"" + intime_base +
"network7\\netload\"";
90 string ifconfigOut = runShell(piperta, ifconfig);
91 bool validIP = hasValipIP(ifconfigOut);
97 runShell(piperta, netload);
99 ifconfigOut = runShell(piperta, ifconfig);
101 validIP = hasValipIP(ifconfigOut);
103 Assert.IsTrue(validIP,
"ifconfig did not return a valid IP address (even after netload)!");
107 public void SetupFixture()
111 ConfigureINtimeNetworkStack();
113 ShutdownSequencers();
115 if (controller !=
null)
117 controller.InterruptEnableSet(
false);
120 controller = MotionController.CreateFromSoftware(TestContext.CurrentContext.TestDirectory);
121 int frameSendReceiveMicroseconds = 0;
122 controller.MemorySet(controller.AddressGet(
RSIControllerAddressType.RSIControllerAddressTypeFRAME_SEND_RECEIVE_MICROSECONDS), frameSendReceiveMicroseconds);
124 for (
int index = 0; index < controller.AxisCountGet(); index++)
126 AxisSetup(controller.AxisGet(index));
135 private void FastWaitForDone(Axis axis)
137 const int MAX_LOOPS = 100;
139 while (!axis.MotionDoneGet())
143 if (loops > MAX_LOOPS)
144 Assert.Fail(
"Failed waiting for motion done (fast) on Axis " + axis.NumberGet());
148 public static UInt64 DedidcatedInputAddressGet(Axis axis)
151 var dedicatedInPointerAddress = axis.AddressGet(
RSIAxisAddressType.RSIAxisAddressTypeDEDICATED_INPUTS_POINTER);
152 var dedicatedInPointer = axis.rsiControl.MemoryGet(dedicatedInPointerAddress);
153 var dedicatedInAddress = axis.rsiControl.HostAddressGet((uint)dedicatedInPointer);
154 return dedicatedInAddress;
157 public void AxisSetup(Axis axis)
159 while (axis.ErrorLogCountGet() > 0)
161 axis.ErrorLogClear();
163 axis.ThrowExceptions(
true);
165 const double USER_UNITS = 1000.0;
166 axis.UserUnitsSet(USER_UNITS);
168 axis.InterruptEnableSet(
false);
170 const double ACCELERATION = 1000000;
171 axis.EStopDecelerationSet(ACCELERATION);
174 axis.AmpFaultActionSet(
RSIAction.RSIActionNONE);
175 axis.HardwareNegLimitActionSet(
RSIAction.RSIActionNONE);
176 axis.HardwareNegLimitTriggerStateSet(
true);
177 axis.HardwarePosLimitActionSet(
RSIAction.RSIActionNONE);
178 axis.HardwarePosLimitTriggerStateSet(
true);
179 axis.ErrorLimitActionSet(
RSIAction.RSIActionNONE);
181 const double COARSE_POSITION_PHANTOM = Double.MaxValue / 10;
182 axis.PositionToleranceCoarseSet(COARSE_POSITION_PHANTOM);
184 const double FINE_POSITION_PHANTOM = Double.MaxValue / 10;
185 axis.PositionToleranceFineSet(FINE_POSITION_PHANTOM);
186 ulong dedicatedInAddress = DedidcatedInputAddressGet(axis);
187 axis.rsiControl.MemorySet(dedicatedInAddress, 0);
191 FastWaitForDone(axis);
193 Assert.That(axis.StateGet(), Is.EqualTo(
RSIState.RSIStateIDLE));
195 axis.CommandPositionSet(0);
196 axis.CommandPositionDirectSet(0);
197 axis.MotionCamRepeatStop();
198 axis.DefaultVelocitySet(Constants.VELOCITY);
199 axis.DefaultAccelerationSet(Constants.ACCELERATION);
200 axis.DefaultDecelerationSet(Constants.ACCELERATION);
201 axis.DefaultJerkPercentSet(Constants.JERK_PERCENT);
202 axis.BacklashWidthSet(0.0);
203 axis.BacklashRateSet(0.0);
206 axis.GearingDisable();
211 axis.MotionAttributeMaskDefaultSet();
214 Assert.That(axis.StateGet(), Is.EqualTo(
RSIState.RSIStateIDLE),
"Axis " + axis.NumberGet() +
" could not clear faults in AxisSetup. Source is: " + axis.SourceNameGet(axis.SourceGet()));
215 Assert.That(axis.CommandPositionGet(), Is.EqualTo(0),
"Axis " + axis.NumberGet() +
" command position is not zero.");
217 axis.FeedRateSet(1.0);
220 axis.EStopDecelerationSet(10000.0);
221 axis.EStopJerkPercentSet(50.0);
222 axis.TriggeredModifyDecelerationSet(10000.0);
223 axis.TriggeredModifyJerkPercentSet(50.0);
224 axis.SoftwareNegLimitActionSet(
RSIAction.RSIActionE_STOP);
225 axis.SoftwarePosLimitActionSet(
RSIAction.RSIActionE_STOP);
226 axis.SoftwareNegLimitTriggerValueSet(-1125899906842620);
227 axis.SoftwarePosLimitTriggerValueSet(1125899906842620);
228 axis.ErrorLimitTriggerValueSet(1000);
230 axis.FilterDualLoopSet((Axis)axis,
RSIMotorFeedback.RSIMotorFeedbackPRIMARY,
false);
232 axis.HomeOffsetSet(0.0);
235 axis.AmpEnableSet(
true);
239 public void TeardownFixture()
241 ShutdownSequencers();
245 public void TearDownSequencers()
247 ShutdownSequencers();
253 this._platform = platform;
255 this._nodeName =
"NodeB";
256 this._rmpNodeName =
"NodeA";
258 GLOBAL_TEST_LOOPS = loops;
266 public void TwoTasksSimultaneously()
268 Assert.That(this._platform, Is.EqualTo(
RSI.
RapidSequencer.Platform.INtime),
"Timing tests are only valid on real-time operating systems!");
276 string rmpPath = TestContext.CurrentContext.TestDirectory;
277 sequencer1.
EngineStart(this._rmpNodeName, rmpPath);
278 sequencer2.EngineStart(this._rmpNodeName, rmpPath);
281 sequencer1.Compile(multipleTasksSampleFile,
"RunEverySample");
282 sequencer2.Compile(multipleTasksSampleFile,
"RunEvery50Samples");
285 string runEverySampleTaskId = sequencer1.RunAsync();
286 string runEvery50SamplesTaskId = sequencer2.RunAsync();
291 for (
int i = 0; i < GLOBAL_TEST_LOOPS; i++)
300 Assert.That(loopCout.Value, Is.EqualTo(1),
"This must be 1 if the program is running every sample. Failed on loop " + i);
302 Assert.That(loopCout50.Value, Is.EqualTo(50),
"This must be 50 if the program is running every 50 samples. Failed on loop " + i);
308 sequencer1.TaskStop(runEverySampleTaskId);
309 sequencer2.TaskStop(runEvery50SamplesTaskId);
314 private void RunFunctionAndTestGlobal(
string functionName,
string globalName,
int expectedValue)
316 Assert.That(this._platform, Is.EqualTo(
RSI.
RapidSequencer.Platform.INtime),
"Timing tests are only valid on real-time operating systems!");
320 string rmpPath = TestContext.CurrentContext.TestDirectory;
323 sequencer.Compile(multipleTasksSampleFile, functionName);
325 string taskId = sequencer.RunAsync();
329 NUnit.Framework.Constraints.IResolveConstraint constraint;
332 constraint = Is.EqualTo(expectedValue);
336 constraint = Is.GreaterThanOrEqualTo(expectedValue);
339 for (
int i = 0; i < GLOBAL_TEST_LOOPS; i++)
343 Assert.That(globalValue.Value, constraint,
"This must be " + expectedValue +
" if the program is running every " + expectedValue +
" samples. Failed on loop #" + i);
347 sequencer.TaskStop(taskId);
351 public void RunEverySample()
353 RunFunctionAndTestGlobal(
"RunEverySample",
"loopCounterDelta", 1);
357 public void RunEvery50Samples()
359 RunFunctionAndTestGlobal(
"RunEvery50Samples",
"loopCounterDelta50", 50);
365 public void BasicGlobalData()
379 string rmpPath = TestContext.CurrentContext.TestDirectory;
383 sequencer.Compile(samplesDirectory +
"BasicGlobalData.sq",
"main");
386 string taskId = sequencer.RunAsync();
394 string globalIntName =
"globalInt";
395 int expectedIntValue = 2;
403 int intValue = globalInt.Value;
406 Assert.That(intValue, Is.EqualTo(expectedIntValue));
413 string globalDoubleName =
"globalDouble";
414 double expectedDoubleValue = globalInt.Value * 3.14159;
420 sequencer.GlobalVariableSet(globalDoubleName, dataType, expectedDoubleValue);
431 double doubleValue = globalDouble.Value;
434 Assert.That(doubleValue, Is.EqualTo(expectedDoubleValue));
437 Assert.That(globalDouble.Type, Is.EqualTo(
RSI.
RapidSequencer.
SequencerGlobal.DataType.Double), $
"Global variable {globalDoubleName} was not of type double!");
443 string output = sequencer.TaskOutputGet(taskId);
444 StringAssert.Contains($
"{expectedDoubleValue}", output, $
"Sequencer program output does not contain expected value {expectedDoubleValue}. Output: {output}");
447 sequencer.TaskStop(taskId);
452 public void MoveSCurve()
454 string fileNameString =
"MoveSCurve.sq";
459 string rmpPath = TestContext.CurrentContext.TestDirectory;
462 string entryPoint =
"main";
463 sequencer.Compile(samplesDirectory + fileNameString, entryPoint);
465 string taskId = sequencer.Run();
467 string output = sequencer.TaskOutputGet(taskId);
470 double expectedFinalPosition = 1.0;
471 Console.WriteLine($
"output: {output}");
472 StringAssert.Contains($
"{expectedFinalPosition}", output, $
"Sequencer program axis move did not reach final destination: {expectedFinalPosition}. Output: {output}");