APIs, concepts, guides, and more
calculate-acceleration-from-velocity.cpp
Note
See IO: Math Blocks 📜 for a detailed explanation of this sample code.
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. We recommend that you wire an external hardware emergency stop (e-stop) button for safety when using our code sample apps. Doing so will help ensure the safety of you and those around you and will prevent potential injury or damage.

The sample apps assume that the system (network, axes, I/O) are configured prior to running the code featured in the sample app. See the Configuration page for more information.
/*
This sample demonstrates how to use MathBlocks to calculate acceleration
from velocity by subtracting the previous velocity from the current velocity.
*/
#include "helpers.h" // import our helper functions.
#include "config.h" // import our configuration.
#include "rsi.h" // import our RapidCode Library.
using namespace RSI::RapidCode; // Import the RapidCode namespace
int main()
{
// print a start message to indicate that the sample app has started
const std::string SAMPLE_APP_NAME = "📜 Math Blocks: Calculate Acceleration from Velocity";
Helpers::PrintHeader(SAMPLE_APP_NAME);
/* CONSTANTS */
/* *NOTICE* The following constants must be configured before attempting to run with hardware. */
const int NUM_AXES = 1; // The number of axes to configure
const int AXIS_INDEX = 0; // The index of the axis to configure
const double VELOCITY = 1.0; // the velocity to move the axis
const double ACCELERATION = 0.123; // something small so we can check the MathBlock is working
/* RAPIDCODE INITIALIZATION */
// create the Controller
// variables to store initial object counts to restore later (starts at -1 to indicate it has not been set)
int initialMathBlockCount = -1;
// set the exit code to an error value.
int exitCode = -1;
try // Ensure that the controller is deleted if an error occurs.
{
// prepare the controller as defined in config.h depending on the configuration
Helpers::CheckErrors(controller);
Config::SetupController(controller, NUM_AXES);
// save initial object counts to restore later
initialMathBlockCount = controller->MathBlockCountGet();
/* SAMPLE APP BODY */
/* Configure the controller object counts */
// normally you would set the number of axes here, but for samples that is handled in the Config::SetupController function
// controller->AxisCountSet(NUM_AXES);
// add the two MathBlocks needed for this sample
const int subtractionMathBlockIndex = initialMathBlockCount;
const int previousVelocityMathBlockIndex = initialMathBlockCount + 1;
controller->MathBlockCountSet(initialMathBlockCount + 2);
// get the axis and make sure the axis is not moving and clear any faults
Axis *axis = controller->AxisGet(AXIS_INDEX);
axis->Abort();
axis->ClearFaults();
// read the configuration of both MathBlocks
MotionController::MathBlockConfig subtractionConfig = controller->MathBlockConfigGet(subtractionMathBlockIndex);
// this index must be greater than the subtraction math block index, so the subtraction data is
// one sample old
MotionController::MathBlockConfig previousVelocityConfig = controller->MathBlockConfigGet(previousVelocityMathBlockIndex);
// set the axis to use the command velocity as the input for the MathBlock
// configure the first MathBlock to subtract the previous velocity from the current velocity
// current velocity:
subtractionConfig.InputAddress0 = axis->AddressGet(INPUT_AXIS_ADDRESS_TYPE);
// previous velocity: (as was calculated by the second MathBlock, so we use its ProcessValue)
subtractionConfig.InputAddress1 =
controller->AddressGet(RSIControllerAddressType::RSIControllerAddressTypeMATHBLOCK_PROCESS_VALUE, previousVelocityMathBlockIndex);
// write 1.0 to the first UserBuffer entry so the second MathBlock can use it for multiplication
uint64_t userBufferAddr0 = controller->AddressGet(RSIControllerAddressType::RSIControllerAddressTypeUSER_BUFFER, 0);
controller->MemoryDoubleSet(userBufferAddr0, 1.0);
// configure the second MathBlock to multiply the current velocity by 1.0 (which we'll use for
// the previous sample's velocity)
previousVelocityConfig.InputAddress0 = axis->AddressGet(INPUT_AXIS_ADDRESS_TYPE);
previousVelocityConfig.InputAddress1 = userBufferAddr0;
// set the MathBlock configurations
controller->MathBlockConfigSet(subtractionMathBlockIndex, subtractionConfig);
controller->MathBlockConfigSet(previousVelocityMathBlockIndex, previousVelocityConfig);
// Wait a sample so we know the RMP is now processing the newly configured MathBlocks
controller->SampleWait(1);
// Set the axis to move with a very small acceleration so we can check the MathBlock is working
axis->AmpEnableSet(true); // Enable the motor.
axis->MoveVelocity(VELOCITY, ACCELERATION);
// Wait several samples so we know the RMP is now processing the move command and accelerating
controller->SampleWait(10);
// Keep in mind firmware velocity is in counts per sample, so we need to convert to UserUnits
// per second squared
double calculatedVelocityDelta = controller->MathBlockProcessValueGet(subtractionMathBlockIndex).Double;
// Reduce the velocity back to 0
axis->MoveVelocity(0, ACCELERATION);
axis->MotionDoneWait(); // Wait for the axis to finish moving.
axis->AmpEnableSet(false); // Disable the motor.
// Convert to UserUnits per second squared
double calculatedAcceleration = calculatedVelocityDelta * controller->SampleRateGet() * controller->SampleRateGet() / axis->UserUnitsGet();
std::cout << "Calculated acceleration from MathBlock: " << calculatedAcceleration << std::endl;
// Check that the newly calculated acceleration is as expected
if (std::abs(calculatedAcceleration - ACCELERATION) <= 0.000001)
{
std::cout << "The MathBlock is calculating the Axis' acceleration by subtracting previous velocity from current velocity." << std::endl;
exitCode = 0;
}
else
{
std::cerr << "Error: The calculated acceleration does not match the expected value" << std::endl;
exitCode = -1;
}
}
catch (const std::exception &ex)
{
std::cerr << ex.what() << std::endl;
exitCode = -1;
}
// Restore the object counts to the original values
if (initialMathBlockCount != -1) { controller->MathBlockCountSet(initialMathBlockCount); }
// Note: The axis count is handled by the Config::Cleanup function
// clean up the controller and any other objects as needed
Config::Cleanup(controller);
// delete the controller as the program exits to ensure memory is deallocated in the correct order
controller->Delete();
// print a message to indicate the sample app has finished and if it was successful or not
Helpers::PrintFooter(SAMPLE_APP_NAME, exitCode);
return exitCode;
}
uint64_t AddressGet(RSIAxisAddressType addressType)
Get the an address for some location on the Axis.
double UserUnitsGet()
Get the number of counts per User Unit.
void MoveVelocity(double velocity)
Represents a single axis of motion control. This class provides an interface for commanding motion,...
Definition rsi.h:5863
static MotionController * Create(CreationParameters *creationParameters)
Initialize and start the RMP EtherCAT controller.
Represents the RMP soft motion controller. This class provides an interface to general controller con...
Definition rsi.h:800
void ClearFaults()
Clear all faults for an Axis or MultiAxis.
void Abort()
Abort an axis.
int32_t MotionDoneWait()
Waits for a move to complete.
int32_t AmpEnableSet(bool enable, int32_t ampActiveTimeoutMilliseconds=AmpEnableTimeoutMillisecondsDefault, bool overrideRestrictedState=false)
Enable all amplifiers.
@ RSIMathBlockOperationSUBTRACT
Subtraction operation.
Definition rsienums.h:1434
@ RSIMathBlockOperationMULTIPLY
Multiplication operation.
Definition rsienums.h:1435
@ RSIControllerAddressTypeUSER_BUFFER
First location in User Buffer.
Definition rsienums.h:408
@ RSIControllerAddressTypeMATHBLOCK_PROCESS_VALUE
the processed value of a math block (must specify object index)
Definition rsienums.h:418
@ RSIDataTypeDOUBLE
double (64-bit floating point)
Definition rsienums.h:668
RSIAxisAddressType
Used to get firmware address used in User Limits, Recorders, etc.
Definition rsienums.h:434
@ RSIAxisAddressTypeCOMMAND_VELOCITY
Command Velocity.
Definition rsienums.h:439
void SetupController(MotionController *controller, int numAxes=0)
Setup the controller and check if the network is in the correct state for the configuration.
Definition config.h:134
MotionController::CreationParameters GetCreationParameters()
Returns a MotionController::CreationParameters object with user-defined parameters.
Definition config.h:68
void Cleanup(MotionController *controller)
[SetupController]
Definition config.h:193
void CheckErrors(RapidCodeObject *rsiObject, const std::source_location &location=std::source_location::current())
Checks for errors in the given RapidCodeObject and throws an exception if any non-warning errors are ...
Definition helpers.h:32
void PrintHeader(std::string sampleAppName)
[NetworkShutdown]
Definition helpers.h:146
void PrintFooter(std::string sampleAppName, int exitCode)
[PrintHeader]
Definition helpers.h:162
CreationParameters for MotionController::Create.
Definition rsi.h:866
RSIDataType ProcessDataType
Data type for processing.
Definition rsi.h:3819
MathBlock configuration structure.
Definition rsi.h:3812
uint64_t InputAddress0
Host memory address for Input0. Represents the left-hand side operand in math operations.
Definition rsi.h:3813
RSIDataType InputDataType0
Data type for Input0. This is the data type of the left-hand side operand in math operations.
Definition rsi.h:3814
uint64_t InputAddress1
Host memory address for Input1. Represents the right-hand side operand in math operations.
Definition rsi.h:3815
RSIDataType InputDataType1
Data type for Input1. This is the data type of the right-hand side operand in math operations.
Definition rsi.h:3816
RSIMathBlockOperation Operation
Math operation to be performed. (+, -, *, /, etc) use RSIMathBlockOperationNONE to disable a MathBloc...
Definition rsi.h:3820