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