class Roby::Schedulers::Basic

The basic schedulers uses the Roby's “core” plan model to decide which tasks can be started.

See the documentation of Roby::Schedulers for more information

The basic scheduler starts the tasks for which:

* the task is pending, executable and owned by the local robot
* the start event is root in all event relations (i.e. there is
  neither signals and forwards pointing to it).
* it is root in the dependency relationship
* if the +include_children+ option of Basic.new is set to true, it
  may be non-root in the dependency relation, in which case it is
  started if and only if it has at least one parent that is running
  (i.e. children are started after their parents).

Attributes

include_children[R]

If true, the scheduler will start tasks which are non-root in the dependency relation, if they have parents that are already running.

plan[R]

The plan on which the scheduler applies

query[R]

The Roby::Query which is used to get the set of tasks that might be startable

Public Class Methods

new(include_children = false, plan = nil) click to toggle source

Create a new Basic schedulers that work on the given plan, and with the provided include_children option.

See Basic for a description of the include_children option.

If plan is set to nil, the scheduler will use Roby.plan

Calls superclass method
# File lib/roby/schedulers/basic.rb, line 53
def initialize(include_children = false, plan = nil)
    super()

    @plan = plan || Roby.plan
    @include_children = include_children
    @query = self.plan.find_tasks.
        executable.
        pending.
        self_owned

    @can_schedule_cache = Hash.new
    @enabled = true
end

Public Instance Methods

can_schedule?(task, time = Time.now, stack = []) click to toggle source
# File lib/roby/schedulers/basic.rb, line 95
def can_schedule?(task, time = Time.now, stack = [])
    if !can_start?(task)
        report_holdoff "cannot be started", task
        return false
    end

    root_task =
        if task.root?(TaskStructure::Dependency)
            true
        else
            planned_tasks = task.planned_tasks
            !planned_tasks.empty? &&
                planned_tasks.all? { |t| !t.executable? }
        end

    if root_task
        true
    elsif include_children && task.parents.any? { |t| t.running? }
        true
    elsif include_children
        report_holdoff "not root, and has no running parent", task
        false
    else
        report_holdoff "not root, and include_children is false", task
        false
    end
end
can_start?(task) click to toggle source
# File lib/roby/schedulers/basic.rb, line 69
def can_start?(task)
    start_event = task.start_event
    if !start_event.controlable?
        report_holdoff "start event not controlable", task
        return false
    end

    if (agent = task.execution_agent) && !agent.ready_event.emitted?
        report_holdoff "task's execution agent %2 is not ready", task, agent
        return false
    end

    if !start_event.root?(EventStructure::CausalLink)
        report_holdoff "start event not root in the causal link relation", task
        return false
    end

    task.each_relation do |r|
        if r.respond_to?(:scheduling?) && !r.scheduling? && !task.root?(r)
            report_holdoff "not root in %2, which forbids scheduling", task, r
            return false 
        end
    end
    true
end
initial_events() click to toggle source

Starts all tasks that are eligible. See the documentation of the Basic class for an in-depth description

# File lib/roby/schedulers/basic.rb, line 125
def initial_events
    @can_schedule_cache.clear
    time = Time.now

    not_executable = self.plan.find_tasks.
        not_executable.
        pending.
        self_owned

    not_executable.each do |task|
        # Try to figure out why ...
        if task.execution_agent && !task.execution_agent.ready?
            report_pending_non_executable_task("execution agent not ready (%2)", task, task.execution_agent)
        elsif task.partially_instanciated?
            report_pending_non_executable_task("partially instanciated", task)
        else
            report_pending_non_executable_task("not executable", task)
        end
    end

    scheduled_tasks = []
    for task in query.reset
        result =
            if @can_schedule_cache.include?(task)
                @can_schedule_cache[task]
            else @can_schedule_cache[task] = can_schedule?(task, time, [])
            end

        if result
            task.start!
            report_trigger task.start_event
            scheduled_tasks << task
        end
    end
    scheduled_tasks
end