Skip to content

Commit f170fcf

Browse files
author
Felix Exner (fexner)
authored
Specifically set RTDE pipeline producer to FIFO scheduling (#139)
* Specifically set RTDE pipeline producer to FIFO scheduling Regardless of the actual kernel used, setting the producer thread to FIFO scheduling seems to improve robustness.
1 parent 8dbe2a1 commit f170fcf

File tree

5 files changed

+153
-54
lines changed

5 files changed

+153
-54
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ add_library(urcl SHARED
4646
src/rtde/rtde_writer.cpp
4747
src/default_log_handler.cpp
4848
src/log.cpp
49+
src/helpers.cpp
4950
)
5051
add_library(ur_client_library::urcl ALIAS urcl)
5152
target_compile_options(urcl PRIVATE -Wall -Wextra -Wno-unused-parameter)

include/ur_client_library/comm/pipeline.h

Lines changed: 24 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "ur_client_library/comm/package.h"
2424
#include "ur_client_library/log.h"
25+
#include "ur_client_library/helpers.h"
2526
#include "ur_client_library/queue/readerwriterqueue.h"
2627
#include <atomic>
2728
#include <chrono>
@@ -244,9 +245,17 @@ class Pipeline
244245
* \param consumer The consumer to run in the pipeline
245246
* \param name The pipeline's name
246247
* \param notifier The notifier to use
248+
* \param producer_fifo_scheduling Should the producer thread use FIFO scheduling?
247249
*/
248-
Pipeline(IProducer<T>& producer, IConsumer<T>* consumer, std::string name, INotifier& notifier)
249-
: producer_(producer), consumer_(consumer), name_(name), notifier_(notifier), queue_{ 32 }, running_{ false }
250+
Pipeline(IProducer<T>& producer, IConsumer<T>* consumer, std::string name, INotifier& notifier,
251+
const bool producer_fifo_scheduling = false)
252+
: producer_(producer)
253+
, consumer_(consumer)
254+
, name_(name)
255+
, notifier_(notifier)
256+
, queue_{ 32 }
257+
, running_{ false }
258+
, producer_fifo_scheduling_(producer_fifo_scheduling)
250259
{
251260
}
252261
/*!
@@ -256,9 +265,16 @@ class Pipeline
256265
* \param producer The producer to run in the pipeline
257266
* \param name The pipeline's name
258267
* \param notifier The notifier to use
268+
* \param producer_fifo_scheduling Should the producer thread use FIFO scheduling?
259269
*/
260-
Pipeline(IProducer<T>& producer, std::string name, INotifier& notifier)
261-
: producer_(producer), consumer_(nullptr), name_(name), notifier_(notifier), queue_{ 32 }, running_{ false }
270+
Pipeline(IProducer<T>& producer, std::string name, INotifier& notifier, const bool producer_fifo_scheduling = false)
271+
: producer_(producer)
272+
, consumer_(nullptr)
273+
, name_(name)
274+
, notifier_(notifier)
275+
, queue_{ 32 }
276+
, running_{ false }
277+
, producer_fifo_scheduling_(producer_fifo_scheduling)
262278
{
263279
}
264280

@@ -349,61 +365,16 @@ class Pipeline
349365
moodycamel::BlockingReaderWriterQueue<std::unique_ptr<T>> queue_;
350366
std::atomic<bool> running_;
351367
std::thread pThread_, cThread_;
368+
bool producer_fifo_scheduling_;
352369

353370
void runProducer()
354371
{
355372
URCL_LOG_DEBUG("Starting up producer");
356-
std::ifstream realtime_file("/sys/kernel/realtime", std::ios::in);
357-
bool has_realtime;
358-
realtime_file >> has_realtime;
359-
if (has_realtime)
373+
if (producer_fifo_scheduling_)
360374
{
375+
pthread_t this_thread = pthread_self();
361376
const int max_thread_priority = sched_get_priority_max(SCHED_FIFO);
362-
if (max_thread_priority != -1)
363-
{
364-
// We'll operate on the currently running thread.
365-
pthread_t this_thread = pthread_self();
366-
367-
// struct sched_param is used to store the scheduling priority
368-
struct sched_param params;
369-
370-
// We'll set the priority to the maximum.
371-
params.sched_priority = max_thread_priority;
372-
373-
int ret = pthread_setschedparam(this_thread, SCHED_FIFO, &params);
374-
if (ret != 0)
375-
{
376-
URCL_LOG_ERROR("Unsuccessful in setting producer thread realtime priority. Error code: %d", ret);
377-
}
378-
// Now verify the change in thread priority
379-
int policy = 0;
380-
ret = pthread_getschedparam(this_thread, &policy, &params);
381-
if (ret != 0)
382-
{
383-
std::cout << "Couldn't retrieve real-time scheduling paramers" << std::endl;
384-
}
385-
386-
// Check the correct policy was applied
387-
if (policy != SCHED_FIFO)
388-
{
389-
URCL_LOG_ERROR("Producer thread: Scheduling is NOT SCHED_FIFO!");
390-
}
391-
else
392-
{
393-
URCL_LOG_INFO("Producer thread: SCHED_FIFO OK");
394-
}
395-
396-
// Print thread scheduling priority
397-
URCL_LOG_INFO("Thread priority is %d", params.sched_priority);
398-
}
399-
else
400-
{
401-
URCL_LOG_ERROR("Could not get maximum thread priority for producer thread");
402-
}
403-
}
404-
else
405-
{
406-
URCL_LOG_WARN("No realtime capabilities found. Consider using a realtime system for better performance");
377+
setFiFoScheduling(this_thread, max_thread_priority);
407378
}
408379
std::vector<std::unique_ptr<T>> products;
409380
while (running_)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
2+
3+
// -- BEGIN LICENSE BLOCK ----------------------------------------------
4+
// Copyright 2022 FZI Forschungszentrum Informatik
5+
// Created on behalf of Universal Robots A/S
6+
//
7+
// Licensed under the Apache License, Version 2.0 (the "License");
8+
// you may not use this file except in compliance with the License.
9+
// You may obtain a copy of the License at
10+
//
11+
// http://www.apache.org/licenses/LICENSE-2.0
12+
//
13+
// Unless required by applicable law or agreed to in writing, software
14+
// distributed under the License is distributed on an "AS IS" BASIS,
15+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
// See the License for the specific language governing permissions and
17+
// limitations under the License.
18+
// -- END LICENSE BLOCK ------------------------------------------------
19+
20+
//----------------------------------------------------------------------
21+
/*!\file
22+
*
23+
* \author Felix Exner exner@fzi.de
24+
* \date 2022-12-15
25+
*
26+
*/
27+
//----------------------------------------------------------------------
28+
29+
#ifndef UR_CLIENT_LIBRARY_HELPERS_H_INCLUDED
30+
#define UR_CLIENT_LIBRARY_HELPERS_H_INCLUDED
31+
32+
#include <thread>
33+
34+
namespace urcl
35+
{
36+
bool setFiFoScheduling(pthread_t& thread, const int priority);
37+
}
38+
#endif // ifndef UR_CLIENT_LIBRARY_HELPERS_H_INCLUDED

src/helpers.cpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
2+
3+
// -- BEGIN LICENSE BLOCK ----------------------------------------------
4+
// Copyright 2022 FZI Forschungszentrum Informatik
5+
// Created on behalf of Universal Robots A/S
6+
//
7+
// Licensed under the Apache License, Version 2.0 (the "License");
8+
// you may not use this file except in compliance with the License.
9+
// You may obtain a copy of the License at
10+
//
11+
// http://www.apache.org/licenses/LICENSE-2.0
12+
//
13+
// Unless required by applicable law or agreed to in writing, software
14+
// distributed under the License is distributed on an "AS IS" BASIS,
15+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
// See the License for the specific language governing permissions and
17+
// limitations under the License.
18+
// -- END LICENSE BLOCK ------------------------------------------------
19+
20+
//----------------------------------------------------------------------
21+
/*!\file
22+
*
23+
* \author Felix Exner exner@fzi.de
24+
* \date 2022-12-15
25+
*
26+
*/
27+
//----------------------------------------------------------------------
28+
29+
#include <ur_client_library/helpers.h>
30+
#include <ur_client_library/log.h>
31+
32+
#include <cstring>
33+
#include <fstream>
34+
#include <iostream>
35+
36+
namespace urcl
37+
{
38+
bool setFiFoScheduling(pthread_t& thread, const int priority)
39+
{
40+
struct sched_param params;
41+
params.sched_priority = priority;
42+
int ret = pthread_setschedparam(thread, SCHED_FIFO, &params);
43+
if (ret != 0)
44+
{
45+
switch (ret)
46+
{
47+
case EPERM:
48+
{
49+
URCL_LOG_ERROR("Your system/user seems not to be setup for FIFO scheduling. We recommend using a lowlatency "
50+
"kernel with FIFO scheduling. See "
51+
"https://github.com/UniversalRobots/Universal_Robots_ROS_Driver/blob/master/ur_robot_driver/"
52+
"doc/real_time.md for details.");
53+
break;
54+
}
55+
default:
56+
57+
{
58+
URCL_LOG_ERROR("Unsuccessful in setting thread to FIFO scheduling with priority %i. %s", priority,
59+
strerror(ret));
60+
}
61+
}
62+
}
63+
// Now verify the change in thread priority
64+
int policy = 0;
65+
ret = pthread_getschedparam(thread, &policy, &params);
66+
if (ret != 0)
67+
{
68+
URCL_LOG_ERROR("Couldn't retrieve scheduling parameters");
69+
return false;
70+
}
71+
72+
// Check the correct policy was applied
73+
if (policy != SCHED_FIFO)
74+
{
75+
URCL_LOG_ERROR("Scheduling is NOT SCHED_FIFO!");
76+
return false;
77+
}
78+
else
79+
{
80+
URCL_LOG_INFO("SCHED_FIFO OK, priority %i", params.sched_priority);
81+
if (params.sched_priority != priority)
82+
{
83+
URCL_LOG_ERROR("Thread priority is %i instead of the expected %i", params.sched_priority, priority);
84+
return false;
85+
}
86+
}
87+
return true;
88+
}
89+
} // namespace urcl

src/rtde/rtde_client.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ RTDEClient::RTDEClient(std::string robot_ip, comm::INotifier& notifier, const st
4141
, input_recipe_(readRecipe(input_recipe_file))
4242
, parser_(output_recipe_)
4343
, prod_(stream_, parser_)
44-
, pipeline_(prod_, PIPELINE_NAME, notifier)
44+
, pipeline_(prod_, PIPELINE_NAME, notifier, true)
4545
, writer_(&stream_, input_recipe_)
4646
, max_frequency_(URE_MAX_FREQUENCY)
4747
, target_frequency_(target_frequency)

0 commit comments

Comments
 (0)