APIs, concepts, guides, and more
Motion: Streaming Buffer Management

Streaming Motion Buffer Management sample application.

This sample code is built for the RMP but the concepts should apply to all RapidSoftware Applications. It gives a very simple initialization of an RMP MotionController. It only prints out errors rather than handling them.

This application assumes that you will be generating points which have times of exactly 1 sample duration. If you want to generate points of size X samples, be sure to divide initial Sample Rate Deduction by X.

Precondition
This sample code presumes that the user has set the tuning paramters(PID, PIV, etc.) prior to running this program so that the motor can rotate in a stable manner.
Warning
This is a sample program to assist in the integration of the RMP motion controller with your application. It may not contain all of the logic and safety features that your application requires.
#if !defined(__INTIME__)
#include "rsi.h" // Import our RapidCode Library.
#include <process.h>
using namespace RSI::RapidCode; // Import the RapidCode namespace
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.
}
#endif
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 Delete(void)
Delete the MotionController and all its objects.
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:794
void NetworkStart()
Start the network with RSINetworkStartupMethodNORMAL.
const RsiError *const ErrorLogGet()
Get the next RsiError in the log.
int32_t ErrorLogCountGet()
Get the number of software errors in the error log.
The RapidCode base class. All non-error objects are derived from this class.
Definition rsi.h:178
Represents the error details thrown as an exception by all RapidCode classes. This class contains an ...
Definition rsi.h:105