rclcpp  master
C++ ROS Client Library API
create_timer.hpp
Go to the documentation of this file.
1 // Copyright 2019 Open Source Robotics Foundation, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef RCLCPP__CREATE_TIMER_HPP_
16 #define RCLCPP__CREATE_TIMER_HPP_
17 
18 #include <chrono>
19 #include <exception>
20 #include <memory>
21 #include <string>
22 #include <utility>
23 
24 #include "rclcpp/duration.hpp"
29 
30 namespace rclcpp
31 {
34 template<typename CallbackT>
35 typename rclcpp::TimerBase::SharedPtr
39  rclcpp::Clock::SharedPtr clock,
40  rclcpp::Duration period,
41  CallbackT && callback,
42  rclcpp::CallbackGroup::SharedPtr group = nullptr)
43 {
45  clock,
47  std::forward<CallbackT>(callback),
48  node_base->get_context());
49 
50  node_timers->add_timer(timer, group);
51  return timer;
52 }
53 
55 template<typename NodeT, typename CallbackT>
56 typename rclcpp::TimerBase::SharedPtr
58  NodeT node,
59  rclcpp::Clock::SharedPtr clock,
60  rclcpp::Duration period,
61  CallbackT && callback,
62  rclcpp::CallbackGroup::SharedPtr group = nullptr)
63 {
64  return create_timer(
67  clock,
68  period,
69  std::forward<CallbackT>(callback),
70  group);
71 }
72 
74 
88 template<typename DurationRepT, typename DurationT, typename CallbackT>
92  CallbackT callback,
93  rclcpp::CallbackGroup::SharedPtr group,
96 {
97  if (node_base == nullptr) {
98  throw std::invalid_argument{"input node_base cannot be null"};
99  }
100 
101  if (node_timers == nullptr) {
102  throw std::invalid_argument{"input node_timers cannot be null"};
103  }
104 
106  throw std::invalid_argument{"timer period cannot be negative"};
107  }
108 
109  // Casting to a double representation might lose precision and allow the check below to succeed
110  // but the actual cast to nanoseconds fail. Using 1 DurationT worth of nanoseconds less than max.
111  constexpr auto maximum_safe_cast_ns =
113 
114  // If period is greater than nanoseconds::max(), the duration_cast to nanoseconds will overflow
115  // a signed integer, which is undefined behavior. Checking whether any std::chrono::duration is
116  // greater than nanoseconds::max() is a difficult general problem. This is a more conservative
117  // version of Howard Hinnant's (the <chrono> guy>) response here:
118  // https://stackoverflow.com/a/44637334/2089061
119  // However, this doesn't solve the issue for all possible duration types of period.
120  // Follow-up issue: https://github.com/ros2/rclcpp/issues/1177
121  constexpr auto ns_max_as_double =
122  std::chrono::duration_cast<std::chrono::duration<double, std::chrono::nanoseconds::period>>(
123  maximum_safe_cast_ns);
124  if (period > ns_max_as_double) {
125  throw std::invalid_argument{
126  "timer period must be less than std::chrono::nanoseconds::max()"};
127  }
128 
129  const auto period_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(period);
130  if (period_ns < std::chrono::nanoseconds::zero()) {
131  throw std::runtime_error{
132  "Casting timer period to nanoseconds resulted in integer overflow."};
133  }
134 
136  period_ns, std::move(callback), node_base->get_context());
137  node_timers->add_timer(timer, group);
138  return timer;
139 }
140 
141 } // namespace rclcpp
142 
143 #endif // RCLCPP__CREATE_TIMER_HPP_
rclcpp::create_wall_timer
rclcpp::WallTimer< CallbackT >::SharedPtr create_wall_timer(std::chrono::duration< DurationRepT, DurationT > period, CallbackT callback, rclcpp::CallbackGroup::SharedPtr group, node_interfaces::NodeBaseInterface *node_base, node_interfaces::NodeTimersInterface *node_timers)
Convenience method to create a timer with node resources.
Definition: create_timer.hpp:90
std::shared_ptr
std::move
T move(T... args)
rclcpp::node_interfaces::NodeBaseInterface::get_context
virtual rclcpp::Context::SharedPtr get_context()=0
Return the context of the node.
rclcpp::node_interfaces::get_node_base_interface
std::shared_ptr< rclcpp::node_interfaces::NodeBaseInterface > get_node_base_interface(NodeType &&node)
Get the NodeBaseInterface as a shared pointer from a pointer to a "Node like" object.
Definition: get_node_base_interface.hpp:72
rclcpp::Duration::to_chrono
DurationT to_chrono() const
Convert Duration into a std::chrono::Duration.
Definition: duration.hpp:146
rclcpp::node_interfaces::NodeTimersInterface::add_timer
virtual void add_timer(rclcpp::TimerBase::SharedPtr timer, rclcpp::CallbackGroup::SharedPtr callback_group)=0
Add a timer to the node.
std::chrono::nanoseconds
get_node_timers_interface.hpp
rclcpp::GenericTimer
Generic timer. Periodically executes a user-specified callback.
Definition: timer.hpp:159
std::chrono::nanoseconds::zero
T zero(T... args)
rclcpp
This header provides the get_node_base_interface() template function.
Definition: allocator_common.hpp:24
rclcpp::node_interfaces::NodeBaseInterface
Pure virtual interface class for the NodeBase part of the Node API.
Definition: node_base_interface.hpp:36
rclcpp::node_interfaces::NodeTimersInterface
Pure virtual interface class for the NodeTimers part of the Node API.
Definition: node_timers_interface.hpp:29
node_base_interface.hpp
std::runtime_error
std::invalid_argument
rclcpp::Duration
Definition: duration.hpp:26
get_node_base_interface.hpp
node_timers_interface.hpp
rclcpp::create_timer
rclcpp::TimerBase::SharedPtr create_timer(std::shared_ptr< node_interfaces::NodeBaseInterface > node_base, std::shared_ptr< node_interfaces::NodeTimersInterface > node_timers, rclcpp::Clock::SharedPtr clock, rclcpp::Duration period, CallbackT &&callback, rclcpp::CallbackGroup::SharedPtr group=nullptr)
Definition: create_timer.hpp:36
rclcpp::WallTimer
Definition: timer.hpp:259
std::chrono::nanoseconds::max
T max(T... args)
rclcpp::node_interfaces::get_node_timers_interface
std::shared_ptr< rclcpp::node_interfaces::NodeTimersInterface > get_node_timers_interface(NodeType &&node)
Get the NodeTimersInterface as a shared pointer from a pointer to a "Node like" object.
Definition: get_node_timers_interface.hpp:72
duration.hpp