The RMP Motion Controller APIs
MathBlock.cs
1
6using RSI.RapidCode.dotNET; // the RapidCode.NET library.
7using System;
8
9#if DOXYGEN // RSI internal documentation use only
10using RSI.RapidCode;
11#endif
12
14public class MathBlockDifferenceOfPositionUserLimit : SampleApp
15{
16 public override int Run()
17 {
19 /* CONSTANTS */
20 // *NOTICE* The following constants must be configured before attempting to run with hardware.
21
22 // Controller Object Counts
23 const int MATHBLOCK_COUNT = 1; // minimum required MathBlocks for this sample
24 const int AXIS_COUNT = 2; // minimum required axes for this sample
25 const int USER_LIMIT_COUNT = 1; // minimum required user limits for this sample
26
27 // Axis Configuration
28 const int FIRST_AXIS_INDEX = 0; // the first axis index
29 const int SECOND_AXIS_INDEX = 1; // the second axis index
30 const double USER_UNITS = 1048576; // counts per unit (the user units)
31
32 // MathBlock Configuration
33 const int MATHBLOCK_INDEX = 0; // the mathblock index
34
35 // User Limit Configuration
36 const int USER_LIMIT_INDEX = 0; // the user limit index
37 const double MAX_POSITION_DIFFERENCE = 0.5 * USER_UNITS; // the maximum position difference before the user limit triggers
38 const RSIAction USER_LIMIT_ACTION = RSIAction.RSIActionABORT; // the action to take when the user limit is triggered
39 const int USER_LIMIT_DURATION = 0; // the time delay before the action is executed after the User Limit has triggered
40
41 // Motion Parameters
42 const double RELATIVE_POSITION = 2 * MAX_POSITION_DIFFERENCE; // the relative position to move the axes
43 const double VELOCITY = 1; // the velocity to move the axes
44 const double ACCELERATION = 10; // the acceleration of the axes movement
45 const double DECELERATION = 10; // the deceleration of the axes movement
46 const double JERK_PCT = 0; // the jerk percentage of the axes movement
47
48 // To run with hardware, set the USE_HARDWARE flag to true AFTER you have configured the parameters above and taken proper safety precautions.
49 USE_HARDWARE = false;
50
51 // Determine which axis address type to use based on the USE_HARDWARE flag
52 RSIAxisAddressType INPUT_AXIS_ADDRESS_TYPE = (USE_HARDWARE) ?
53 (RSIAxisAddressType.RSIAxisAddressTypeACTUAL_POSITION) : (RSIAxisAddressType.RSIAxisAddressTypeCOMMAND_POSITION);
54
55 /* SAMPLE APP BODY */
56
57 // Initialize MotionController class.
58 // NOTICE: Replace "rmpPath" with the path location of the RMP.rta (usually the RapidSetup folder)
59 // if project directory is different than rapid setup directory.
60 MotionController controller = HelperFunctionsCS.CreateController(/*rmpPath*/);
61
62 // Use a try/catch/finally to ensure that the controller is deleted when done.
63 try
64 {
65 HelperFunctionsCS.CheckErrors(controller); // [Helper Function] Check that the axis has been initialize correctly.
66
67 // Setup the controller for the appropriate hardware configuration.
68 if (USE_HARDWARE)
69 {
70 HelperFunctionsCS.SetupControllerForHardware(controller);
71 }
72 else
73 {
74 HelperFunctionsCS.SetupControllerForPhantoms(controller, AXIS_COUNT, new int[] { FIRST_AXIS_INDEX, SECOND_AXIS_INDEX });
75 }
76
77 // configure the controller object counts
78 controller.MathBlockCountSet(MATHBLOCK_COUNT);
79 controller.MotionCountSet(AXIS_COUNT + 1);
80 controller.UserLimitCountSet(USER_LIMIT_COUNT);
81
82 // get both axis objects and check for errors
83 Axis axis0 = controller.AxisGet(FIRST_AXIS_INDEX);
84 HelperFunctionsCS.CheckErrors(axis0);
85 axis0.UserUnitsSet(USER_UNITS); // set the user units (counts per unit)
86 axis0.PositionSet(0); // set the initial position to 0
87 axis0.ErrorLimitActionSet(RSIAction.RSIActionNONE); // Set Error Limit Action.
88
89 Axis axis1 = controller.AxisGet(SECOND_AXIS_INDEX);
90 HelperFunctionsCS.CheckErrors(axis1);
91 axis1.UserUnitsSet(USER_UNITS); // set the user units (counts per unit)
92 axis1.PositionSet(0); // set the initial position to 0
93 axis1.ErrorLimitActionSet(RSIAction.RSIActionNONE); // Set Error Limit Action.
94
95 // configure a multiaxis for the two axes
96 MultiAxis multiAxis = controller.MultiAxisGet(AXIS_COUNT);
97 HelperFunctionsCS.CheckErrors(multiAxis);
98
99 multiAxis.AxisRemoveAll();
100 multiAxis.AxisAdd(axis0);
101 multiAxis.AxisAdd(axis1);
102
103 multiAxis.Abort(); // make sure the multiaxis is not moving
104 multiAxis.ClearFaults(); // clear any faults
105
106 // read the configuration of the MathBlock
107 MotionController.MathBlockConfig mathBlockConfig = controller.MathBlockConfigGet(MATHBLOCK_INDEX);
108
109 // configure the MathBlock to subtract the position of the second axis from the position of the first axis
110 mathBlockConfig.InputAddress0 = axis0.AddressGet(INPUT_AXIS_ADDRESS_TYPE);
111 mathBlockConfig.InputDataType0 = RSIDataType.RSIDataTypeDOUBLE;
112 mathBlockConfig.InputAddress1 = axis1.AddressGet(INPUT_AXIS_ADDRESS_TYPE);
113 mathBlockConfig.InputDataType1 = RSIDataType.RSIDataTypeDOUBLE;
114 mathBlockConfig.ProcessDataType = RSIDataType.RSIDataTypeDOUBLE;
115 mathBlockConfig.Operation = RSIMathBlockOperation.RSIMathBlockOperationSUBTRACT;
116
117 // set the MathBlock configuration
118 controller.MathBlockConfigSet(MATHBLOCK_INDEX, mathBlockConfig);
119
120 // wait a sample so we know the RMP is now processing the newly configured MathBlocks
121 controller.SampleWait(1);
122 Console.WriteLine("MathBlock configured to subtract the position of the second axis from the position of the first axis.");
123
124 // get the address of the MathBlock's ProcessValue to use in the UserLimit
125 ulong mathBlockProcessValueAddress = controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeMATHBLOCK_PROCESS_VALUE, MATHBLOCK_INDEX);
126
127 // configure the UserLimit to trigger when the absolute position difference is greater than MAX_POSITION_DIFFERENCE
128 controller.UserLimitConditionSet(USER_LIMIT_INDEX, 0, RSIUserLimitLogic.RSIUserLimitLogicABS_GT, mathBlockProcessValueAddress, MAX_POSITION_DIFFERENCE);
129
130 // set the UserLimit action to abort motion (Note: since the axes are in a multiaxis, the other axis will also be aborted)
131 controller.UserLimitConfigSet(USER_LIMIT_INDEX, RSIUserLimitTriggerType.RSIUserLimitTriggerTypeSINGLE_CONDITION, USER_LIMIT_ACTION, FIRST_AXIS_INDEX, USER_LIMIT_DURATION);
132 Console.WriteLine("UserLimit configured to trigger when the absolute position difference is greater than " + MAX_POSITION_DIFFERENCE + " and abort motion.");
133
134 // command motion to trigger the UserLimit
135 Console.WriteLine("Moving the axes to trigger the UserLimit...");
136 axis0.AmpEnableSet(true); // Enable the motor.
137 axis0.MoveRelative(RELATIVE_POSITION, VELOCITY, ACCELERATION, DECELERATION, JERK_PCT); // Move the axis to trigger the UserLimit.
138 axis0.MotionDoneWait(); // Wait for the axis to finish moving.
139
140 // disable the motor and the UserLimit
141 axis0.AmpEnableSet(false); // Disable the motor.
142 controller.UserLimitDisable(USER_LIMIT_INDEX); // Disable User Limit.
143
144 // the motion should have been aborted and both axes should be in an error state
145 if (axis0.StateGet().Equals(RSIState.RSIStateERROR) &&
146 axis1.StateGet().Equals(RSIState.RSIStateERROR))
147 {
148 Console.WriteLine("Both axes are in the error state after the UserLimit triggered (This is the intended behavior).");
149 return 0;
150 }
151 else
152 {
153 Console.WriteLine("Error: The axes should be in an error state after the UserLimit triggers, but they are not.");
154 Console.WriteLine("First Axis State: " + axis0.StateGet());
155 Console.WriteLine("Second Axis State: " + axis1.StateGet());
156 return -1;
157 }
158 }
159 catch (Exception e)
160 {
161 Console.WriteLine("Error: " + e.Message);
162 return -1;
163 }
164 finally
165 {
166 controller.Delete(); // Delete the controller object.
167 }
169 }
170}
171
172public class MathBlockCalculateAccelerationFromVelocity : SampleApp
173{
174 public override int Run()
175 {
177 /* CONSTANTS */
178 // *NOTICE* The following constants must be configured before attempting to run with hardware.
179
180 // Controller Object Counts
181 const int MATHBLOCK_COUNT = 2; // minimum required MathBlocks for this sample
182 const int AXIS_COUNT = 1; // minimum required axes for this sample
183
184 // Axis Configuration
185 const int AXIS_INDEX = 0; // the axis index
186 const double USER_UNITS = 1048576; // counts per unit (the user units)
187
188 // MathBlock Configuration
189 const int SUBTRACTION_MATHBLOCK_INDEX = 0; // the first mathblock index (for subtraction)
190
191 // the second mathblock index (for multiplying CommandVelocity * 1.0)
192 const int PREVIOUS_VELOCITY_MATHBLOCK_INDEX = 1; // index must be higher here than the subtraction math block index, so the subtraction data is one sample old
193 const double ONE = 1.0; // we'll write 1.0 to the UserBuffer so the MathBlock can use it for multiplication
194 const int USERBUFFER_INDEX = 0; // where we'll write 1.0 so the math block can use it
195
196 // Motion Parameters
197 const double VELOCITY = 1.0; // the velocity to move the axis
198 const double ACCELERATION = 0.123; // something small so we can check the MathBlock is working
199
200 // To run with hardware, set the USE_HARDWARE flag to true AFTER you have configured the parameters above and taken proper safety precautions.
201 USE_HARDWARE = false;
202
203 // Determine which axis address type to use based on the USE_HARDWARE flag
204 RSIAxisAddressType INPUT_AXIS_ADDRESS_TYPE = RSIAxisAddressType.RSIAxisAddressTypeCOMMAND_VELOCITY;
205
206 /* SAMPLE APP BODY */
207
208 // Initialize MotionController class.
209 // NOTICE: Replace "rmpPath" with the path location of the RMP.rta (usually the RapidSetup folder)
210 // if project directory is different than rapid setup directory.
211 MotionController controller = HelperFunctionsCS.CreateController(/*rmpPath*/);
212
213 // Use a try/catch/finally to ensure that the controller is deleted when done.
214 try
215 {
216 HelperFunctionsCS.CheckErrors(controller); // [Helper Function] Check that the axis has been initialize correctly.
217
218 // Setup the controller for the appropriate hardware configuration.
219 if (USE_HARDWARE)
220 {
221 HelperFunctionsCS.SetupControllerForHardware(controller);
222 }
223 else
224 {
225 HelperFunctionsCS.SetupControllerForPhantoms(controller, AXIS_COUNT, new int[] { AXIS_INDEX });
226 }
227
228 // configure the controller object counts
229 controller.MathBlockCountSet(MATHBLOCK_COUNT);
230
231 // write 1.0 to the UserBuffer so the MathBlock can use it for multiplication
232 controller.MemoryDoubleSet(controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeUSER_BUFFER, USERBUFFER_INDEX), ONE);
233
234 // get Axis object and check for errors
235 Axis axis = controller.AxisGet(AXIS_INDEX);
236 HelperFunctionsCS.CheckErrors(axis);
237 axis.UserUnitsSet(USER_UNITS); // set the user units (counts per unit)
238 axis.PositionSet(0); // set the initial position to 0
239 axis.ErrorLimitActionSet(RSIAction.RSIActionNONE); // Set Error Limit Action.
240
241 axis.Abort(); // make sure the axis is not moving
242 axis.ClearFaults(); // clear any faults
243
244 // read the configuration of both MathBlocks
245 MotionController.MathBlockConfig subtractionConfig = controller.MathBlockConfigGet(SUBTRACTION_MATHBLOCK_INDEX);
246 MotionController.MathBlockConfig previousVelocityConfig = controller.MathBlockConfigGet(PREVIOUS_VELOCITY_MATHBLOCK_INDEX);
247
248 // configure the first MathBlock to subtract the previous velocity from the current velocity
249 // current velocity:
250 subtractionConfig.InputAddress0 = axis.AddressGet(INPUT_AXIS_ADDRESS_TYPE);
251 subtractionConfig.InputDataType0 = RSIDataType.RSIDataTypeDOUBLE;
252 // previous velocity: (as was calculated by the second MathBlock, so we use its ProcesValue)
253 subtractionConfig.InputAddress1 = controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeMATHBLOCK_PROCESS_VALUE, PREVIOUS_VELOCITY_MATHBLOCK_INDEX);
254 subtractionConfig.InputDataType1 = RSIDataType.RSIDataTypeDOUBLE;
255 subtractionConfig.ProcessDataType = RSIDataType.RSIDataTypeDOUBLE;
256 subtractionConfig.Operation = RSIMathBlockOperation.RSIMathBlockOperationSUBTRACT;
257
258 // configure the second MathBlock to multiply the current velocity by 1.0 (which we'll use for the previous sample's velocity)
259 previousVelocityConfig.InputAddress0 = axis.AddressGet(INPUT_AXIS_ADDRESS_TYPE);
260 previousVelocityConfig.InputDataType0 = RSIDataType.RSIDataTypeDOUBLE;
261 previousVelocityConfig.InputAddress1 = controller.AddressGet(RSIControllerAddressType.RSIControllerAddressTypeUSER_BUFFER, USERBUFFER_INDEX);
262 previousVelocityConfig.InputDataType1 = RSIDataType.RSIDataTypeDOUBLE;
263 previousVelocityConfig.ProcessDataType = RSIDataType.RSIDataTypeDOUBLE;
264 previousVelocityConfig.Operation = RSIMathBlockOperation.RSIMathBlockOperationMULTIPLY;
265
266 // set the MathBlock configurations
267 controller.MathBlockConfigSet(SUBTRACTION_MATHBLOCK_INDEX, subtractionConfig);
268 controller.MathBlockConfigSet(PREVIOUS_VELOCITY_MATHBLOCK_INDEX, previousVelocityConfig);
269
270 // wait a sample so we know the RMP is now processing the newly configured MathBlocks
271 controller.SampleWait(1);
272
273 // Set the axis to move with a very small acceleration so we can check the MathBlock is working
274 axis.AmpEnableSet(true); // Enable the motor.
275 axis.MoveVelocity(VELOCITY, ACCELERATION);
276
277 // wait several samples so we know the RMP is now processing the move command and accelerating
278 controller.SampleWait(10);
279
280 // keep in mind firmware velocity is in counts per sample squared, so we need to convert to UserUnits per second squared
281 double calculatedAccelerationCountsPerSampleSquared = controller.MathBlockProcessValueGet(SUBTRACTION_MATHBLOCK_INDEX).Double;
282
283 // reduce the velocity back to 0
284 axis.MoveVelocity(0, ACCELERATION);
285
286 axis.MotionDoneWait(); // Wait for the axis to finish moving.
287 axis.AmpEnableSet(false); // Disable the motor.
288
289 // convert to UserUnits per second squared
290 double calculatedAcceleration = calculatedAccelerationCountsPerSampleSquared * controller.SampleRateGet() * controller.SampleRateGet() / axis.UserUnitsGet();
291 Console.WriteLine($"Calculated acceleration from MathBlock: {calculatedAcceleration}");
292
293 // check that the newly calculated acceleration is as expected
294 if (Math.Abs(calculatedAcceleration - ACCELERATION) <= 0.000001)
295 {
296 Console.WriteLine("The MathBlock is calculating the Axis' acceleration by subtracting previous velocity from current velocity.");
297 return 0;
298 }
299 else
300 {
301 Console.WriteLine("Error: The MathBlock is not calculating the Axis' acceleration as expected.");
302 return -1;
303 }
304 }
305 catch (Exception e)
306 {
307 Console.WriteLine("Error: " + e.Message);
308 return -1;
309 }
310 finally
311 {
312 controller.Delete(); // Delete the controller object.
313 }
315 }
316}
uint64_t AddressGet(RSIAxisAddressType addressType)
Get the an address for some location on the Axis.
double UserUnitsGet()
Get the number of counts per User Unit.
void UserUnitsSet(double countsPerUserUnit)
Sets the number of counts per User Unit.
void ErrorLimitActionSet(RSIAction action)
Set the action that will occur when the Error Limit Event triggers.
void MoveVelocity(double velocity)
void PositionSet(double position)
Set the Command and Actual positions.
void MoveRelative(double relativePosition, double vel, double accel, double decel, double jerkPct)
Command a relative 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
Axis * AxisGet(int32_t axisNumber)
AxisGet returns a pointer to an Axis object and initializes its internals.
void UserLimitDisable(int32_t number)
Disable the processing of a User Limit.
void MathBlockCountSet(int32_t mathBlockCount)
Set the number of processed MathBlocks in the MotionController.
void UserLimitConditionSet(int32_t number, int32_t conditionNumber, RSIUserLimitLogic logic, uint64_t addressOfUInt32, uint32_t userLimitMask, uint32_t limitValueUInt32)
Set the conditions for a User Limit with a 32-bit integer trigger value.
void MotionCountSet(int32_t motionCount)
Set the number of processed Motion Supervisors in the controller.
void MemoryDoubleSet(uint64_t address, double dataDouble)
Write a 64-bit double value to controller memory.
uint64_t AddressGet(RSIControllerAddressType type)
Get the an address for some location on the MotionController.
void SampleWait(uint32_t samples)
Wait for controller firmware to execute samples.
void UserLimitConfigSet(int32_t number, RSIUserLimitTriggerType triggerType, RSIAction action, int32_t actionAxis, double duration, bool singleShot)
Configure a User Limit.
void Delete(void)
Delete the MotionController and all its objects.
MultiAxis * MultiAxisGet(int32_t motionSupervisorNumber)
MultiAxisGet returns a pointer to a MultiAxis object and initializes its internals.
void UserLimitCountSet(int32_t userLimitCount)
Set the number of processed UserLimits in the MotionController.
Represents the RMP soft motion controller. This class provides an interface to general controller con...
Definition rsi.h:762
MathBlockConfig MathBlockConfigGet(int32_t mathBlockNumber)
Get a MathBlock configuration.
FirmwareValue MathBlockProcessValueGet(int32_t mathBlockNumber)
Get a MathBlock process value.
void MathBlockConfigSet(int32_t mathBlockNumber, MathBlockConfig &config)
Set a MathBlock configuration.
void AxisRemoveAll()
Remove all axes from a MultiAxis group.s.
void AxisAdd(Axis *axis)
Add an Axis to a MultiAxis group.
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.
int32_t MotionDoneWait()
Waits for a move to complete.
RSIState StateGet()
Get the Axis or MultiAxis state.
RSIMathBlockOperation
MathBlock operations.
Definition rsienums.h:1340
RSIControllerAddressType
Used to get firmware address used in User Limits, Sequencers, etc.
Definition rsienums.h:404
RSIDataType
Data types for User Limits and other triggers.
Definition rsienums.h:644
RSIUserLimitLogic
Logic options for User Limits.
Definition rsienums.h:631
RSIAction
Action to perform on an Axis.
Definition rsienums.h:1051
RSIAxisAddressType
Used to get firmware address used in User Limits, Sequencers, etc.
Definition rsienums.h:425
RSIUserLimitTriggerType
Trigger types for UserLimits.
Definition rsienums.h:618
MathBlock configuration structure.
Definition rsi.h:3707
double Double
Double precision (64-bit) floating-point.
Definition rsi.h:485