StreamingMotionBufferManagement.cpp
#include "rsi.h" // Import our RapidCode Library.
#include <process.h>
using namespace RSI::RapidCode;
const int AXIS_COUNT = 2;
const int DESIRED_POINTS = 50; //We'd like to keep a buffer of 50 points.
const int SYNC_PERIOD = 10; //Every 10 samples.
int32_t lastSample = 0;
#pragma region Fixed Size Implementation
//Some applications might like to send block of say 10 points.
//This means they might end up with anywhere from DESIRED_POINTS to DESIRED_POINTS + (POINT_BLOCK_COUNT - 1) in points at the time of Motion Call.
//We want to adjust desired points and keep track of the extra for future calculations.
//You don't need to do it this way unless you've a reason to.
//If you are using fixed size blocks, you might just want to just use MotionIdGet() and ExecutingMotionIdGet() to determine the number of blocks to send.
const int POINT_BLOCK_COUNT = 10;
int32_t extraPointsSentToEvenOutBlock = 0;
int32_t AdjustPointsNeededToBlockCount(int32_t initialCount)
{
int32_t calculatedCount = 0;
int32_t adjustedInitialCount = initialCount - extraPointsSentToEvenOutBlock;
while ((adjustedInitialCount > 0) && (adjustedInitialCount > calculatedCount))
{
calculatedCount += POINT_BLOCK_COUNT;
}
//Adjust ExtraPointsSent so it can be used in future cycles.
extraPointsSentToEvenOutBlock += calculatedCount - initialCount;
return calculatedCount;
}
#pragma endregion
volatile int _continueMonitoring = true;
//In this example the expected passed Object is a Controller Object.
void monitoringThread(void* tmp)
{
MotionController* controller = (MotionController*)tmp;
//Configure Sync Interrupts here.
controller->SyncInterruptPeriodSet(SYNC_PERIOD);
controller->SyncInterruptEnableSet(true);
while (_continueMonitoring)
{
//SyncInterruptWait will wait until the next Interrupt generated by the controller.
//This is the best way to periodically trigger your application while getting useful information about jitter.
int32_t sampleRecieved = controller->SyncInterruptWait();
int32_t pointsNeeded = sampleRecieved - lastSample;
//Some applications may want to see specific block counts. You likely don't need to do this. See region (Fixed Size Implementation) Notes above.
pointsNeeded = AdjustPointsNeededToBlockCount(pointsNeeded);
//Note this application doesn't do the following as it is intended to help organization rather than preform motion. Please see other examples for that.
//Generate pointsNeeded Points.
//Potentially Command Move with generated Points -or- signal thread to do so -or- any number of things.
//Save sample for next calculation.
lastSample = sampleRecieved;
//One possible point lookup method might be to keep a rotating buffer of points which you use SampleRate Modulus BufferSize for setting/lookup.
//SampleRateGet() Modulus BufferSize would be your key for current point.
}
}
//Print out any errors on the associated Object.
void checkErrors(RapidCodeObject *object)
{
while (object->ErrorLogCountGet() > 0)
{
printf("Error Found: %s\n", object->ErrorLogGet()->text);
}
}
void streamingMotionBufferManagementMain()
{
// Initialize MotionController. An example path to RapidCode diretory provided.
// NOTE: Use CreateFromBoard(#) and skip NetworkStart() for SynqNet.
MotionController *controller = MotionController::CreateFromSoftware(/*rmpPath*/);;// .XX\\");
checkErrors(controller);
try
{
// Initialize the Network.
controller->NetworkStart();
checkErrors(controller);
//Create Monitoring Thread.
_beginthread(monitoringThread, 0, controller);
//Wait for some exit condition
bool exitCondition = false;
while (!exitCondition)
{
//In theory, you application will be doing a lot in here. Note this application has no way to trigger exitCondition and will run forever.
}
}
catch (RsiError const& err)
{
printf("\n%s\n", err.text);
}
controller->Delete(); // Delete the controller as the program exits to ensure memory is deallocated in the correct order.
//Exit Gracefully
_continueMonitoring = false;
//Wait an appropriate time to get from the top of the Monitoring Loop to the bottom of it.
}