.. _program_listing_file_include_rclcpp_timer.hpp: Program Listing for File timer.hpp ================================== |exhale_lsh| :ref:`Return to documentation for file ` (``include/rclcpp/timer.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // Copyright 2014 Open Source Robotics Foundation, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef RCLCPP__TIMER_HPP_ #define RCLCPP__TIMER_HPP_ #include #include #include #include #include #include #include #include #include #include "rclcpp/clock.hpp" #include "rclcpp/context.hpp" #include "rclcpp/function_traits.hpp" #include "rclcpp/macros.hpp" #include "rclcpp/rate.hpp" #include "rclcpp/utilities.hpp" #include "rclcpp/visibility_control.hpp" #include "tracetools/tracetools.h" #include "tracetools/utils.hpp" #include "rcl/error_handling.h" #include "rcl/timer.h" #include "rmw/error_handling.h" #include "rmw/rmw.h" namespace rclcpp { struct TimerInfo { Time expected_call_time; Time actual_call_time; }; class TimerBase { public: RCLCPP_SMART_PTR_DEFINITIONS_NOT_COPYABLE(TimerBase) RCLCPP_PUBLIC explicit TimerBase( Clock::SharedPtr clock, std::chrono::nanoseconds period, rclcpp::Context::SharedPtr context, bool autostart = true); RCLCPP_PUBLIC virtual ~TimerBase(); RCLCPP_PUBLIC void cancel(); RCLCPP_PUBLIC bool is_canceled(); RCLCPP_PUBLIC void reset(); RCLCPP_PUBLIC virtual std::shared_ptr call() = 0; RCLCPP_PUBLIC virtual void execute_callback(const std::shared_ptr & data) = 0; RCLCPP_PUBLIC std::shared_ptr get_timer_handle(); RCLCPP_PUBLIC std::chrono::nanoseconds time_until_trigger(); virtual bool is_steady() = 0; RCLCPP_PUBLIC bool is_ready(); RCLCPP_PUBLIC bool exchange_in_use_by_wait_set_state(bool in_use_state); RCLCPP_PUBLIC void set_on_reset_callback(std::function callback); RCLCPP_PUBLIC void clear_on_reset_callback(); protected: std::recursive_mutex callback_mutex_; // Declare callback before timer_handle_, so on destruction // the callback is destroyed last. Otherwise, the rcl timer // callback would point briefly to a destroyed function. // Clearing the callback on timer destructor also makes sure // the rcl callback is cleared before on_reset_callback_. std::function on_reset_callback_{nullptr}; Clock::SharedPtr clock_; std::shared_ptr timer_handle_; std::atomic in_use_by_wait_set_{false}; RCLCPP_PUBLIC void set_on_reset_callback(rcl_event_callback_t callback, const void * user_data); }; using VoidCallbackType = std::function; using TimerCallbackType = std::function; using TimerInfoCallbackType = std::function; template< typename FunctorT, typename std::enable_if< rclcpp::function_traits::same_arguments::value || rclcpp::function_traits::same_arguments::value || rclcpp::function_traits::same_arguments::value >::type * = nullptr > class GenericTimer : public TimerBase { public: RCLCPP_SMART_PTR_DEFINITIONS(GenericTimer) explicit GenericTimer( Clock::SharedPtr clock, std::chrono::nanoseconds period, FunctorT && callback, rclcpp::Context::SharedPtr context, bool autostart = true ) : TimerBase(clock, period, context, autostart), callback_(std::forward(callback)) { TRACETOOLS_TRACEPOINT( rclcpp_timer_callback_added, static_cast(get_timer_handle().get()), reinterpret_cast(&callback_)); #ifndef TRACETOOLS_DISABLED if (TRACETOOLS_TRACEPOINT_ENABLED(rclcpp_callback_register)) { char * symbol = tracetools::get_symbol(callback_); TRACETOOLS_DO_TRACEPOINT( rclcpp_callback_register, reinterpret_cast(&callback_), symbol); std::free(symbol); } #endif } virtual ~GenericTimer() { // Stop the timer from running. cancel(); } std::shared_ptr call() override { auto timer_call_info_ = std::make_shared(); rcl_ret_t ret = rcl_timer_call_with_info(timer_handle_.get(), timer_call_info_.get()); if (ret == RCL_RET_TIMER_CANCELED) { return nullptr; } if (ret != RCL_RET_OK) { throw std::runtime_error("Failed to notify timer that callback occurred"); } return timer_call_info_; } void execute_callback(const std::shared_ptr & data) override { TRACETOOLS_TRACEPOINT(callback_start, reinterpret_cast(&callback_), false); execute_callback_delegate<>(*static_cast(data.get())); TRACETOOLS_TRACEPOINT(callback_end, reinterpret_cast(&callback_)); } // void specialization template< typename CallbackT = FunctorT, typename std::enable_if< rclcpp::function_traits::same_arguments::value >::type * = nullptr > void execute_callback_delegate(const rcl_timer_call_info_t &) { callback_(); } template< typename CallbackT = FunctorT, typename std::enable_if< rclcpp::function_traits::same_arguments::value >::type * = nullptr > void execute_callback_delegate(const rcl_timer_call_info_t &) { callback_(*this); } template< typename CallbackT = FunctorT, typename std::enable_if< rclcpp::function_traits::same_arguments::value >::type * = nullptr > void execute_callback_delegate(const rcl_timer_call_info_t & timer_call_info) { const TimerInfo info{Time{timer_call_info.expected_call_time, clock_->get_clock_type()}, Time{timer_call_info.actual_call_time, clock_->get_clock_type()}}; callback_(info); } bool is_steady() override { return clock_->get_clock_type() == RCL_STEADY_TIME; } protected: RCLCPP_DISABLE_COPY(GenericTimer) FunctorT callback_; }; template< typename FunctorT, typename std::enable_if< rclcpp::function_traits::same_arguments::value || rclcpp::function_traits::same_arguments::value || rclcpp::function_traits::same_arguments::value >::type * = nullptr > class WallTimer : public GenericTimer { public: RCLCPP_SMART_PTR_DEFINITIONS(WallTimer) WallTimer( std::chrono::nanoseconds period, FunctorT && callback, rclcpp::Context::SharedPtr context, bool autostart = true) : GenericTimer( std::make_shared(RCL_STEADY_TIME), period, std::move(callback), context, autostart) {} protected: RCLCPP_DISABLE_COPY(WallTimer) }; } // namespace rclcpp #endif // RCLCPP__TIMER_HPP_