APIs, concepts, guides, and more
CalculateAccelerationFromVelocity.cpp
1
10#include "SampleAppsHelper.h" // Import our helper functions.
11#include "rsi.h" // Import our RapidCode Library.
12
13using namespace RSI::RapidCode; // Import our RapidCode namespace
14
15int main()
16{
17 // Print a start message to indicate that the sample app has started
18 const std::string SAMPLE_APP_NAME = "Math Blocks: Calculate Acceleration from Velocity";
19 SampleAppsHelper::PrintHeader(SAMPLE_APP_NAME);
20
22 /* CONSTANTS */
23 /* *NOTICE* The following constants must be configured before attempting to run with hardware. */
24 const int NUM_AXES = 1; // The number of axes to configure
25 const int AXIS_INDEX = 0; // The index of the axis to configure
26 const double VELOCITY = 1.0; // the velocity to move the axis
27 const double ACCELERATION = 0.123; // something small so we can check the MathBlock is working
28
29 /* RAPIDCODE INITIALIZATION */
30 // Create the Controller
32 MotionController *controller = MotionController::Create(&params);
33
34 // Variables to store initial object counts to restore later (starts at -1 to indicate it has not been set)
35 int initialMathBlockCount = -1;
36
37 // Set the exit code to an error value.
38 int exitCode = -1;
39 try // Ensure that the controller is deleted if an error occurs.
40 {
41 // Prepare the controller as defined in SampleAppsHelper.h depending on the configuration
43 SampleAppsHelper::SetupController(controller, NUM_AXES);
44
45 // Save initial object counts to restore later
46 initialMathBlockCount = controller->MathBlockCountGet();
47
48 /* SAMPLE APP BODY */
49
50 /* Configure the controller object counts */
51 // Normally you would set the number of axes here, but for samples that is handled in the SampleAppsHelper::SetupController function
52 // controller->AxisCountSet(NUM_AXES);
53
54 // Add the two MathBlocks needed for this sample
55 const int subtractionMathBlockIndex = initialMathBlockCount;
56 const int previousVelocityMathBlockIndex = initialMathBlockCount + 1;
57 controller->MathBlockCountSet(initialMathBlockCount + 2);
58
59 // Get the axis and make sure the axis is not moving and clear any faults
60 Axis *axis = controller->AxisGet(AXIS_INDEX);
62 axis->Abort();
63 axis->ClearFaults();
64
65 // Read the configuration of both MathBlocks
66 MotionController::MathBlockConfig subtractionConfig = controller->MathBlockConfigGet(subtractionMathBlockIndex);
67
68 // This index must be greater than the subtraction math block index, so the subtraction data is
69 // one sample old
70 MotionController::MathBlockConfig previousVelocityConfig = controller->MathBlockConfigGet(previousVelocityMathBlockIndex);
71
72 // Set the axis to use the command velocity as the input for the MathBlock
73 RSIAxisAddressType INPUT_AXIS_ADDRESS_TYPE = RSIAxisAddressType::RSIAxisAddressTypeCOMMAND_VELOCITY;
74
75 // Configure the first MathBlock to subtract the previous velocity from the current velocity
76 // Current velocity:
77 subtractionConfig.InputAddress0 = axis->AddressGet(INPUT_AXIS_ADDRESS_TYPE);
78 subtractionConfig.InputDataType0 = RSIDataType::RSIDataTypeDOUBLE;
79
80 // Previous velocity: (as was calculated by the second MathBlock, so we use its ProcessValue)
81 subtractionConfig.InputAddress1 =
82 controller->AddressGet(RSIControllerAddressType::RSIControllerAddressTypeMATHBLOCK_PROCESS_VALUE, previousVelocityMathBlockIndex);
83 subtractionConfig.InputDataType1 = RSIDataType::RSIDataTypeDOUBLE;
84
85 subtractionConfig.ProcessDataType = RSIDataType::RSIDataTypeDOUBLE;
86 subtractionConfig.Operation = RSIMathBlockOperation::RSIMathBlockOperationSUBTRACT;
87
88 // Write 1.0 to the first UserBuffer entry so the second MathBlock can use it for multiplication
89 uint64_t userBufferAddr0 = controller->AddressGet(RSIControllerAddressType::RSIControllerAddressTypeUSER_BUFFER, 0);
90 controller->MemoryDoubleSet(userBufferAddr0, 1.0);
91
92 // Configure the second MathBlock to multiply the current velocity by 1.0 (which we'll use for
93 // the previous sample's velocity)
94 previousVelocityConfig.InputAddress0 = axis->AddressGet(INPUT_AXIS_ADDRESS_TYPE);
95 previousVelocityConfig.InputDataType0 = RSIDataType::RSIDataTypeDOUBLE;
96 previousVelocityConfig.InputAddress1 = userBufferAddr0;
97 previousVelocityConfig.InputDataType1 = RSIDataType::RSIDataTypeDOUBLE;
98 previousVelocityConfig.ProcessDataType = RSIDataType::RSIDataTypeDOUBLE;
99 previousVelocityConfig.Operation = RSIMathBlockOperation::RSIMathBlockOperationMULTIPLY;
100
101 // Set the MathBlock configurations
102 controller->MathBlockConfigSet(subtractionMathBlockIndex, subtractionConfig);
103 controller->MathBlockConfigSet(previousVelocityMathBlockIndex, previousVelocityConfig);
104
105 // Wait a sample so we know the RMP is now processing the newly configured MathBlocks
106 controller->SampleWait(1);
107
108 // Set the axis to move with a very small acceleration so we can check the MathBlock is working
109 axis->AmpEnableSet(true); // Enable the motor.
110 axis->MoveVelocity(VELOCITY, ACCELERATION);
111
112 // Wait several samples so we know the RMP is now processing the move command and accelerating
113 controller->SampleWait(10);
114
115 // Keep in mind firmware velocity is in counts per sample, so we need to convert to UserUnits
116 // per second squared
117 double calculatedVelocityDelta = controller->MathBlockProcessValueGet(subtractionMathBlockIndex).Double;
118
119 // Reduce the velocity back to 0
120 axis->MoveVelocity(0, ACCELERATION);
121
122 axis->MotionDoneWait(); // Wait for the axis to finish moving.
123 axis->AmpEnableSet(false); // Disable the motor.
124
125 // Convert to UserUnits per second squared
126 double calculatedAcceleration = calculatedVelocityDelta * controller->SampleRateGet() * controller->SampleRateGet() / axis->UserUnitsGet();
127 std::cout << "Calculated acceleration from MathBlock: " << calculatedAcceleration << std::endl;
128
129 // Check that the newly calculated acceleration is as expected
130 if (std::abs(calculatedAcceleration - ACCELERATION) <= 0.000001)
131 {
132 std::cout << "The MathBlock is calculating the Axis' acceleration by subtracting previous velocity from current velocity." << std::endl;
133 exitCode = 0;
134 }
135 else
136 {
137 std::cerr << "Error: The calculated acceleration does not match the expected value" << std::endl;
138 exitCode = -1;
139 }
140 }
141 catch (const std::exception &ex)
142 {
143 std::cerr << ex.what() << std::endl;
144 exitCode = -1;
145 }
146 // Restore the object counts to the original values
147 if (initialMathBlockCount != -1) { controller->MathBlockCountSet(initialMathBlockCount); }
148 // Note: The axis count is handled by the SampleAppsHelper::Cleanup function
149
150 // Clean up the controller and any other objects as needed
151 SampleAppsHelper::Cleanup(controller);
152
153 // Delete the controller as the program exits to ensure memory is deallocated in the correct order
154 controller->Delete();
156
157 // Print a message to indicate the sample app has finished and if it was successful or not
158 SampleAppsHelper::PrintFooter(SAMPLE_APP_NAME, exitCode);
159
160 return exitCode;
161}
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:5643
Axis * AxisGet(int32_t axisNumber)
AxisGet returns a pointer to an Axis object and initializes its internals.
void MathBlockCountSet(int32_t mathBlockCount)
Set the number of processed MathBlocks in the MotionController.
void MemoryDoubleSet(uint64_t address, double dataDouble)
Write a 64-bit double value to controller memory.
uint64_t AddressGet(RSIControllerAddressType type)
Get the an address for some location on the MotionController.
static MotionController * Create()
Initialize and start the RMP EtherCAT controller.
void SampleWait(uint32_t samples)
Wait for controller firmware to execute samples.
int32_t MathBlockCountGet()
Get the number of MathBlocks processing in the firmware.
void Delete(void)
Delete the MotionController and all its objects.
Represents the RMP soft motion controller. This class provides an interface to general controller con...
Definition rsi.h:796
MathBlockConfig MathBlockConfigGet(int32_t mathBlockNumber)
Get a MathBlock configuration.
FirmwareValue MathBlockProcessValueGet(int32_t mathBlockNumber)
Get a MathBlock process value.
void MathBlockConfigSet(int32_t mathBlockNumber, MathBlockConfig &config)
Set a MathBlock configuration.
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.
RSIAxisAddressType
Used to get firmware address used in User Limits, Recorders, etc.
Definition rsienums.h:433
static void PrintFooter(std::string sampleAppName, int exitCode)
Print a message to indicate the sample app has finished and if it was successful or not.
static void CheckErrors(RapidCodeObject *rsiObject)
Checks for errors in the given RapidCodeObject and throws an exception if any non-warning errors are ...
static void PrintHeader(std::string sampleAppName)
Print a start message to indicate that the sample app has started.
static void Cleanup(MotionController *controller)
Cleanup the controller and restore the object counts to the original values.
static MotionController::CreationParameters GetCreationParameters()
Returns a MotionController::CreationParameters object with user-defined parameters.
static void SetupController(MotionController *controller, int numAxes=0)
Setup the controller with user defined axis counts and configuration.
CreationParameters for MotionController::Create.
Definition rsi.h:857
RSIDataType ProcessDataType
Data type for processing.
Definition rsi.h:3770
MathBlock configuration structure.
Definition rsi.h:3763
uint64_t InputAddress0
Host memory address for Input0. Represents the left-hand side operand in math operations.
Definition rsi.h:3764
RSIDataType InputDataType0
Data type for Input0. This is the data type of the left-hand side operand in math operations.
Definition rsi.h:3765
uint64_t InputAddress1
Host memory address for Input1. Represents the right-hand side operand in math operations.
Definition rsi.h:3766
RSIDataType InputDataType1
Data type for Input1. This is the data type of the right-hand side operand in math operations.
Definition rsi.h:3767
RSIMathBlockOperation Operation
Math operation to be performed. (+, -, *, /, etc) use RSIMathBlockOperationNONE to disable a MathBloc...
Definition rsi.h:3771
double Double
Double precision (64-bit) floating-point.
Definition rsi.h:473