The RMP Motion Controller APIs
UpdateBufferPoints.cpp
#include <cassert>
#include "rsi.h" // Import our RapidCode Library.
#include <cmath>
using namespace RSI::RapidCode;
void PrintUpdateBufferErrors(RapidCodeObject *rsiClass)
{
bool hasError = rsiClass->ErrorLogCountGet() > 0;
while (rsiClass->ErrorLogCountGet() > 0)
{
const RsiError* err = rsiClass->ErrorLogGet();
printf("%s\n", err->text);
}
if (hasError)
{
exit(1);
}
}
void PrintUpdateBufferNetworkErrors(MotionController *rsiClass)
{
bool hasError = rsiClass->NetworkLogMessageCountGet() > 0;
while (rsiClass->NetworkLogMessageCountGet() > 0)
{
const char *err = rsiClass->NetworkLogMessageGet(0);
printf("%s\n", err);
}
if (hasError)
{
exit(1);
}
}
void updateBufferPointsMain()
{
const double TIME_SLICE = 0.001; // 0.001s = 1ms
const int AXIS_COUNT = 1; // number of axes
const int REVS = 5; // number of revolutions
const int RPS = 1; // revs / sec
const int CPS = (int)std::powl(2, 20); // encoder counts per rev (set as appropiate)
const int TOTAL_POINTS = (int)(REVS / TIME_SLICE / RPS); // total number of points
const int BUFFER_SZ = 100; // Number of points to send in a buffer
const int EMPTY_CT = 10; // Number of points that remains in the beffer before an e-stop
// Initizalize the controller from software w/ multiple axes
MotionController *controller;
MultiAxis *multiAxis;
PrintUpdateBufferErrors(controller);
try
{
controller->NetworkStart();
PrintUpdateBufferNetworkErrors(controller);
// add an additional axis for the multiaxis supervisor
controller->MotionCountSet(AXIS_COUNT + 1);
// create the multiaxis using the ID of the first free axis (0 indexed)
multiAxis = controller->MultiAxisGet(AXIS_COUNT);
PrintUpdateBufferErrors(multiAxis);
// populate the multiaxis
for (int i = 0; i < AXIS_COUNT; i++)
{
Axis *tempAxis;
tempAxis = controller->AxisGet(i);
PrintUpdateBufferErrors(tempAxis);
tempAxis->EStopAbort();
tempAxis->ClearFaults();
tempAxis->PositionSet(0);
tempAxis->UserUnitsSet(CPS);
multiAxis->AxisAdd(tempAxis);
}
// populate the positions and times
std::vector<double> positions, times;
for (int i = 0; i < TOTAL_POINTS; i += AXIS_COUNT)
{
positions.push_back(i * TIME_SLICE * RPS);
times.push_back(TIME_SLICE);
}
// prepare the controller (and drive)
multiAxis->Abort();
multiAxis->ClearFaults();
assert(multiAxis->StateGet() == RSIState::RSIStateIDLE);
multiAxis->AmpEnableSet(true);
// reset the motion ID to 0
multiAxis->MovePT(RSIMotionType::RSIMotionTypePT, &positions[0], &times[0], 1, -1, false, true);
multiAxis->MotionIdSet(0);
// Establish how to keep track of what blocks have been sent
int curMotionElementID = 0, curMotionID = 0, finalMotionID = 0;
int numPointsToSend = BUFFER_SZ;
int endOfLastSent = 0;
bool exitCondition = false;
// Set up a motion hold gate so we can start buffering blocks
const int motionHoldGate = 3;
controller->MotionHoldGateSet(motionHoldGate, true);
multiAxis->MotionHoldGateSet(motionHoldGate);
for (int i = 0; i < 2; ++i)
{
multiAxis->MovePT(RSIMotionType::RSIMotionTypePT, &positions[0] + endOfLastSent * AXIS_COUNT, &times[0] + endOfLastSent, numPointsToSend, EMPTY_CT, false, exitCondition);
endOfLastSent += numPointsToSend;
++finalMotionID;
}
// Set up the interrupt frequency period
controller->SyncInterruptPeriodSet(10); // this generates an interrupt every x cycles of a 1KHz sample rate
// With our timeslices of 1ms, this is 10*1ms=10ms
controller->SyncInterruptEnableSet(true);
controller->MotionHoldGateSet(motionHoldGate, false); // release the hold gate to start moving
while (!exitCondition)
{
int32_t sampleRecieved = controller->SyncInterruptWait(); // see above for timing
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.
// There's an additional delay to retrieve the data as well.
curMotionElementID = multiAxis->MotionElementIdExecutingGet();
/*
Each MovePT assigns a new MotionID for each call to a move update (with the bufferred points)
Working under the assumption that each Buffer gets a new ID, send two (or several) smaller ones
and when the change in IDs is greater than some number, send a new one
*/
// change this logic to manage the number of buffered moves (and points) as appropiate
// generate points as appropiate
if (std::abs(finalMotionID - curMotionID) < 2)
{
// check end condition
if (TOTAL_POINTS <= (endOfLastSent + BUFFER_SZ))
{
numPointsToSend = TOTAL_POINTS - endOfLastSent; // send the remaining points
exitCondition = true;
}
multiAxis->MovePT(RSIMotionType::RSIMotionTypePT, &positions[0] + endOfLastSent * AXIS_COUNT, &times[0] + endOfLastSent, numPointsToSend, EMPTY_CT, false, exitCondition);
printf("MotionID %d\nEnd of Last Sent %d\nElement ID %d\nNum to Send %d\nIs Done %s\n===========================================\n\n",
curMotionID, endOfLastSent, curMotionElementID, numPointsToSend, exitCondition ? "yes" : "no");
endOfLastSent += numPointsToSend;
++finalMotionID;
}
}
printf("Updates Done. Waiting to finish motion.\n");
multiAxis->MotionDoneWait();
printf("Motion Complete. Final Motion ID: %d\tFinal Element ID %d\n", multiAxis->MotionIdExecutingGet(), multiAxis->MotionElementIdExecutingGet());
multiAxis->EStopAbort();
}
catch (RsiError const& err) {
printf("\n%s\n", err.text);
}
controller->Delete();
}
RSI::RapidCode::MultiAxis::MotionElementIdExecutingGet
uint16_t MotionElementIdExecutingGet()
RSI::RapidCode::MultiAxis::AxisAdd
void AxisAdd(Axis *axis)
Add an Axis to a MultiAxis group.
RSI::RapidCode::MultiAxis
The MultiAxis object allows you to map two or more axes together and command synchronized motion.
Definition: rsi.h:10986
RSI::RapidCode::MotionController::MotionHoldGateSet
void MotionHoldGateSet(int32_t gateNumber, bool hold)
Set the Motion Hold Gate.
RSI::RapidCode::RapidCodeMotion::ClearFaults
void ClearFaults()
Clear all faults for an Axis or MultiAxis.
RSI::RapidCode::RsiError
The RsiError object contains information about any RapidCode API object's error/exception.
Definition: rsi.h:90
RSI::RapidCode::RapidCodeMotion::EStopAbort
void EStopAbort()
E-Stop, then abort an axis.
RSI::RapidCode::MotionController::NetworkStart
void NetworkStart()
Start the network with RSINetworkStartupMethodNORMAL.
RSI::RapidCode::MotionController::Delete
void Delete(void)
Delete the MotionController and all its objects.
RSI::RapidCode::RapidCodeMotion::MotionHoldGateSet
void MotionHoldGateSet(bool hold)
Set the Motion Hold Gate.
RSI::RapidCode::MotionController::CreateFromSoftware
static MotionController * CreateFromSoftware()
Initialize and start the RMP EtherCAT controller.
RSI::RapidCode::RapidCodeMotion::StateGet
RSIState StateGet()
Get the Axis or MultiAxis state.
RSI::RapidCode
RSI::RapidCode::MotionController::NetworkLogMessageGet
const char *const NetworkLogMessageGet(int32_t messageIndex)
RSI::RapidCode::RapidCodeObject
The RapidCode base class. All non-error objects are derived from this class.
Definition: rsi.h:145
RSI::RapidCode::MultiAxis::MotionIdExecutingGet
uint16_t MotionIdExecutingGet()
RSI::RapidCode::MotionController::SyncInterruptPeriodSet
void SyncInterruptPeriodSet(uint32_t samples)
Configure the period for the Sync Interrupt on the controller.
RSI::RapidCode::MotionController::AxisGet
Axis * AxisGet(int32_t axisNumber)
AxisGet returns a pointer to an Axis object and initializes its internals.
RSI::RapidCode::RapidCodeObject::ErrorLogGet
const RsiError *const ErrorLogGet()
Get the next RsiError in the log.
RSI::RapidCode::RapidCodeMotion::MotionIdSet
void MotionIdSet(uint16_t id)
Set the Motion identifier.
RSI::RapidCode::Axis::PositionSet
void PositionSet(double position)
Set the Command and Actual positions.
RSI::RapidCode::RapidCodeMotion::Abort
void Abort()
Abort an axis.
RSI::RapidCode::Axis::UserUnitsSet
void UserUnitsSet(double countsPerUserUnit)
Sets the number of counts per User Unit.
RSI::RapidCode::MotionController::SyncInterruptEnableSet
void SyncInterruptEnableSet(bool enable)
Configure Sync (periodic) interrupts for the controller.
RSI::RapidCode::MotionController
The MotionController object represents the RMP INtime soft motion controller.
Definition: rsi.h:743
RSI::RapidCode::MotionController::MotionCountSet
void MotionCountSet(int32_t motionCount)
Set the number of processed Motion Supervisors in the controller.
RSI::RapidCode::Axis
The Axis object manages a single physical axis on a motion controller.
Definition: rsi.h:5852
RSI::RapidCode::RapidCodeMotion::AmpEnableSet
void AmpEnableSet(bool enable)
Enable all amplifiers.
RSI::RapidCode::RapidCodeObject::ErrorLogCountGet
int32_t ErrorLogCountGet()
Get the number of software errors in the error log.
RSI::RapidCode::RapidCodeMotion::MotionDoneWait
int32_t MotionDoneWait()
Waits for a move to complete.
RSI::RapidCode::MotionController::MultiAxisGet
MultiAxis * MultiAxisGet(int32_t motionSupervisorNumber)
MultiAxisGet returns a pointer to a MultiAxis object and initializes its internals.
RSI::RapidCode::MotionController::NetworkLogMessageCountGet
int32_t NetworkLogMessageCountGet()
RSI::RapidCode::RapidCodeMotion::MovePT
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.
RSI::RapidCode::MotionController::SyncInterruptWait
int32_t SyncInterruptWait()
Suspend the current thread until an interrupt arrives from the controller.