diff --git a/rclpy/rclpy/exceptions.py b/rclpy/rclpy/exceptions.py index ee22e8b38..27d736fa5 100644 --- a/rclpy/rclpy/exceptions.py +++ b/rclpy/rclpy/exceptions.py @@ -46,6 +46,7 @@ def __init__(self, name_type: str, name: str, error_msg: str, invalid_index: int InvalidHandle = _rclpy.InvalidHandle +TimerCancelledError = _rclpy.TimerCancelledError class InvalidNamespaceException(NameValidationException): diff --git a/rclpy/rclpy/executors.py b/rclpy/rclpy/executors.py index 336a2b0f5..2d4295d7c 100644 --- a/rclpy/rclpy/executors.py +++ b/rclpy/rclpy/executors.py @@ -41,7 +41,7 @@ from rclpy.clock import Clock from rclpy.clock_type import ClockType from rclpy.context import Context -from rclpy.exceptions import InvalidHandle +from rclpy.exceptions import InvalidHandle, TimerCancelledError from rclpy.guard_condition import GuardCondition from rclpy.impl.implementation_singleton import rclpy_implementation as _rclpy from rclpy.service import Service @@ -384,8 +384,10 @@ async def _execute(): except InvalidHandle: # Timer is a Destroyable, which means that on __enter__ it can throw an # InvalidHandle exception if the entity has already been destroyed. Handle that here - # by just returning an empty argument, which means we will skip doing any real work - # in _execute_timer below + # by just returning an empty argument, which means we will skip doing any real work. + pass + except TimerCancelledError: + # If this exception occurs when calling call_timer(), we will skip doing any real work. pass return None diff --git a/rclpy/src/rclpy/_rclpy_pybind11.cpp b/rclpy/src/rclpy/_rclpy_pybind11.cpp index f33fdaa2f..97ca23ac9 100644 --- a/rclpy/src/rclpy/_rclpy_pybind11.cpp +++ b/rclpy/src/rclpy/_rclpy_pybind11.cpp @@ -118,6 +118,8 @@ PYBIND11_MODULE(_rclpy_pybind11, m) { m, "NodeNameNonExistentError", rclerror.ptr()); py::register_exception( m, "UnsupportedEventTypeError", rclerror.ptr()); + py::register_exception( + m, "TimerCancelledError", rclerror.ptr()); py::register_exception( m, "NotImplementedError", PyExc_NotImplementedError); py::register_exception( diff --git a/rclpy/src/rclpy/exceptions.hpp b/rclpy/src/rclpy/exceptions.hpp index 521146fd0..dc6f6aed3 100644 --- a/rclpy/src/rclpy/exceptions.hpp +++ b/rclpy/src/rclpy/exceptions.hpp @@ -70,6 +70,11 @@ class UnsupportedEventTypeError : public RCLError using RCLError::RCLError; }; +class TimerCancelledError : public RCLError +{ + using RCLError::RCLError; +}; + class NotImplementedError : public RCLError { using RCLError::RCLError; diff --git a/rclpy/src/rclpy/timer.cpp b/rclpy/src/rclpy/timer.cpp index c3e744f09..37321820b 100644 --- a/rclpy/src/rclpy/timer.cpp +++ b/rclpy/src/rclpy/timer.cpp @@ -90,7 +90,11 @@ void Timer::call_timer() { rcl_ret_t ret = rcl_timer_call(rcl_timer_.get()); if (ret != RCL_RET_OK) { - throw RCLError("failed to call timer"); + if (ret == RCL_RET_TIMER_CANCELED) { + throw TimerCancelledError("Timer has been canceled"); + } else { + throw RCLError("failed to call timer"); + } } }