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.



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

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



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

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



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

def machine
  @machine
end

#proxyObject

The proxy object class the state machine is working on



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

def proxy
  @proxy
end

#statesObject (readonly)

All state of the state machine



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

def states
  @states
end

#transitionsObject (readonly)

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



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

def transitions
  @transitions
end

Instance Method Details

#do_poll(task) ⇒ Object

Define general poll handler



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

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



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
177
# File 'lib/roby/coordination/task_state_machine.rb', line 132

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

    paths = []
    new_paths = []
    initialized = false

    until event_list.empty?
        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 !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.empty?
        raise "event list is ambiguous, requiring more events"
    end

    raise "event list is invalid"
end

#initialize_copy(other) ⇒ Object



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

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)


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

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

#updateObject



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

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