Peeja-rubot 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.autotest +4 -0
- data/Adapters.txt +3 -0
- data/History.txt +4 -0
- data/Manifest.txt +47 -0
- data/README.txt +53 -0
- data/Rakefile +31 -0
- data/bin/rubot +20 -0
- data/examples/navigate.rbt +60 -0
- data/ext/rubot_aria/RAGenericAction.cpp +87 -0
- data/ext/rubot_aria/RAGenericAction.h +96 -0
- data/ext/rubot_aria/RARobotManager.cpp +73 -0
- data/ext/rubot_aria/RARobotManager.h +30 -0
- data/ext/rubot_aria/extconf.rb +9 -0
- data/ext/rubot_aria/rubot_aria.cpp +63 -0
- data/lib/rubot.rb +14 -0
- data/lib/rubot/adapters.rb +39 -0
- data/lib/rubot/adapters/aria.rb +5 -0
- data/lib/rubot/adapters/aria/action_desired.rb +18 -0
- data/lib/rubot/adapters/aria/robot.rb +30 -0
- data/lib/rubot/adapters/asimov.rb +2 -0
- data/lib/rubot/dsl.rb +161 -0
- data/lib/rubot/meta.rb +13 -0
- data/spec/load_paths.rb +9 -0
- data/spec/rubot/adapters/aria/robot_manager_spec.rb +12 -0
- data/spec/rubot/adapters/aria/robot_spec.rb +38 -0
- data/spec/rubot/adapters/aria_spec.rb +5 -0
- data/spec/rubot/adapters/spec_helper.rb +16 -0
- data/spec/rubot/dsl_spec.rb +22 -0
- data/spec/rubot_spec.rb +4 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +19 -0
- data/tasks/ann.rake +76 -0
- data/tasks/annotations.rake +22 -0
- data/tasks/doc.rake +48 -0
- data/tasks/gem.rake +110 -0
- data/tasks/manifest.rake +49 -0
- data/tasks/post_load.rake +26 -0
- data/tasks/rubyforge.rake +57 -0
- data/tasks/setup.rb +227 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +44 -0
- data/tasks/test.rake +38 -0
- metadata +121 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "Aria.h"
|
4
|
+
#include "RAGenericAction.h"
|
5
|
+
|
6
|
+
/*
|
7
|
+
* RARobotManager
|
8
|
+
* Encapsulates an ArRobot and its connection.
|
9
|
+
*
|
10
|
+
*/
|
11
|
+
|
12
|
+
class RARobotManager
|
13
|
+
{
|
14
|
+
public:
|
15
|
+
RARobotManager();
|
16
|
+
virtual ~RARobotManager();
|
17
|
+
void go(const char *argString);
|
18
|
+
void stop();
|
19
|
+
void addAction(RAGenericAction *action, int priority);
|
20
|
+
void addSensor(Rice::Symbol sensor);
|
21
|
+
double getRobotRadius() { return myRobot.getRobotRadius(); }
|
22
|
+
|
23
|
+
private:
|
24
|
+
ArRobot myRobot;
|
25
|
+
ArFunctorC<RARobotManager> myStopCB;
|
26
|
+
ArKeyHandler *myRobotKeyHandler;
|
27
|
+
|
28
|
+
// Sensors
|
29
|
+
ArSonarDevice *mySonar;
|
30
|
+
};
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#include "rice/Module.hpp"
|
2
|
+
#include "rice/Data_Type.hpp"
|
3
|
+
#include "rice/Constructor.hpp"
|
4
|
+
#include "rice/Exception.hpp"
|
5
|
+
#include "rice/Array.hpp"
|
6
|
+
#include "Aria.h"
|
7
|
+
|
8
|
+
#include "RAGenericAction.h"
|
9
|
+
#include "RARobotManager.h"
|
10
|
+
|
11
|
+
using namespace std;
|
12
|
+
using namespace Rice;
|
13
|
+
|
14
|
+
extern "C"
|
15
|
+
void Init_rubot_aria()
|
16
|
+
{
|
17
|
+
static char inited = 0;
|
18
|
+
if (!inited) Aria::init(Aria::SIGHANDLE_NONE);
|
19
|
+
inited = 1;
|
20
|
+
|
21
|
+
Object rb_MRubot = Class(rb_cObject).const_get("Rubot");
|
22
|
+
Object rb_MAdapters = Module(rb_MRubot).const_get("Adapters");
|
23
|
+
Object rb_MAria = Module(rb_MAdapters)
|
24
|
+
.define_module("Aria")
|
25
|
+
;
|
26
|
+
|
27
|
+
|
28
|
+
Data_Type<RARobotManager> rb_cRobotManager = Module(rb_MAria)
|
29
|
+
.define_class<RARobotManager>("RobotManager")
|
30
|
+
.define_constructor(Constructor<RARobotManager>())
|
31
|
+
.define_method("go", &RARobotManager::go)
|
32
|
+
.define_method("add_behavior", &RARobotManager::addAction)
|
33
|
+
.define_method("add_sensor", &RARobotManager::addSensor)
|
34
|
+
.define_method("robot_radius", &RARobotManager::getRobotRadius)
|
35
|
+
;
|
36
|
+
|
37
|
+
Data_Type<RAGenericAction> rb_cBehavior = Module(rb_MAria)
|
38
|
+
.define_class<RAGenericAction>("Behavior")
|
39
|
+
.define_constructor(Constructor<RAGenericAction, const char *>())
|
40
|
+
.define_method("set_fire_proc", &RAGenericAction::setFireProc)
|
41
|
+
.define_method("set_sensors", &RAGenericAction::setSensors)
|
42
|
+
.define_method("get_sensor", &RAGenericAction::getSensor)
|
43
|
+
.define_method("get_desired", &RAGenericAction::getActionDesired)
|
44
|
+
;
|
45
|
+
|
46
|
+
Data_Type<ArActionDesiredWrap> rb_cActionDesired = Module(rb_MAria)
|
47
|
+
.define_class<ArActionDesiredWrap>("ActionDesired")
|
48
|
+
.define_method("velocity", &ArActionDesiredWrap::getVel)
|
49
|
+
.define_method("velocity_strength", &ArActionDesiredWrap::getVelStrength)
|
50
|
+
.define_method("set_velocity", &ArActionDesiredWrap::setVel)
|
51
|
+
.define_method("delta_heading", &ArActionDesiredWrap::getDeltaHeading)
|
52
|
+
.define_method("delta_heading_strength", &ArActionDesiredWrap::getDeltaHeadingStrength)
|
53
|
+
.define_method("set_delta_heading", &ArActionDesiredWrap::setDeltaHeading)
|
54
|
+
.define_method("heading", &ArActionDesiredWrap::getHeading)
|
55
|
+
.define_method("heading_strength", &ArActionDesiredWrap::getHeadingStrength)
|
56
|
+
.define_method("set_heading", &ArActionDesiredWrap::setHeading)
|
57
|
+
;
|
58
|
+
|
59
|
+
Data_Type<ArRangeDeviceWrap> rb_cRangeDevice = Module(rb_MAria)
|
60
|
+
.define_class<ArRangeDeviceWrap>("RangeDevice")
|
61
|
+
.define_method("range", &ArRangeDeviceWrap::currentReadingPolar)
|
62
|
+
;
|
63
|
+
}
|
data/lib/rubot.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# Require everything except things under rubot/adapters/ (which load lazily).
|
2
|
+
# (Dir[File.join(::File.dirname(__FILE__), '**', '*.rb')] -
|
3
|
+
# Dir[File.join(::File.dirname(__FILE__), 'rubot', 'adapters', '**')]).sort.each {|rb| require rb}
|
4
|
+
|
5
|
+
unless defined? Rubot
|
6
|
+
|
7
|
+
module Rubot; end
|
8
|
+
|
9
|
+
require 'rubot/meta'
|
10
|
+
|
11
|
+
require 'rubot/adapters'
|
12
|
+
require 'rubot/dsl'
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'facets/string/snakecase'
|
2
|
+
require 'facets/module/alias'
|
3
|
+
|
4
|
+
# This module contains the robotics adapters. For instance, the ACME
|
5
|
+
# Robotics adapter would be <tt>Rubot::Adapters::AcmeRobotics</tt>. Its robot
|
6
|
+
# class would be <tt>Rubot::Adapters::AcmeRobotics::Robot</tt>, and one can be
|
7
|
+
# created with
|
8
|
+
#
|
9
|
+
# fred = Rubot::Adapters::AcmeRobotics::Robot.new
|
10
|
+
#
|
11
|
+
# or, in Rubot syntax,
|
12
|
+
#
|
13
|
+
# robot :fred do
|
14
|
+
# adapter :acme_robotics
|
15
|
+
# end
|
16
|
+
module Rubot
|
17
|
+
# Raised when attempting to create a robot with an unrecognized adapter.
|
18
|
+
class AdapterMissingError < Exception; end
|
19
|
+
|
20
|
+
module Adapters
|
21
|
+
class << self
|
22
|
+
def const_missing_with_autoload(name)
|
23
|
+
# TODO: Handle missing adapter without obscuring all LoadErrors.
|
24
|
+
# begin
|
25
|
+
req_name = "rubot/adapters/#{name.to_s.snakecase}"
|
26
|
+
require req_name
|
27
|
+
if const_defined? name
|
28
|
+
return const_get(name)
|
29
|
+
else
|
30
|
+
raise AdapterMissingError, "Adapter #{name} not loaded by '#{req_name}'."
|
31
|
+
end
|
32
|
+
# rescue LoadError
|
33
|
+
# raise AdapterMissingError, "Adapter #{name} not found."
|
34
|
+
# end
|
35
|
+
end
|
36
|
+
alias_method_chain :const_missing, :autoload
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Rubot::Adapters::Aria
|
2
|
+
class ActionDesired
|
3
|
+
%w[ velocity delta_heading heading ].each do |channel|
|
4
|
+
eval <<-CHAN_DEF
|
5
|
+
private :set_#{channel}
|
6
|
+
|
7
|
+
def #{channel}=(val)
|
8
|
+
# Use current channel strength, or maximum (1) if not set.
|
9
|
+
set_#{channel} val, (#{channel}_strength != 0 ? #{channel}_strength : 1)
|
10
|
+
end
|
11
|
+
|
12
|
+
def #{channel}_strength=(strength)
|
13
|
+
set_#{channel} #{channel}, strength
|
14
|
+
end
|
15
|
+
CHAN_DEF
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Rubot::Adapters::Aria
|
2
|
+
class Robot
|
3
|
+
attr_reader :options
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@options = {}
|
7
|
+
@manager = RobotManager.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
args = ''
|
12
|
+
args << "-remoteHost #{@options[:host]} " if @options[:host]
|
13
|
+
args << "-remoteRobotTcpPort #{@options[:port]} " if @options[:port]
|
14
|
+
@manager.go args
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_behavior(behavior, priority)
|
18
|
+
raise ArgumentError, "Behavior must be an Aria::Behavior" unless behavior.instance_of? Behavior
|
19
|
+
@manager.add_behavior(behavior, priority)
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_sensor(sensor)
|
23
|
+
@manager.add_sensor(sensor)
|
24
|
+
end
|
25
|
+
|
26
|
+
def radius
|
27
|
+
@manager.robot_radius
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/rubot/dsl.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'facets/string/camelcase'
|
2
|
+
require 'facets/symbol/to_proc'
|
3
|
+
|
4
|
+
module Rubot::DSL
|
5
|
+
BehaviorFactories = {}
|
6
|
+
Robots = {}
|
7
|
+
|
8
|
+
class BehaviorFactoryBuilder
|
9
|
+
def initialize(name, args, &block)
|
10
|
+
@name = name.to_sym
|
11
|
+
@args = args
|
12
|
+
@sensors = []
|
13
|
+
self.instance_eval(&block)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Defines the block of code to run when this behavior fires.
|
17
|
+
#
|
18
|
+
# behavior :do_stuff do
|
19
|
+
# fire do
|
20
|
+
# # Do stuff
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
def fire(&block)
|
24
|
+
@fire = block
|
25
|
+
end
|
26
|
+
|
27
|
+
# Specifies sensors to make available to the fire block.
|
28
|
+
#
|
29
|
+
# behavior :log_sonar do
|
30
|
+
# sensors :sonar
|
31
|
+
# fire do
|
32
|
+
# puts "Sonar is reading #{sonar.range(-70,70)}"
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
def sensors(*sensors)
|
36
|
+
@sensors += sensors.map(&:to_sym)
|
37
|
+
end
|
38
|
+
|
39
|
+
def build
|
40
|
+
BehaviorFactory.new(@name, @args, @fire, @sensors.uniq)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class BehaviorFactory
|
45
|
+
def initialize(name, accepted_args, fire, sensors)
|
46
|
+
@name = name
|
47
|
+
@accepted_args = accepted_args
|
48
|
+
@fire = fire
|
49
|
+
@sensors = sensors
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_for_robot(robot, adapter, given_args={})
|
53
|
+
BehaviorContext.new(@name, @accepted_args, @fire, @sensors, robot, adapter, given_args).behavior
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class BehaviorContext
|
58
|
+
attr_reader :behavior, :robot
|
59
|
+
def initialize(name, accepted_args, fire, sensors, robot, adapter, given_args={})
|
60
|
+
@name = name
|
61
|
+
@accepted_args = accepted_args
|
62
|
+
@fire = fire
|
63
|
+
@sensors = sensors
|
64
|
+
@robot = robot
|
65
|
+
@given_args = given_args
|
66
|
+
@behavior = Rubot::Adapters.const_get(adapter)::Behavior.new name.to_s
|
67
|
+
# Have the behavior execute the fire proc in context of this object.
|
68
|
+
@behavior.set_fire_proc Proc.new { self.instance_eval(&@fire) }
|
69
|
+
@behavior.set_sensors @sensors
|
70
|
+
end
|
71
|
+
|
72
|
+
# Return the named sensor or argument.
|
73
|
+
def method_missing(sym, *args)
|
74
|
+
if @sensors.include? sym
|
75
|
+
@behavior.get_sensor(sym)
|
76
|
+
elsif @accepted_args.include? sym
|
77
|
+
@given_args[sym]
|
78
|
+
else
|
79
|
+
super
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def desired
|
84
|
+
@behavior.get_desired
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class RobotBuilder
|
89
|
+
attr_reader :adapter
|
90
|
+
def initialize(name, &block)
|
91
|
+
@name = name.to_sym
|
92
|
+
@options = {}
|
93
|
+
@sensors = []
|
94
|
+
@behaviors = []
|
95
|
+
self.instance_eval(&block)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Set the adapter for the robot, if name is given.
|
99
|
+
def adapter(name)
|
100
|
+
# TODO: Stop user from changing the adapter once set.
|
101
|
+
@adapter = name.to_s.camelcase(true).to_sym
|
102
|
+
end
|
103
|
+
|
104
|
+
def sensors(*sensors)
|
105
|
+
@sensors += sensors.map(&:to_sym)
|
106
|
+
end
|
107
|
+
|
108
|
+
def behaviors(&block)
|
109
|
+
@behaviors += RobotBehaviorsBuilder.new(&block).behaviors
|
110
|
+
end
|
111
|
+
|
112
|
+
def method_missing(opt, *args)
|
113
|
+
@options[opt] = ( args.size == 1 ? args.first : args )
|
114
|
+
nil
|
115
|
+
end
|
116
|
+
|
117
|
+
def build
|
118
|
+
raise "Robot #{@name} declared without an adapter." unless @adapter
|
119
|
+
robot = Rubot::Adapters.const_get(@adapter)::Robot.new
|
120
|
+
robot.options.merge! @options
|
121
|
+
@sensors.each { |s| robot.add_sensor s }
|
122
|
+
@behaviors.each do |name, priority, args|
|
123
|
+
b = BehaviorFactories[name].create_for_robot(robot, @adapter, args)
|
124
|
+
robot.add_behavior b, priority
|
125
|
+
end
|
126
|
+
robot
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Builds up a list of behaviors for the robot.
|
131
|
+
class RobotBehaviorsBuilder
|
132
|
+
attr_reader :behaviors
|
133
|
+
def initialize(&block)
|
134
|
+
@behaviors = []
|
135
|
+
self.instance_eval(&block)
|
136
|
+
end
|
137
|
+
|
138
|
+
def method_missing(name, args={})
|
139
|
+
priority = args.delete(:priority) do |_|
|
140
|
+
# TODO: raise hell if priority is not given.
|
141
|
+
end
|
142
|
+
@behaviors << [name.to_sym, priority, args]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def behavior(name, &block)
|
147
|
+
name, args = name.to_a.first if name.instance_of? Hash
|
148
|
+
args ||= []
|
149
|
+
bb = BehaviorFactoryBuilder.new(name, args, &block)
|
150
|
+
BehaviorFactories[name.to_sym] = bb.build
|
151
|
+
end
|
152
|
+
|
153
|
+
def robot(name, &block)
|
154
|
+
rb = RobotBuilder.new(name, &block)
|
155
|
+
Robots[name.to_sym] = rb.build
|
156
|
+
end
|
157
|
+
|
158
|
+
def run(name)
|
159
|
+
Robots[name].run
|
160
|
+
end
|
161
|
+
end
|
data/lib/rubot/meta.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
module Rubot
|
2
|
+
# :stopdoc:
|
3
|
+
VERSION = '0.5.0'
|
4
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
5
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
6
|
+
# :startdoc:
|
7
|
+
|
8
|
+
# Returns the version string for the library.
|
9
|
+
#
|
10
|
+
def self.version
|
11
|
+
VERSION
|
12
|
+
end
|
13
|
+
end
|
data/spec/load_paths.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Adds load paths to extensions for RSpec. At build, extensions end up in lib/ anyhow.
|
2
|
+
Dir['ext/*'].each do |dir|
|
3
|
+
if test ?d, dir
|
4
|
+
$LOAD_PATH.unshift dir
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
# The rake task takes care of this for us, but autotest needs it.
|
9
|
+
$LOAD_PATH.unshift 'lib' unless $LOAD_PATH.include? 'lib'
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. .. .. spec_helper])
|
2
|
+
|
3
|
+
describe Rubot::Adapters::Aria::RobotManager do
|
4
|
+
it "should be creatable" do
|
5
|
+
lambda { Rubot::Adapters::Aria::RobotManager.new }.should_not raise_error
|
6
|
+
end
|
7
|
+
|
8
|
+
# We can't really test that #go works, but we can make sure it's defined.
|
9
|
+
it "should connect to robot" do
|
10
|
+
Rubot::Adapters::Aria::RobotManager.instance_methods.should include("go")
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. .. .. spec_helper])
|
2
|
+
|
3
|
+
# fred = Rubot::Adapters::Aria::Robot.new
|
4
|
+
# fred.options[:host] = 'localhost'
|
5
|
+
|
6
|
+
include Rubot::Adapters::Aria
|
7
|
+
|
8
|
+
describe Robot do
|
9
|
+
before(:each) do
|
10
|
+
@mock_manager = mock("manager")
|
11
|
+
RobotManager.stub!(:new).and_return(@mock_manager)
|
12
|
+
@robot = Robot.new
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have options hash" do
|
16
|
+
@robot.options[:be_awesome] = true
|
17
|
+
@robot.options.keys.should include(:be_awesome)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should run the robot" do
|
21
|
+
@mock_manager.should_receive(:go)
|
22
|
+
@robot.run
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should connect to the specified host" do
|
26
|
+
@robot.options[:host] = 'robothost'
|
27
|
+
@mock_manager.should_receive(:go).with(/-remoteHost robothost/)
|
28
|
+
@robot.run
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should connect to the specified port" do
|
32
|
+
@robot.options[:port] = 3456
|
33
|
+
@mock_manager.should_receive(:go).with(/-remoteRobotTcpPort 3456/)
|
34
|
+
@robot.run
|
35
|
+
end
|
36
|
+
|
37
|
+
# TODO: Add serial connection support.
|
38
|
+
end
|