Skip to content

Commit 39b61b5

Browse files
author
Felix Exner (fexner)
authored
Use SCHED_FIFO for controller_manager's main thread (#719)
Previous investigations showed that using FIFO scheduling helps keeping cycle times also non non-RT kernels. This combined with non-blocking read can result in a very stable system. This is, in fact, very close to what the actual controller_manager_node does except that we always use FIFO scheduling independent of the actual kernel in use.
1 parent ee6b50f commit 39b61b5

File tree

1 file changed

+25
-6
lines changed

1 file changed

+25
-6
lines changed

ur_robot_driver/src/ur_ros2_control_node.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
// ROS includes
4242
#include "controller_manager/controller_manager.hpp"
4343
#include "rclcpp/rclcpp.hpp"
44+
#include "realtime_tools/thread_priority.hpp"
4445

4546
// code is inspired by
4647
// https://github.com/ros-controls/ros2_control/blob/master/controller_manager/src/ros2_control_node.cpp
@@ -56,14 +57,32 @@ int main(int argc, char** argv)
5657

5758
// control loop thread
5859
std::thread control_loop([controller_manager]() {
59-
// use fixed time step
60-
const rclcpp::Duration dt = rclcpp::Duration::from_seconds(1.0 / controller_manager->get_update_rate());
60+
if (!realtime_tools::configure_sched_fifo(50)) {
61+
RCLCPP_WARN(controller_manager->get_logger(), "Could not enable FIFO RT scheduling policy");
62+
}
63+
64+
// for calculating sleep time
65+
auto const period = std::chrono::nanoseconds(1'000'000'000 / controller_manager->get_update_rate());
66+
auto const cm_now = std::chrono::nanoseconds(controller_manager->now().nanoseconds());
67+
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> next_iteration_time{ cm_now };
68+
69+
// for calculating the measured period of the loop
70+
rclcpp::Time previous_time = controller_manager->now();
6171

6272
while (rclcpp::ok()) {
63-
// ur client library is blocking and is the one that is controlling time step
64-
controller_manager->read(controller_manager->now(), dt);
65-
controller_manager->update(controller_manager->now(), dt);
66-
controller_manager->write(controller_manager->now(), dt);
73+
// calculate measured period
74+
auto const current_time = controller_manager->now();
75+
auto const measured_period = current_time - previous_time;
76+
previous_time = current_time;
77+
78+
// execute update loop
79+
controller_manager->read(controller_manager->now(), measured_period);
80+
controller_manager->update(controller_manager->now(), measured_period);
81+
controller_manager->write(controller_manager->now(), measured_period);
82+
83+
// wait until we hit the end of the period
84+
next_iteration_time += period;
85+
std::this_thread::sleep_until(next_iteration_time);
6786
}
6887
});
6988

0 commit comments

Comments
 (0)