I wrote a small test wrt. the behavior of ROS 2 timers in case of a timer callback that (always or occasionally) takes longer than the timer period, see this repository.
Posting here as I think it can be of relevance to others.
The conclusions:
Consider a timer at a rate of 1s,
- The first callback call however takes 3s calculation time,
- The next calls take only a few milliseconds.
In case of a mutually exclusive callback group:
- The first call will be made at t = 1s,
- This blocks execution of the 2nd call (obviously since mutually exclusive),
- The 2nd call will start instantly after completion of the 1st call (i.e. at t = 4s),
- The 3rd call will start at t = 5s,
- The 4th call will start at t = 6s,
- Etc.
This means that next intended callback time is defined as:
previous callback start time + timer period
,
as otherwise calls 2, 3 and 4 would all be made asap after completion of call 1, and call 5 at t = 5s.
(this is not entirely correct; see clarification by @ottojo in next post)
In case of a reentrant callback group:
- The first call is made at t = 1s, runs until t = 4s,
- The 2nd call is started at t = 2s in another (available) thread,
- The 3rd call is started at t = 3s also in an available thread,
- Etc.
As long as there are enough available threads (and computing power), then it does not matter if the callbacks takes longer than the timer period, the callbacks will still be called at the correct rate.
However if the executor runs out of available threads, then similar behavior as in the mutually exclusive case is obtained (i.e. execution of the next call is blocked until a previous one is done).