APIs, concepts, guides, and more
record-performance.cpp
/*
This sample demonstrates how to record and analyze performance metrics
including firmware and network timing statistics.
*/
#include <iomanip>
#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
// helper function to calculate the minimum, maximum, and average of a vector of integers
static std::vector<int> MinMaxAvg(std::vector<int> data)
{
int min = data[0];
int max = data[0];
int sum = 0;
for (int i = 0; i < data.size(); i++)
{
if (data[i] < min)
{
min = data[i];
}
if (data[i] > max)
{
max = data[i];
}
sum += data[i];
}
int avg = sum / data.size();
return {min, max, avg};
}
int main()
{
const std::string SAMPLE_APP_NAME = "📜 Utilities: Record Performance";
// print a start message to indicate that the sample app has started
Helpers::PrintHeader(SAMPLE_APP_NAME);
/* CONSTANTS */
const int RECORD_PERIOD_SAMPLES = 1; // Number of samples between each record.
const int RECORD_TIME = 1000; // Time in milliseconds to record for.
/* RAPIDCODE INITIALIZATION */
// create the controller
int exitCode = -1; // Set the exit code to an error value.
try // Ensure that the controller is deleted if an error occurs.
{
Helpers::CheckErrors(controller);
/* SAMPLE APP BODY */
// check if the network is started
int valuesPerRecord;
bool networkTimingEnabled = false;
if (controller->NetworkStateGet() != RSINetworkState::RSINetworkStateOPERATIONAL)
{
std::cout << "Network is not operational. Only Firmware Timing Deltas will be recorded." << std::endl;
valuesPerRecord = 1;
}
else
{
// enable network timing
controller->NetworkTimingEnableSet(true);
networkTimingEnabled = true;
valuesPerRecord = 3;
}
// add a recorder
int recorderIndex = controller->RecorderCountGet();
controller->RecorderCountSet(recorderIndex + 1);
// check if the recorder is running already, if it is then stop it
if (controller->RecorderEnabledGet(recorderIndex))
{
controller->RecorderStop(recorderIndex);
controller->RecorderReset(recorderIndex);
}
// configure the recorder
controller->RecorderPeriodSet(RECORD_PERIOD_SAMPLES);
controller->RecorderCircularBufferSet(false);
controller->RecorderDataCountSet(valuesPerRecord);
controller->RecorderDataAddressSet(0, controller->AddressGet(RSIControllerAddressType::RSIControllerAddressTypeFIRMWARE_TIMING_DELTA));
if (networkTimingEnabled)
{
controller->RecorderDataAddressSet(1, controller->AddressGet(RSIControllerAddressType::RSIControllerAddressTypeNETWORK_TIMING_DELTA));
controller->RecorderDataAddressSet(2, controller->AddressGet(RSIControllerAddressType::RSIControllerAddressTypeNETWORK_TIMING_RECEIVE_DELTA));
}
// start the recorder
controller->RecorderStart(recorderIndex);
controller->OS->Sleep(RECORD_TIME);
controller->RecorderStop(recorderIndex);
int recordCount = controller->RecorderRecordCountGet(recorderIndex);
std::cout << "There are " << recordCount << " records available." << std::endl;
// read the records
std::vector<int> firmawareTimingDeltas(recordCount);
std::vector<int> networkTimingDeltas(recordCount);
std::vector<int> networkTimingReceiveDeltas(recordCount);
for (int i = 0; i < recordCount; i++)
{
controller->RecorderRecordDataRetrieve(recorderIndex);
firmawareTimingDeltas[i] = controller->RecorderRecordDataValueGet(recorderIndex, 0);
if (networkTimingEnabled)
{
networkTimingDeltas[i] = controller->RecorderRecordDataValueGet(recorderIndex, 1);
networkTimingReceiveDeltas[i] = controller->RecorderRecordDataValueGet(recorderIndex, 2);
}
}
// calculate the statistics
std::vector<int> firmwareTimingStats = MinMaxAvg(firmawareTimingDeltas);
std::cout << "Firmware Timing Deltas (us): ";
std::cout << " Min = " << std::setw(4) << firmwareTimingStats[0];
std::cout << " Max = " << std::setw(4) << firmwareTimingStats[1];
std::cout << " Avg = " << std::setw(4) << firmwareTimingStats[2] << std::endl;
if (networkTimingEnabled)
{
std::vector<int> networkTimingStats = MinMaxAvg(networkTimingDeltas);
std::cout << "Network Timing Deltas (us): ";
std::cout << " Min = " << std::setw(4) << networkTimingStats[0];
std::cout << " Max = " << std::setw(4) << networkTimingStats[1];
std::cout << " Avg = " << std::setw(4) << networkTimingStats[2] << std::endl;
std::vector<int> networkTimingReceiveStats = MinMaxAvg(networkTimingReceiveDeltas);
std::cout << "Network Timing Receive Deltas (us):";
std::cout << " Min = " << std::setw(4) << networkTimingReceiveStats[0];
std::cout << " Max = " << std::setw(4) << networkTimingReceiveStats[1];
std::cout << " Avg = " << std::setw(4) << networkTimingReceiveStats[2] << std::endl;
}
// delete the recorder
controller->RecorderCountSet(recorderIndex);
exitCode = 0; // set the exit code to success.
}
catch (const std::exception &ex)
{
std::cerr << ex.what() << std::endl;
exitCode = -1;
}
// 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;
}
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
@ RSINetworkStateOPERATIONAL
EtherCAT operational, good state.
Definition rsienums.h:573
@ RSIControllerAddressTypeNETWORK_TIMING_DELTA
the latest time delta between the current network packet send time and the previous (microseconds)....
Definition rsienums.h:416
@ RSIControllerAddressTypeNETWORK_TIMING_RECEIVE_DELTA
the latest time delta between the current network packet receive time and the previous (microseconds)...
Definition rsienums.h:417
@ RSIControllerAddressTypeFIRMWARE_TIMING_DELTA
the latest time delta between the current RMP sample and the previous (microseconds)
Definition rsienums.h:415
MotionController::CreationParameters GetCreationParameters()
Returns a MotionController::CreationParameters object with user-defined parameters.
Definition config.h:68
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