APIs, concepts, guides, and more
PathMotion.cs
1
47using RSI.RapidCode.dotNET; // Import our RapidCode Library.
48using NUnit.Framework;
49using System;
50using System.Linq;
51using System.Threading;
52
53#if DOXYGEN // RSI internal documentation use only
54using RSI.RapidCode;
56#endif
57
58
59[TestFixture]
60[Category("Software")]
61public class PathMotion : SampleAppTestBase
62{
63 [SetUp]
64 public void Setup()
65 {
66 jointsMultiAxis?.AxisRemoveAll();
67 }
68
69 [TearDown]
70 public void Teardown()
71 {
72 robot?.EStop();
73 robot?.MotionDoneWait();
74 robot?.ClearFaults();
75 Robot.RobotDelete(controller, robot);
76 robot = null;
77
78 jointsMultiAxis?.Abort();
79 Thread.Sleep(50);
80 jointsMultiAxis?.ClearFaults();
81 }
82
83 private void VerifyModel(KinematicModel model, LinearUnits expectedUnits, string expectedName)
84 {
85 var actualUnits = model.UnitsGet();
86 Assert.That(actualUnits, Is.EqualTo(expectedUnits), $"Expected model units to be '{expectedUnits}' but was '{actualUnits}' instead!");
87 var actualName = model.NameGet();
88 Assert.That(actualName, Is.EqualTo(expectedName), $"Expected model name to be '{expectedName}' but was '{actualName}' instead!");
89 }
90
91 [Test]
92 public void GantryPrimeAxis()
93 {
94 prime_axis = z_axis;
96 // We assume the axes have been confgured and homed properly prior this this program.
97
98 const string xLabel = "X-Axis";
99 const string yLabel = "Y-Axis";
100 const string primeLabel = "Y-Prime";
101
102 // Set the expected labels for each axis.
103 x_axis.UserLabelSet(xLabel);
104 y_axis.UserLabelSet(yLabel);
105 prime_axis.UserLabelSet(primeLabel);
106
107 // The joint index of each axis is the index within the MultiAxis object.
108 // "X-Axis" has joint index 0
109 // "Y-Axis" has joint index 1
110 // "Y-Prime" has joint index 2
111 Axis[] axes = new Axis[] { x_axis, y_axis, prime_axis };
112 jointsMultiAxis.AxesAdd(axes, axes.Length);
113
114 const LinearUnits units = LinearUnits.Millimeters;
115 const string modelName = "RSI_XY_Yp";
116 const double scaling = 1.0, offset = 0.0;
117 LinearModelBuilder builder = new LinearModelBuilder(modelName);
118 builder.UnitsSet(units);
119 builder.JointAdd(new LinearJointMapping(0, CartesianAxis.X) { ExpectedLabel = xLabel, Scaling = scaling, Offset = offset });
120 builder.JointAdd(new LinearJointMapping(1, CartesianAxis.Y) { ExpectedLabel = yLabel, Scaling = scaling, Offset = offset });
121 builder.JointAdd(new LinearJointMapping(2, CartesianAxis.Y) { ExpectedLabel = primeLabel, Scaling = scaling, Offset = offset });
122
123 // Create a Robot object where the y and y prime will be geared 1:1
124 const int motionFrameBufferSize = 50; // This is the minimum valid motion frame buffer size.
125 robot = Robot.RobotCreate(controller, jointsMultiAxis, builder, motionFrameBufferSize);
128
129 VerifyModel(robot.ModelGet(), units, modelName);
130 }
131
132 [Test, Timeout(Constants.MAX_TEST_TIME)]
133 public void SimplePathMotion()
134 {
136 // We assume the axes have been confgured and homed properly prior this this program.
137 const string xLabel = "X-Axis";
138 const string yLabel = "Y-Axis";
139 const string zLabel = "Z-Axis";
140 const string aLabel = "A-Axis";
141 const string bLabel = "B-Axis";
142 const string cLabel = "C-Axis";
143
144 // Set the expected labels for each axis.
145 x_axis.UserLabelSet(xLabel);
146 y_axis.UserLabelSet(yLabel);
147 z_axis.UserLabelSet(zLabel);
148 a_axis.UserLabelSet(aLabel);
149 b_axis.UserLabelSet(bLabel);
150 c_axis.UserLabelSet(cLabel);
151
152 // The joint index of each axis is the index within the MultiAxis object.
153 // "X-Axis" has joint index 0
154 // "Y-Axis" has joint index 1
155 // "Z-Axis" has joint index 2
156 // "A-Axis" has joint index 3
157 // "B-Axis" has joint index 4
158 // "C-Axis" has joint index 5
159 Axis[] axes = new Axis[] { x_axis, y_axis, z_axis, a_axis, b_axis, c_axis };
160 jointsMultiAxis.AxesAdd(axes, axes.Length);
161 jointsMultiAxis.ClearFaults();
162
163 const LinearUnits units = LinearUnits.Meters;
164 const string modelName = "RSI_XYZABC_Meters";
165 const double scaling = 1.0, offset = 0.0;
166 LinearModelBuilder builder = new LinearModelBuilder(modelName);
167 builder.UnitsSet(units);
168 builder.JointAdd(new LinearJointMapping(0, CartesianAxis.X) { ExpectedLabel = xLabel, Scaling = scaling, Offset = offset });
169 builder.JointAdd(new LinearJointMapping(1, CartesianAxis.Y) { ExpectedLabel = yLabel, Scaling = scaling, Offset = offset });
170 builder.JointAdd(new LinearJointMapping(2, CartesianAxis.Z) { ExpectedLabel = zLabel, Scaling = scaling, Offset = offset });
171 builder.JointAdd(new LinearJointMapping(3, CartesianAxis.Roll) { ExpectedLabel = aLabel, Scaling = scaling, Offset = offset });
172 builder.JointAdd(new LinearJointMapping(4, CartesianAxis.Pitch) { ExpectedLabel = bLabel, Scaling = scaling, Offset = offset });
173 builder.JointAdd(new LinearJointMapping(5, CartesianAxis.Yaw) { ExpectedLabel = cLabel, Scaling = scaling, Offset = offset });
174
175 // Create a Robot object with a multi axis containing all joints and the kinematic type
176 robot = Robot.RobotCreate(controller, jointsMultiAxis, builder, MotionController.AxisFrameBufferSizeDefault);
178
179 robot.PathAccelerationSet(1000); // UserUnits per sec sqd
180 robot.PathVelocitySet(50); // UserUnits per sec
181
183 robot.PathProgrammingModeSet(PathMode.Absolute);
184 robot.PathLine(new Pose(1, 1, 0));
185 robot.PathArc(new Pose(0, 2, 0), new Vector3d(0, 1, 0), RotationDirection.Clockwise);
186
187 jointsMultiAxis.ClearFaults();
188 jointsMultiAxis.AmpEnableSet(true);
189 robot.Run(); // Starts the motion. Calling with the false arguement for non blocking behavior
190 bool isRunning = robot.IsRunning();
192
193 VerifyModel(robot.ModelGet(), units, modelName);
194 }
195
196 [Test]
197 public void ChangingUnits()
198 {
200 // We assume the axes have been confgured and homed properly prior this this program.
201 const string xLabel = "X-Axis";
202 const string yLabel = "Y-Axis";
203 const string zLabel = "Z-Axis";
204 const string aLabel = "A-Axis";
205 const string bLabel = "B-Axis";
206 const string cLabel = "C-Axis";
207
208 // Set the expected labels for each axis.
209 x_axis.UserLabelSet(xLabel);
210 y_axis.UserLabelSet(yLabel);
211 z_axis.UserLabelSet(zLabel);
212 a_axis.UserLabelSet(aLabel);
213 b_axis.UserLabelSet(bLabel);
214 c_axis.UserLabelSet(cLabel);
215
216 // The joint index of each axis is the index within the MultiAxis object.
217 // "X-Axis" has joint index 0
218 // "Y-Axis" has joint index 1
219 // "Z-Axis" has joint index 2
220 // "A-Axis" has joint index 3
221 // "B-Axis" has joint index 4
222 // "C-Axis" has joint index 5
223 Axis[] axes = new Axis[] { x_axis, y_axis, z_axis, a_axis, b_axis, c_axis };
224 jointsMultiAxis.AxesAdd(axes, axes.Length);
225
226 const LinearUnits units = LinearUnits.Millimeters;
227 const string modelName = "RSI_XYZABC_Millimeters";
228 const double scaling = 1.0, offset = 0.0;
229 LinearModelBuilder builder = new LinearModelBuilder(modelName);
230 builder.UnitsSet(units);
231 builder.JointAdd(new LinearJointMapping(0, CartesianAxis.X) { ExpectedLabel = xLabel, Scaling = scaling, Offset = offset });
232 builder.JointAdd(new LinearJointMapping(1, CartesianAxis.Y) { ExpectedLabel = yLabel, Scaling = scaling, Offset = offset });
233 builder.JointAdd(new LinearJointMapping(2, CartesianAxis.Z) { ExpectedLabel = zLabel, Scaling = scaling, Offset = offset });
234 builder.JointAdd(new LinearJointMapping(3, CartesianAxis.Roll) { ExpectedLabel = aLabel, Scaling = scaling, Offset = offset });
235 builder.JointAdd(new LinearJointMapping(4, CartesianAxis.Pitch) { ExpectedLabel = bLabel, Scaling = scaling, Offset = offset });
236 builder.JointAdd(new LinearJointMapping(5, CartesianAxis.Yaw) { ExpectedLabel = cLabel, Scaling = scaling, Offset = offset });
237
238 // Create a Robot object with a multi axis containing all joints and the kinematic type
239 robot = Robot.RobotCreate(controller, jointsMultiAxis, builder, MotionController.AxisFrameBufferSizeDefault);
241
242 //NOTE: to use the above kinematic model you must have a gantry (linear 1:1 kinematics) and each linear axis must have its user units scaled to millimeters
243
244 robot.PathAccelerationSet(10); //Sets the PATH acceleration to 10 Millimeters per second sqd
245 robot.PathVelocitySet(10); //Sets the PATH velocity to 10 Millimeters per second
246
247 Console.WriteLine(robot.PathUnitsGet());//This will print the int value for the enum for Millimeters
248
249 robot.PathUnitsSet(LinearUnits.Centimeters);
250
251 robot.PathAccelerationSet(10); //Sets the PATH acceleration to 10 Centimeters per second sqd
252 robot.PathVelocitySet(10); //Sets the PATH velocity to 10 Centimeters per second
253
254 Console.WriteLine(robot.PathLinearScalingGet());//Will print the scale factor to convert CM to MM
255
256 //NOTE: you can also set this directly. Doing so will result in PathUnitsGet() returning NONE
258
259 VerifyModel(robot.ModelGet(), units, modelName);
260 }
261
262 public void PathPoint()
263 {
265 const ulong frameCount = 500;
266 ulong totalFrames = frameCount;
267 ulong startFrame = 0;
268
269 while (totalFrames == frameCount)
270 {
271 RapidVectorRobotPosition positions = robot.PathPlannedPositionsGet(startFrame, frameCount);
272 totalFrames = positions.Size();
273
274 foreach (RobotPosition position in positions.ToArray())
275 {
276 Pose pose = position.Pose;
277 Vector3d spatial = pose.Position;
278 double xCoord = spatial.X, yCoord = spatial.Y, zCoord = spatial.Z;
279 Quaternion orientation = pose.Orientation;
280 }
281
282 //Add code here to create the rendering out of the positions you have collected.
283 //Use your prefered 3d library.
284 //Example:
285 //vector3 = new Vector3D(xPosition, yPosition, zPosition);
286 //linePositions.Add(Vector3DToVector3(vector3));
287
288 startFrame += totalFrames;
289 }
291 }
292}
static void CheckErrors(RapidCodeObject rsiObject)
Check if the RapidCodeObject has any errors.
Helper Functions for checking logged creation errors, starting the network, etc.
void UserLabelSet(const char *const userLabel)
Set the axis User defined Label.
Represents a single axis of motion control. This class provides an interface for commanding motion,...
Definition rsi.h:5643
void UnitsSet(LinearUnits units)
Set the units the built model will use.
Describes the mathematical kinematic model of a robot.
The Builder for a linear kinematic model. Constructs a single Linear Kinematic Model to use when crea...
void JointAdd(const LinearJointMapping &joint)
adds a joint to the model using the configuration specified within the LinearJoint structure.
Vector3d Position
The position component of the Pose.
Quaternion Orientation
The orientation component of the Pose.
Quaternion for representing rotations.
uint64_t MotionDoneWait()=0
Waits for a move to complete.
RapidVector< RobotPosition > PathPlannedPositionsGet(uint64_t startFrame, uint64_t frameCount)=0
Get Positions (see RobotPosition) representing the planned motion in cartesian space that will happen...
void PathVelocitySet(double unitsPerSecond)=0
Sets the target linear cartesian velocity for each move (UserUnits/second).
bool IsRunning()=0
Returns whether or not the robot is in motion (from executor or other source). Can be used to determi...
double PathLinearScalingGet() const =0
Gets scaling between input to path motion and output of path motion to the kinematic model.
static Robot * RobotCreate(MotionController *controller, MultiAxis *multiAxis, KinematicModelBuilder *builder, uint32_t motionFrameBufferSize)
Create a Robot object to use G-Code, path motion, etc.
void PathAccelerationSet(double unitsPerSecondSquared)=0
Sets the target acceleration for the machine (UserUnits/second^2). Should be set appropriately based ...
LinearUnits PathUnitsGet() const =0
Gets the units of path motion.
void PathArc(const Pose &target, double radius, RotationDirection direction)=0
Appends an arc on to the current on the PathPlaneGet() plane XY by default.
void PathUnitsSet(LinearUnits units)=0
Defines the units Cartesian Path Motion is in.
void PathLine(const Pose &target)=0
void EStop()=0
Commands a joint EStop and clears the loaded moves.
void PathProgrammingModeSet(PathMode mode)=0
Sets the programming mode (Relative/Absolute).
void Run()=0
Run the loaded path lines/arcs. The behavior is non-blocking. Use Robot.MotionDoneWait() to block.
Represents a collection of joints in Cartesian space with forward and inverse kinematics....
void ClearFaults()=0
Clears the MultiAxis fault then the Robot's error bit.
const KinematicModel & ModelGet()=0
Get the model this robot was created with.
static void RobotDelete(MotionController *controller, Robot *robot)
Delete a Robot.
A representation of the robot containing the Pose and the positions of the free axes.
RSI::RapidCode::Cartesian::Pose Pose
The Robot's Pose.
Vector3d is used for three-dimensional points and vectors.
static constexpr int32_t AxisFrameBufferSizeDefault
The default value of the AxisFrameBufferSize, also the minimum allowable value.
Definition rsi.h:845
Represents the RMP soft motion controller. This class provides an interface to general controller con...
Definition rsi.h:796
void AxisRemoveAll()
Remove all axes from a MultiAxis group.s.
void AxesAdd(Axis **axes, int32_t axisCount)
void ClearFaults()
Clear all faults for an Axis or MultiAxis.
void AmpEnableSet(bool enable)
Enable all amplifiers.
void Abort()
Abort an axis.
PathMode
Motion types. For G-code use and Cartesian path motion.
CartesianAxis
This enum specifies which Cartesian axis a LinearJointMapping maps a robot joint to.
RotationDirection
Rotational directions about an axis.
LinearUnits
Unit types. For Cartesian Robot/G-Code use.
The Cartesian namespace.