Class: Roby::Schedulers::Temporal

Inherits:
Basic show all
Defined in:
lib/roby/schedulers/temporal.rb

Overview

The temporal scheduler adds to the decisions made by the Basic scheduler information given by the temporal constraint network.

See the documentation of Roby::Schedulers for more information

Instance Attribute Summary collapse

Attributes inherited from Basic

#include_children, #plan, #query

Instance Method Summary collapse

Methods inherited from Basic

#can_start?, #initial_events

Methods inherited from Reporting

#report_action, #report_holdoff, #report_pending_non_executable_task, #report_trigger

Constructor Details

#initialize(with_basic = true, with_children = true, plan = nil) ⇒ Temporal

Returns a new instance of Temporal.



17
18
19
20
21
22
# File 'lib/roby/schedulers/temporal.rb', line 17

def initialize(with_basic = true, with_children = true, plan = nil)
    super(with_children, plan)
    @basic_constraints = with_basic
    @scheduling_constraints_graph = self.plan.
        event_relation_graph_for(EventStructure::SchedulingConstraints)
end

Instance Attribute Details

#scheduling_constraints_graphObject (readonly)

The proper graph object that contains the scheduling constraints



15
16
17
# File 'lib/roby/schedulers/temporal.rb', line 15

def scheduling_constraints_graph
  @scheduling_constraints_graph
end

Instance Method Details

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

Returns:

  • (Boolean)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/roby/schedulers/temporal.rb', line 24

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

    start_event = task.start_event

    event_filter = lambda do |ev|
        if ev.respond_to?(:task)
            ev.task != task &&
                !stack.include?(ev.task) &&
                !scheduling_constraints_graph.related_tasks?(ev.task, task)
        else true
        end
    end

    meets_constraints = start_event.meets_temporal_constraints?(time, &event_filter)
    if !meets_constraints
        if failed_temporal = start_event.find_failed_temporal_constraint(time, &event_filter)
            report_holdoff "temporal constraints not met (%2: %3)", task, failed_temporal[0], failed_temporal[1]
        end
        if failed_occurence = start_event.find_failed_occurence_constraint(true, &event_filter)
            report_holdoff "occurence constraints not met (%2)", task, failed_occurence
        end
        return false
    end

    start_event.each_backward_scheduling_constraint do |parent|
        begin
            stack.push task
            if !can_schedule?(parent.task, time, stack)
                report_holdoff "held by a schedule_as constraint with %2", task, parent
                return false
            end
        ensure
            stack.pop
        end
    end

    if basic_constraints?
        if super
            return true
        else
            # Special case: check in Dependency if there are some
            # parents for which a forward constraint from +self+ to
            # +parent.start_event+ exists. If it is the case, start
            # the task
            task.each_parent_task do |parent|
                parent.start_event.each_backward_temporal_constraint do |constraint|
                    if constraint.respond_to?(:task) && constraint.task == task
                        Schedulers.debug { "Temporal: #{task} has no running parent, but a constraint from #{constraint} to #{parent}.start exists. Scheduling." }
                        return true
                    end
                end
            end
            return false
        end
    else
        return true
    end
end