Class: Roby::Schedulers::Basic

Inherits:
Reporting show all
Defined in:
lib/roby/schedulers/basic.rb

Overview

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).

Direct Known Subclasses

Temporal

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Reporting

#report_action, #report_holdoff, #report_pending_non_executable_task, #report_trigger

Constructor Details

#initialize(include_children = false, plan = nil) ⇒ Basic

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



55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/roby/schedulers/basic.rb', line 55

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

    @enabled = true
end

Instance Attribute Details

#include_childrenObject (readonly)

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



47
48
49
# File 'lib/roby/schedulers/basic.rb', line 47

def include_children
  @include_children
end

#planObject (readonly)

The plan on which the scheduler applies



40
41
42
# File 'lib/roby/schedulers/basic.rb', line 40

def plan
  @plan
end

#queryObject (readonly)

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



43
44
45
# File 'lib/roby/schedulers/basic.rb', line 43

def query
  @query
end

Instance Method Details

#basic_scheduling_root_task?(task) ⇒ Boolean

Returns:

  • (Boolean)


116
117
118
119
120
121
122
# File 'lib/roby/schedulers/basic.rb', line 116

def basic_scheduling_root_task?(task)
    return true if task.root?(TaskStructure::Dependency)

    planned_tasks = task.planned_tasks
    !planned_tasks.empty? &&
        planned_tasks.all? { |t| !t.executable? }
end

#can_schedule?(task, time = Time.now, stack = []) ⇒ Boolean

Returns:

  • (Boolean)


96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/roby/schedulers/basic.rb', line 96

def can_schedule?(task, time = Time.now, stack = [])
    unless can_start?(task)
        report_holdoff "cannot be started", task
        return false
    end

    root_task = basic_scheduling_root_task?(task)
    if root_task
        true
    elsif include_children && task.parents.any?(&: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) ⇒ Boolean

Returns:

  • (Boolean)


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/roby/schedulers/basic.rb', line 70

def can_start?(task)
    start_event = task.start_event
    unless 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

    unless 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_eventsObject

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



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/roby/schedulers/basic.rb', line 126

def initial_events
    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
        if can_schedule?(task, time, [])
            task.start!
            report_trigger task.start_event
            scheduled_tasks << task
        end
    end
    scheduled_tasks
end