The RMP Motion Controller APIs
UpdateBufferPoints.cpp
1
25#include <cassert>
26#include "rsi.h" // Import our RapidCode Library.
27#include <cmath>
28#include "SampleApps.h"
29#include "HelperFunctionsCpp.h" // Import our SampleApp helper functions.
30
31using namespace RSI::RapidCode;
32
34int UpdateBufferPoints::Run()
35{
36 /* CONSTANTS */
37 // *NOTICE* The following constants must be configured before attempting to run with hardware.
38
39 // Axis configuration parameters
40 const int AXIS_COUNT = 1; // number of axes
41 const int AXIS_NUMBER = 0; // axis number
42
43 const double USER_UNITS = 1048576; // counts per unit / user units (set as appropiate)
44
45 // Motion parameters
46 const double TIME_SLICE = 0.001; // 0.001s = 1ms
47 const int REVS = 2; // number of revolutions
48 const int RPS = 1; // revs / sec
49 const int TOTAL_POINTS = (int)(REVS / TIME_SLICE / RPS); // total number of points
50 const int BUFFER_SZ = 100; // Number of points to send in a buffer
51 const int EMPTY_CT = 10; // Number of points that remains in the beffer before an e-stop
52
53 // To run with hardware, set the USE_HARDWARE flag to true AFTER you have configured the parameters above and taken proper safety precautions.
54 USE_HARDWARE = false;
55
56 /* SAMPLE APP BODY */
57
58 // Initizalize the controller from software w/ multiple axes
61
62 // Setup the controller for the appropriate hardware configuration.
63 if (USE_HARDWARE)
64 {
66 }
67 else
68 {
69 HelperFunctionsCpp::SetupControllerForPhantoms(controller, AXIS_COUNT, { AXIS_NUMBER });
70 }
71
72 MultiAxis* multiAxis;
73
74 try
75 {
76 // add an additional axis for the multiaxis supervisor
77 controller->MotionCountSet(AXIS_COUNT + 1);
78
79 // create the multiaxis using the ID of the first free axis (0 indexed)
80 multiAxis = controller->MultiAxisGet(AXIS_COUNT);
82
83 // Get the axis and configure it
84 Axis* axis = controller->AxisGet(AXIS_NUMBER); // Initialize Axis Class. (Use RapidSetup Tool to see what is your axis number)
85 HelperFunctionsCpp::CheckErrors(axis); // [Helper Function] Check that the axis has been initialize correctly.
86
87 axis->PositionSet(0); // Make sure motor starts at position 0 everytime.
88 axis->UserUnitsSet(USER_UNITS); // Change your user units.
89 axis->ErrorLimitActionSet(RSIAction::RSIActionNONE); // Set Error Limit Action.
90 axis->Abort(); // If there is any motion happening, abort it.
91 axis->ClearFaults(); // Clear faults.>
92
93 multiAxis->AxisAdd(axis); // Add the axis to the multiaxis supervisor
94
95 // populate the positions and times
96 std::vector<double> positions, times;
97 for (int i = 0; i < TOTAL_POINTS; i += AXIS_COUNT)
98 {
99 positions.push_back(i * TIME_SLICE * RPS);
100 times.push_back(TIME_SLICE);
101 }
102
103 // prepare the controller (and drive)
104 multiAxis->Abort();
105 multiAxis->ClearFaults();
106 assert(multiAxis->StateGet() == RSIState::RSIStateIDLE);
107 multiAxis->AmpEnableSet(true);
108
109 // reset the motion ID to 0
110 multiAxis->MovePT(RSIMotionType::RSIMotionTypePT, &positions[0], &times[0], 1, -1, false, true);
111 multiAxis->MotionIdSet(0);
112
113 // Establish how to keep track of what blocks have been sent
114 int curMotionElementID = 0, curMotionID = 0, finalMotionID = 0;
115 int numPointsToSend = BUFFER_SZ;
116 int endOfLastSent = 0;
117 bool exitCondition = false;
118
119 // Set up a motion hold gate so we can start buffering blocks
120 const int motionHoldGate = 3;
121 controller->MotionHoldGateSet(motionHoldGate, true);
122 multiAxis->MotionHoldGateSet(motionHoldGate);
123
124 for (int i = 0; i < 2; ++i)
125 {
126 multiAxis->MovePT(RSIMotionType::RSIMotionTypePT, &positions[0] + endOfLastSent * AXIS_COUNT, &times[0] + endOfLastSent, numPointsToSend, EMPTY_CT, false, exitCondition);
127 endOfLastSent += numPointsToSend;
128 ++finalMotionID;
129 }
130
131 // Set up the interrupt frequency period
132 controller->SyncInterruptPeriodSet(10); // this generates an interrupt every x cycles of a 1KHz sample rate
133 // With our timeslices of 1ms, this is 10*1ms=10ms
134 controller->SyncInterruptEnableSet(true);
135
136 controller->MotionHoldGateSet(motionHoldGate, false); // release the hold gate to start moving
137
138 while (!exitCondition)
139 {
140 int32_t sampleRecieved = controller->SyncInterruptWait(); // see above for timing
141 curMotionID = multiAxis->MotionIdExecutingGet(); // this takes an unspecified amount of time (non-rtos) so this is going to be called sometime after the interrupt gets handled.
142 // There's an additional delay to retrieve the data as well.
143 curMotionElementID = multiAxis->MotionElementIdExecutingGet();
144
145 /*
146 Each MovePT assigns a new MotionID for each call to a move update (with the bufferred points)
147 Working under the assumption that each Buffer gets a new ID, send two (or several) smaller ones
148 and when the change in IDs is greater than some number, send a new one
149 */
150
151 // change this logic to manage the number of buffered moves (and points) as appropiate
152 // generate points as appropiate
153 if (std::abs(finalMotionID - curMotionID) < 2)
154 {
155 // check end condition
156 if (TOTAL_POINTS <= (endOfLastSent + BUFFER_SZ))
157 {
158 numPointsToSend = TOTAL_POINTS - endOfLastSent; // send the remaining points
159 exitCondition = true;
160 }
161 multiAxis->MovePT(RSIMotionType::RSIMotionTypePT, &positions[0] + endOfLastSent * AXIS_COUNT, &times[0] + endOfLastSent, numPointsToSend, EMPTY_CT, false, exitCondition);
162
163 printf("MotionID %d\nEnd of Last Sent %d\nElement ID %d\nNum to Send %d\nIs Done %s\n===========================================\n\n",
164 curMotionID, endOfLastSent, curMotionElementID, numPointsToSend, exitCondition ? "yes" : "no");
165
166 endOfLastSent += numPointsToSend;
167 ++finalMotionID;
168 }
169 }
170 printf("Updates Done. Waiting to finish motion.\n");
171 multiAxis->MotionDoneWait();
172 printf("Motion Complete. Final Motion ID: %d\tFinal Element ID %d\n", multiAxis->MotionIdExecutingGet(), multiAxis->MotionElementIdExecutingGet());
173
174 multiAxis->EStopAbort();
175 }
176 catch (RsiError const& err) {
177 printf("\n%s\n", err.text);
178 return -1;
179 }
180 controller->Delete();
181 return 0;
182}
static void SetupControllerForHardware(MotionController *controller)
Sets up the controller for hardware use by resetting it and starting the network.
static void CheckErrors(RapidCodeObject *rsiObject)
Checks for errors in the given RapidCodeObject and throws an exception if any non-warning errors are ...
static void SetupControllerForPhantoms(MotionController *controller, int axisCount, std::vector< int > axisNums)
Sets up the controller for phantom axes, including configuring specified axes as phantom.
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 PositionSet(double position)
Set the Command and Actual positions.
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 MotionCountSet(int32_t motionCount)
Set the number of processed Motion Supervisors in the controller.
void SyncInterruptEnableSet(bool enable)
Configure Sync (periodic) interrupts for the controller.
void SyncInterruptPeriodSet(uint32_t samples)
Configure the period for the Sync Interrupt on the controller.
void MotionHoldGateSet(int32_t gateNumber, bool hold)
Set the Motion Hold Gate.
static MotionController * CreateFromSoftware()
Initialize and start the RMP EtherCAT controller.
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.
int32_t SyncInterruptWait()
Suspend the current thread until an interrupt arrives from the controller.
Represents the RMP soft motion controller. This class provides an interface to general controller con...
Definition rsi.h:762
uint16_t MotionElementIdExecutingGet()
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.
void MotionIdSet(uint16_t id)
Set the Motion identifier.
RSIState StateGet()
Get the Axis or MultiAxis state.
void MotionHoldGateSet(bool hold)
Set the Motion Hold Gate.
void MovePT(RSIMotionType type, const double *const position, const double *const time, int32_t pointCount, int32_t emptyCount, bool retain, bool final)
A move commanded by a list of position and time points.
void EStopAbort()
E-Stop, then abort an axis.
Represents the error details thrown as an exception by all RapidCode classes. This class contains an ...
Definition rsi.h:105
@ RSIMotionTypePT
simple Position and Time algorithm
@ RSIActionNONE
None - do not perform any action.
@ RSIStateIDLE
Idle, ready for anything.