Created
June 10, 2009 01:41
-
-
Save llatzhar/126958 to your computer and use it in GitHub Desktop.
HSM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 1 state 1 block | |
module Hsm | |
class Event | |
def initialize(name) | |
@name = name | |
end | |
end | |
# system events | |
INIT = Event.new('INIT') | |
ENTER = Event.new('ENTER') | |
EXIT = Event.new('EXIT') | |
SUPER = Event.new('SUPER') | |
module Machine | |
def initHsm | |
@states = {} | |
@cur = nil | |
end | |
def register(name, &block) | |
@states[name] = block | |
end | |
def start(name) | |
# TODO 順に入っていく | |
@cur = name | |
dispatch(ENTER) | |
end | |
def to_top(from) | |
a = [] | |
s = from | |
while s != :top | |
a << s | |
s = _super(s) | |
end | |
a << :top | |
end | |
def lca(from, to) | |
l = :top | |
i = 0 | |
while true | |
if from[i] != to[i] | |
break | |
else | |
l = from[i] | |
end | |
i += 1 | |
end | |
l | |
end | |
# TODO おかしい気がする? cur != src | |
def trans(dest) | |
#puts "TRANS: from=#{@cur.inspect} to=#{dest.inspect}" | |
if @cur == dest | |
trigger(@cur, EXIT) | |
trigger(dest, ENTER) | |
else | |
cur2top = to_top(@cur) | |
dest2top = to_top(dest) | |
ancestor = lca(cur2top.reverse, dest2top.reverse) | |
#puts "lca=#{ancestor.inspect}" | |
# EXIT: cur -> lca | |
cur2top[0, cur2top.index(ancestor)].each do |s| | |
trigger(s, EXIT) | |
end | |
# ENTER: lca -> dest | |
dest2top[0, dest2top.index(ancestor)].reverse.each do |s| | |
trigger(s, ENTER) | |
end | |
@cur = dest | |
end | |
end | |
def trigger(state, event) | |
@states[state].call(event) | |
end | |
def _super(state) | |
@states[state].call(SUPER) | |
end | |
def dispatch(event) | |
st = @cur | |
while true | |
#puts "START DISPATCH: st=#{st.inspect} ev=#{event.inspect}" | |
s = trigger(st, event) | |
#puts "return = #{s.inspect}" | |
if s != 0 and s != :top | |
st = s | |
else | |
break | |
end | |
end | |
#puts "END DISPATCH" | |
end | |
end | |
end | |
if __FILE__ == $0 | |
#main | |
#define events | |
module Hsm | |
TIRE = Event.new('TIRE') | |
ALERM = Event.new('ALERM') | |
end | |
# define state machine | |
class MyMachine | |
include Hsm::Machine | |
def initialize | |
init | |
register(:sleeping) do |e| | |
puts @cur.inspect + ' ' + e.inspect | |
case e | |
when Hsm::ENTER | |
puts 'sleep.' | |
next 0 | |
when Hsm::TIRE | |
puts 'sleeping.' | |
next 0 | |
when Hsm::ALERM | |
puts 'ooohh' | |
trans(:sitting) | |
next 0 | |
when Hsm::EXIT | |
puts 'awake?.' | |
next 0 | |
end | |
next :top | |
end | |
register(:awake) do |e| | |
puts @cur.inspect + ' ' + e.inspect | |
case e | |
when Hsm::ENTER | |
puts 'awake.' | |
next 0 | |
when Hsm::TIRE | |
puts 'im tired.' | |
trans(:sitting) | |
next 0 | |
when Hsm::ALERM | |
puts 'uuum?' | |
next 0 | |
when Hsm::EXIT | |
puts 'dance end.' | |
next 0 | |
end | |
next :top | |
end | |
register(:dancing) do |e| | |
puts @cur.inspect + ' ' + e.inspect | |
case e | |
when Hsm::SUPER | |
next :awake | |
when Hsm::ENTER | |
puts 'dance start.' | |
next 0 | |
when Hsm::TIRE | |
puts 'im tired.' | |
trans(:sitting) | |
next 0 | |
when Hsm::EXIT | |
puts 'dance end.' | |
next 0 | |
end | |
next :awake | |
end | |
register(:sitting) do |e| | |
puts @cur.inspect + ' ' + e.inspect | |
case e | |
when Hsm::SUPER | |
next :awake | |
when Hsm::ENTER | |
puts 'start sitting.' | |
next 0 | |
when Hsm::TIRE | |
puts 'yes, im tired yet.' | |
trans(:sleeping) | |
next 0 | |
when Hsm::EXIT | |
puts 'end sitting.' | |
next 0 | |
end | |
next :awake | |
end | |
start(:dancing) | |
end | |
end | |
m = MyMachine.new | |
m.dispatch(Hsm::ALERM) | |
m.dispatch(Hsm::TIRE) | |
m.dispatch(Hsm::TIRE) | |
m.dispatch(Hsm::ALERM) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment