Class: Roby::TaskStateMachine

Inherits:
Object
  • Object
show all
Defined in:
lib/roby/coordination/task_state_machine.rb

Overview

The state machine that can be associate with a task

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(machine) ⇒ TaskStateMachine

Returns a new instance of TaskStateMachine.



66
67
68
69
70
71
72
73
74
# File 'lib/roby/coordination/task_state_machine.rb', line 66

def initialize(machine)
    # Required to initialize underlying state_machine
    super()

    @proxy       = machine.owner_class.new
    @machine     = machine

    update
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args, &block) ⇒ Object



109
110
111
112
113
114
115
116
117
# File 'lib/roby/coordination/task_state_machine.rb', line 109

def method_missing(m, *args, &block)
    # If proxy provides missing method, then use the proxy
    if proxy.respond_to?(m)
        proxy.public_send(m, *args, &block)
    else
        # otherwise pass it on
        super
    end
end

Instance Attribute Details

#machineObject

Underlying state machine



57
58
59
# File 'lib/roby/coordination/task_state_machine.rb', line 57

def machine
  @machine
end

#proxyObject

The proxy object class the state machine is working on



54
55
56
# File 'lib/roby/coordination/task_state_machine.rb', line 54

def proxy
  @proxy
end

#statesObject (readonly)

All state of the state machine



64
65
66
# File 'lib/roby/coordination/task_state_machine.rb', line 64

def states
  @states
end

#transitionsObject (readonly)

Existing transitions Transition comes with methods: event, from_name, to_name



61
62
63
# File 'lib/roby/coordination/task_state_machine.rb', line 61

def transitions
  @transitions
end

Instance Method Details

#do_poll(task) ⇒ Object

Define general poll handler



120
121
122
123
124
125
126
# File 'lib/roby/coordination/task_state_machine.rb', line 120

def do_poll(task)
    begin 
        proxy.poll(task)
    rescue NoMethodError => e
        # poll only if the state has a poll handler defined
    end
end

#identify_state(event_list) ⇒ Object

Identifies the current state given a list of subsequent events Provides a list with the most recent event being last in the list



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/roby/coordination/task_state_machine.rb', line 131

def identify_state(event_list)
    # initalize with all transitions possible
    paths = {}
    @transitions.each do |transition|
        paths[transition] = []
    end

    paths = []
    new_paths = []
    initialized = false

    while event_list.size > 0 
        current_event = event_list.first
        # expand path
        @transitions.each do |transition|
            # Get transitions that match event
            if current_event == transition.event()
                # expand first set of transactions
                if not initialized
                    new_paths << [ transition ]
                else
                    # find transitions that lead to the last transition
                    paths.each do |path|
                        if path.last.from_name == transition.to_name
                            path << transition
                            new_paths << path 
                        end
                    end
                end
            end
        end
        paths = new_paths
        new_paths = []
        initialized = true
        event_list.delete_at(0)
    end

    if paths.size == 1
        # Retrieve last (by time) transitions target state
        return paths[0].last.to_name
    elsif paths.size > 0
        throw "Event list is ambigious, requiring more events"
    end

    throw "Event list is invalid"
end

#initialize_copy(other) ⇒ Object



98
99
100
101
102
103
# File 'lib/roby/coordination/task_state_machine.rb', line 98

def initialize_copy(other)
    other.name = name 
    other.proxy = name.new
    other.machine = machine.dup
    other.update
end

#respond_to_missing?(m, include_private) ⇒ Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/roby/coordination/task_state_machine.rb', line 105

def respond_to_missing?(m, include_private)
    proxy.respond_to?(m) || super
end

#updateObject



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/roby/coordination/task_state_machine.rb', line 76

def update
    @states = []

    # introspect to retrieve all transactions of the statemachine
    @transitions = []
    collection = @machine.states
    collection.each do |s_o|
        collection.each do |s_i|
            # status_transitions is added to TaskStateMachine using meta programming
            transitions = proxy.status_transitions(from: s_o.name.to_sym, to: s_i.name.to_sym)
            @transitions << transitions
        end
        @transitions.flatten!
    end

    # Infer all available states from existing transitions
    @transitions.each do |t|
        @states << t.from_name unless @states.index(t.from_name)
        @states << t.to_name unless @states.index(t.to_name)
    end
end