control_loop.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * BSD 3-Clause License
3  *
4  * Copyright (c) 2021, Qiayuan Liao
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 are met:
9  *
10  * * Redistributions of source code must retain the above copyright notice, this
11  * list of conditions and the following disclaimer.
12  *
13  * * Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * * Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived from
19  * this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *******************************************************************************/
33 
34 //
35 // Created by qiayuan on 12/30/20.
36 //
37 #include "rm_hw/control_loop.h"
38 
39 namespace rm_hw
40 {
42  : nh_(nh), hardware_interface_(std::move(hardware_interface))
43 {
44  // Load ros params
45  int error = 0, thread_priority;
46  ros::NodeHandle nh_p("~");
47  error += !nh_p.getParam("loop_frequency", loop_hz_);
48  error += !nh_p.getParam("cycle_time_error_threshold", cycle_time_error_threshold_);
49  error += !nh_p.getParam("thread_priority", thread_priority);
50  if (error > 0)
51  {
52  char error_message[] = "could not retrieve one of the required parameters\n\trm_hw/loop_hz or "
53  "rm_hw/cycle_time_error_threshold or "
54  "rm_hw/thread_priority";
55  ROS_ERROR_STREAM(error_message);
56  throw std::runtime_error(error_message);
57  }
58 
59  // Initialise the hardware interface:
60  // 1. retrieve configuration from rosparam
61  // 2. initialise the hardware and interface it with ros_control
62  hardware_interface_->setCanBusThreadPriority(thread_priority);
63  hardware_interface_->init(nh, nh_p);
64  // Create the controller manager
65  controller_manager_.reset(new controller_manager::ControllerManager(hardware_interface_.get(), nh_));
66 
67  // Get current time for use with first update
68  last_time_ = clock::now();
69 
70  // Setup loop thread
71  loop_thread_ = std::thread([&]() {
72  while (loop_running_)
73  {
74  if (loop_running_)
75  update();
76  }
77  });
78  sched_param sched{ .sched_priority = thread_priority };
79  if (pthread_setschedparam(loop_thread_.native_handle(), SCHED_FIFO, &sched) != 0)
80  ROS_WARN("Failed to set threads priority (one possible reason could be that the user and the group permissions "
81  "are not set properly.).\n");
82 }
83 
85 {
86  const auto current_time = clock::now();
87  // Compute desired duration rounded to clock decimation
88  const duration<double> desired_duration(1.0 / loop_hz_);
89  // Get change in time
90  duration<double> time_span = duration_cast<duration<double>>(current_time - last_time_);
91  elapsed_time_ = ros::Duration(time_span.count());
92  last_time_ = current_time;
93 
94  // Check cycle time for excess delay
95  const double cycle_time_error = (elapsed_time_ - ros::Duration(desired_duration.count())).toSec();
96  if (cycle_time_error > cycle_time_error_threshold_)
97  ROS_WARN_STREAM("Cycle time exceeded error threshold by: " << cycle_time_error - cycle_time_error_threshold_
98  << "s, "
99  << "cycle time: " << elapsed_time_ << "s, "
100  << "threshold: " << cycle_time_error_threshold_ << "s");
101  // Input
102  // get the hardware's state
104 
105  // Control
106  // let the controller compute the new command (via the controller manager)
108 
109  // Output
110  // send the new command to hardware
112 
113  // Sleep
114  const auto sleep_till = current_time + duration_cast<clock::duration>(desired_duration);
115  std::this_thread::sleep_until(sleep_till);
116 }
117 
119 {
120  loop_running_ = false;
121  if (loop_thread_.joinable())
122  loop_thread_.join();
123 }
124 } // namespace rm_hw
controller_manager::ControllerManager
rm_hw::RmRobotHWLoop::~RmRobotHWLoop
~RmRobotHWLoop()
Definition: control_loop.cpp:149
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(args)
control_loop.h
update
void update(controller_manager::ControllerManager &cm, const ros::TimerEvent &e)
rm_hw::RmRobotHWLoop::RmRobotHWLoop
RmRobotHWLoop(ros::NodeHandle &nh, std::shared_ptr< RmRobotHW > hardware_interface)
Create controller manager. Load loop frequency. Start control loop which call rm_hw::RmRobotHWLoop::u...
Definition: control_loop.cpp:72
rm_hw::RmRobotHWLoop::last_time_
clock::time_point last_time_
Definition: control_loop.h:120
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
hardware_interface
rm_hw::RmRobotHWLoop::loop_thread_
std::thread loop_thread_
Definition: control_loop.h:116
ROS_WARN
#define ROS_WARN(...)
rm_hw::RmRobotHWLoop::hardware_interface_
std::shared_ptr< RmRobotHW > hardware_interface_
Definition: control_loop.h:131
rm_hw::RmRobotHWLoop::update
void update()
Timed method that reads current hardware's state, runs the controller code once and sends the new com...
Definition: control_loop.cpp:115
rm_hw::RmRobotHWLoop::loop_hz_
double loop_hz_
Definition: control_loop.h:118
rm_hw::RmRobotHWLoop::controller_manager_
std::shared_ptr< controller_manager::ControllerManager > controller_manager_
Definition: control_loop.h:128
rm_hw::RmRobotHWLoop::cycle_time_error_threshold_
double cycle_time_error_threshold_
Definition: control_loop.h:113
std
rm_hw::RmRobotHWLoop::elapsed_time_
ros::Duration elapsed_time_
Definition: control_loop.h:119
rm_hw::RmRobotHWLoop::loop_running_
std::atomic_bool loop_running_
Definition: control_loop.h:117
rm_hw
Definition: control_loop.h:48
ros::Duration
ros::NodeHandle
ros::Time::now
static Time now()


rm_hw
Author(s): Qiayuan Liao
autogenerated on Tue May 6 2025 02:23:44