APIs, concepts, guides, and more
Real-Time Tasks

Learn how to implement and work with real-time tasks.

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.


In this page:


⚙️ Real-Time Tasks: Shared Global Data

This is the global data structure shared between Real-Time Tasks 📖 and the main application that is used in all the RTTasks samples.

Defined in the RTTaskFunctions library:

struct GlobalData
{
GlobalData() { std::memset(this, 0, sizeof(*this)); }
GlobalData(GlobalData&& other) { std::memcpy(this, &other, sizeof(*this)); }
// A shared integer counter
RSI_GLOBAL(int64_t, counter);
// Shared double variables
RSI_GLOBAL(double, average);
};
inline constexpr GlobalMetadataMap<RSI::RapidCode::RealTimeTasks::GlobalMaxSize> GlobalMetadata(
{
REGISTER_GLOBAL(counter),
REGISTER_GLOBAL(average),
});

Source: rttaskglobals.h


📜 Real-Time Tasks: Hello RTTasks

Learn the basics of creating and running Real-Time Tasks 📖 with proper initialization and execution patterns.

// tell the task manager the name of the function to run as a task, the name
// of the library that contains the function, and the directory where the
// library is located. The Increment function is defined in the RTTaskFunctions library.
// it increments a global counter variable.
std::cout << "Submitting task..." << std::endl;
RTTaskCreationParameters params("Increment");
RTTask task = manager->TaskSubmit(params);
// wait for the task to run for a bit
// get the counter global tag to see if the task ran correctly
std::cout << "Getting counter global tag..." << std::endl;
RSI::RapidCode::FirmwareValue counter = manager->GlobalValueGet("counter");
if (counter.Int64 <= 0)
{
// the task did not run correctly
exitCode = -1;
std::cout << "Counter is not greater than 0. The task did not run correctly." << std::endl;
}
else
{
// the task ran correctly
exitCode = 0;
std::cout << "Counter: " << counter.Int64 << std::endl;
}

Source: hello-rttasks.cpp

Defined in the RTTaskFunctions library:

// increment the counter in the global data
RSI_TASK(Increment)
{
data->counter += 1;
}

Source: rttaskfunctions.cpp


📜 Real-Time Tasks: Random Walk

Learn how to implement random walk motion patterns using Real-Time Tasks 📖 for continuous motion generation.

// configure the axis
Axis *axis = controller->AxisGet(0);
axis->PositionSet(0);
axis->AmpEnableSet(true);
// create the task manager
RTTaskManagerCreationParameters parameters = RTTaskHelper::GetTaskManagerCreationParameters();
std::cout << "Creating task manager..." << std::endl;
manager = RTTaskManager::Create(parameters);
Helpers::CheckErrors(&manager.value());
// call the initialization task to initialize the global variables and get pointers to RapidCode objects
// in the RTTaskFunctions library. This needs to be called before any task that uses RapidCode objects.
RTTaskHelper::SubmitInitializationTask(manager.value());
// tell the task manager the name of the function to run as a task, the name
// of the library that contains the function, and the directory where the
// library is located. The RandomWalk function is defined in the RTTaskFunctions library.
// it moves the axis back and forth based on std::rand().
std::cout << "Submitting task..." << std::endl;
RTTaskCreationParameters params("RandomWalk");
params.Period = 5;
RTTask task = manager->TaskSubmit(params);
// wait for the task to run for a bit
// get the counter global tag to see if the task ran correctly
std::cout << "Getting counter global tag..." << std::endl;
FirmwareValue counter = manager->GlobalValueGet("counter");
if (counter.Int64 <= 0)
{
// the task did not run correctly
exitCode = -1;
std::cout << "Counter is not greater than 0. The task did not run correctly." << std::endl;
}
else
{
// the task ran correctly
exitCode = 0;
std::cout << "Counter: " << counter.Int64 << std::endl;
}
// the average global tag is the position the axis should be at if the RandomWalk task is working correctly
FirmwareValue average = manager->GlobalValueGet("average");
std::cout << "Average: " << average.Double << std::endl;
// Print the final axis position
std::cout << "Axis position: " << axis->CommandPositionGet() << std::endl;
task.Stop();
axis->MotionDoneWait(TIMEOUT_MS); // The axis might still be moving from the task, so wait for it to finish
axis->AmpEnableSet(false);

Source: random-walk.cpp

Defined in the RTTaskFunctions library:

// randomly move the axis back and forth
RSI_TASK(RandomWalk)
{
int random = std::rand() % 2;
double step = random ? 0.05 : -0.025; // randomly increment or decrement the average
data->average += step;
data->counter += 1;
RTAxisGet(0)->MoveSCurve(data->average);
}

Source: rttaskfunctions.cpp


⚙️ Real-Time Tasks: Task Manager Creation Parameters

Learn how to configure RTTaskManager's for different platforms and builds.

// get the creation parameters for the task manager
#if defined(WIN32) && defined(NDEBUG)
// if we are on windows and not debug, then we need to create an intime task manager
RTTaskManagerCreationParameters GetTaskManagerCreationParameters()
{
RTTaskManagerCreationParameters parameters;
std::snprintf(
parameters.RTTaskDirectory,
RTTaskManagerCreationParameters::DirectoryLengthMaximum,
RMP_INSTALL_PATH // the rmp install directory
);
parameters.Platform = PlatformType::INtime;
std::snprintf(
parameters.NodeName,
RTTaskManagerCreationParameters::NameLengthMaximum,
"NodeA"
);
return parameters;
}
#else
// otherwise, we are on linux or debug, so we can create a native task manager
RTTaskManagerCreationParameters GetTaskManagerCreationParameters()
{
RTTaskManagerCreationParameters parameters;
std::snprintf(
parameters.RTTaskDirectory,
RTTaskManagerCreationParameters::DirectoryLengthMaximum,
RMP_INSTALL_PATH // the rmp install directory
);
// for linux real-time set this to an isolated core
// parameters.CpuCore = -1;
return parameters;
}
#endif // defined(WIN32) && defined(NDEBUG)

Source: rttasks-helpers.h


⚙️ Real-Time Tasks: Initialize RapidCode Objects

Learn how to submit an initialization task that primes RapidCode objects before real-time execution.

// this calls a task to initialize the global variables and get pointers to rapidcode objects
// in the rttaskfunctions library. it needs to be called before any task
// that uses rapidcode objects.
void SubmitInitializationTask(RTTaskManager &manager)
{
std::cout << "Running initialization task..." << std::endl;
RTTaskCreationParameters initParams("Initialize");
initParams.Repeats = RTTaskCreationParameters::RepeatNone;
RTTask task = manager.TaskSubmit(initParams);
constexpr int timeoutMs = 5000;
task.ExecutionCountAbsoluteWait(1, timeoutMs); // wait for the task to execute once.
}

Source: rttasks-helpers.h

Defined in the RTTaskFunctions library:

// initialize the global data and random number generator
RSI_TASK(Initialize)
{
data->counter = 0;
data->average = 0;
std::srand(std::time(nullptr));
}

Source: rttaskfunctions.cpp