There's an approach to robotic control called Reactive Action Packages. It's a way of specifying what to what, when, in what sequence, and with what taking priority over what. All of it specified in a robust manner and driven by external sensors. Anyway, I've coded my take on RAPs a number of times and never really been happy with the result. This time though my solution really feels right. Groovy builders work so well here:The basic idea is that this DSL can be evaluated each time my robot needs to take an action. DSL statements are evaluated in sequence until one provides an action. So, if it's lost it explores. If it's not lost and it's score is under 1000 and it's already at somePlace then it does someAction. Sweet!
this.brain = new NodeBuilder()
.code {
when('lost') {
explore()
}
when('score < 1000') {
go('somePlace')
someAction()
}
}
The only gotcha to evaluating the NodeBuilder result is that closure('aString') statement1 ; statement2 } evaluates to a Node whose value() is ['aString', node1, node2]:this.eval = { code ->
if (code instanceof Node) {
return evalNode(code)
}
def iterator = code.iterator()
def result = null
while(!result && iterator.hasNext()) {
def node = iterator.next()
result = eval(node)
}
return result
}
this.evalNode = { node ->
def result = actions[node.name()](node.value())
return result
}actions are defined easily enough:The last piece of the puzzle is setting up the this.actions = [
when: { args ->
if (shell.evaluate(args[0])) {
return eval(args[1,-1])
}
return false;
},
explore: { "EXPLORE" },
go: { to ->
def loc = shell.evaluate("loc")
if (loc == to) {
return false
}
def direction = navigator.directionTo(loc, to)
return "DIR $direction"
},
someAction: { "SOME_ACTION" }]GroovyShell with it's context and evaluating the DSL code:To those who made builders a part of Groovy: thanks so much!this.act = {
shell = new GroovyShell()
shell.setVariable("loc", loc)
shell.setVariable("score", score)
def action = eval(brain.value())
if (action) {
// do magic
} else {
println "No action chosen!"
}
}
Tapestry and Kaptcha
-
Another bit of interesting work I did, for another client, was to implement
a CAPTCHA system. I chose the library Kaptcha and built services and
componen...
9 hours ago

1 comments:
list[1,-1] doesn't work as I thought it did. [1,2][1,-1] == [2,2] !!
Instead, use list.tail().
Post a Comment