- Teer and ROS
- Execution flow
Teer and ROS
The teer_ros package patches parts of teer to add support for ROS' time and protect condition variables when being accessed from other threads. This is transparent, and to use teer with ros you just have to add teer_ros as a dependency in your manifest and do an import teer_ros in your script.
A task in Teer is a coroutine, an instantiation of the continuation concept. In teer tasks are implemented using the yield Python keyword, originally designed for generators, but that works well to implement generic coroutines. Tasks are controlled by the scheduler (see below).
The scheduler is responsible for managing tasks and running them using a round-robin policy. In ROS, the scheduler protects access to tasks using a threading.Condition. This section introduces the methods to create, pause, resume, and kill tasks. In general, helper methods are available for groups of tasks, we let the reader refer to the docstring for these. A task can retrieve a reference to the scheduler by calling yield GetScheduler().
Creating and running a scheduler
Your scheduler should be a subclass of Scheduler and it should hold your condition variables as ConditionVariable (see below). Then, you can run it after initialising your node using the run() method.
Getting task identifiers
The list_all_tids() method returns the list of all task identifiers, while the get_current_tid() method returns the identifier of the current task.
Creating a new task
Tasks are created by the new_task() method that takes the function to execute in the task and returns the task identifier (tid).
Killing a task
Tasks can be killed by the kill_task() method that takes the tid of the task to kill and returns whether the operation was a success.
Pausing a task
Tasks can be paused by the pause_task() method that takes the tid of the task to pause and returns whether the operation was a success.
Resuming a task
Tasks can be resumed by the resume_task() method that takes the tid of the task to resume and returns whether the operation was a success.
A debug print that shows the task identifier along with a message is available through the printd() method.
The current_time() method returns the current time, with ROS it uses ros' time.
A condition variable looks like a normal variable, excepted that when it is assigned, the scheduler checks tasks that wait on conditions referring to this variable, and if true, schedule these tasks. Condition variables are implemented using Python's descriptor mechanism and a bit of introspection voodoo. Therefore, condition variables must be members of a subclass of Scheduler.
As the coroutine mechanism of teer is a cooperative-multitasking model, a task runs until it passes the hand to another one. A task does this through the yield keyword, followed by the action to perform.
Switch to another task
To simply switch to another task, do:
Waiting a certain duration
To wait for a certain duration in seconds, do:
The task will continue after duration seconds, excepted if at that time it is paused, in case it will continue when resumed.
An alternative way to run loops at certain frequencies is to create a Rate object, by calling create_rate() on the scheduler and passing the rate in Hz. Then, a task can wait the remaining duration of the period by doing:
Waiting a condition to become true
To wait on a condition, do:
The task will continue when condition_function evaluates to true, excepted if it is paused, in case it will continue when resumed and the condition is true. Note that condition_function will typically be a lambda involving one or more condition variables, for instance:
yield WaitCondition(lambda: sched.variable > value)
where sched is the scheduler and variable a certain condition variable.
Waiting for a task to finish
To wait for a task to finish, do
The task will continue when task tid has finished, excepted if this task is paused, in case it will continue when resumed and tid finished. It is also possible to wait until a group of tasks has finished, either until the have all finished, with WaitAllTasks, or until any has finished, with WaitAnyTasks.