Worker.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2016, Philipp Leemann
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Robotic Systems Lab nor ETH Zurich
18  * nor the names of its contributors may be used to endorse or
19  * promote products derived from this software without specific
20  * prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
42 #include <limits>
43 
44 #include <pthread.h>
45 #include <cstring> // strerror(..)
46 #include <ctime>
47 #include <ros/ros.h>
48 #include "bota_worker/Worker.hpp"
49 
50 namespace bota_worker
51 {
52 Worker::Worker(const std::string& name, const double timestep, const WorkerCallback& callback)
53  : Worker(WorkerOptions(name, timestep, callback))
54 {
55 }
56 
57 Worker::Worker(const std::string& name, const double timestep, const WorkerCallback& callback,
58  const WorkerCallbackFailureReaction& callbackFailureReaction)
59  : Worker(WorkerOptions(name, timestep, callback, callbackFailureReaction))
60 {
61 }
62 
64  : options_(options), running_(false), done_(false), thread_(), rate_(options) // NOLINT(cppcoreguidelines-slicing)
65 {
66 }
67 
68 Worker::Worker(Worker&& other) noexcept
69  : options_(std::move(other.options_))
70  , running_(other.running_.load())
71  , done_(other.done_.load())
72  , thread_(std::move(other.thread_))
73  , rate_(std::move(other.rate_))
74 {
75 }
76 
78 {
79  stop(true);
80 }
81 
82 bool Worker::start(const int priority)
83 {
84  if (running_)
85  {
86  ROS_ERROR("Worker [%s] cannot be started, already/still running.", options_.name_.c_str());
87  done_ = true;
88  return false;
89  }
90  if (options_.timeStep_ < 0.0)
91  {
92  ROS_ERROR("Worker [%s] cannot be started, invalid timestep: %f", options_.name_.c_str(), options_.timeStep_.load());
93  done_ = true;
94  return false;
95  }
96 
97  running_ = true;
98  done_ = false;
99 
100  thread_ = std::thread(&Worker::run, this);
101 
102  sched_param sched{};
103  sched.sched_priority = 0;
104  if (priority != 0)
105  {
106  sched.sched_priority = priority;
107  }
108  else if (options_.defaultPriority_ != 0)
109  {
110  sched.sched_priority = options_.defaultPriority_;
111  }
112 
113  if (sched.sched_priority != 0)
114  {
115  if (pthread_setschedparam(thread_.native_handle(), SCHED_FIFO, &sched) != 0)
116  {
117  ROS_WARN("Failed to set thread priority for worker [%s]: %s", options_.name_.c_str(), strerror(errno));
118  }
119  }
120 
121  ROS_INFO("Worker [%s] started", options_.name_.c_str());
122  return true;
123 }
124 
125 void Worker::stop(const bool wait)
126 {
127  running_ = false;
128  if (wait && thread_.joinable())
129  {
130  thread_.join();
131  }
132 }
133 
134 void Worker::setTimestep(const double timeStep)
135 {
136  if (timeStep <= 0.0)
137  {
138  ROS_ERROR("Cannot change timestep of Worker [%s] to %f, invalid value.", options_.name_.c_str(), timeStep);
139  return;
140  }
141  options_.timeStep_ = timeStep;
142  if (!std::isinf(timeStep))
143  {
144  // We will use the rate, so we set its parameters.
145  rate_.getOptions().timeStep_ = timeStep;
146  }
147 }
148 
149 void Worker::setEnforceRate(const bool enforceRate)
150 {
151  options_.enforceRate_ = enforceRate;
152  rate_.getOptions().enforceRate_ = enforceRate;
153 }
154 
156 {
157  if (std::isinf(options_.timeStep_))
158  {
159  // Run the callback once.
160  static timespec now;
161  clock_gettime(CLOCK_MONOTONIC, &now);
163  {
164  ROS_WARN("Worker [%s] callback returned false. Calling failure reaction.", options_.name_.c_str());
166  }
167  }
168  else
169  {
170  // Reset the rate step time.
171  rate_.reset();
172 
173  // Run the callback repeatedly.
174  do
175  {
177  {
178  ROS_WARN("Worker [%s] callback returned false. Calling failure reaction.", options_.name_.c_str());
180  }
181 
182  rate_.sleep();
183 
184  } while (running_);
185  }
186 
187  ROS_INFO("Worker [%s] terminated.", options_.name_.c_str());
188  done_ = true;
189 }
190 
191 } // namespace bota_worker
virtual ~Worker()
Definition: Worker.cpp:77
WorkerOptions options_
Definition: Worker.hpp:112
void stop(const bool wait=true)
Definition: Worker.cpp:125
WorkerCallbackFailureReaction callbackFailureReaction_
#define ROS_WARN(...)
void sleep()
Definition: Rate.cpp:96
std::function< void(void)> WorkerCallbackFailureReaction
bool start(const int priority=0)
Definition: Worker.cpp:82
void setEnforceRate(const bool enforceRate)
Definition: Worker.cpp:149
std::atomic< double > timeStep_
Time step in seconds.
Definition: RateOptions.hpp:59
std::atomic< bool > done_
Definition: Worker.hpp:115
std::function< bool(const WorkerEvent &)> WorkerCallback
std::atomic< bool > running_
Definition: Worker.hpp:114
#define ROS_INFO(...)
RateOptions & getOptions()
Definition: Rate.hpp:140
void setTimestep(const double timeStep)
Definition: Worker.cpp:134
const timespec & getSleepEndTime() const
Definition: Rate.hpp:177
std::thread thread_
Definition: Worker.hpp:117
std::atomic< bool > enforceRate_
Boolean indicating whether the rate should be enforced.
Definition: RateOptions.hpp:65
std::string name_
Name for printing.
Definition: RateOptions.hpp:57
#define ROS_ERROR(...)
void reset()
Definition: Rate.cpp:74


bota_worker
Author(s):
autogenerated on Wed Mar 3 2021 03:09:10