Class: Roby::Coordination::ActionStateMachine

Inherits:
Actions show all
Extended by:
Models::ActionStateMachine
Includes:
Hooks, Hooks::InstanceHooks
Defined in:
lib/roby/coordination/action_state_machine.rb

Overview

A state machine defined on action interfaces

In such state machine, each state is represented by the task returned by the corresponding action, and the transitions are events on these tasks

Defined Under Namespace

Classes: StateInfo

Instance Attribute Summary collapse

Attributes included from Models::ActionStateMachine

#starting_state

Attributes included from Models::Actions

#action_interface

Attributes included from Models::Base

#name, #root

Attributes inherited from Actions

#current_task, #resolved_captures, #task_info

Attributes inherited from Base

#arguments, #instances, #parent

Instance Method Summary collapse

Methods included from Models::ActionStateMachine

capture, compute_unreachable_states, find_state_by_name, map_tasks, parse, parse_names, start, state, to_s, toplevel_state?, transition, validate_task

Methods included from Models::Actions

#dependency, #depends_on, #event_active_in_state?, #forward, #from, #from_state, #map_tasks, #method_missing, #parse, #rebind, #required_tasks_for, #respond_to_missing?, #root_event?, #setup_submodel, #toplevel_state?

Methods included from Models::Base

#find_event, #find_task_by_name, #map_tasks, #method_missing, #parse_names, #respond_to_missing?, #setup_submodel, #task, #task_model, #use_fault_response_table, #used_fault_response_table, #validate_event, #validate_or_create_task, #validate_task

Methods included from Models::Arguments

#argument, #validate_arguments

Methods included from Hooks

included

Methods inherited from Actions

#action_interface_model, #remove_current_task, #resolve_task_info, #start_task, #task_info_for

Methods inherited from Base

#attach_fault_response_tables_to, #bind_coordination_task_to_instance, #instance_for, #model, #plan, #root_task

Constructor Details

#initialize(root_task, arguments = {}) ⇒ ActionStateMachine

Returns a new instance of ActionStateMachine.



23
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
# File 'lib/roby/coordination/action_state_machine.rb', line 23

def initialize(root_task, arguments = {})
    super(root_task, arguments)
    @task_info = resolve_state_info

    start_state = model.starting_state
    if arguments[:start_state]
        start_state = model.find_state_by_name(arguments[:start_state])
        unless start_state
            raise ArgumentError,
                  "The starting state #{arguments[:start_state]} is "\
                  "unkown, make sure its defined in #{self}"
        end
    end

    model.each_capture do |capture, (in_state, captured_event)|
        if in_state == model.root
            captured_event = instance_for(model.root).find_event(captured_event.symbol)
            captured_event.resolve.once do |event|
                if root_task.running?
                    resolved_captures[capture] = capture.filter(self, event)
                end
            end
        end
    end

    root_task.execute do
        if start_state
            @current_state = start_state
            instanciate_state(instance_for(start_state))
        end
    end
end

Instance Attribute Details

#current_stateObject (readonly)

The current state



19
20
21
# File 'lib/roby/coordination/action_state_machine.rb', line 19

def current_state
  @current_state
end

Instance Method Details

#dependency_options_for(toplevel, task, roles) ⇒ Object



80
81
82
83
84
85
86
# File 'lib/roby/coordination/action_state_machine.rb', line 80

def dependency_options_for(toplevel, task, roles)
    options = super
    options[:success] = task_info[toplevel].transitions.map do |source, _|
        source.symbol.emitted?.from_now if source.task == task
    end.compact
    options
end

#instanciate_state(state) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/roby/coordination/action_state_machine.rb', line 88

def instanciate_state(state)
    begin
        start_task(state)
    rescue Models::Capture::Unbound => e
        raise e, "in the action state machine #{model} running on #{root_task} while starting #{state.name}, #{e.message}", e.backtrace
    end

    state_info = task_info[state]
    tasks, known_transitions, captures =
        state_info.required_tasks,
        state_info.transitions,
        state_info.captures

    transitioned = false
    captures.each do |capture, captured_event|
        captured_event.resolve.once do |event|
            if !transitioned && root_task.running?
                resolved_captures[capture] = capture.filter(self, event)
            end
        end
    end
    known_transitions.each do |source_event, new_state|
        source_event.resolve.once do |event|
            if !transitioned && root_task.running?
                transitioned = true
                begin
                    instanciate_state_transition(event.task, new_state)
                rescue Exception => e
                    event.task.plan.add_error(
                        ActionStateTransitionFailed.new(root_task, state, event, new_state, e)
                    )
                end
            end
        end
    end
end

#instanciate_state_transition(task, new_state) ⇒ Object



125
126
127
128
129
130
# File 'lib/roby/coordination/action_state_machine.rb', line 125

def instanciate_state_transition(task, new_state)
    remove_current_task
    instanciate_state(new_state)
    @current_state = new_state
    run_hook :on_transition, task, new_state
end

#resolve_state_infoObject



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/roby/coordination/action_state_machine.rb', line 56

def resolve_state_info
    task_info.each_with_object({}) do |(task, task_info), h|
        task_info = StateInfo.new(
            task_info.required_tasks,
            task_info.forwards,
            Set.new, {}
        )
        model.each_transition do |in_state, event, new_state|
            in_state = instance_for(in_state)
            if in_state == task
                task_info.transitions <<
                    [instance_for(event), instance_for(new_state)]
            end
        end
        model.each_capture do |capture, (in_state, event)|
            in_state = instance_for(in_state)
            if in_state == task
                task_info.captures[capture] = instance_for(event)
            end
        end
        h[task] = task_info
    end
end